一些背景知识:我正在编写一个通用的从高级到低级的编译器。在高级方面,它理解类、方法、字段、虚拟方法调用等;在低级方面,它理解函数、结构、数组等。前端将编译后的语言形式,如java(主要焦点)和c翻译成我的ir。中间步骤将类、方法、字段和虚拟调用等降低为函数调用和结构。后端输出c、llvm-ir(主焦点)或潜在的其他内容。
目前,类型(如整数、浮点数、结构、类等)是(大多数情况下)不可变的。类允许您添加字段和方法,因为这些字段和方法不会更改类型(即类指针)。每个翻译单元(“module”)只有一个给定类型,即结构、指针、数组和其他“派生”类型。换句话说,类型具有结构等价性,比如LLVM,而不是名称等价性,比如C++。
我遇到的问题是将Java前端抛出的ClassType实例转换为LLVM后端理解的StructType实例(带有vtable指针和类的所有字段),这样系统就可以在整个过程中保持一致的状态。其中一个困难是保持结构的等价性——两个不同的类可能被降低到同一个结构,这必须在降低过程开始时检测到,或者在降低过程结束后纠正。
这个冗长的解释让我想到了我的问题:像haskell这样的懒惰的评估语言能提供一个方便的解决方案吗?如果是这样,那么如何将其转换回java,也许使用“promise”模式?

最佳答案

我不确定你是在寻找一般性的答案还是更具体的答案,但听起来像是,

lower :: Eq b => a -> b
lower = undefined

generate :: Eq b => [a] -> [b]
generate xs = go $ map lower xs
    where go [] = []
          go (y:ys) = y : go (filter (not . (==y)) ys)

它逐渐产生独特的元素。增量方面只是由于懒惰的缺点,除非您也可以使eq实例变得懒惰(例如,仅通过比较某种结构散列代码,这可能会让您跳过成本更高的代码生成步骤)。

10-06 04:12
查看更多