module Untyped.Calculus (
Computation, Computer,
eval1,
compute, safecompute, bigstep,
canStep, isStuck
) where
import Sidekick ( failAll, showAll, protectWith )
import Untyped.Term ( Term(..), isNatVal, isVal, (|->) )
type Computation = [Term]
type Computer = Term -> Computation
eval1 :: Term -> Term
eval1 term = case term of
TmUnit -> TmStop
TmTrue -> TmStop
TmFalse -> TmStop
TmIf TmTrue t1 _ -> t1
TmIf TmFalse _ t2 -> t2
TmIf t t1 t2
| canStep t -> TmIf t' t1 t2
| otherwise -> TmStop
where t' = eval1 t
TmZero -> TmStop
TmSucc t
| canStep t -> TmSucc t'
| otherwise -> TmStop
where t' = eval1 t
TmPred TmZero -> TmZero
TmPred t@(TmSucc nv)
| canStep t -> TmPred t'
| isNatVal nv -> nv
| otherwise -> TmStop
where t' = eval1 t
TmIsZero TmZero -> TmTrue
TmIsZero t@(TmSucc nv)
| canStep t -> TmIsZero t'
| isNatVal nv -> TmFalse
| otherwise -> TmStop
where t' = eval1 t
(TmAbs x t) `TmApp` t2 -> (x |-> t2) t
t1 `TmApp` t2
| canStep t1 -> t1' `TmApp` t2
| isVal t1 && canStep t2 -> t1 `TmApp` t2'
| otherwise -> TmStop
where [t1',t2'] = map eval1 [t1,t2]
TmLoop -> TmLoop
_________________________ -> TmStop
canStep :: Term -> Bool
canStep t = case (eval1 t) of
TmStop -> False
______ -> True
isStuck :: Term -> Bool
isStuck = failAll [canStep, isVal]
compute :: Computer
compute = takeWhile (/= TmStop) . (iterate eval1)
safecompute :: Computer
safecompute = (protectWith TmLoop [TmStop]) . (iterate eval1)
bigstep :: Computer -> Term -> Term
bigstep = (last .)