Как бы я реализовал в этом случае CallE, который будет иметь интрепетер для проверки вызовов функций? - PullRequest
0 голосов
/ 23 февраля 2020

Я улучшаю некоторые Haskell, но застрял, пытаясь написать интерпретатор для тестирования языка, который проверяет математику и отношения. Я проверил все случаи типа данных, кроме CallE. Я считаю, что я должен создать новую среду и значения карты, используя метод строки карты в Haskell, но я не знаю, как это будет выглядеть. Извините за ошибки, английский sh не мой лучший язык!

// --------------- 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

Ответы [ 2 ]

0 голосов
/ 24 февраля 2020

Если ваши функции встроены, как вы говорите, вам, вероятно, просто нужно включить имя функции.

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

Здесь много шаблонных логи c, которые я бы включил в функция, чтобы вы могли сказать:

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

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

(и аналогично для двоичных функций)

0 голосов
/ 23 февраля 2020

Предположительно CallE принимает имя подпрограммы и список аргументов, причем подпрограмма как-то определена в среде. Так что вам придется искать имя в среде, чтобы получить определение. Кажется, у вас нет конструктора для этого, поэтому вам придется его определить. Вероятно, что-то вроде

Routine String [String]

Первое String - это имя процедуры, второе - список имен формальных параметров. Передайте формальные имена параметров и фактические аргументы от CallE до envExtendMany, чтобы получить внутреннюю среду, и вызовите interpExpr с этой новой средой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...