symantic-parser-0.2.1.20210803: src/Symantic/Parser/Grammar/ObserveSharing.hs
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE TupleSections #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Symantic.Parser.Grammar.ObserveSharing
( module Symantic.ObserveSharing
, module Symantic.Parser.Grammar.ObserveSharing
) where
import Control.Monad (mapM)
import Data.Function (($), (.))
import Data.Hashable (Hashable, hashWithSalt)
import System.IO.Unsafe (unsafePerformIO) -- For 'new'
import Text.Show (Show(..))
import qualified Control.Applicative as F
import Symantic.Parser.Grammar.Combinators
import Symantic.Derive
import Symantic.ObserveSharing hiding (observeSharing)
import qualified Symantic.ObserveSharing as ObserveSharing
import qualified Language.Haskell.TH.Syntax as TH
-- | Like 'Observable.observeSharing'
-- but type-binding @(letName)@ to 'TH.Name'
-- to avoid the trouble to always set it.
observeSharing :: Letsable TH.Name repr => ObserveSharing TH.Name repr a -> repr a
observeSharing os = lets defs body
where (body, defs) = ObserveSharing.observeSharing os
-- | Needed by 'observeSharing'.
instance Hashable TH.Name where
hashWithSalt s = hashWithSalt s . show
instance MakeLetName TH.Name where
makeLetName _ = TH.qNewName "name"
-- Combinators semantics for the 'ObserveSharing' interpreter.
instance
( Referenceable TH.Name repr
, CombAlternable repr
) => CombAlternable (ObserveSharing TH.Name repr)
instance
( Referenceable TH.Name repr
, CombApplicable repr
) => CombApplicable (ObserveSharing TH.Name repr)
instance
( Referenceable TH.Name repr
, CombFoldable repr
) => CombFoldable (ObserveSharing TH.Name repr)
instance
( Referenceable TH.Name repr
, CombLookable repr
) => CombLookable (ObserveSharing TH.Name repr)
instance
( Referenceable TH.Name repr
, CombMatchable repr
) => CombMatchable (ObserveSharing TH.Name repr) where
-- Here the default definition does not fit
-- since there is no liftDerived* for the type of 'conditional'
-- and its default definition does not handles 'bs'
-- as needed by the 'ObserveSharing' interpreter.
conditional a bs d = observeSharingNode $ ObserveSharing $ conditional
F.<$> unObserveSharing a
F.<*> mapM (\(p, b) -> (p,) F.<$> unObserveSharing b) bs
F.<*> unObserveSharing d
instance
( Referenceable TH.Name repr
, CombSelectable repr
) => CombSelectable (ObserveSharing TH.Name repr)
instance
( Referenceable TH.Name repr
, CombSatisfiable tok repr
) => CombSatisfiable tok (ObserveSharing TH.Name repr)
instance
( Referenceable TH.Name repr
, CombRegisterableUnscoped repr
) => CombRegisterable (ObserveSharing TH.Name repr) where
new ini f =
-- 'unsafePerformIO' is used here because propagating 'IO'
-- would prevent 'observeSharing' to recognize recursive let,
-- causing an infinite loop on them.
let !regName = unsafePerformIO $ TH.newName "reg" in
let reg = UnscopedRegister regName in
newUnscoped reg ini (f (Register reg))
get = getUnscoped . unRegister
put reg x = putUnscoped (unRegister reg) x
instance
( Referenceable TH.Name repr
, CombRegisterableUnscoped repr
) => CombRegisterableUnscoped (ObserveSharing TH.Name repr)
-- * Class 'CombRegisterableUnscoped'
-- | These combinators are used to remove the @Rank2Types@ from 'CombRegisterable'
-- in order to be able to 'observeSharing'.
class CombRegisterableUnscoped (repr::ReprComb) where
newUnscoped :: UnscopedRegister a -> repr a -> repr b -> repr b
getUnscoped :: UnscopedRegister a -> repr a
putUnscoped :: UnscopedRegister a -> repr a -> repr ()
default newUnscoped ::
FromDerived2 CombRegisterableUnscoped repr =>
UnscopedRegister a -> repr a -> repr b -> repr b
default getUnscoped ::
FromDerived CombRegisterableUnscoped repr =>
UnscopedRegister a -> repr a
default putUnscoped ::
FromDerived1 CombRegisterableUnscoped repr =>
UnscopedRegister a -> repr a -> repr ()
newUnscoped = liftDerived2 . newUnscoped
getUnscoped = liftDerived . getUnscoped
putUnscoped = liftDerived1 . putUnscoped
-- Combinators semantics for the 'FinalizeSharing' interpreter.
instance
( CombApplicable repr
) => CombApplicable (FinalizeSharing TH.Name repr)
instance
( CombAlternable repr
) => CombAlternable (FinalizeSharing TH.Name repr)
instance
( CombFoldable repr
) => CombFoldable (FinalizeSharing TH.Name repr)
instance
( CombLookable repr
) => CombLookable (FinalizeSharing TH.Name repr)
instance
( CombMatchable repr
) => CombMatchable (FinalizeSharing TH.Name repr) where
conditional a bs d = FinalizeSharing $ conditional
F.<$> unFinalizeSharing a
F.<*> mapM (\(p, b) -> (p,) F.<$> unFinalizeSharing b) bs
F.<*> unFinalizeSharing d
instance
( CombSatisfiable tok repr
) => CombSatisfiable tok (FinalizeSharing TH.Name repr)
instance
( CombSelectable repr
) => CombSelectable (FinalizeSharing TH.Name repr)
instance
( CombRegisterableUnscoped repr
) => CombRegisterableUnscoped (FinalizeSharing TH.Name repr)
-- | Call trace stack updated by 'call' and 'refJoin'.
-- Used to avoid infinite loops when tying the knot with 'polyfix'.
type CallTrace = [TH.Name]