@@ -91,18 +91,19 @@ allocateSc h (name, args, body) = (h', (name, a))
9191-- Add primitives to the heap
9292primitives :: AssocList Name Primitive
9393primitives =
94- [ (" negate" , Neg )
95- , (" +" , Add )
96- , (" -" , Sub )
97- , (" *" , Mul )
98- , (" /" , Div )
99- , (" if" , If )
100- , (" >" , Greater )
101- , (" >=" , GreaterEq )
102- , (" <" , Less )
103- , (" <=" , LessEq )
104- , (" ==" , Eq )
105- , (" ~=" , NotEq )
94+ [ (" negate" , Neg )
95+ , (" +" , Add )
96+ , (" -" , Sub )
97+ , (" *" , Mul )
98+ , (" /" , Div )
99+ , (" if" , If )
100+ , (" >" , Greater )
101+ , (" >=" , GreaterEq )
102+ , (" <" , Less )
103+ , (" <=" , LessEq )
104+ , (" ==" , Eq )
105+ , (" ~=" , NotEq )
106+ , (" casePair" , CasePair )
106107 ]
107108
108109allocatePrim :: TiHeap -> (Name , Primitive ) -> (TiHeap , (Name , Addr ))
@@ -225,6 +226,7 @@ primStep state Eq = primComp state (==)
225226primStep state NotEq = primComp state (/=)
226227primStep state (Constr tag arity) = primConstr state tag arity
227228primStep state If = primIf state
229+ primStep state CasePair = primCasePair state
228230
229231-- Exercise 2.16: evaluation of `negate` (the only unary primitive)
230232primNeg :: TiState -> TiState
@@ -331,11 +333,33 @@ primIf (s, d, h, e, stats) = state' where
331333 | otherwise = error " primIf: conditional is not a boolean"
332334 -- Stack and dump if argument is not evaluated
333335 s'' = [condAddr]
334- d' = s' : d
336+ d' = tail s : d
335337 -- Get arguments
336338 condAddr : thenAddr : elseAddr : _ = getArgs h s
337339 cond = hLookup h condAddr
338340
341+ -- Exercise 2.22: implement `casePair` primitive. This is fairly similar
342+ -- to the evaluation of primIf
343+ primCasePair :: TiState -> TiState
344+ primCasePair (s, d, h, e, stats) = state' where
345+ state' | s' == [] = error " primCasePair: not enough arguments to casePair"
346+ | isDataNode pair = (s', d, h'', e, stats)
347+ | otherwise = (s'', d', h, e, stats)
348+ -- Stack, heap, and n if conditional is already evaluated
349+ s' = drop 2 s
350+ rootAddr : _ = s'
351+ (h', ap) = hAlloc h $ NAp handlerAddr pair1Addr
352+ h'' = hUpdate h' rootAddr $ NAp ap pair2Addr
353+ -- Stack and dump if argument is not evaluated
354+ s'' = [pairAddr]
355+ d' = tail s : d
356+ -- Get arguments
357+ (pair1Addr, pair2Addr) = getPairAddrs pair
358+ getPairAddrs (NData 1 [pair1Addr', pair2Addr']) = (pair1Addr', pair2Addr')
359+ getPairAddrs _ = error " primCasePair: argument is not a pair"
360+ pairAddr : handlerAddr : _ = getArgs h s
361+ pair = hLookup h pairAddr
362+
339363-- Looks up all the arguments (names) for NAp nodes on the spine
340364getArgs :: TiHeap -> TiStack -> [Addr ]
341365getArgs _ [] = error " getArgs: empty stack"
0 commit comments