0

I am improving on some Haskell but have become stuck down trying to write an interpreter for testing language which tests math and relations. I have tested all data type cases but CallE. I believe I must make a new environment and map values using the map string method in Haskell but I do not know how it will look. Sorry for mistakes, English is not my best language!

// --------------- Declarations ----------------
data Expr = 
    IntE Integer
  | PlusE Expr Expr 
  | TimesE Expr Expr
  | BoolE Bool
  | IfE Expr Expr Expr
  | VarE String
  | LetE String Expr Expr
  | CallE String [Expr]
  deriving (Eq,Ord,Show)

data Command =
    DefC String [String] Expr
  deriving (Eq,Ord,Show)

data Program =
    Program [Command] Expr
  deriving (Eq,Ord,Show)

data Value = 
    IntV Integer
  | BoolV Bool
  deriving (Eq,Ord,Show)

data Answer = 
    ValueA Value
  | BadA
  deriving (Eq,Ord,Show)

type Env = Map String Value
type FEnv = Map String ([String],Expr)


// --------------- Helper functions ----------------

interpExprMany :: FEnv -> Env -> [Expr] -> Maybe [Value]
interpExprMany fenv env es = case es of
  [] -> Just []
  e:es' -> case interpExpr fenv env e of
    ValueA v -> case interpExprMany fenv env es' of
      Just vs -> Just (v:vs)
      Nothing -> Nothing
    BadA -> Nothing


extendEnvMany :: [String] -> [Value] -> Env -> Maybe Env
extendEnvMany as bs env = case (as, bs) of
  (as1:ass1, bs2:bss2) -> extendEnvMany ass1 bss2 (Map.insert as1 bs2 env)
  ([], []) -> Just env


// --------------- Implementation of interpreter----------------

interpExpr :: FEnv -> Env -> Expr -> Answer
interpExpr fenv env e = case e of

  IntE i -> ValueA (IntV i)
  BoolE b -> ValueA (BoolV b)

  PlusE e1 e2 -> case (interpExpr fenv env e1,interpExpr fenv env e2) of
    (ValueA (IntV i1),ValueA (IntV i2)) -> ValueA (IntV (i1 + i2))
    _ -> BadA

  IfE e1 e2 e3 -> case interpExpr fenv env e1 of
    ValueA (BoolV b) ->
      if b 
      then interpExpr fenv env e2
      else interpExpr fenv env e3

  VarE x -> case Map.lookup x env of
    Just v -> ValueA v
...
...
...

CallE fx es -> undefined
Jackie
  • 1

2 Answers2

0

Presumably CallE takes a routine name and a list of arguments, with the routine defined in the environment somehow. So you are going to have to look up the name in the environment to get the definition. You don't seem to have a constructor for this, so you will have to define one. Probably something like

Routine String [String]

The first String is the routine name, the second is the list of formal parameter names. Pass the formal parameter names and the actual arguments from CallE to envExtendMany to get the inner environment, and call interpExpr with that new environment.

Paul Johnson
  • 17,438
  • 3
  • 42
  • 59
0

If your functions are built-in like you say, you probably just need to switch on the function name.

CallE "sqr" [x] -> case interpExpr fenv env x of
                       ValueA (IntV v) -> ValueA (IntV (v ^ 2))
                       _ -> BadA
CallE "pow" [x,y] -> ...

There is a lot of boilerplate logic here that I would factor into a function so you can say:

CallE "sqr" [x] -> func1 (^2) x
CallE "sqrt" [x] -> func1 (floor . sqrt . fromIntegral) x
...

func1 :: (Integer -> Integer) -> Answer -> Answer
func1 f x = ... 

(And similarly for binary functions)

luqui
  • 59,485
  • 12
  • 145
  • 204