If-statements in my language should be in the following form:
if ((4 div 2) = 2)-> print(1)
[] ((4 div 2) > 1)-> print(2)
[] ((4 div 2) > 2)-> print(3)
fi
The output to this should be one and two printed to the console however if I were to switch the positions of the middle and last statement, only the first statement would be evaluated and then the program would terminate. It seems that the behaviour that is exhibited is that the evaluation of the if-statements is predicated upon the value of the guard such that if 1..n guards are true and if the n+1 guard is false, then the "falseness" breaks the evaluation.
I think I narrowed down the issue to how an if-statement is individually evaluated.
evalStatement_ env (If cond expr) = evalVal env cond >>= \x -> case x of
HBool False -> return ()
HBool True -> traverse_ (evalStatement_ env) expr
If a statement whose guard (cond
) is evaluated to false then the path that's taken is return ()
. It seems that if this is taken then the program stops because when all guards are true then the statements can be executed. But in my evaluation of basic datatypes, I also have return ()
:
evalStatement_ env (Eval val) = do
result <- evalVal env val
return ()
This function takes a HVal
and evaluates it and returns ()
but given the behaviour of what is occurring with if-statements, this has left me really confused because in this case, the program doesn't stop.
The other possible issue could be down to my representation of if-statements.
data HVal
= HInteger Integer
| HBool Bool
| HString String
| HList [HVal]
| Length HVal
| Arith HVal Op HVal
| Assign String HVal
deriving (Eq, Read)
data HStatement
= Eval HVal
| Print HVal
| Do HVal [HStatement]
| Selection [HStatement]
| If HVal [HStatement]
| Skip String
deriving (Eq, Read)
An if-statement is built up from a single HVal
, the guard/cond and a list of HStatements
which carry out what is to be evaluated if the guard is true. Selection
however is what actually handles the work. It is supposed to be representative of multiple if-statements hence the list.
parseIf :: Parser HStatement
parseIf = do
string "if" <|> string "[]"
spaces
string "("
cond <- parseVals
string ")->"
spaces
expr <- many1 (try (parseSkip) <|> try (parseDo <* spaces) <|> try (parsePrint) <|> try (parseEvalHVal))
return $ If cond expr
parseSelection :: Parser HStatement
parseSelection = liftM Selection $ (many1 parseIf)
So when I go to evaluate Selection
, what's supposed to occur is that the evalStatement_ env
function is applied to each entry within the list which in turn allows for the entirety of the list to be evaluated but clearly that's not the case! When I went to print out what was actually "in' the Selection
in the following program, only the first statement was found within the block:
if ((4 div 2) = 2)-> print(1)
[] ((4 div 2) < 1)-> print(2)
[] ((4 div 2) > 1)-> print(3)
fi
./Main if.oli
[Print (1 )
[]
]
1
This leads me to believe it's either a parsing error or there's something to do with return ()
but I genuinely don't know how to proceed.
----- EVAULATION FUNCTIONS -----
evalStatement_ :: Env -> HStatement -> IOThrowsError ()
evalStatement_ env (Do cond expr) = evalVal env cond >>= \x -> case x of
HBool False -> return ()
HBool True -> do
traverse_ (evalStatement_ env) expr
evalStatement_ env (Do cond expr)
evalStatement_ env (Skip skip) = return ()
evalStatement_ env (Print (HString val)) = getVar env val >>= \x -> liftIO $ putStrLn $ show x
evalStatement_ env (Print val) = evalVal env val >>= \x -> liftIO $ putStrLn $ show x
evalStatement_ env (Eval val) = do
result <- evalVal env val
return ()
evalStatement_ env (If cond expr) = evalVal env cond >>= \x -> case x of
HBool False -> return ()
HBool True -> traverse_ (evalStatement_ env) expr
evalStatement_ env (Selection selection) = do
traverse_ (evalStatement_ env) selection
Aucun commentaire:
Enregistrer un commentaire