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 个)。