1 {-# LANGUAGE TemplateHaskell #-}
2 module Symantic.Parser.Automaton.Eval where
4 import Control.Monad (Monad(..))
5 import Data.Bool (Bool)
6 import Data.Char (Char)
7 import Data.Either (Either(..))
8 import Data.Function (($))
9 import Data.String (String)
10 import Language.Haskell.TH (CodeQ, Code(..))
12 import qualified Data.Eq as Eq
13 import qualified Language.Haskell.TH.Syntax as TH
15 import Symantic.Univariant.Trans
16 import Symantic.Parser.Automaton.Input
17 import Symantic.Parser.Automaton.Instructions
18 import qualified Symantic.Parser.Staging as H
21 newtype Eval inp vs es ret a = Eval { unEval ::
22 EvalCtx inp vs es ret a -> CodeQ (Either ParsingError a)
25 type Cont inp a x = x -> inp -> Either ParsingError a
26 type SubRoutine inp a x = Cont inp a x -> inp -> ExceptionHandler inp a -> Either ParsingError a
27 type ParsingError = String
28 type ExceptionHandler inp a = inp -> Either ParsingError a
31 data EvalCtx inp vs (es::Peano) r a = EvalCtx
32 { valueStack :: ValueStack vs
33 , exceptionStack :: ExceptionStack inp es a
35 , inputOps :: InputOps inp
36 , retCode :: CodeQ (Cont inp a r)
39 -- ** Type 'ValueStack'
40 data ValueStack vs where
41 ValueStackEmpty :: ValueStack '[]
42 ValueStackCons :: CodeQ v -> ValueStack vs -> ValueStack (v ': vs)
44 -- ** Type 'ExceptionStack'
45 data ExceptionStack inp es a where
46 ExceptionStackEmpty :: ExceptionStack inp 'Zero a
47 ExceptionStackCons :: CodeQ (ExceptionHandler inp a) -> ExceptionStack inp es a -> ExceptionStack inp ('Succ es) a
49 instance Stackable Eval where
50 push x k = Eval $ \inh -> unEval k inh
51 { valueStack = ValueStackCons (liftCode x) (valueStack inh) }
52 pop k = Eval $ \inh -> unEval k inh
53 { valueStack = let ValueStackCons _ xs = valueStack inh in xs }
54 liftI2 f k = Eval $ \inh -> unEval k inh
56 let ValueStackCons y (ValueStackCons x xs) = valueStack inh in
57 ValueStackCons (liftCode2 f x y) xs
59 swap k = Eval $ \inh -> unEval k inh
61 let ValueStackCons y (ValueStackCons x xs) = valueStack inh in
62 ValueStackCons x (ValueStackCons y xs)
64 instance Branchable Eval where
65 case_ kx ky = Eval $ \inh ->
66 let ValueStackCons v vs = valueStack inh in
69 Left x -> $$(unEval kx inh{ valueStack = ValueStackCons [||x||] vs })
70 Right y -> $$(unEval ky inh{ valueStack = ValueStackCons [||y||] vs })
72 choices fs ks kd = Eval $ \inh ->
73 let ValueStackCons v vs = valueStack inh in
74 go inh{valueStack = vs} v fs ks
76 go inh x (f:fs') (Eval k:ks') = [||
77 if $$(liftCode1 f x) then $$(k inh)
78 else $$(go inh x fs' ks')
80 go inh _ _ _ = unEval kd inh
81 instance Exceptionable Eval where
83 let ExceptionStackCons e _es = exceptionStack inh in
84 [|| $$e $$(input inh) ||]
85 commit k = Eval $ \inh ->
86 let ExceptionStackCons _e es = exceptionStack inh in
87 unEval k inh{exceptionStack = es}
88 catch k h = Eval $ \inh ->
89 setupHandler inh (buildHandler inh h) k
90 instance Inputable Eval where
91 seek k = Eval $ \inh ->
92 let ValueStackCons input vs = valueStack inh in
93 unEval k inh{valueStack = vs, input}
94 tell k = Eval $ \inh ->
95 unEval k inh{valueStack = ValueStackCons (input inh) (valueStack inh)}
96 instance Routinable Eval where
97 call (Label n) k = Eval $ \inh ->
98 callWithContinuation (Code $ TH.unsafeTExpCoerce (return (TH.VarE n))) (suspend k inh) (input inh) (exceptionStack inh)
99 jump (Label n) = Eval $ \inh ->
100 callWithContinuation (Code $ TH.unsafeTExpCoerce (return (TH.VarE n))) (retCode inh) (input inh) (exceptionStack inh)
101 ret = Eval $ \inh -> unEval (resume (retCode inh)) inh
102 subroutine _n _v k = k
103 instance Readable Eval where
104 read p k = sat (liftCode p) k fail
108 -- InputPosition inp =>
110 InstrPure (Char -> Bool) ->
111 Eval inp (Char ': vs) ('Succ es) r a ->
112 Eval inp vs ('Succ es) r a
114 bankrupt <- asks isBankrupt
115 hasChange <- asks hasCoin
116 if | bankrupt -> maybeEmitCheck (Just 1) <$> k
117 | hasChange -> maybeEmitCheck Nothing <$> local spendCoin k
118 | otherwise -> local breakPiggy (maybeEmitCheck . Just <$> asks coins <*> local spendCoin k)
120 maybeEmitCheck Nothing mk inh = sat (genDefunc p) mk (raise inh) inh
121 maybeEmitCheck (Just n) mk inh =
122 [|| let bad = $$(raise inh) in $$(emitLengthCheck n (sat (genDefunc p) mk [||bad||]) [||bad||] inh)||]
126 CodeQ (Char -> Bool) ->
127 Eval inp (Char ': vs) es r a ->
128 Eval inp vs es r a ->
130 sat p k bad = Eval $ \inh ->
131 next (inputOps inh) (input inh) $ \c inp -> [||
134 { valueStack = ValueStackCons c (valueStack inh)
137 else $$(unEval bad inh)
141 callWithContinuation ::
142 CodeQ (SubRoutine inp a x) ->
143 CodeQ (Cont inp a x) ->
145 ExceptionStack inp ('Succ es) a ->
146 CodeQ (Either ParsingError a)
147 callWithContinuation sub r inp (ExceptionStackCons h _) =
148 [|| $$sub $$r $$inp $! $$h ||]
151 Eval inp (x ': xs) es r a ->
152 EvalCtx inp xs es r a ->
154 suspend k inh = [|| \x !inp ->
156 { valueStack = ValueStackCons [||x||] (valueStack inh)
161 resume :: CodeQ (Cont inp a x) -> Eval inp (x ': xs) es r a
162 resume k = Eval $ \inh ->
163 let ValueStackCons x _ = valueStack inh in
164 [|| $$k $$x $$(input inh) ||]
167 EvalCtx inp vs es r a ->
168 (CodeQ inp -> CodeQ (ExceptionHandler inp a)) ->
169 Eval inp vs ('Succ es) r a ->
170 CodeQ (Either ParsingError a)
171 setupHandler inh handler k = [||
173 { exceptionStack = ExceptionStackCons
174 (handler (input inh))
179 EvalCtx inp vs es r a ->
180 Eval inp (inp ': vs) es r a ->
181 CodeQ inp -> CodeQ (ExceptionHandler inp a)
182 buildHandler inh handler e = [|| \inp ->
183 $$(unEval handler inh
184 { valueStack = ValueStackCons e (valueStack inh)
189 liftCode :: InstrPure a -> CodeQ a
191 {-# INLINE liftCode #-}
193 liftCode1 :: InstrPure (a -> b) -> CodeQ a -> CodeQ b
194 liftCode1 p a = case p of
195 InstrPureSameOffset -> [|| $$same $$a ||]
196 InstrPureHaskell h -> go a h
198 go :: CodeQ a -> H.Haskell (a -> b) -> CodeQ b
200 (H.:$) -> [|| \x -> $$qa x ||]
201 (H.:.) -> [|| \g x -> $$qa (g x) ||]
202 H.Flip -> [|| \x y -> $$qa y x ||]
203 (H.:.) H.:@ f H.:@ g -> [|| $$(go (go qa g) f) ||]
204 H.Const -> [|| \_ -> $$qa ||]
205 H.Flip H.:@ H.Const -> H.id
206 h@(H.Flip H.:@ _f) -> [|| \x -> $$(liftCode2 (InstrPureHaskell h) qa [||x||]) ||]
207 H.Eq x -> [|| $$(trans x) Eq.== $$qa ||]
209 h -> [|| $$(trans h) $$qa ||]
211 liftCode2 :: InstrPure (a -> b -> c) -> CodeQ a -> CodeQ b -> CodeQ c
212 liftCode2 p a b = case p of
213 InstrPureSameOffset -> [|| $$same $$a $$b ||]
214 InstrPureHaskell h -> go a b h
216 go :: CodeQ a -> CodeQ b -> H.Haskell (a -> b -> c) -> CodeQ c
218 (H.:$) -> [|| $$qa $$qb ||]
219 (H.:.) -> [|| \x -> $$qa ($$qb x) ||]
220 H.Flip -> [|| \x -> $$qa x $$qb ||]
221 H.Flip H.:@ H.Const -> [|| $$qb ||]
222 H.Flip H.:@ f -> go qb qa f
223 H.Const -> [|| $$qa ||]
224 H.Cons -> [|| $$qa : $$qb ||]
225 h -> [|| $$(trans h) $$qa $$qb ||]