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\""
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to