一些背景知识:我正在编写一个通用的高级到低级编译器。在高级方面,它理解类,方法,字段,虚方法调用等。在低级方面,它理解函数,结构,数组等。前端翻译Java等语言的编译形式(主要焦点)和C#进入我的IR。中间步骤将类,方法,字段和虚拟调用等降低为函数调用和结构。后端吐出C,LLVM IR(主要焦点),或者可能是其他。
目前,类型(如整数,浮点数,结构,类等)(大多数)是不可变的。类允许您添加字段和方法,因为它们不会更改类型(即类指针)。每个翻译单元(“模块”)只有一种给定类型 - 结构,指针,数组和其他“派生”类型。换句话说,类型具有结构等价,如LLVM - 而不是名称等价,如C ++。
我遇到的问题是将Java前端吐出的ClassType实例转换为LLVM后端理解的StructType实例(带有vtable指针和类的所有字段),以这种方式系统在整个过程中保持一致的状态。其中一个困难是保持结构等效 - 两个不同的类别可能会降低到相同的结构,这必须在降低过程开始时检测到,或者在降低过程后进行纠正。
这个冗长的解释让我想到了一个问题:像Haskell这样的懒惰评估语言能提供一个方便的解决方案吗?如果是这样,如何将其转换回Java,也许使用“Promise”模式?
答案 0 :(得分:1)
我不确定您是否正在寻找一般性答案或更具体的内容,但听起来像是,
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实例变得懒惰(例如,通过仅仅比较某种结构哈希码,可能会让你跳过更昂贵的代码生成步骤。)