Skip to content

Commit aaeac47

Browse files
committed
Implement lists for TI Mark 5
1 parent dd82932 commit aaeac47

File tree

6 files changed

+91
-17
lines changed

6 files changed

+91
-17
lines changed

examples/list.core

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- List example
2+
-- Requires TI Mark 5.
3+
main = length (Cons (Cons 2 3) (Cons 2 (Cons 3 Nil)))

examples/pair.core

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
-- Pair test
22
-- Requires TI Mark 5.
3-
main = fst (snd (fst (MkPair (MkPair 1 (MkPair 2 3)) 4)))
3+
main = fst (snd (fst (Pair (Pair 1 (Pair 2 3)) 4)))

src/CorePrelude.hs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module CorePrelude
33
, extraPreludeDefs
44
) where
55

6+
import Evaluators.TemplateInstantiation.Node
67
import Language
78

89
-- Standard Prelude for Core
@@ -28,21 +29,15 @@ preludeDefs =
2829
, ("twice", ["f"], EAp (EAp (EVar "compose") (EVar "f")) (EVar "f"))
2930
]
3031

31-
-- Standard definitions for true/false
32-
-- Mirrors definitions for nodes in Evaluators.TemplateInstantiation.Node
33-
trueExpr, falseExpr :: CoreExpr
34-
trueExpr = EConstr 1 0
35-
falseExpr = EConstr 2 0
36-
3732
-- Introduced in section 2.3.4.
3833
-- Execise 2.20: Add definitions for conditionals.
3934
-- Exercise 2.22: Add definitions for pair.
4035
extraPreludeDefs :: CoreProgram
4136
extraPreludeDefs =
4237
[
4338
-- Standard definitions for true/false
44-
("True" , [], trueExpr)
45-
, ("False", [], falseExpr)
39+
("True" , [], EConstr tagTrue 0)
40+
, ("False", [], EConstr tagFalse 0)
4641
-- Conditionals
4742
, ( "and"
4843
, ["x", "y"]
@@ -62,7 +57,26 @@ extraPreludeDefs =
6257
, EAp (EAp (EAp (EVar "if") (EVar "x")) (EVar "False")) (EVar "True")
6358
)
6459
-- Pairs
65-
, ("mkPair", [] , EConstr 1 2)
60+
, ("Pair", [] , EConstr tagPair 2)
6661
, ("fst", ["p"], EAp (EAp (EVar "casePair") (EVar "p")) (EVar "K"))
6762
, ("snd", ["p"], EAp (EAp (EVar "casePair") (EVar "p")) (EVar "K1"))
63+
-- Lists
64+
, ("Nil" , [] , EConstr tagNil 0)
65+
, ("Cons", [] , EConstr tagCons 2)
66+
, ( "head"
67+
, ["l"]
68+
, EAp (EAp (EAp (EVar "caseList") (EVar "l")) (EVar "abort")) (EVar "K")
69+
)
70+
, ( "tail"
71+
, ["l"]
72+
, EAp (EAp (EAp (EVar "caseList") (EVar "l")) (EVar "abort")) (EVar "K1")
73+
)
74+
, ( "length"
75+
, ["xs"]
76+
, EAp (EAp (EAp (EVar "caseList") (EVar "xs")) (ENum 0)) (EVar "length2")
77+
)
78+
, ( "length2"
79+
, ["x", "xs"]
80+
, EAp (EAp (EVar "+") (ENum 1)) (EAp (EVar "length") (EVar "xs"))
81+
)
6882
]

src/Evaluators/TemplateInstantiation/Evaluator.hs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ primitives =
104104
, ("==" , Eq)
105105
, ("~=" , NotEq)
106106
, ("casePair", CasePair)
107+
, ("caseList", CaseList)
108+
, ("abort" , Abort)
107109
]
108110

109111
allocatePrim :: TiHeap -> (Name, Primitive) -> (TiHeap, (Name, Addr))
@@ -227,6 +229,8 @@ primStep state NotEq = primComp state (/=)
227229
primStep state (Constr tag arity) = primConstr state tag arity
228230
primStep state If = primIf state
229231
primStep state CasePair = primCasePair state
232+
primStep state CaseList = primCaseList state
233+
primStep state Abort = primAbort state
230234

