1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE UndecidableInstances #-} -- For ShowLetName
3 module Symantic.Parser.Machine.View where
5 import Data.Bool (Bool(..))
6 import Data.Either (Either(..))
7 import Data.Function (($), (.), id, on)
8 import Data.Functor ((<$>))
9 import Data.Kind (Type)
10 import Data.Ord (Ord(..))
11 import Data.Semigroup (Semigroup(..))
12 import Data.String (String)
13 import Data.Tuple (fst)
14 import Text.Show (Show(..))
15 import qualified Data.HashMap.Strict as HM
16 import qualified Data.List as List
17 import qualified Data.Map.Strict as Map
18 import qualified Data.Set as Set
19 import qualified Data.Tree as Tree
20 import qualified Language.Haskell.TH.Syntax as TH
21 import Prelude (error)
23 import Symantic.Parser.Grammar.Combinators (UnscopedRegister(..))
24 import Symantic.Parser.Grammar.ObserveSharing
25 import Symantic.Parser.Machine.Instructions
26 import Symantic.Parser.Machine.Generate
28 -- * Type 'ViewMachine'
29 data ViewMachine (showName::Bool) inp (vs:: [Type]) a
31 { viewGen :: Gen inp vs a
32 -- ^ Provide 'GenAnalysis', which is important for debugging
33 -- and improving golden tests, see 'viewInstrCmd'.
35 LetRecs TH.Name GenAnalysis -> -- Output of 'runOpenRecs'.
36 Tree.Forest (String, String) ->
37 Tree.Forest (String, String)
41 ViewMachine sN inp vs a ->
42 ViewMachine sN inp vs a
45 -- | Helper to view a command.
47 Either TH.Name (Gen inp vs a) ->
48 LetRecs TH.Name GenAnalysis ->
49 (String, String) -> Tree.Forest (String, String) -> Tree.Tree (String, String)
50 viewInstrCmd gen lm (n, no) = Tree.Node $ (n
51 <> "\nminReads="<>showsPrec 11 (minReads ga) ""
52 <> "\nmayRaise="<>showsPrec 11 (Map.keys (mayRaise ga)) ""
56 Right r -> genAnalysis r lm
57 Left l -> HM.findWithDefault (error (show (l, HM.keys lm))) l lm
59 -- | Helper to view an argument.
60 viewInstrArg :: String -> Tree.Forest (String, String) -> Tree.Tree (String, String)
61 viewInstrArg n = Tree.Node $ ("<"<>n<>">", "")
63 instance Show (ViewMachine sN inp vs a) where
64 show vm = List.unlines $ drawTrees $
65 unViewMachine vm (mutualFix (genAnalysisByLet (viewGen vm))) []
67 draw :: Tree.Tree (String, String) -> [String]
68 draw (Tree.Node (x, n) ts0) =
69 shift "" " " (List.zipWith (<>) (List.lines x) (n : List.repeat "")) <>
70 shift "| " "| " (drawTrees ts0)
72 drawTrees [t] = draw t
73 drawTrees (t:ts) = draw t <> drawTrees ts
74 shift ind0 ind = List.zipWith (<>) (ind0 : List.repeat ind)
76 instance InstrValuable (ViewMachine sN) where
77 pushValue a k = ViewMachine
78 { unViewMachine = \lm next ->
79 viewInstrCmd (Right gen) lm ("pushValue "<>showsPrec 10 a "", "") [] :
80 unViewMachine k lm next
82 } where gen = pushValue a (viewGen k)
83 popValue k = ViewMachine
84 { unViewMachine = \lm next ->
85 viewInstrCmd (Right gen) lm ("popValue", "") [] :
86 unViewMachine k lm next
88 } where gen = popValue (viewGen k)
89 lift2Value f k = ViewMachine
90 { unViewMachine = \lm next ->
91 viewInstrCmd (Right gen) lm ("lift2Value "<>showsPrec 10 f "", "") [] :
92 unViewMachine k lm next
94 } where gen = lift2Value f (viewGen k)
95 swapValue k = ViewMachine
96 { unViewMachine = \lm next ->
97 viewInstrCmd (Right gen) lm ("swapValue", "") [] :
98 unViewMachine k lm next
100 } where gen = swapValue (viewGen k)
101 instance InstrExceptionable (ViewMachine sN) where
102 raise exn = ViewMachine
103 { unViewMachine = \lm next ->
104 viewInstrCmd (Right gen) lm ("raise "<>show exn, "") [] : next
106 } where gen = raise exn
107 fail flr = ViewMachine
108 { unViewMachine = \lm next ->
109 viewInstrCmd (Right gen) lm ("fail "<>show (Set.toList flr), "") [] : next
111 } where gen = fail flr
112 commit exn k = ViewMachine
113 { unViewMachine = \lm next ->
114 viewInstrCmd (Right gen) lm ("commit "<>show exn, "") [] :
115 unViewMachine k lm next
117 } where gen = commit exn (viewGen k)
118 catch exn ok ko = ViewMachine
119 { unViewMachine = \lm next ->
120 viewInstrCmd (Right gen) lm ("catch "<>show exn, "")
121 [ viewInstrArg "ok" (unViewMachine ok lm [])
122 , viewInstrArg "ko" (unViewMachine ko lm [])
125 } where gen = catch exn (viewGen ok) (viewGen ko)
126 instance InstrBranchable (ViewMachine sN) where
127 caseBranch l r = ViewMachine
128 { unViewMachine = \lm next ->
129 viewInstrCmd (Right gen) lm ("case", "")
130 [ viewInstrArg "left" (unViewMachine l lm [])
131 , viewInstrArg "right" (unViewMachine r lm [])
134 } where gen = caseBranch (viewGen l) (viewGen r)
135 choicesBranch bs d = ViewMachine
136 { unViewMachine = \lm next ->
137 viewInstrCmd (Right gen) lm ("choicesBranch", "") (
138 ((\(p, b) -> viewInstrArg ("branch "<>showsPrec 10 p "") $
139 unViewMachine b lm []) <$> bs) <>
140 [ viewInstrArg "default" (unViewMachine d lm []) ]
143 } where gen = choicesBranch ((viewGen <$>) <$> bs) (viewGen d)
145 ShowLetName sN TH.Name =>
146 InstrCallable (ViewMachine sN) where
147 defLet defs k = ViewMachine
148 { unViewMachine = \lm next ->
149 (<> unViewMachine k lm next) $
150 List.sortBy (compare `on` (((fst <$>) <$>) . Tree.levels)) $
151 ((\(n, SomeLet sub) ->
152 viewInstrCmd (Left n) lm
153 ("let", " "<>showLetName @sN n)
154 (unViewMachine sub lm []))
157 } where gen = defLet ((\(SomeLet x) -> SomeLet (viewGen x)) <$> defs) (viewGen k)
158 jump isRec ln@(LetName n) = ViewMachine
159 { unViewMachine = \lm next ->
160 viewInstrCmd (Right gen) lm ("jump", " "<>showLetName @sN n) [] : next
162 } where gen = jump isRec ln
163 call isRec ln@(LetName n) k = ViewMachine
164 { unViewMachine = \lm next ->
165 viewInstrCmd (Right gen) lm ("call", " "<>showLetName @sN n) [] :
166 unViewMachine k lm next
168 } where gen = call isRec ln (viewGen k)
170 { unViewMachine = \lm next ->
171 viewInstrCmd (Right gen) lm ("ret", "") [] : next
175 ShowLetName sN TH.Name =>
176 InstrJoinable (ViewMachine sN) where
177 defJoin ln@(LetName n) j k = ViewMachine
178 { unViewMachine = \lm next ->
179 viewInstrCmd (Left n) lm
180 ("join", " "<>showLetName @sN n)
181 (unViewMachine j lm []) :
182 unViewMachine k lm next
184 } where gen = defJoin ln (viewGen j) (viewGen k)
185 refJoin ln@(LetName n) = ViewMachine
186 { unViewMachine = \lm next ->
187 viewInstrCmd (Right gen) lm ("refJoin", " "<>showLetName @sN n) [] : next
189 } where gen = refJoin ln
190 instance InstrInputable (ViewMachine sN) where
191 pushInput k = ViewMachine
192 { unViewMachine = \lm next ->
193 viewInstrCmd (Right gen) lm ("pushInput", "") [] :
194 unViewMachine k lm next
196 } where gen = pushInput (viewGen k)
197 loadInput k = ViewMachine
198 { unViewMachine = \lm next ->
199 viewInstrCmd (Right gen) lm ("loadInput", "") [] :
200 unViewMachine k lm next
202 } where gen = loadInput (viewGen k)
204 InstrReadable tok Gen =>
205 InstrReadable tok (ViewMachine sN) where
206 read es p k = ViewMachine
207 { unViewMachine = \lm next ->
208 viewInstrCmd (Right gen) lm ("read "<>showsPrec 10 p "", "") [] :
209 unViewMachine k lm next
211 } where gen = read es p (viewGen k)
213 ShowLetName sN TH.Name =>
214 InstrIterable (ViewMachine sN) where
215 iter jumpName@(LetName n) ok ko = ViewMachine
216 { unViewMachine = \lm next ->
217 viewInstrCmd (Right gen) lm ("iter", " "<>showLetName @sN n)
218 [ viewInstrArg "ok" (unViewMachine ok lm [])
219 , viewInstrArg "ko" (unViewMachine ko lm [])
222 } where gen = iter jumpName (viewGen ok) (viewGen ko)
224 ShowLetName sN TH.Name =>
225 InstrRegisterable (ViewMachine sN) where
226 newRegister reg@(UnscopedRegister r) k = ViewMachine
227 { unViewMachine = \lm next ->
228 viewInstrCmd (Right gen) lm ("newRegister", " "<>showLetName @sN r) [] :
229 unViewMachine k lm next
231 } where gen = newRegister reg (viewGen k)
232 readRegister reg@(UnscopedRegister r) k = ViewMachine
233 { unViewMachine = \lm next ->
234 viewInstrCmd (Right gen) lm ("readRegister", " "<>showLetName @sN r) [] :
235 unViewMachine k lm next
237 } where gen = readRegister reg (viewGen k)
238 writeRegister reg@(UnscopedRegister r) k = ViewMachine
239 { unViewMachine = \lm next ->
240 viewInstrCmd (Right gen) lm ("writeRegister", " "<>showLetName @sN r) [] :
241 unViewMachine k lm next
243 } where gen = writeRegister reg (viewGen k)