我正在编写我自己的编译器,我正在努力实现一个模块系统。有人能指点我吗,该怎么做?其他语言是如何解决这一问题的?此外,我还试图避免使用c和c++ (头文件)。不过,我喜欢Go/Golang中的模块系统。
我不知道这是否相关,但我正在使用LLVM (也许有一种神奇的方法来导入符号)。
我最初的做法是:
这就形成了一个树结构:
import3.mylang
..。等。
然后我会遍历每个节点并复制它的符号(函数、全局变量等)。到父节点的符号表。如果父节点为null,则它是一个入口点文件,编译器可以启动输出对象文件。
为什么我觉得这很糟糕?
collisions
提前感谢
发布于 2022-08-08 18:03:42
我觉得你的方法真的很好。编译时间的速度不是那么重要,可用性才是。为了避免名称冲突,您可以使用某种模块名称空间(importname.foo()而不是foo()),并且只要foo不存在,就允许这两种方法。或者,您可以在父符号表中插入占位符,每当用户使用该名称时,就会抛出编译时错误(类似于歧义符号)。应该是这样的: main.mylang
import module1
import module2
int main() {}module1.mylang
import module2
void foo() {}
void bar() {}module2.mylang
import module1
void bar() {}
void fun() {}找到循环之后,树将如下所示:
main
├──module1
│ └──module2
└──module2
└──module1像这样的图表:
main
├─>main()
├─>foo() (module1)
├─>bar() (defined twice, throw error when used)
├─>fun() (module2)
├─>module1<───────────┐
│ ├─>foo() (module1) │
│ └─>bar() (module1) │
└─>import2<───────────┘
├─>bar() (module2)
└─>fun() (module2)我对llvm不太了解,但我很确定普通的表不足以归档这个文件。您至少需要嵌套的表,即使不是像我所描述的那样类似于图的结构。而且,在经典的C/C++体系结构中,这是不可能的,除非您使用唯一标识符作为符号,并且不让用户知道(比如c++函数重载)。例如,您可以调用一个函数__import1_bar和另一个__import2_bar,每当用户使用bar()时,您可以在这个图中查找他想要调用的一个函数。在主函数中,使用import1.bar()将引导您到__import1_bar (如图所示),import2.bar()或import1.import2.bar()将引导您到__import2_bar。
祝你好运弄明白。但这无疑是一个有趣的问题。
https://stackoverflow.com/questions/73244684
复制相似问题