我正在尝试构建一个解释器
type ide = string;;
type integer = int;;
(*Eccezioni*)
exception WrongMatchException;;
exception EmptyEnvException;;
exception UnboundRecordException;;
type exp =
| Ide of ide (*Identificatore*)
| Int of int (*Valori Interi*)
| Bool of int (*Valori Booleani*)
| Add of exp * exp (*Operatori Matematici*)
| Sub of exp * exp
| Mul of exp * exp
| Eq of exp * exp
| Leq of exp * exp
| And of exp * exp (*Operatori Logici*)
| Or of exp * exp
| Not of exp
| Fun of ide * exp (*Funzione con un parametro, non ricorsiva*)
| IfThenElse of exp * exp * exp (*Classico If Then Else *)
| LetIn of ide * exp * exp (*Blocco Let*)
| Function of ide * exp (*Applicazione funzionale Ide(E)*)
| CreateTuple of ide * exp (*Espressione Tupla*)
| GetIndex of exp * integer (*Accesso Elemento Tupla*)
| GetFirstN of exp * integer (* Seleziona elementi Tupla*)
| TupleEquals of exp * exp (*Confronto tra tuple*)
| Map of ide * exp (*Applica funzione ad elementi tupla*)
;;
(*Elementi di una tupla*)
type elts =
| Elemento of exp
| Lista of exp list
;;
(* the empty environment *)
(* emptyEnv: 'a -> 'b *)
let emptyEnv = fun x -> raise EmptyEnvException;;
let emptyFunEnv = fun x -> raise EmptyEnvException;;
(*bind: ('a -> 'b) -> ide -> exp -> (ide -> exp ) *)
let bind env (variable: ide) value = fun y ->
if variable = y then value else env y;;
let rec eval (expression: exp) env funenv =
match expression with
| Int i -> i
| Ide i -> env i
| Bool i -> match i with
| 0 -> false
| 1 -> true
| Add (e1, e2) -> (eval e1 env funenv) + (eval e2 env funenv)
| Sub (e1, e2) -> (eval e1 env funenv) - (eval e2 env funenv)
| Mul (e1, e2) -> (eval e1 env funenv) * (eval e2 env funenv)
| Eq (e1, e2) -> (eval e1 env funenv) = (eval e2 env funenv)
| Leq (e1, e2) -> (eval e1 env funenv) <= (eval e2 env funenv)
| And (e1, e2) -> if eval e1 env funenv then eval e2 env funenv else false
| Or (e1, e2) -> if eval e1 env funenv then eval e2 envfunenv else false
| Not (e1) -> if (eval e1 env funenv) then false else true
(*| Fun (funName, arg) -> (*Chiamata di funzione*)
let value = eval arg env in
let (param, body, ambiente) = fenv funName in
let env1 = bind env param value in
eval body env1 fenv *)
| IfThenElse (e1, e2, e3) -> if eval e1 env funenv then eval e2 env funenv
else eval e3 env funenv
| Let (id, value, body) -> let value = eval id env funenv in
let env1 = bind env id value in
eval body env1 funenv
| GetIndex (id, i) -> (eval id env funenv)[eval i env funenv]
| GetFirstN (exp, i) -> (eval exp env funenv) fst (eval i env funenv)
| TupleEquals (exp1, exp2) -> (eval exp1 env funenv) = (eval exp2 env funenv)
| Map (funx, exp) -> funx @ (eval exp env funenv)
| _ -> raise WrongMatchException
;;
当我尝试编译此代码时,输出为
File "progetto.ml", line 53, characters 3-15:
Error: This pattern matches values of type exp
but a pattern was expected which matches values of type int
第 53 行在哪里
| Add (e1, e2) -> (eval e1 env funenv) + (eval e2 env funenv)
我不明白为什么会产生错误。 ide i 是一个字符串,而不是整数。为什么错误没有出现在那里,但只出现在 53 行及以下(算术运算)?
最佳答案
从语法上讲,错误行看起来像是其上方的 match
的延续。
您可以更改此设置:
| Bool i -> match i with
| 0 -> false
| 1 -> true
对此:
| Bool i -> (match i with
| 0 -> false
| 1 -> true)
(作为旁注,这场比赛并不详尽。)
关于匹配中的 OCaml 类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32158791/