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 lm (n, no) = Tree.Node $ (n
57 <> "\nminReads="<>showsPrec 11 (minReads ga) ""
58 <> "\nmayRaise="<>show (Map.keys (mayRaise ga))
59 <> "\nfreeRegs="<>show (hideableName @sN (Set.toList (freeRegs ga)))
63 Right r -> genAnalysis r lm
64 Left l -> HM.findWithDefault (error (show (l, HM.keys lm))) l lm
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 InstrValuable (ViewMachine sN) where
86 pushValue a k = ViewMachine
87 { unViewMachine = \lm next ->
88 viewInstrCmd @sN (Right gen) lm ("pushValue "<>showSplice a, "") [] :
89 unViewMachine k lm next
91 } where gen = pushValue a (viewGen k)
92 popValue k = ViewMachine
93 { unViewMachine = \lm next ->
94 viewInstrCmd @sN (Right gen) lm ("popValue", "") [] :
95 unViewMachine k lm next
97 } where gen = popValue (viewGen k)
98 lift2Value f k = ViewMachine
99 { unViewMachine = \lm next ->
100 viewInstrCmd @sN (Right gen) lm ("lift2Value "<>showSplice f, "") [] :
101 unViewMachine k lm next
103 } where gen = lift2Value f (viewGen k)
104 swapValue k = ViewMachine
105 { unViewMachine = \lm next ->
106 viewInstrCmd @sN (Right gen) lm ("swapValue", "") [] :
107 unViewMachine k lm next
109 } where gen = swapValue (viewGen k)
112 InstrExceptionable (ViewMachine sN) where
113 raise exn = ViewMachine
114 { unViewMachine = \lm next ->
115 viewInstrCmd @sN (Right gen) lm ("raise "<>show exn, "") [] : next
117 } where gen = raise exn
118 fail flr = ViewMachine
119 { unViewMachine = \lm next ->
120 viewInstrCmd @sN (Right gen) lm ("fail "<>show (Set.toList flr), "") [] : next
122 } where gen = fail flr
123 commit exn k = ViewMachine
124 { unViewMachine = \lm next ->
125 viewInstrCmd @sN (Right gen) lm ("commit "<>show exn, "") [] :
126 unViewMachine k lm next
128 } where gen = commit exn (viewGen k)
129 catch exn ok ko = ViewMachine
130 { unViewMachine = \lm next ->
131 viewInstrCmd @sN (Right gen) lm ("catch "<>show exn, "")
132 [ viewInstrArg "ok" (unViewMachine ok lm [])
133 , viewInstrArg "ko" (unViewMachine ko lm [])
136 } where gen = catch exn (viewGen ok) (viewGen ko)
139 InstrBranchable (ViewMachine sN) where
140 caseBranch l r = ViewMachine
141 { unViewMachine = \lm next ->
142 viewInstrCmd @sN (Right gen) lm ("case", "")
143 [ viewInstrArg "left" (unViewMachine l lm [])
144 , viewInstrArg "right" (unViewMachine r lm [])
147 } where gen = caseBranch (viewGen l) (viewGen r)
148 choicesBranch bs d = ViewMachine
149 { unViewMachine = \lm next ->
150 viewInstrCmd @sN (Right gen) lm ("choicesBranch", "") (
151 ((\(p, b) -> viewInstrArg ("branch "<>showSplice p) $
152 unViewMachine b lm []) <$> bs) <>
153 [ viewInstrArg "default" (unViewMachine d lm []) ]
156 } where gen = choicesBranch ((viewGen <$>) <$> bs) (viewGen d)
159 InstrCallable (ViewMachine sN) where
160 defLet defs k = ViewMachine
161 { unViewMachine = \lm next ->
162 (<> unViewMachine k lm next) $
163 List.sortBy (compare `on` (((fst <$>) <$>) . Tree.levels)) $
164 ((\(n, SomeLet sub) ->
165 viewInstrCmd @sN (Left n) lm
166 ("let", " "<>show (hideableName @sN n))
167 (unViewMachine sub lm []))
170 } where gen = defLet ((\(SomeLet x) -> SomeLet (viewGen x)) <$> defs) (viewGen k)
171 jump isRec ln@(LetName n) = ViewMachine
172 { unViewMachine = \lm next ->
173 viewInstrCmd @sN (Right gen) lm ("jump", " "<>show (hideableName @sN n)) [] : next
175 } where gen = jump isRec ln
176 call isRec ln@(LetName n) k = ViewMachine
177 { unViewMachine = \lm next ->
178 viewInstrCmd @sN (Right gen) lm ("call", " "<>show (hideableName @sN n)) [] :
179 unViewMachine k lm next
181 } where gen = call isRec ln (viewGen k)
183 { unViewMachine = \lm next ->
184 viewInstrCmd @sN (Right gen) lm ("ret", "") [] : next
189 InstrJoinable (ViewMachine sN) where
190 defJoin ln@(LetName n) j k = ViewMachine
191 { unViewMachine = \lm next ->
192 viewInstrCmd @sN (Left n) lm
193 ("join", " "<>show (hideableName @sN n))
194 (unViewMachine j lm []) :
195 unViewMachine k lm next
197 } where gen = defJoin ln (viewGen j) (viewGen k)
198 refJoin ln@(LetName n) = ViewMachine
199 { unViewMachine = \lm next ->
200 viewInstrCmd @sN (Right gen) lm ("refJoin", " "<>show (hideableName @sN n)) [] : next
202 } where gen = refJoin ln
205 InstrInputable (ViewMachine sN) where
206 pushInput k = ViewMachine
207 { unViewMachine = \lm next ->
208 viewInstrCmd @sN (Right gen) lm ("pushInput", "") [] :
209 unViewMachine k lm next
211 } where gen = pushInput (viewGen k)
212 loadInput k = ViewMachine
213 { unViewMachine = \lm next ->
214 viewInstrCmd @sN (Right gen) lm ("loadInput", "") [] :
215 unViewMachine k lm next
217 } where gen = loadInput (viewGen k)
220 , InstrReadable tok Gen
221 ) => InstrReadable tok (ViewMachine sN) where
222 read es p k = ViewMachine
223 { unViewMachine = \lm next ->
224 viewInstrCmd @sN (Right gen) lm ("read "<>showSplice p, "") [] :
225 unViewMachine k lm next
227 } where gen = read es p (viewGen k)
230 InstrIterable (ViewMachine sN) where
231 iter jumpName@(LetName n) ok ko = ViewMachine
232 { unViewMachine = \lm next ->
233 viewInstrCmd @sN (Right gen) lm ("iter", " "<>show (hideableName @sN n))
234 [ viewInstrArg "ok" (unViewMachine ok lm [])
235 , viewInstrArg "ko" (unViewMachine ko lm [])
238 } where gen = iter jumpName (viewGen ok) (viewGen ko)
241 InstrRegisterable (ViewMachine sN) where
242 newRegister reg@(UnscopedRegister r) k = ViewMachine
243 { unViewMachine = \lm next ->
244 viewInstrCmd @sN (Right gen) lm ("newRegister", " "<>show (hideableName @sN r)) [] :
245 unViewMachine k lm next
247 } where gen = newRegister reg (viewGen k)
248 readRegister reg@(UnscopedRegister r) k = ViewMachine
249 { unViewMachine = \lm next ->
250 viewInstrCmd @sN (Right gen) lm ("readRegister", " "<>show (hideableName @sN r)) [] :
251 unViewMachine k lm next
253 } where gen = readRegister reg (viewGen k)
254 writeRegister reg@(UnscopedRegister r) k = ViewMachine
255 { unViewMachine = \lm next ->
256 viewInstrCmd @sN (Right gen) lm ("writeRegister", " "<>show (hideableName @sN r)) [] :
257 unViewMachine k lm next
259 } where gen = writeRegister reg (viewGen k)