I am trying to write an evaluator which executes a simple if-block of code. The only two conditions that I'm interested in at the moment is when the condition to enter the block is true or false or if the condition is a relational expression.
The former pattern works fine and it makes sense to me in the implementation of it.
evalCond (Bool cond) = if cond then True else False
I consider my condition to be one of my HenryVal
booleans value and then I return the correct Boolean value after the check.
When it comes to the relational expression evaluation I'm not so sure where it's going wrong. An arithmetic expression is given by <x op y>
(without spaces) and that returns the correct binary expression piece of data. For example <5<10>
would return RBinary Less (Integer 5) (Integer 10)
. So when I go to the evaluation function of every different expression, the condition is passed into it's own function which evaluates it to True or False. I consider this condition at that moment of time a String because it's the only way in which it can be passed to the condition evaluation function. If I were to pass RBinary op x y
, I am left with an error because RBinary expects three arguments, not one.
Furthermore I know the evaluation works because in ghci, if I were to enter the following I would be left with the correct evaluation:
cond = "4 Less 5"
(henryBool2Bool (evalRBinOp (int2HenryInt (str2Int ((words cond) !! 0))) (evalROp ((words cond) !! 1)) (int2HenryInt (str2Int ((words cond) !! 2))) ))
Through command line arguments, if I enter the following I get the error:
./hask "if <5<10>then x:=5 else x:=10"
hask: hask.hs:(336,1)-(338,137): Non-exhaustive patterns in function evalCond
So I thought perhaps a function which translates a string into an RBinary expression would be better as then if it's being passed in as a string then I can evaluate the string as an RBinary expression but that gave me the same non-exhaustive pattern error.
Below is my code which includes my data types and my evaluator functions.
data HenryVal = Atom String
| String String
| Integer Integer
| Bool Bool
| Not HenryVal
| Neg HenryVal
| List [HenryVal]
| Seq [HenryVal]
| Assign String HenryVal
| If HenryVal HenryVal HenryVal
| While HenryVal HenryVal
| Skip
| ABinOp ABinOp
| RBinOp RBinOp
| ABinary ABinOp HenryVal HenryVal
| BBinary BBinOp HenryVal HenryVal
| RBinary RBinOp HenryVal HenryVal
data BBinOp = And | Or deriving (Show)
data RBinOp = Greater
| GEqual
| Less
| LEqual
deriving (Show)
data ABinOp = Add
| Subtract
| Multiply
| Divide
deriving (Show)
evalRBinOp :: HenryVal -> RBinOp -> HenryVal -> HenryVal
evalRBinOp (Integer a) Greater (Integer b) = Bool (a > b)
evalRBinOp (Integer a) Less (Integer b) = Bool (a < b)
evalRBinOp (Integer a) GEqual (Integer b) = Bool (a >= b)
evalRBinOp (Integer a) LEqual (Integer b) = Bool (a <= b)
evalCond :: HenryVal -> Bool
evalCond (Bool cond) = if cond then True else False
evalCond (String cond) = if (henryBool2Bool (eval (str2rbinary cond))) then True else False
--evalCond (String cond) = if (henryBool2Bool (evalRBinOp (int2HenryInt (str2Int ((words cond) !! 0))) (evalROp ((words cond) !! 1)) (int2HenryInt (str2Int ((words cond) !! 2))) )) == True then True else False
henryVal2Rop :: HenryVal -> RBinOp
henryVal2Rop (RBinOp Less) = Less
henryVal2Rop (RBinOp Greater) = Greater
str2Int :: String -> Integer
str2Int str = read (str) :: Integer
int2HenryInt :: Integer -> HenryVal
int2HenryInt num = Integer num
henryBool2Bool :: HenryVal -> Bool
henryBool2Bool (Bool True) = True
henryBool2Bool (Bool False) = False
henryBool2Bool (String "True") = True
henryBool2Bool (String "False") = False
str2rbinary :: String -> HenryVal
str2rbinary string = RBinary (evalROp ((words string) !! 1)) (int2HenryInt (str2Int ((words string) !! 0))) (int2HenryInt (str2Int ((words string) !! 2)))
evalROp :: String -> RBinOp
evalROp "Less" = Less
evalROp "Greater" = Greater
evalROp "GEqual" = GEqual
evalROp "LEqual" = LEqual
eval :: HenryVal -> HenryVal
eval val@(Atom _) = val
eval val@(String _) = val
eval val@(Integer _) = val
eval val@(Bool _) = val
eval val@(Neg _) = val
eval val@(Not _) = val
eval (List [Atom "quote", val]) = val
eval val@(List _) = val
eval val@(Seq _) = val
eval (If cond a b) = if (evalCond cond) then (eval a) else (eval b)
eval (While cond a) = a
eval (Assign var val) = val
eval val@(ABinOp _) = val
eval val@(RBinOp _) = val
eval (Skip) = Skip
eval (ABinary op x y) = evalABinOp (eval x) op (eval y)
eval (BBinary op x y) = evalBBinOp (eval x) op (eval y)
eval (RBinary op x y) = evalRBinOp (eval x) op (eval y)