I'm designing an imperative language but I'm having issues in implementing loop functionality. A loop would take the following form:
Do (n < 10)->
Loop Body
I can parse a loop correctly however when it comes to evaluating the loop, two problems arise. The first is I can't exit loop without returning a faux exit success code, though I do think it's because of how I'm implementing the loop. The second issue is that I can't evaluate the body of the loop when there exists more than one expression. I discovered this because I originally had my loop represented as follows:
data HVal
= HInteger Integer
| HBool Bool
| HString String
| HList [HVal]
| Expr HVal Op HVal -- Arithmetic, Relational, and Boolean
| Assign String HVal
| Do HVal HVal
In this instance the following evaluation function for a loop works when the body consists of a single expression:
evalDo :: Env -> HVal -> HVal -> IOThrowsError HVal
evalDo env cond expr = eval env cond >>= \x -> case x of
HBool True -> eval env expr >>= \y -> eval env $ Do cond y
HBool False -> return $ HInteger 1
This function evaluates the following loop correctly:
n := 0
Do (n < 10)->
n := (n + 1)
When it came to evaluating a longer loop body I found that it made more sense to change the loop representation to:
Do HVal [HVal]
My logic behind this is that a loop will consist of the guard and then a list of expressions to be evaluated upon in the loop body. I then made a change to evalDo:
evalDo :: Env -> HVal -> [HVal] -> IOThrowsError HVal
evalDo env cond expr = eval env cond >>= \x -> case x of
HBool False -> return $ HInteger 1
HBool True -> do
y <- return $ map (\x -> eval env x) expr
eval env $ Do cond expr
This however causes the following loop to go into an infinite loop:
n := 0
r := 1
Do (n < 10)->
n := (n + 1)
r := (r * 2)
I think the problem stems from the return when I evaluate the expression but I receive the following error when I don't have it:
Couldn't match type ‘[]’ with ‘ExceptT HError IO’
Expected type: ExceptT HError IO (IOThrowsError HVal)
Actual type: [IOThrowsError HVal]
Any guidance or help on this would be great.