1 {-# LANGUAGE AllowAmbiguousTypes #-} -- For SuccThrowAll uses
2 {-# LANGUAGE ConstraintKinds #-} -- For Machine
3 {-# LANGUAGE DerivingStrategies #-} -- For Show (LetName a)
4 -- | Semantic of the parsing instructions used
5 -- to make the parsing control-flow explicit,
6 -- in the convenient tagless-final encoding.
7 module Symantic.Parser.Machine.Instructions where
9 import Data.Bool (Bool(..))
10 import Data.Either (Either)
11 import Data.Eq (Eq(..))
12 import Data.Function ((.))
13 import Data.Kind (Type)
14 import GHC.TypeLits (KnownSymbol)
15 import Text.Show (Show(..))
16 import Data.Proxy (Proxy(..))
17 import qualified Language.Haskell.TH as TH
18 import qualified Symantic.Parser.Haskell as H
20 import Symantic.Parser.Grammar
21 import Symantic.Parser.Machine.Input
24 type TermInstr = H.Term TH.CodeQ
27 -- | All the 'Instr'uctions.
28 type Machine tok repr =
38 -- ** Type 'ReprInstr'
39 type ReprInstr = Type -> [Type] -> Type -> Type
42 -- | 'TH.Name' of a 'subroutine' or 'defJoin'
43 -- indexed by the return type of the factorized 'Instr'uctions.
44 -- This helps type-inferencing.
45 newtype LetName a = LetName { unLetName :: TH.Name }
49 -- ** Class 'Stackable'
50 class Stackable (repr::ReprInstr) where
53 repr inp (v ': vs) a ->
59 TermInstr (x -> y -> z) ->
60 repr inp (z ': vs) a ->
61 repr inp (y ': x ': vs) a
63 repr inp (x ': y ': vs) a ->
64 repr inp (y ': x ': vs) a
68 repr inp (y ': vs) a ->
70 mapI f = push f . liftI2 (H.flip H..@ (H.$))
71 -- | @('appI' k)@ pops @(x)@ and @(x2y)@ from the 'valueStack',
72 -- pushes @(x2y x)@ and continues with the next 'Instr'uction @(k)@.
74 repr inp (y ': vs) a ->
75 repr inp (x ': (x -> y) ': vs) a
78 -- ** Class 'Routinable'
79 class Routinable (repr::ReprInstr) where
81 LetName v -> repr inp '[] v ->
85 LetName v -> repr inp (v ': vs) a ->
93 -- ** Class 'Branchable'
94 class Branchable (repr::ReprInstr) where
96 repr inp (x ': vs) r ->
97 repr inp (y ': vs) r ->
98 repr inp (Either x y ': vs) r
100 [TermInstr (v -> Bool)] ->
104 -- | @('ifI' ok ko)@ pops a 'Bool' from the 'valueStack'
105 -- and continues either with the 'Instr'uction @(ok)@ if it is 'True'
106 -- or @(ko)@ otherwise.
110 repr inp (Bool ': vs) a
111 ifI ok ko = choices [H.id] [ok] ko
113 -- ** Class 'Raisable'
114 class Raisable (repr::ReprInstr) where
115 --type ThrowableConstraint repr (lbl::Symbol) (fs::[(Symbol, Peano)]) :: Constraint
117 --ThrowableConstraint repr lbl =>
120 [ErrorItem (InputToken inp)] ->
123 --ThrowableConstraint repr "fail" =>
124 [ErrorItem (InputToken inp)] ->
126 fail = raise (Proxy @"fail")
128 --ThrowableConstraint repr lbl =>
134 --ThrowableConstraint repr lbl =>
138 repr inp (Cursor inp ': vs) ret ->
141 -- ** Class 'Inputable'
142 class Inputable (repr::ReprInstr) where
145 repr inp (Cursor inp ': vs) a
147 repr inp (Cursor inp ': vs) a ->
150 -- ** Class 'Joinable'
151 class Joinable (repr::ReprInstr) where
153 LetName v -> repr inp (v ': vs) a ->
160 -- ** Class 'Readable'
161 class Readable (tok::Type) (repr::ReprInstr) where
163 tok ~ InputToken inp =>
165 TermInstr (tok -> Bool) ->
166 repr inp (tok ': vs) a ->