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