231235
-- Exercise 2.16: evaluation of `negate` (the only unary primitive)
232236
primNeg :: TiState -> TiState
@@ -355,11 +359,47 @@ primCasePair (s, d, h, e, stats) = state' where
355359
d' = tail s : d
356360
-- Get arguments
357361
(pair1Addr, pair2Addr) = getPairAddrs pair
358-
getPairAddrs (NData 1 [pair1Addr', pair2Addr']) = (pair1Addr', pair2Addr')
362+
getPairAddrs (NData tagPair' [pair1Addr', pair2Addr'])
363+
| tagPair == tagPair' = (pair1Addr', pair2Addr')
364+
| otherwise = error "primCasePair: argument is not a pair (incorrect tag)"
359365
getPairAddrs _ = error "primCasePair: argument is not a pair"
360366
pairAddr : handlerAddr : _ = getArgs h s
361367
pair = hLookup h pairAddr
362368

369+
-- Exercise 2.24: implement `caseList` primitive. This is like a combination
370+
-- of `caseIf` and `casePair`.
371+
primCaseList :: TiState -> TiState
372+
primCaseList (s, d, h, e, stats) = state' where
373+
state' | s' == [] = error "primCaseList: not enough arguments to caseList"
374+
| isDataNode lst = (s', d, h', e, stats)
375+
| otherwise = (s'', d', h, e, stats)
376+
-- Stack, heap, and n if conditional is already evaluated
377+
s' = drop 3 s
378+
rootAddr : _ = s'
379+
h' = updateHeap lst
380+
where
381+
updateHeap (NData tag _)
382+
| tag == tagNil = updateHeapNil
383+
| tag == tagCons = updateHeapCons lst
384+
| otherwise = error "primCaseList: argument is not a list"
385+
updateHeap _ = error "primCaseList: argument is not a list"
386+
updateHeapNil = hUpdate h rootAddr $ NInd f1Addr
387+
updateHeapCons (NData _ [cons1Addr, cons2Addr]) = h'''
388+
where
389+
(h'', ap) = hAlloc h $ NAp f2Addr cons1Addr
390+
h''' = hUpdate h'' rootAddr $ NAp ap cons2Addr
391+
updateHeapCons _ = error "primCaseList: Cons: wrong number of arguments"
392+
-- Stack and dump if argument is not evaluated
393+
s'' = [lstAddr]
394+
d' = tail s : d
395+
-- Get arguments
396+
lstAddr : f1Addr : f2Addr : _ = getArgs h s
397+
lst = hLookup h lstAddr
398+
399+
-- Exercise 2.24: Implement primitive `abort`.
400+
primAbort :: TiState -> TiState
401+
primAbort = error "primAbort: abort: fatal error"
402+
363403
-- Looks up all the arguments (names) for NAp nodes on the spine
364404
getArgs :: TiHeap -> TiStack -> [Addr]
365405
getArgs _ [] = error "getArgs: empty stack"

src/Evaluators/TemplateInstantiation/Node.hs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ module Evaluators.TemplateInstantiation.Node
44
, trueNode
55
, falseNode
66
, boolToNode
7+
, tagTrue
8+
, tagFalse
9+
, tagPair
10+
, tagNil
11+
, tagCons
712
) where
813

914
import Alloc
@@ -19,14 +24,22 @@ data Node = NAp Addr Addr -- Application
1924
deriving (Eq, Show)
2025

2126
data Primitive = Neg | Add | Sub | Mul | Div
22-
| Constr Int Int | If | CasePair
27+
| Constr Int Int | If | CasePair | CaseList
2328
| Greater | GreaterEq | Less | LessEq | Eq | NotEq
29+
| Abort
2430
deriving (Eq, Show)
2531

26-
-- Standard representations of booleans in Core
32+
-- Standard representations of special structured datatypes in Core
33+
tagTrue, tagFalse, tagPair, tagNil, tagCons :: Int
34+
tagTrue = 0
35+
tagFalse = 1
36+
tagPair = 2
37+
tagNil = 3
38+
tagCons = 4
39+
2740
trueNode, falseNode :: Node
28-
trueNode = NData 1 []
29-
falseNode = NData 2 []
41+
trueNode = NData tagTrue []
42+
falseNode = NData tagFalse []
3043

3144
boolToNode :: Bool -> Node
3245
boolToNode True = trueNode

test/Evaluators/TemplateInstantiation/EvaluatorTests.hs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ progChurch, progCons, progInfinite1, progInfinite2, progInfinite3 :: String
1212
progAnd1, progAnd2, progAnd3, progAnd4 :: String
1313
progOr1, progOr2, progOr3, progOr4 :: String
1414
progXor1, progXor2, progXor3, progXor4 :: String
15-
progFac, progFib, progPair :: String
15+
progFac, progFib, progPair, progList :: String
1616

1717
-- Exercise 2.4
1818
progSKK3 = "main = S K K 3"
@@ -109,7 +109,10 @@ progFib = "fib n = if (n < 2) n (fib (n - 1) + fib (n - 2)) ;\
109109
\main = fib 6"
110110

111111
-- Exercise 2.22: Pair
112-
progPair = "main = fst (snd (fst (MkPair (MkPair 1 (MkPair 2 3)) 4)))"
112+
progPair = "main = fst (snd (fst (Pair (Pair 1 (Pair 2 3)) 4)))"
113+
114+
-- Lists
115+
progList = "main = length (Cons (Cons 2 3) (Cons 2 (Cons 3 Nil)))"
113116

114117
tests :: Test
115118
tests = test
@@ -145,4 +148,5 @@ tests = test
145148
, "factorial" ~: runGetNumResult progFac ~=? 6
146149
, "naive fib" ~: runGetNumResult progFib ~=? 8
147150
, "pairs" ~: runGetNumResult progPair ~=? 2
151+
, "list" ~: runGetNumResult progList ~=? 3
148152
]

0 commit comments

Comments
 (0)