@@ -104,6 +104,8 @@ primitives =
104104 , (" ==" , Eq )
105105 , (" ~=" , NotEq )
106106 , (" casePair" , CasePair )
107+ , (" caseList" , CaseList )
108+ , (" abort" , Abort )
107109 ]
108110
109111allocatePrim :: TiHeap -> (Name , Primitive ) -> (TiHeap , (Name , Addr ))
@@ -227,6 +229,8 @@ primStep state NotEq = primComp state (/=)
227229primStep state (Constr tag arity) = primConstr state tag arity
228230primStep state If = primIf state
229231primStep 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)
232236primNeg :: 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
364404getArgs :: TiHeap -> TiStack -> [Addr ]
365405getArgs _ [] = error " getArgs: empty stack"
0 commit comments