我有一组Ocaml类型来表示一个语法树。有类型的程序,类,方法,表达式等。例如,一种方法是通过一个记录类型是这样表示的:ocaml中的类型建模
type method = { return:typeid; args:typeid list; body:expr }
它包括一个返回类型,一种类型的每个参数,并且主体定义。我想键入检查语法树,并产生一种新的树,看起来非常像旧的树,除了每个表达式都有一个明确的typeid(仅在类型检查后知道)与它相关联。
一种选择是声明一组平行的类型:
type typed_expr = expr * typeid
type typed_method = { return:typeid; args:typeid list; body:typed_expr }
(* ... there are more types *)
的typed_method是必要的,因为typed_expr是不同的类型。但我不想为未检查的AST和检查的AST维护两组几乎相同的类型。
另一种方法是如下定义表达式:
type expr = {...; typ:typeid option}
这使我使用相同的类型定义为输入既检验器和输出。区别在于我将大量检查移动到检查的语法树的使用者代码中。这里有一个合同,typ
字段永远不会在类型检查器输出中为None
,并且在类型检查器输入中始终为None
。
现在,每次我使用键入的树时,访问typ
字段内部值的唯一方法是首先检查它是否为None(它不应该是)。这使得所有后来的消费者代码因为额外的检查而变得丑陋。
这些方法都不令我感到满意。你会如何模型?
为了避免重复,人们也可以考虑将表达式体留出类型化的AST,以便它只携带'typeid'。那么类型化和非类型化的树都需要始终遵守相同的树结构,并且如果需要一起使用表达体和id,则必须同时迭代两棵树。 - 只是一个想法,可能是无稽之谈 – user3240588