1 {-# LANGUAGE PatternSynonyms #-} -- For Instr
2 {-# LANGUAGE ViewPatterns #-} -- For unSomeInstr
3 -- | Initial encoding with bottom-up optimizations of 'Instr'uctions,
4 -- re-optimizing downward as needed after each optimization.
5 -- There is only one optimization (for 'pushValue') so far,
6 -- but the introspection enabled by the 'Instr' data-type
7 -- is also useful to optimize with more context in the 'Machine'.
8 module Symantic.Parser.Machine.Optimize where
10 import Data.Bool (Bool(..))
11 import Data.Either (Either)
12 import Data.Function ((.))
13 import Data.Kind (Constraint)
14 import Data.Maybe (Maybe(..))
16 import Type.Reflection (Typeable, typeRep, eqTypeRep, (:~~:)(..))
17 import qualified Data.Functor as Functor
18 import qualified Language.Haskell.TH as TH
20 import Symantic.Parser.Grammar
21 import Symantic.Parser.Machine.Input
22 import Symantic.Parser.Machine.Instructions
23 import Symantic.Typed.Trans
25 -- * Data family 'Instr'
26 -- | 'Instr'uctions of the 'Machine'.
27 -- This is an extensible data-type.
29 (instr :: ReprInstr -> Constraint)
30 :: ReprInstr -> ReprInstr
32 -- | Convenient utility to pattern-match a 'SomeInstr'.
33 pattern Instr :: Typeable comb =>
34 Instr comb repr inp vs a ->
35 SomeInstr repr inp vs a
36 pattern Instr x <- (unSomeInstr -> Just x)
38 -- ** Type 'SomeInstr'
39 -- | Some 'Instr'uction existentialized over the actual instruction symantic class.
40 -- Useful to handle a list of 'Instr'uctions
41 -- without requiring impredicative quantification.
42 -- Must be used by pattern-matching
43 -- on the 'SomeInstr' data-constructor,
44 -- to bring the constraints in scope.
46 -- As in 'SomeComb', a first pass of optimizations
47 -- is directly applied in it
48 -- to avoid introducing an extra newtype,
49 -- this also give a more undestandable code.
50 data SomeInstr repr inp vs a =
52 ( Trans (Instr instr repr inp vs) (repr inp vs)
55 SomeInstr (Instr instr repr inp vs a)
57 instance Trans (SomeInstr repr inp vs) (repr inp vs) where
58 trans (SomeInstr x) = trans x
60 -- | @(unSomeInstr i :: 'Maybe' ('Instr' comb repr inp vs a))@
61 -- extract the data-constructor from the given 'SomeInstr'
62 -- iif. it belongs to the @('Instr' comb repr a)@ data-instance.
64 forall instr repr inp vs a.
66 SomeInstr repr inp vs a ->
67 Maybe (Instr instr repr inp vs a)
68 unSomeInstr (SomeInstr (i::Instr i repr inp vs a)) =
69 case typeRep @instr `eqTypeRep` typeRep @i of
74 data instance Instr InstrValuable repr inp vs a where
77 SomeInstr repr inp (v ': vs) a ->
78 Instr InstrValuable repr inp vs a
80 SomeInstr repr inp vs a ->
81 Instr InstrValuable repr inp (v ': vs) a
83 Splice (x -> y -> z) ->
84 SomeInstr repr inp (z : vs) a ->
85 Instr InstrValuable repr inp (y : x : vs) a
87 SomeInstr repr inp (x ': y ': vs) a ->
88 Instr InstrValuable repr inp (y ': x ': vs) a
89 instance InstrValuable repr => Trans (Instr InstrValuable repr inp vs) (repr inp vs) where
91 PushValue x k -> pushValue x (trans k)
92 PopValue k -> popValue (trans k)
93 Lift2Value f k -> lift2Value f (trans k)
94 SwapValue k -> swapValue (trans k)
95 instance InstrValuable repr => InstrValuable (SomeInstr repr) where
96 -- 'PopValue' after a 'PushValue' is a no-op.
97 pushValue _v (Instr (PopValue i)) = i
98 pushValue v i = SomeInstr (PushValue v i)
99 popValue = SomeInstr . PopValue
100 lift2Value f = SomeInstr . Lift2Value f
101 swapValue = SomeInstr . SwapValue
103 -- InstrExceptionable
104 data instance Instr InstrExceptionable repr inp vs a where
107 Instr InstrExceptionable repr inp vs a
110 Instr InstrExceptionable repr inp vs a
113 SomeInstr repr inp vs ret ->
114 Instr InstrExceptionable repr inp vs ret
117 SomeInstr repr inp vs ret ->
118 SomeInstr repr inp (Cursor inp ': vs) ret ->
119 Instr InstrExceptionable repr inp vs ret
120 instance InstrExceptionable repr => Trans (Instr InstrExceptionable repr inp vs) (repr inp vs) where
122 Raise exn -> raise exn
124 Commit exn k -> commit exn (trans k)
125 Catch exn l r -> catch exn (trans l) (trans r)
126 instance InstrExceptionable repr => InstrExceptionable (SomeInstr repr) where
127 raise = SomeInstr . Raise
128 fail = SomeInstr . Fail
129 commit exn = SomeInstr . Commit exn
130 catch exn x = SomeInstr . Catch exn x
133 data instance Instr InstrBranchable repr inp vs a where
135 SomeInstr repr inp (x ': vs) a ->
136 SomeInstr repr inp (y ': vs) a ->
137 Instr InstrBranchable repr inp (Either x y ': vs) a
139 [Splice (v -> Bool)] ->
140 [SomeInstr repr inp vs a] ->
141 SomeInstr repr inp vs a ->
142 Instr InstrBranchable repr inp (v ': vs) a
143 instance InstrBranchable repr => Trans (Instr InstrBranchable repr inp vs) (repr inp vs) where
145 CaseBranch l r -> caseBranch (trans l) (trans r)
146 ChoicesBranch ps bs d -> choicesBranch ps (trans Functor.<$> bs) (trans d)
147 instance InstrBranchable repr => InstrBranchable (SomeInstr repr) where
148 caseBranch l = SomeInstr . CaseBranch l
149 choicesBranch ps bs = SomeInstr . ChoicesBranch ps bs
152 data instance Instr InstrCallable repr inp vs a where
154 LetBindings TH.Name (SomeInstr repr inp '[]) ->
155 SomeInstr repr inp vs a ->
156 Instr InstrCallable repr inp vs a
159 SomeInstr repr inp (v ': vs) a ->
160 Instr InstrCallable repr inp vs a
162 Instr InstrCallable repr inp '[a] a
165 Instr InstrCallable repr inp '[] a
166 instance InstrCallable repr => Trans (Instr InstrCallable repr inp vs) (repr inp vs) where
168 DefLet subs k -> defLet ((\(SomeLet sub) -> SomeLet (trans sub)) Functor.<$> subs) (trans k)
170 Call n k -> call n (trans k)
172 instance InstrCallable repr => InstrCallable (SomeInstr repr) where
173 defLet subs = SomeInstr . DefLet subs
174 jump = SomeInstr . Jump
175 call n = SomeInstr . Call n
179 data instance Instr InstrJoinable repr inp vs a where
182 SomeInstr repr inp (v ': vs) a ->
183 SomeInstr repr inp vs a ->
184 Instr InstrJoinable repr inp vs a
187 Instr InstrJoinable repr inp (v ': vs) a
188 instance InstrJoinable repr => Trans (Instr InstrJoinable repr inp vs) (repr inp vs) where
190 DefJoin n sub k -> defJoin n (trans sub) (trans k)
191 RefJoin n -> refJoin n
192 instance InstrJoinable repr => InstrJoinable (SomeInstr repr) where
193 defJoin n sub = SomeInstr . DefJoin n sub
194 refJoin = SomeInstr . RefJoin
197 data instance Instr InstrInputable repr inp vs a where
199 SomeInstr repr inp (Cursor inp ': vs) a ->
200 Instr InstrInputable repr inp vs a
202 SomeInstr repr inp vs a ->
203 Instr InstrInputable repr inp (Cursor inp ': vs) a
204 instance InstrInputable repr => Trans (Instr InstrInputable repr inp vs) (repr inp vs) where
206 PushInput k -> pushInput (trans k)
207 LoadInput k -> loadInput (trans k)
208 instance InstrInputable repr => InstrInputable (SomeInstr repr) where
209 pushInput = SomeInstr . PushInput
210 loadInput = SomeInstr . LoadInput
213 data instance Instr (InstrReadable tok) repr inp vs a where
216 Splice (InputToken inp -> Bool) ->
217 SomeInstr repr inp (InputToken inp ': vs) a ->
218 Instr (InstrReadable tok) repr inp vs a
220 ( InstrReadable tok repr, tok ~ InputToken inp ) =>
221 Trans (Instr (InstrReadable tok) repr inp vs) (repr inp vs) where
223 Read fs p k -> read fs p (trans k)
225 ( InstrReadable tok repr, Typeable tok ) =>
226 InstrReadable tok (SomeInstr repr) where
227 read fs p = SomeInstr . Read fs p