-- integer expressions

data IntExpr = INT Int | Var String | Sum [IntExpr] | Prod [IntExpr] |
	       Sub IntExpr IntExpr


-- Boolean expressions

data BoolExpr = BOOL Bool | Gt IntExpr IntExpr | Not BoolExpr


-- command expressions

data ComExpr = Skip | Assign String IntExpr | Seq [ComExpr] |
	       If BoolExpr ComExpr ComExpr | While BoolExpr ComExpr


-- interpreter for IntExpr

evInt :: IntExpr -> (String -> Int) -> Int

evInt (INT i) state     = i
evInt (Var x) state     = state x
evInt (Sum s) state     = foldl (+) 0 (map (flip evInt state) s)
evInt (Prod s) state    = foldl (*) 1 (map (flip evInt state) s)
evInt (Sub e1 e2) state = evInt e1 state - evInt e2 state


-- interpreter for BoolExpr

evBool :: BoolExpr -> (String -> Int) -> Bool

evBool (BOOL b) state   = b
evBool (Gt e1 e2) state = evInt e1 state > evInt e2 state
evBool (Not be) state   = not (evBool be state)


-- interpreter for ComExpr

evCom :: ComExpr -> (String -> Int) -> String -> Int

evCom Skip state         = state
evCom (Assign x e) state = (\y -> if x == y then evInt e state else state y)
evCom (Seq cs) state      = foldl (flip evCom) state cs
evCom (If be c1 c2) state = if evBool be state then evCom c1 state
					       else evCom c2 state
evCom (While be c) state  = if evBool be state 
			    then evCom (Seq [c,While be c]) state
			    else state







