Skip to content

Commit e1480a8

Browse files
committed
Add structured printing for G-Machine
1 parent 5d78274 commit e1480a8

File tree

5 files changed

+82
-15
lines changed

5 files changed

+82
-15
lines changed

src/CorePrelude.hs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,10 @@ extraPreludeDefs =
9191

9292
-- Extra prelude defs (for GM)
9393
extraPreludeDefsGM :: CoreProgram
94-
extraPreludeDefsGM = parse "if c t f = case c of <1> -> f ; <2> -> t"
94+
extraPreludeDefsGM = parse $ concat
95+
[ "if c t f = case c of <1> -> f ; <2> -> t ;"
96+
, "False = Pack{1,0} ;"
97+
, "True = Pack{2,0} ;"
98+
, "Nil = Pack{3,0} ;"
99+
, "Cons = Pack{4,2}"
100+
]

src/Evaluators/GMachine/Compiler.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type GmCompiledSC = (Name, Int, GmCode)
1919
type GmCompiler = CoreExpr -> GmEnv Int -> GmCode
2020

2121
compile :: CoreProgram -> GmState
22-
compile prog = GmState "" initialCode [] [] h e statInitial
22+
compile prog = GmState [] initialCode [] [] h e statInitial
2323
where (h, e) = buildInitialHeap prog
2424

2525
buildInitialHeap :: CoreProgram -> (GmHeap, GmEnv Addr)

src/Evaluators/GMachine/Evaluator.hs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,11 @@ printI state = state { gmCode = is', gmOutput = o', gmStack = s' }
297297
node = hLookup (gmHeap state) a
298298
-- Updated stack and instructions depends on the data node
299299
(is', o', s') = printI' node
300-
printI' (NNum n) = (gmCode state, gmOutput state ++ " " ++ show n, as)
301-
printI' (NConstr _ args) =
302-
(printIs (length args) ++ gmCode state, gmOutput state, args ++ as)
300+
printI' (NNum n) = (gmCode state, gmOutput state ++ [PPNNum n], as)
301+
printI' (NConstr tag args) =
302+
( printIs (length args) ++ gmCode state
303+
, gmOutput state ++ [PPNStruct tag (length args)]
304+
, args ++ as
305+
)
303306
where printIs n = concat $ take n $ repeat [Eval, Print]
304307
printI' _ = error "print: non-data node"

src/Evaluators/GMachine/PrintUtils.hs

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ instance Show Instruction where
5353
show (Split n) = "split " ++ show n
5454
show Print = "print"
5555

56-
-- TODO: show output in "structured form" (Exercise 3.36); also requires
56+
-- Show output in "structured form" (Exercise 3.36); also requires
5757
-- changes in the print opcode
5858
showOutput :: [GmState] -> String
59-
showOutput trace = gmOutput state where state = last trace
59+
showOutput trace = printTree $ gmOutput state where state = last trace
6060

6161
showTrace :: [GmState] -> String
6262
showTrace states = iDisplay $ iConcat
@@ -96,7 +96,7 @@ showInstructions is = iConcat
9696

9797
showState :: GmState -> Iseq
9898
showState state = iConcat
99-
[ showOutput' state
99+
[ showOutput'
100100
, iNewline
101101
, showStack state
102102
, iNewline
@@ -105,12 +105,9 @@ showState state = iConcat
105105
, showInstructions $ gmCode state
106106
, iNewline
107107
]
108-
109-
-- Show the GmOutput (different from `showOutput`, which is part of the
110-
-- interface for the compiler); introduced in Mark 6
111-
showOutput' :: GmState -> Iseq
112-
showOutput' state =
113-
iConcat [iStr "Output:\"", iStr $ gmOutput state, iStr "\""]
108+
where
109+
showOutput' =
110+
iConcat [iStr "Output: \"\n", iStr $ showOutput [state], iStr "\""]
114111

115112
showStack :: GmState -> Iseq
116113
showStack state = iConcat
@@ -170,3 +167,58 @@ shortShowStack s =
170167
showStats :: GmState -> Iseq
171168
showStats state =
172169
iConcat [iStr "Steps taken = ", iNum $ statGetSteps $ gmStats state]
170+
171+
-- Inorder to tree
172+
printToTree :: [PrintPreorderNode] -> Maybe PrintTreeNode
173+
printToTree [] = Nothing
174+
printToTree inord = getResult $ printToTree' [(1, PTNStruct (-1) [])] inord
175+
where
176+
getResult (Just [(0, PTNStruct (-1) [n])]) = Just $ reverseTree n
177+
getResult Nothing = Nothing
178+
getResult _ = error "printToTree: invalid tree"
179+
reverseTree n@(PTNNum _) = n
180+
reverseTree (PTNStruct tag children) =
181+
PTNStruct tag $ reverse $ reverseTree <$> children
182+
183+
-- Helper function for inorder -> tree
184+
printToTree'
185+
:: [(Int, PrintTreeNode)]
186+
-> [PrintPreorderNode]
187+
-> Maybe [(Int, PrintTreeNode)]
188+
-- Done
189+
printToTree' final@[(0, _)] [] = Just final
190+
-- 0 elements left, pop the stack
191+
printToTree' ((0, n) : (arity, PTNStruct tag children) : ppns) inord =
192+
printToTree' ((arity, PTNStruct tag (n : children)) : ppns) inord
193+
printToTree' ((arity, PTNStruct tag children) : ppns) (n : ns) = printToTree''
194+
n
195+
where
196+
printToTree'' (PPNNum n') =
197+
printToTree' ((arity - 1, PTNStruct tag (PTNNum n' : children)) : ppns) ns
198+
printToTree'' (PPNStruct tag' arity') = printToTree'
199+
((arity', PTNStruct tag' []) : (arity - 1, PTNStruct tag children) : ppns)
200+
ns
201+
printToTree' _ _ = Nothing
202+
203+
-- Print tree
204+
printTree :: [PrintPreorderNode] -> String
205+
printTree = toString . printToTree
206+
where
207+
toString Nothing = ""
208+
toString (Just tree) = iDisplay $ printTree' tree
209+
210+
printTree' :: PrintTreeNode -> Iseq
211+
printTree' (PTNNum n ) = iNum n
212+
printTree' (PTNStruct tag children) = printNode tag $ length children
213+
where
214+
printNode 1 0 = iStr "False"
215+
printNode 2 0 = iStr "True"
216+
printNode 3 0 = iStr "Nil"
217+
printNode 4 2 = regularStruct $ iStr "Cons"
218+
printNode n _ = regularStruct $ iNum n
219+
regularStruct tag' = iConcat
220+
[ tag'
221+
, iStr "{"
222+
, iIndent $ iInterleave (iStr ",\n") $ printTree' <$> children
223+
, iStr "}"
224+
]

src/Evaluators/GMachine/State.hs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ module Evaluators.GMachine.State
88
, GmEnv
99
, GmState(..)
1010
, Node(..)
11+
, PrintPreorderNode(..)
12+
, PrintTreeNode(..)
1113
, statInitial
1214
, statIncSteps
1315
, statGetSteps
@@ -41,7 +43,11 @@ data Instruction
4143
| Print
4244
deriving Eq
4345

44-
type GmOutput = String
46+
data PrintPreorderNode = PPNStruct Int Int | PPNNum Int
47+
deriving Show
48+
data PrintTreeNode = PTNStruct Int [PrintTreeNode] | PTNNum Int
49+
deriving Show
50+
type GmOutput = [PrintPreorderNode]
4551

4652
type GmStack = [Addr]
4753
type GmHeap = Heap Node

0 commit comments

Comments
 (0)