Error: This variant pattern is expected to have type prim1. The constructor Id does not belong to type prim1
Error: This variant pattern is expected to have type prim1. The constructor Id does not belong to type prim1
我对 ocmal 没有太多经验,编译器错误消息也不是很有帮助。我没有看到代码有任何明显的问题。我有完整的代码和下面的错误消息。谢谢。
完整的编译器错误消息:
File "compile.ml",
| Id(x) ->
^^
错误:此变体模式的类型应为 prim1
构造函数Id不属于类型prim1
type reg =
| EAX
| ESP
type arg =
| Const of int
| Reg of reg
| RegOffset of int * reg
type instruction =
| IMov of arg * arg
| IAdd of arg * arg
| IRet
type prim1 =
| Add1
| Sub1
type expr =
| Number of int
| Prim1 of prim1 * expr
| Let of (string * expr) list * expr
| Id of string
let rec find (ls : (string * int) list) (x : string) =
match ls with
| [] -> None
| (y,v)::rest ->
if y = x then Some(v) else find rest x
let rec compile_env (p : expr) (stack_index : int) (env : (string * int) list) : instruction list =
match p with
| Number(n) -> [ IMov(Reg(EAX), Const(n)) ]
| Prim1(op, e) ->
match op with
| Add1 -> (compile_env e stack_index env) @ [ IAdd(Reg(EAX), Const(1)) ]
| Sub1 -> (compile_env e stack_index env) @ [ IAdd(Reg(EAX), Const(-1)) ]
| Id(x) ->
match find env x with
| None -> failwith "%s not in scope" x
| Some value -> [IMov(Reg(EAX), RegOffset(value, Reg(ESP)))]
| Let(binds, body) ->
match binds with
| [] -> [] @ (compile_env body stack_index env)
| (str, exp)::rest ->
let new_env = env @ [(str, -4*stack_index)] in
let eval_expr = (compile_env exp stack_index env) in
let eval_tail = (compile_env Let(rest, body) stack_index+1 new_env) in
eval_expr @ [IMov(RegOffset(-4*stack_index, Reg(ESP)), Reg(EAX))] @ eval_tail
您的问题似乎是嵌套了 match
表达式。困难在于编译器认为外部 match
的下一个案例实际上是内部 match
.
的下一个案例
解决方案是将所有内部匹配表达式括起来。
它应该看起来像这样:
match p with
| Number(n) -> [ IMov(Reg(EAX), Const(n)) ]
| Prim1(op, e) ->
(match op with
| Add1 -> (compile_env e stack_index env) @ [ IAdd(Reg(EAX), Const(1)) ]
| Sub1 -> (compile_env e stack_index env) @ [ IAdd(Reg(EAX), Const(-1)) ]
)
. . .
您需要对所有嵌套的 match
表达式执行此操作(我看到其中的 3 个)。
我对 ocmal 没有太多经验,编译器错误消息也不是很有帮助。我没有看到代码有任何明显的问题。我有完整的代码和下面的错误消息。谢谢。
完整的编译器错误消息:
File "compile.ml",
| Id(x) ->
^^
错误:此变体模式的类型应为 prim1 构造函数Id不属于类型prim1
type reg =
| EAX
| ESP
type arg =
| Const of int
| Reg of reg
| RegOffset of int * reg
type instruction =
| IMov of arg * arg
| IAdd of arg * arg
| IRet
type prim1 =
| Add1
| Sub1
type expr =
| Number of int
| Prim1 of prim1 * expr
| Let of (string * expr) list * expr
| Id of string
let rec find (ls : (string * int) list) (x : string) =
match ls with
| [] -> None
| (y,v)::rest ->
if y = x then Some(v) else find rest x
let rec compile_env (p : expr) (stack_index : int) (env : (string * int) list) : instruction list =
match p with
| Number(n) -> [ IMov(Reg(EAX), Const(n)) ]
| Prim1(op, e) ->
match op with
| Add1 -> (compile_env e stack_index env) @ [ IAdd(Reg(EAX), Const(1)) ]
| Sub1 -> (compile_env e stack_index env) @ [ IAdd(Reg(EAX), Const(-1)) ]
| Id(x) ->
match find env x with
| None -> failwith "%s not in scope" x
| Some value -> [IMov(Reg(EAX), RegOffset(value, Reg(ESP)))]
| Let(binds, body) ->
match binds with
| [] -> [] @ (compile_env body stack_index env)
| (str, exp)::rest ->
let new_env = env @ [(str, -4*stack_index)] in
let eval_expr = (compile_env exp stack_index env) in
let eval_tail = (compile_env Let(rest, body) stack_index+1 new_env) in
eval_expr @ [IMov(RegOffset(-4*stack_index, Reg(ESP)), Reg(EAX))] @ eval_tail
您的问题似乎是嵌套了 match
表达式。困难在于编译器认为外部 match
的下一个案例实际上是内部 match
.
解决方案是将所有内部匹配表达式括起来。
它应该看起来像这样:
match p with
| Number(n) -> [ IMov(Reg(EAX), Const(n)) ]
| Prim1(op, e) ->
(match op with
| Add1 -> (compile_env e stack_index env) @ [ IAdd(Reg(EAX), Const(1)) ]
| Sub1 -> (compile_env e stack_index env) @ [ IAdd(Reg(EAX), Const(-1)) ]
)
. . .
您需要对所有嵌套的 match
表达式执行此操作(我看到其中的 3 个)。