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 newtype LetName a = LetName { unLetName :: TH.Name }
49 -- ** Class 'Stackable'
50 class Stackable (repr::ReprInstr) where
53 repr inp (v ': vs) n a ->
57 repr inp (v ': vs) n a
59 TermInstr (x -> y -> z) ->
60 repr inp (z ': vs) es a ->
61 repr inp (y ': x ': vs) es a
63 repr inp (x ': y ': vs) n r ->
64 repr inp (y ': x ': vs) n r
68 repr inp (y ': vs) es a ->
69 repr inp (x ': vs) es 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) es a ->
75 repr inp (x ': (x -> y) ': vs) es a
78 -- ** Class 'Routinable'
79 class Routinable (repr::ReprInstr) where
81 LetName v -> repr inp '[] ('Succ 'Zero) v ->
82 repr inp vs ('Succ es) a ->
83 repr inp vs ('Succ es) a
85 LetName v -> repr inp (v ': vs) ('Succ es) a ->
86 repr inp vs ('Succ es) a
91 repr inp '[] ('Succ es) a
93 -- ** Class 'Branchable'
94 class Branchable (repr::ReprInstr) where
96 repr inp (x ': vs) n r ->
97 repr inp (y ': vs) n r ->
98 repr inp (Either x y ': vs) n r
100 [TermInstr (v -> Bool)] ->
101 [repr inp vs es a] ->
103 repr inp (v ': vs) es a
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) es a
111 ifI ok ko = choices [H.id] [ok] ko
113 -- ** Class 'Failable'
114 class Failable (repr::ReprInstr) where
116 [ErrorItem (InputToken inp)] ->
117 repr inp vs ('Succ es) a
120 repr inp vs ('Succ es) a
122 repr inp vs ('Succ es) a ->
123 repr inp (Cursor inp ': vs) es a ->
126 -- ** Class 'Inputable'
127 class Inputable (repr::ReprInstr) where
130 repr inp (Cursor inp ': vs) es a
132 repr inp (Cursor inp ': vs) es a ->
135 -- ** Class 'Joinable'
136 class Joinable (repr::ReprInstr) where
139 repr inp (v ': vs) es a ->
144 repr inp (v ': vs) es a
146 -- ** Class 'Readable'
147 class Readable (tok::Type) (repr::ReprInstr) where
149 tok ~ InputToken inp =>
151 TermInstr (tok -> Bool) ->
152 repr inp (tok ': vs) ('Succ es) a ->
153 repr inp vs ('Succ es) a