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 pushValue _v (Instr (PopValue i)) = i
97 pushValue v i = SomeInstr (PushValue v i)
98 popValue = SomeInstr . PopValue
99 lift2Value f = SomeInstr . Lift2Value f
100 swapValue = SomeInstr . SwapValue
102 -- InstrExceptionable
103 data instance Instr InstrExceptionable repr inp vs a where
106 Instr InstrExceptionable repr inp vs a
109 Instr InstrExceptionable repr inp vs a
112 SomeInstr repr inp vs ret ->
113 Instr InstrExceptionable repr inp vs ret
116 SomeInstr repr inp vs ret ->
117 SomeInstr repr inp (Cursor inp ': vs) ret ->
118 Instr InstrExceptionable repr inp vs ret
119 instance InstrExceptionable repr => Trans (Instr InstrExceptionable repr inp vs) (repr inp vs) where
121 Raise exn -> raise exn
123 Commit exn k -> commit exn (trans k)
124 Catch exn l r -> catch exn (trans l) (trans r)
125 instance InstrExceptionable repr => InstrExceptionable (SomeInstr repr) where
126 raise = SomeInstr . Raise
127 fail = SomeInstr . Fail
128 commit exn = SomeInstr . Commit exn
129 catch exn x = SomeInstr . Catch exn x
132 data instance Instr InstrBranchable repr inp vs a where
134 SomeInstr repr inp (x ': vs) a ->
135 SomeInstr repr inp (y ': vs) a ->
136 Instr InstrBranchable repr inp (Either x y ': vs) a
138 [Splice (v -> Bool)] ->
139 [SomeInstr repr inp vs a] ->
140 SomeInstr repr inp vs a ->
141 Instr InstrBranchable repr inp (v ': vs) a
142 instance InstrBranchable repr => Trans (Instr InstrBranchable repr inp vs) (repr inp vs) where
144 CaseBranch l r -> caseBranch (trans l) (trans r)
145 ChoicesBranch ps bs d -> choicesBranch ps (trans Functor.<$> bs) (trans d)
146 instance InstrBranchable repr => InstrBranchable (SomeInstr repr) where
147 caseBranch l = SomeInstr . CaseBranch l
148 choicesBranch ps bs = SomeInstr . ChoicesBranch ps bs
151 data instance Instr InstrCallable repr inp vs a where
153 LetBindings TH.Name (SomeInstr repr inp '[]) ->
154 SomeInstr repr inp vs a ->
155 Instr InstrCallable repr inp vs a
158 SomeInstr repr inp (v ': vs) a ->
159 Instr InstrCallable repr inp vs a
161 Instr InstrCallable repr inp '[a] a
164 Instr InstrCallable repr inp '[] a
165 instance InstrCallable repr => Trans (Instr InstrCallable repr inp vs) (repr inp vs) where
167 DefLet subs k -> defLet ((\(SomeLet sub) -> SomeLet (trans sub)) Functor.<$> subs) (trans k)
169 Call n k -> call n (trans k)
171 instance InstrCallable repr => InstrCallable (SomeInstr repr) where
172 defLet subs = SomeInstr . DefLet subs
173 jump = SomeInstr . Jump
174 call n = SomeInstr . Call n
178 data instance Instr InstrJoinable repr inp vs a where
181 SomeInstr repr inp (v ': vs) a ->
182 SomeInstr repr inp vs a ->
183 Instr InstrJoinable repr inp vs a
186 Instr InstrJoinable repr inp (v ': vs) a
187 instance InstrJoinable repr => Trans (Instr InstrJoinable repr inp vs) (repr inp vs) where
189 DefJoin n sub k -> defJoin n (trans sub) (trans k)
190 RefJoin n -> refJoin n
191 instance InstrJoinable repr => InstrJoinable (SomeInstr repr) where
192 defJoin n sub = SomeInstr . DefJoin n sub
193 refJoin = SomeInstr . RefJoin
196 data instance Instr InstrInputable repr inp vs a where
198 SomeInstr repr inp (Cursor inp ': vs) a ->
199 Instr InstrInputable repr inp vs a
201 SomeInstr repr inp vs a ->
202 Instr InstrInputable repr inp (Cursor inp ': vs) a
203 instance InstrInputable repr => Trans (Instr InstrInputable repr inp vs) (repr inp vs) where
205 PushInput k -> pushInput (trans k)
206 LoadInput k -> loadInput (trans k)
207 instance InstrInputable repr => InstrInputable (SomeInstr repr) where
208 pushInput = SomeInstr . PushInput
209 loadInput = SomeInstr . LoadInput
212 data instance Instr (InstrReadable tok) repr inp vs a where
215 Splice (InputToken inp -> Bool) ->
216 SomeInstr repr inp (InputToken inp ': vs) a ->
217 Instr (InstrReadable tok) repr inp vs a
219 ( InstrReadable tok repr, tok ~ InputToken inp ) =>
220 Trans (Instr (InstrReadable tok) repr inp vs) (repr inp vs) where
222 Read fs p k -> read fs p (trans k)
224 ( InstrReadable tok repr, Typeable tok ) =>
225 InstrReadable tok (SomeInstr repr) where
226 read fs p = SomeInstr . Read fs p