{-# LANGUAGE PatternSynonyms #-} -- For Instr
{-# LANGUAGE ViewPatterns #-} -- For unSomeInstr
-{-# LANGUAGE UndecidableInstances #-}
-- | Initial encoding with bottom-up optimizations of 'Instr'uctions,
-- re-optimizing downward as needed after each optimization.
-- There is only one optimization (for 'pushValue') so far,
import Data.Bool (Bool(..))
import Data.Either (Either)
-import Data.Maybe (Maybe(..))
import Data.Function ((.))
import Data.Kind (Constraint)
-import Data.Proxy (Proxy(..))
-import GHC.TypeLits (KnownSymbol)
+import Data.Maybe (Maybe(..))
+import Data.Set (Set)
import Type.Reflection (Typeable, typeRep, eqTypeRep, (:~~:)(..))
import qualified Data.Functor as Functor
import qualified Language.Haskell.TH as TH
import Symantic.Parser.Grammar
import Symantic.Parser.Machine.Input
import Symantic.Parser.Machine.Instructions
-import Symantic.Univariant.Trans
+import Symantic.Typed.Trans
-- * Data family 'Instr'
-- | 'Instr'uctions of the 'Machine'.
-- This is an extensible data-type.
data family Instr
(instr :: ReprInstr -> Constraint)
- (repr :: ReprInstr)
- :: ReprInstr
+ :: ReprInstr -> ReprInstr
-- | Convenient utility to pattern-match a 'SomeInstr'.
pattern Instr :: Typeable comb =>
-- As in 'SomeComb', a first pass of optimizations
-- is directly applied in it
-- to avoid introducing an extra newtype,
--- this also give a more comprehensible code.
+-- this also give a more undestandable code.
data SomeInstr repr inp vs a =
forall instr.
- (Trans (Instr instr repr inp vs) (repr inp vs), Typeable instr) =>
+ ( Trans (Instr instr repr inp vs) (repr inp vs)
+ , Typeable instr
+ ) =>
SomeInstr (Instr instr repr inp vs a)
instance Trans (SomeInstr repr inp vs) (repr inp vs) where
-- InstrValuable
data instance Instr InstrValuable repr inp vs a where
PushValue ::
- TermInstr v ->
+ Splice v ->
SomeInstr repr inp (v ': vs) a ->
Instr InstrValuable repr inp vs a
PopValue ::
SomeInstr repr inp vs a ->
Instr InstrValuable repr inp (v ': vs) a
Lift2Value ::
- TermInstr (x -> y -> z) ->
+ Splice (x -> y -> z) ->
SomeInstr repr inp (z : vs) a ->
Instr InstrValuable repr inp (y : x : vs) a
SwapValue ::
Lift2Value f k -> lift2Value f (trans k)
SwapValue k -> swapValue (trans k)
instance InstrValuable repr => InstrValuable (SomeInstr repr) where
+ -- 'PopValue' after a 'PushValue' is a no-op.
pushValue _v (Instr (PopValue i)) = i
pushValue v i = SomeInstr (PushValue v i)
popValue = SomeInstr . PopValue
-- InstrExceptionable
data instance Instr InstrExceptionable repr inp vs a where
- RaiseException ::
- KnownSymbol lbl =>
- Proxy lbl ->
- [ErrorItem (InputToken inp)] ->
+ Raise ::
+ ExceptionLabel ->
+ Instr InstrExceptionable repr inp vs a
+ Fail ::
+ Set SomeFailure ->
Instr InstrExceptionable repr inp vs a
- PopException ::
- KnownSymbol lbl =>
- Proxy lbl ->
+ Commit ::
+ Exception ->
SomeInstr repr inp vs ret ->
Instr InstrExceptionable repr inp vs ret
- CatchException ::
- KnownSymbol lbl =>
- Proxy lbl ->
+ Catch ::
+ Exception ->
SomeInstr repr inp vs ret ->
SomeInstr repr inp (Cursor inp ': vs) ret ->
Instr InstrExceptionable repr inp vs ret
instance InstrExceptionable repr => Trans (Instr InstrExceptionable repr inp vs) (repr inp vs) where
trans = \case
- RaiseException lbl err -> raiseException lbl err
- PopException lbl k -> popException lbl (trans k)
- CatchException lbl l r -> catchException lbl (trans l) (trans r)
+ Raise exn -> raise exn
+ Fail fs -> fail fs
+ Commit exn k -> commit exn (trans k)
+ Catch exn l r -> catch exn (trans l) (trans r)
instance InstrExceptionable repr => InstrExceptionable (SomeInstr repr) where
- raiseException lbl = SomeInstr . RaiseException lbl
- popException lbl = SomeInstr . PopException lbl
- catchException lbl x = SomeInstr . CatchException lbl x
+ raise = SomeInstr . Raise
+ fail = SomeInstr . Fail
+ commit exn = SomeInstr . Commit exn
+ catch exn x = SomeInstr . Catch exn x
-- InstrBranchable
data instance Instr InstrBranchable repr inp vs a where
SomeInstr repr inp (y ': vs) a ->
Instr InstrBranchable repr inp (Either x y ': vs) a
ChoicesBranch ::
- [TermInstr (v -> Bool)] ->
+ [Splice (v -> Bool)] ->
[SomeInstr repr inp vs a] ->
SomeInstr repr inp vs a ->
Instr InstrBranchable repr inp (v ': vs) a
-- InstrReadable
data instance Instr (InstrReadable tok) repr inp vs a where
Read ::
- [ErrorItem (InputToken inp)] ->
- TermInstr (InputToken inp -> Bool) ->
+ Set SomeFailure ->
+ Splice (InputToken inp -> Bool) ->
SomeInstr repr inp (InputToken inp ': vs) a ->
Instr (InstrReadable tok) repr inp vs a
instance
( InstrReadable tok repr, tok ~ InputToken inp ) =>
Trans (Instr (InstrReadable tok) repr inp vs) (repr inp vs) where
trans = \case
- Read es p k -> read es p (trans k)
+ Read fs p k -> read fs p (trans k)
instance
( InstrReadable tok repr, Typeable tok ) =>
InstrReadable tok (SomeInstr repr) where
- read es p = SomeInstr . Read es p
+ read fs p = SomeInstr . Read fs p