
Ok, that got the variables working. Example: *Minim> evaluateprog $ ProgramTree ( ProgramLeaf $ AssignmentStatement( VarAssignment (Variable "test") ( ValueFromConstant (Constant 3)))) ( PrintStatement (PrintValue( ValueFromVariable(Variable "test")))) 3.0 3.0 I'm having eval return the IO monad, the Map, and a Double. That means we can use the same Eval class to evaluate for example the value of a Value. Next step is either to get the parsing working for the functional eval parts, or to get looping working. Yes, I'm aware that this is Haskell 101 :-D module Minim where import Char import List import Control.Monad import Control.Monad.State import Control.Monad.Reader import qualified Text.ParserCombinators.Parsec as Parsec import qualified Data.Map as Map {- <program> := <statement> | <statement> <program>; <statement> := <assignment> | <conditional> | <goto> | <tag>; | <print> | <input> <assignment> := (<var> is <val>) { assign a value to a variable } | (++ <var>) { increment a variable } | (-- <var>); { decrement a variable } <val> := <constant> | <var>; <var> := any symbol; <constant> := any number <conditional> := (if <test> then <statement> else <statement>); <test> := (<val> <comp> <val>) | (<test> and <test>); { boolean AND} | (<test> or <test>) {boolean OR} | (not <test>); {boolean NOT} <comp> := > | < | =; <goto> := (goto <tag>); {go to} <tag> := any symbol <print> := (print <string>) | (print <val>); nl; {nl is new line} <input> := (input <var>); {input the users response to var} <string> := any string; -} testtry = Parsec.try (Parsec.string "hello") Parsec.<|> Parsec.string "help" string :: Parsec.Parser String string = Parsec.many1 Parsec.letter minimprint = do Parsec.string "print" Parsec.many1 (Parsec.char ' ') Parsec.char '"' stringvalue <- string Parsec.char '"' return (Print stringvalue) parens :: Parsec.Parser () parens = do Parsec.char '(' parens Parsec.char ')' parens Parsec.<|> return () class Eval a where eval :: a -> StateT (Map.Map String Double) IO Double data Program = ProgramLeaf Statement | ProgramTree Program Statement deriving(Show) instance Eval Program where eval (ProgramLeaf statement) = eval statement eval (ProgramTree program statement) = do eval program eval statement data Statement = PrintStatement Print | AssignmentStatement Assignment deriving(Show) instance Eval Statement where eval ( PrintStatement print) = eval print eval ( AssignmentStatement assignment) = eval assignment data Print = Print String | PrintValue Value deriving(Show) instance Eval Print where eval (Print value) = do liftIO $ putStrLn value return 0 eval (PrintValue value) = do evaluatedvalue <- eval value liftIO $ putStrLn (show(evaluatedvalue)) return evaluatedvalue data Assignment = VarAssignment Variable Value | Increment Variable | Decrement Variable deriving(Show) instance Eval Assignment where eval (VarAssignment (Variable varname) (ValueFromConstant (Constant constant))) = do oldmap <- get let newmap = Map.insert varname constant oldmap put newmap return constant data Variable = Variable String deriving(Show) data Value = ValueFromConstant Constant | ValueFromVariable Variable deriving(Show) instance Eval Value where eval (ValueFromConstant (Constant i )) = return i eval (ValueFromVariable (Variable varname )) = do map <- get return (map Map.! varname) newtype Constant = Constant Double deriving(Show) instance Eval Constant where eval (Constant i) = return i evaluateprog prog = evalStateT( eval prog ) Map.empty minimparse minimsentence = case (Parsec.runParser minimprint () "" minimsentence) of (Right statement) -> evaluateprog statement Left error -> do putStrLn("error: " ++ show(error)) return 0 test = minimparse "print \"hello\""