用Ocaml编写的编译器中的表达式类型

时间:2011-06-17 21:18:15

标签: compiler-construction types ocaml

我正在Ocaml中编写一个小编译器。在ast.mli中,我定义了两种表达式

type int_expr =
  | Integer_constant of int
  | Evar of string
  | Ebinop of binop * int_expr * int_expr
  | Ecell of int_expr * int_expr (* Sheet[ , ] *)

type bool_expr = 
  | Bool_constant of bool
  | Bcmp of cmp * int_expr * int_expr
  | Band of bool_expr * bool_expr
  | Bor of bool_expr * bool_expr
  | Bnot of bool_expr

interp.ml中,我想定义一个名为eval_expression的函数来计算任何可能是int_expr或bool_expr的表达式

let rec eval_expression env = function
  | Integer_constant n -> Integer n
  | Ebinop (op, n, m) -> ...
  | Evar x -> ...
  | Ecell (r, c) -> ... 
  | Bool_constant b -> ...
  | Bnot c -> ...
  | Bor (c1, c2) -> ...
  | Band (c1, c2) -> ...

但是在编译时会返回错误:

ocamlc  -c interp.ml
File "interp.ml", line 63, characters 4-19:
Error: This pattern matches values of type Ast.bool_expr
       but a pattern was expected which matches values of type Ast.int_expr
make: *** [interp.cmo] Error 2

有人能告诉我如何更改表达式类型的结构以便eval_expression有效吗?非常感谢你!

1 个答案:

答案 0 :(得分:4)

您需要为任意类型的表达式编写另一种类型:

type expr = Iexpr of int_expr
          | Bexpr of bool_expr

和最终值的类型,可以是整数或布尔值

type value = Ivalue of int
           | Bvalue of bool

并编写一个函数evaluate : expr -> value

对于它的价值,我从未觉得以这种方式将允许的表达式静态分离为int-typed和bool-typed表达式在ML类语言中确实值得。一旦向对象语言添加更丰富的类型,最终会出现大量重复语法。你真正想要的是将对象语言类型踢入你的实现语言的类型层,但最终在ML中变得非常难看。它在Haskell更丰富的类型和类型的机器中更好一点,但它仍然感觉像一个非常受影响的编程风格。

最后,对于小小的一次性解释器,我通常只为我的对象语言的类型和表达式编写单独的tpexpr类型,并将eval写为expr -> tp -> value