{-  This is a simple interpreter, implemented in Haskell,
 -  for (a subset of) the expression language with basic
 -  types, as presented in slides 46 to 51.
 -
 -  See: http://courses.softlab.ntua.gr/pl2/
 -
 -  Nikolaos S. Papaspyrou (nickie@softlab.ntua.gr)
 -  November 30, 2004.
 -}

data Term = Const Int | TTrue | FFalse | Neg Term | Plus Term Term
          | Less Term Term | If Term Term Term
  deriving Show

isvalue :: Term -> Bool
isvalue (Const n) = True
isvalue TTrue = True
isvalue FFalse = True
isvalue _ = False

neg :: Term -> Term
neg (Const n) = Const (-n)

plus :: Term -> Term -> Term
plus (Const n1) (Const n2) = Const (n1+n2)

less :: Term -> Term -> Term
less (Const n1) (Const n2) = if n1<n2 then TTrue else FFalse

iif :: Term -> Term -> Term -> Term
iif TTrue t1 t2 = t1
iif FFalse t1 t2 = t2

arrow :: Term -> Term
arrow (Const n) = Const n
arrow (Neg t) | isvalue t  =  neg t
              | otherwise  =  Neg (arrow t)
arrow (Plus t1 t2) | isvalue t1 && isvalue t2  =  plus t1 t2
                   | isvalue t1                =  Plus t1 (arrow t2)
                   | otherwise                 =  Plus (arrow t1) t2
arrow (Less t1 t2) | isvalue t1 && isvalue t2  =  less t1 t2
                   | isvalue t1                =  Less t1 (arrow t2)
                   | otherwise                 =  Less (arrow t1) t2
arrow (If t t1 t2) | isvalue t  =  iif t t1 t2
                   | otherwise  =  If (arrow t) t1 t2

manyarrows :: Term -> Term
manyarrows t | isvalue t  =  t
             | otherwise  =  manyarrows (arrow t)
