1 {-# LANGUAGE AllowAmbiguousTypes #-}
2 {-# LANGUAGE OverloadedStrings #-}
3 {-# LANGUAGE UndecidableInstances #-} -- For HideableName
4 module Symantic.Parser.Machine.View where
6 import Data.Bool (Bool(..))
7 import Data.Either (Either(..))
8 import Data.Function (($), (.), id, on)
9 import Data.Functor ((<$>))
10 import Data.Kind (Type)
11 import Data.Ord (Ord(..))
12 import Data.Semigroup (Semigroup(..))
13 import Data.String (String)
14 import Data.Tuple (fst)
15 import Text.Show (Show(..))
16 import qualified Data.HashMap.Strict as HM
17 import qualified Data.List as List
18 import qualified Data.Map.Strict as Map
19 import qualified Data.Set as Set
20 import qualified Data.Tree as Tree
21 import Language.Haskell.TH.HideName
22 import qualified Language.Haskell.TH.Syntax as TH
23 import Prelude (error)
25 import Symantic.Optimize (normalOrderReduction)
26 import Symantic.Parser.Grammar.Combinators (UnscopedRegister(..))
27 import Symantic.Parser.Grammar.ObserveSharing
28 import Symantic.Parser.Machine.Instructions
29 import Symantic.Parser.Machine.Generate
31 -- * Type 'ViewMachine'
32 data ViewMachine (showName::Bool) inp (vs:: [Type]) a
34 { viewGen :: Gen inp vs a
35 -- ^ Provide 'GenAnalysis', which is important for debugging
36 -- and improving golden tests, see 'viewInstrCmd'.
38 LetRecs TH.Name GenAnalysis -> -- Output of 'mutualFix'.
39 Tree.Forest (String, String) ->
40 Tree.Forest (String, String)
43 viewMachine :: ViewMachine sN inp vs a -> ViewMachine sN inp vs a
46 showSplice :: Splice a -> String
47 showSplice p = showsPrec 10 (normalOrderReduction p) ""
49 -- | Helper to view a command.
51 forall (sN::Bool) inp vs a.
53 Either TH.Name (Gen inp vs a) ->
54 LetRecs TH.Name GenAnalysis ->
55 (String, String) -> Tree.Forest (String, String) -> Tree.Tree (String, String)
56 viewInstrCmd gen finalByLet (cmd, no) = Tree.Node $ (cmd
57 <> "\nminReads="<>showsPrec 11 (minReads ga) ""
58 <> "\nmayRaise="<>show (Map.keys (mayRaise ga))
59 <> "\nfreeRegs="<>show (hideableName @sN (Set.toList (freeRegs ga)))
63 Right a -> genAnalysis a finalByLet
64 Left n -> HM.findWithDefault (error (show (n, HM.keys finalByLet))) n finalByLet
66 -- | Helper to view an argument.
67 viewInstrArg :: String -> Tree.Forest (String, String) -> Tree.Tree (String, String)
68 viewInstrArg n = Tree.Node $ ("<"<>n<>">", "")
70 instance Show (ViewMachine sN inp vs a) where
71 show vm = List.unlines $ drawTrees $
72 unViewMachine vm (mutualFix (genAnalysisByLet (viewGen vm))) []
74 draw :: Tree.Tree (String, String) -> [String]
75 draw (Tree.Node (x, n) ts0) =
76 shift "" " " (List.zipWith (<>) (List.lines x) (n : List.repeat "")) <>
77 shift "| " "| " (drawTrees ts0)
79 drawTrees [t] = draw t
80 drawTrees (t:ts) = draw t <> drawTrees ts
81 shift ind0 ind = List.zipWith (<>) (ind0 : List.repeat ind)
85 InstrComment (ViewMachine sN) where
86 comment msg k = ViewMachine
87 { unViewMachine = \lm next ->
88 viewInstrCmd @sN (Right gen) lm ("comment "<>show msg, "") [] :
89 unViewMachine k lm next
91 } where gen = comment msg (viewGen k)
94 InstrValuable (ViewMachine sN) where
95 pushValue a k = ViewMachine
96 { unViewMachine = \lm next ->
97 viewInstrCmd @sN (Right gen) lm ("pushValue "<>showSplice a, "") [] :
98 unViewMachine k lm next
100 } where gen = pushValue a (viewGen k)
101 popValue k = ViewMachine
102 { unViewMachine = \lm next ->
103 viewInstrCmd @sN (Right gen) lm ("popValue", "") [] :
104 unViewMachine k lm next
106 } where gen = popValue (viewGen k)
107 lift2Value f k = ViewMachine
108 { unViewMachine = \lm next ->
109 viewInstrCmd @sN (Right gen) lm ("lift2Value "<>showSplice f, "") [] :
110 unViewMachine k lm next
112 } where gen = lift2Value f (viewGen k)
113 swapValue k = ViewMachine
114 { unViewMachine = \lm next ->
115 viewInstrCmd @sN (Right gen) lm ("swapValue", "") [] :
116 unViewMachine k lm next
118 } where gen = swapValue (viewGen k)
121 InstrExceptionable (ViewMachine sN) where
122 raise exn = ViewMachine
123 { unViewMachine = \lm next ->
124 viewInstrCmd @sN (Right gen) lm ("raise "<>show exn, "") [] : next
126 } where gen = raise exn
127 fail flr = ViewMachine
128 { unViewMachine = \lm next ->
129 viewInstrCmd @sN (Right gen) lm ("fail "<>show (Set.toList flr), "") [] : next
131 } where gen = fail flr
132 commit exn k = ViewMachine
133 { unViewMachine = \lm next ->
134 viewInstrCmd @sN (Right gen) lm ("commit "<>show exn, "") [] :
135 unViewMachine k lm next
137 } where gen = commit exn (viewGen k)
138 catch exn ok ko = ViewMachine
139 { unViewMachine = \lm next ->
140 viewInstrCmd @sN (Right gen) lm ("catch "<>show exn, "")
141 [ viewInstrArg "ok" (unViewMachine ok lm [])
142 , viewInstrArg "ko" (unViewMachine ko lm [])
145 } where gen = catch exn (viewGen ok) (viewGen ko)
148 InstrBranchable (ViewMachine sN) where
149 caseBranch l r = ViewMachine
150 { unViewMachine = \lm next ->
151 viewInstrCmd @sN (Right gen) lm ("case", "")
152 [ viewInstrArg "left" (unViewMachine l lm [])
153 , viewInstrArg "right" (unViewMachine r lm [])
156 } where gen = caseBranch (viewGen l) (viewGen r)
157 choicesBranch bs d = ViewMachine
158 { unViewMachine = \lm next ->
159 viewInstrCmd @sN (Right gen) lm ("choicesBranch", "") (
160 ((\(p, b) -> viewInstrArg ("branch "<>showSplice p) $
161 unViewMachine b lm []) <$> bs) <>
162 [ viewInstrArg "default" (unViewMachine d lm []) ]
165 } where gen = choicesBranch ((viewGen <$>) <$> bs) (viewGen d)
168 InstrCallable (ViewMachine sN) where
169 defLet defs k = ViewMachine
170 { unViewMachine = \lm next ->
171 (<> unViewMachine k lm next) $
172 List.sortBy (compare `on` (((fst <$>) <$>) . Tree.levels)) $
173 ((\(n, SomeLet sub) ->
174 viewInstrCmd @sN (Left n) lm
175 ("let", " "<>show (hideableName @sN n))
176 (unViewMachine sub lm []))
179 } where gen = defLet ((\(SomeLet x) -> SomeLet (viewGen x)) <$> defs) (viewGen k)
180 jump isRec ln@(LetName n) = ViewMachine
181 { unViewMachine = \lm next ->
182 viewInstrCmd @sN (Right gen) lm ("jump", " "<>show (hideableName @sN n)) [] : next
184 } where gen = jump isRec ln
185 call isRec ln@(LetName n) k = ViewMachine
186 { unViewMachine = \lm next ->
187 viewInstrCmd @sN (Right gen) lm ("call", " "<>show (hideableName @sN n)) [] :
188 unViewMachine k lm next
190 } where gen = call isRec ln (viewGen k)
192 { unViewMachine = \lm next ->
193 viewInstrCmd @sN (Right gen) lm ("ret", "") [] : next
198 InstrJoinable (ViewMachine sN) where
199 defJoin ln@(LetName n) j k = ViewMachine
200 { unViewMachine = \lm next ->
201 viewInstrCmd @sN (Left n) lm
202 ("join", " "<>show (hideableName @sN n))
203 (unViewMachine j lm []) :
204 unViewMachine k lm next
206 } where gen = defJoin ln (viewGen j) (viewGen k)
207 refJoin ln@(LetName n) = ViewMachine
208 { unViewMachine = \lm next ->
209 viewInstrCmd @sN (Right gen) lm ("refJoin", " "<>show (hideableName @sN n)) [] : next
211 } where gen = refJoin ln
214 InstrInputable (ViewMachine sN) where
215 pushInput k = ViewMachine
216 { unViewMachine = \lm next ->
217 viewInstrCmd @sN (Right gen) lm ("pushInput", "") [] :
218 unViewMachine k lm next
220 } where gen = pushInput (viewGen k)
221 loadInput k = ViewMachine
222 { unViewMachine = \lm next ->
223 viewInstrCmd @sN (Right gen) lm ("loadInput", "") [] :
224 unViewMachine k lm next
226 } where gen = loadInput (viewGen k)
229 , InstrReadable tok Gen
230 ) => InstrReadable tok (ViewMachine sN) where
231 read es p k = ViewMachine
232 { unViewMachine = \lm next ->
233 viewInstrCmd @sN (Right gen) lm ("read "<>showSplice p, "") [] :
234 unViewMachine k lm next
236 } where gen = read es p (viewGen k)
239 InstrIterable (ViewMachine sN) where
240 iter jumpName@(LetName n) ok ko = ViewMachine
241 { unViewMachine = \lm next ->
242 viewInstrCmd @sN (Right gen) lm ("iter", " "<>show (hideableName @sN n))
243 [ viewInstrArg "ok" (unViewMachine ok lm [])
244 , viewInstrArg "ko" (unViewMachine ko lm [])
247 } where gen = iter jumpName (viewGen ok) (viewGen ko)
250 InstrRegisterable (ViewMachine sN) where
251 newRegister reg@(UnscopedRegister r) k = ViewMachine
252 { unViewMachine = \lm next ->
253 viewInstrCmd @sN (Right gen) lm ("newRegister", " "<>show (hideableName @sN r)) [] :
254 unViewMachine k lm next
256 } where gen = newRegister reg (viewGen k)
257 readRegister reg@(UnscopedRegister r) k = ViewMachine
258 { unViewMachine = \lm next ->
259 viewInstrCmd @sN (Right gen) lm ("readRegister", " "<>show (hideableName @sN r)) [] :
260 unViewMachine k lm next
262 } where gen = readRegister reg (viewGen k)
263 writeRegister reg@(UnscopedRegister r) k = ViewMachine
264 { unViewMachine = \lm next ->
265 viewInstrCmd @sN (Right gen) lm ("writeRegister", " "<>show (hideableName @sN r)) [] :
266 unViewMachine k lm next
268 } where gen = writeRegister reg (viewGen k)