我在某些Haskell上有所改进,但一直试图编写用于测试数学和关系的语言的解释器而陷入困境。除了CallE,我已经测试了所有数据类型的情况。我相信我必须使用Haskell中的map字符串方法创建一个新环境并映射值,但我不知道它的外观。对不起,我的英语不是我最好的语言!
// --------------- 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
大概CallE
具有例程名称和参数列表,并且该例程以某种方式在环境中定义。因此,您将不得不在环境中查找名称以获取定义。您似乎没有为此的构造函数,因此您必须定义一个。大概像
Routine String [String]
第一个String
是例程名称,第二个是形式参数名称列表。将形式参数名称和实际参数从CallE
传递到envExtendMany
以获取内部环境,然后使用该新环境调用interpExpr
。
如果您说的是内置函数,则可能只需要打开函数名称即可。
CallE "sqr" [x] -> case interpExpr fenv env x of
ValueA (IntV v) -> ValueA (IntV (v ^ 2))
_ -> BadA
CallE "pow" [x,y] -> ...
这里有很多样板逻辑,我会将其分解为一个函数,以便您可以说:
CallE "sqr" [x] -> func1 (^2) x
CallE "sqrt" [x] -> func1 (floor . sqrt . fromIntegral) x
...
func1 :: (Integer -> Integer) -> Answer -> Answer
func1 f x = ...
(以及类似的二进制函数)