简体   繁体   中英

Error: This variant pattern is expected to have type prim1. The constructor Id does not belong to type prim1

I don't have much experience with ocmal and the compiler error message isn't very helpful. I don't see any obvious problem with the code. I have the full code and the error message below. Thank you.

Full compiler error message:

File "compile.ml", 
     | Id(x) ->
       ^^

Error: This variant pattern is expected to have type prim1 The constructor Id does not belong to type 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

It looks like your problem is that you have nested match expressions. The difficulty is that the compiler is thinking that the next case of the outer match is in fact the next case of the inner match .

The solution is to parenthesize all of the the inner match expressions.

It should look something like this:

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)) ]
        )
    . . .

You need to do this for all of the nested match expressions (I see 3 of them).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM