Work for CS-381, Programming Language Fundamentals
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

53 lines
1.7 KiB

module KarelSemantics where
import Prelude hiding (Either(..))
import Data.Function (fix)
import KarelSyntax
import KarelState
-- | Valuation function for Test.
test :: Test -> World -> Robot -> Bool
test (Not t) w r = not $ test t w r
test (Facing c) w (_, c', _) = c == c'
test (Clear d) w (p, c, _) = isClear (neighbor (cardTurn d c) p) w
test Beeper w (p, _, _) = hasBeeper p w
test Empty w (_, _, i) = i == 0
-- | Valuation function for Stmt.
stmt :: Stmt -> Defs -> World -> Robot -> Result
stmt Shutdown _ _ r = Done r
stmt PickBeeper _ w r = let p = getPos r
in if hasBeeper p w
then OK (decBeeper p w) (incBag r)
else Error ("No beeper to pick at: " ++ show p)
stmt Move _ w (p, c, i) =
case w np of
Just n -> OK w (np, c, i)
Nothing -> Error ("Blocked at: " ++ show np)
where np = neighbor c p
stmt PutBeeper _ w (p, c, i) = case i of
0 -> Error ("No beeper to put.")
n -> OK (incBeeper p w) (p, c, n - 1)
stmt (Turn d) _ w (p, c, i) = OK w (p, cardTurn d c, i)
stmt (Call m) e w r = case lookup m e of
Just x -> stmt x e w r
Nothing -> Error ("Undefined macro: " ++ m)
stmt (Iterate n s) e w r = several (take n $ cycle [s]) e w r
stmt (If c t el) e w r =
if test c w r
then stmt t e w r
else stmt el e w r
stmt (While t es) e w r =
if test t w r
then onOK (\w' r' -> stmt (While t es) e w' r') (stmt es e w r)
else OK w r
stmt (Block es) e w r = several es e w r
several :: [Stmt] -> Defs -> World -> Robot -> Result
several xs d w r = foldl (\rs s -> onOK (\w' r' -> stmt s d w' r') rs) (OK w r) xs
-- | Run a Karel program.
prog :: Prog -> World -> Robot -> Result
prog (m,s) w r = stmt s m w r