1 {-# LANGUAGE ConstraintKinds #-} -- For Machine
2 {-# LANGUAGE DerivingStrategies #-} -- For Show (LetName a)
3 -- | Semantic of the parsing instructions used
4 -- to make the parsing control-flow explicit,
5 -- in the convenient tagless-final encoding.
6 module Symantic.Parser.Machine.Instructions where
8 import Data.Bool (Bool(..))
9 import Data.Either (Either)
10 import Data.Eq (Eq(..))
11 import Data.Function ((.))
12 import Data.Kind (Type)
13 -- import GHC.TypeLits (Symbol)
14 import Text.Show (Show(..))
15 import qualified Language.Haskell.TH as TH
16 import qualified Symantic.Parser.Haskell as H
18 import Symantic.Parser.Grammar
19 import Symantic.Parser.Machine.Input
22 type TermInstr = H.Term TH.CodeQ
25 -- | Type-level natural numbers,
26 -- using the Peano recursive encoding.
27 data Peano = Zero | Succ Peano
30 -- | All the 'Instr'uctions.
31 type Machine tok repr =
41 -- ** Type 'ReprInstr'
42 type ReprInstr = Type -> [Type] -> Peano -> Type -> Type
45 -- | 'TH.Name' of a 'subroutine' or 'defJoin'
46 -- indexed by the return type of the factorized 'Instr'uctions.
47 -- This helps type-inferencing.
48 newtype LetName a = LetName { unLetName :: TH.Name }
52 -- ** Class 'Stackable'
53 class Stackable (repr::ReprInstr) where
56 repr inp (v ': vs) n a ->
60 repr inp (v ': vs) n a
62 TermInstr (x -> y -> z) ->
63 repr inp (z ': vs) es a ->
64 repr inp (y ': x ': vs) es a
66 repr inp (x ': y ': vs) n r ->
67 repr inp (y ': x ': vs) n r
71 repr inp (y ': vs) es a ->
72 repr inp (x ': vs) es a
73 mapI f = push f . liftI2 (H.flip H..@ (H.$))
74 -- | @('appI' k)@ pops @(x)@ and @(x2y)@ from the 'valueStack',
75 -- pushes @(x2y x)@ and continues with the next 'Instr'uction @(k)@.
77 repr inp (y ': vs) es a ->
78 repr inp (x ': (x -> y) ': vs) es a
81 -- ** Class 'Routinable'
82 class Routinable (repr::ReprInstr) where
84 LetName v -> repr inp '[] ('Succ 'Zero) v ->
85 repr inp vs ('Succ es) a ->
86 repr inp vs ('Succ es) a
88 LetName v -> repr inp (v ': vs) ('Succ es) a ->
89 repr inp vs ('Succ es) a
94 repr inp '[] ('Succ es) a
96 -- ** Class 'Branchable'
97 class Branchable (repr::ReprInstr) where
99 repr inp (x ': vs) n r ->
100 repr inp (y ': vs) n r ->
101 repr inp (Either x y ': vs) n r
103 [TermInstr (v -> Bool)] ->
104 [repr inp vs es a] ->
106 repr inp (v ': vs) es a
107 -- | @('ifI' ok ko)@ pops a 'Bool' from the 'valueStack'
108 -- and continues either with the 'Instr'uction @(ok)@ if it is 'True'
109 -- or @(ko)@ otherwise.
113 repr inp (Bool ': vs) es a
114 ifI ok ko = choices [H.id] [ok] ko
116 -- ** Class 'Failable'
117 class Failable (repr::ReprInstr) where
119 [ErrorItem (InputToken inp)] ->
120 repr inp vs ('Succ es) a
123 repr inp vs ('Succ es) a
125 repr inp vs ('Succ es) a ->
126 repr inp (Cursor inp ': vs) es a ->
129 -- ** Class 'Inputable'
130 class Inputable (repr::ReprInstr) where
133 repr inp (Cursor inp ': vs) es a
135 repr inp (Cursor inp ': vs) es a ->
138 -- ** Class 'Joinable'
139 class Joinable (repr::ReprInstr) where
142 repr inp (v ': vs) es a ->
147 repr inp (v ': vs) es a
149 -- ** Class 'Readable'
150 class Readable (tok::Type) (repr::ReprInstr) where
152 tok ~ InputToken inp =>
154 TermInstr (tok -> Bool) ->
155 repr inp (tok ': vs) ('Succ es) a ->
156 repr inp vs ('Succ es) a