将类型检查器干净地转换为AST注释器

时间:2015-09-17 23:52:00

标签: compiler-construction functional-programming abstract-syntax-tree typechecking

我正在编写功能样式的编译器。类型检查器目前相当简单:它(大部分)只是从ExprType的函数。

现在,我想在工作流程中添加一个步骤,以保留后续阶段的类型信息。有很多方法可以做到这一点(符号表等),但一个简单的方法是转换成一个看起来像AST但包含类型信息的IR。例如,如果AST数据类型是:

datatype Expr = Literal of int
              | Add of Expr * Expr
              | ...

然后输入的IR将是:

type TExpr = Type * TExpr'
datatype TExpr' = TLiteral of int
                | TAdd of TExpr * TExpr
                | ...

所以我现在的目标是将我的类型检查器转换为类型注释器:函数Expr -> TExpr而不是Expr -> Type。这是我的问题:如果不在类型检查器函数中添加一堆样板杂乱,你会怎么做?

天真地,我需要在整个地方添加包装和展开代码,破坏了类型检查器功能的简单易读性。也就是说,类型检查器中的Add目前的情况如下:

let lhs_t = check lhs in
let rhs_t = check rhs in
case (lhs_t, rhs_t) of
  (Int, Int) => Int
| (_, _) => Error

干净整洁!完全符合形式主义的打字判断! ❤️

如果我使用其他翻译逻辑来破坏类型检查程序,它会看起来像这样(现在check的类型为Expr -> TExpr):

(* Recursive calls to translate the children. *)
let lhs_typed = check lhs in
let rhs_typed = check rhs in
(* We don't care about the expression for checking, just the resulting
 * type. So extract that from each child. *)
let lhs_t, _ = lhs_typed in
let rhs_t, _ = rhs_typed in
case (Int, Int) =>
  (* Construct a TExpr with the new type. *)
  (Int, TAdd (lhs_typed, rhs_typed))
| (_, _) => Error

令人不快地将有趣的类型检查逻辑与用于破坏和构建TExpr的无聊样板混合在一起。

有没有办法将这些组件分开?也就是说,类型检查逻辑可以存在于一个递归函数中,而翻译机制可以作为它的外部客户端吗?如果你想要的话,如果仍然很容易运行类型检查器而不用进行翻译,那么奖励积分。

奖金上下文:这是Edward Z. Yang's post on "The AST Typing Problem"的“单独IR”选项。我认为通用编程是la Scrap Your Boilerplate,但不能完全适应这种情况。关于SO的相关但不同的问题:

0 个答案:

没有答案