具有惰性求值的复杂结构转换

发布于 2024-09-13 12:06:02 字数 593 浏览 6 评论 0原文

一些背景:我正在编写一个通用的高级到低级编译器。在高级方面,它理解类、方法、字段、虚拟方法调用等,在低级方面,它理解函数、结构、数组等。前端翻译 Java 等语言的编译形式(主要焦点)和 C# 进入我的 IR。中间步骤将类、方法、字段和虚拟调用等降低为函数调用和结构。后端输出 C、LLVM IR(主要焦点)或其他潜在的内容。

目前,类型(如整数、浮点数、结构、类等)(大部分)是不可变的。类允许您添加字段和方法,因为它们不会更改类型(即类指针)。每个翻译单元(“模块”)只有一种给定类型 - 结构体、指针、数组和其他“派生”类型。换句话说,类型具有结构等效性,如 LLVM,而不是名称等效性,如 C++。

我遇到的问题是将 Java 前端吐出的 ClassType 实例转换为 LLVM 后端理解的 StructType 实例(带有 vtable 指针和该类的所有字段),以系统维护的方式整个过程中保持一致的状态。困难之一是维持结构等效性 - 两个不同的类别可能会降低到相同的结构,并且必须在降低过程开始时检测到这一点,或者在降低过程之后进行纠正。

这个冗长的解释让我想到了我的问题:像 Haskell 这样的惰性求值语言可以提供一个方便的解决方案吗?如果是这样,如何将其转换回 Java,也许使用“Promise”模式?

Some background: I am writing a generic high-level to low-level compiler. On the high-level side, it understands classes, methods, fields, virtual method calls, etc. and on the low-level side, it understands functions, structures, arrays, etc. Front-ends translate compiled forms of languages like Java (the main focus) and C# into my IR. An intermediate step lowers the classes, methods, fields, and virtual calls, etc. into function calls and structures. The back end spits out C, LLVM IR (the main focus), or potentially others.

Currently, types (like integers, floats, structs, classes, and so on), are (mostly) immutable. Classes allow you to add fields and methods because these don't change the type (i.e. the class pointer). There is only one of any given type per translation unit ("Module") - structs, pointers, arrays, and other "derived" types. In other words, types have structure equivalence, like LLVM - instead of name equivalence, like C++.

The problem I am running into is translating instances of ClassType that the Java front-end spits out into StructType instances (with a vtable pointer and all of the fields of the class) that the LLVM backend understands, in such a way that the system maintains a consistent state throughout the process. One of the difficulties is maintaining structure equivalence - two different classes might be lowered to the same structure, and this must either be detected at the start of the lowering process, or corrected after the lowering process.

This long-winded explanation brings me to my question: can lazy-evaluation languages like Haskell offer a convenient solution? If so, how can this be translated back into Java, perhaps using the "Promise" pattern?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

咋地 2024-09-20 12:06:02

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

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 实例变得懒惰(例如,通过仅比较某种结构哈希代码,这可能会让您跳过成本更高的代码生成步骤)。

I am not sure if you are looking for a general answer or something more specific, but it sounds something like,

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)

Which produces unique elements incrementally. The incremental aspect is just due to lazy cons, unless you can also make your Eq instance lazy (e.g. by comparing solely on some kind of structural hash code that might let you skip a more costly code generation step).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文