|
@@ -4,17 +4,27 @@
|
|
|
> 源代码 git: http://gogs.mkyr.fun:99/myuan/elang
|
|
|
|
|
|
|
|
|
-## 目标
|
|
|
+## 前言
|
|
|
|
|
|
-本节的目标是把上一节的「语言」编译到 llvm, 不过要想简单快捷地生成 llvm IR, 官方的方案是 C++, 也有一些其他语言的绑定, 比如 Python/Julia, 总而言之, 这一节把 AST 用易语言输出出去后, 就不得不远离易语言了.
|
|
|
+本节的目标是把上一节的「语言」编译到 llvm, 要想简单快捷地生成 llvm IR, 官方的方案是 C++, 虽然有 C 绑定, 但是我测试编译出来的 dll 易语言总是报找不到到导出函数, 而在 dllexport viewer 中却可以看到. 编译 llvm dll 然后让易语言调用花了大部分的时, 以至于这篇文章拖到了现在.
|
|
|
|
|
|
-另外还有一个选项是 binaryen, 如果是 binaryen IR 的话, 倒还可以用易语言手写生成, 但是 binaryen 最终是运行在 wasm 上的, 不直接原生运行的话, 就代表着无法简单使用操作系统 API, 以及与已有的易语言生态相容.
|
|
|
+另外还有一个选项是 binaryen, 如果是 binaryen IR 的话, 倒还可以用易语言手写生成, 但是 binaryen 最终是运行在 wasm 上的, 不直接原生运行的话, 就代表着无法简单使用操作系统 API, 以及与已有的易语言生态相容, 那么这次的经验就对未来无用了.
|
|
|
|
|
|
-## AST 导出
|
|
|
+最终, 我选择了 Python 的 llvmlite 绑定, Python 的 llvmlite 也是对 C API 的封装, 未来也许有机会白嫖 llvmlite 的 DLL.
|
|
|
+
|
|
|
+## 未来
|
|
|
+
|
|
|
+编译器前端要用 DSL 生成不能用易语言写, 后端又不能调用 llvm, 所以生成 IR 的逻辑也不能用易语言写, 可以说`使用易语言编译易语言`的最终目标完全落空. 我之前写过的那些目标本来都是为了这个最终目标努力的, 虽然某些目标仍然可以用易语言实现(比如易语言实现 lisp, 栈虚拟机, 语法扩展), 但是我现在的确非常意兴阑珊.
|
|
|
+
|
|
|
+加上易语言又跟易语言 IDE 强绑定, 之前考虑易语言语法扩展的时候, 我还觉得可以扩展 IDE 来兼容新语法, 但是后来我翻了一些逆向出来的东西, 发现以我的能力基本碰不了易语言 IDE 核心逻辑部分, 如果是在其他地方写然后转译成易语言, 那等于换了一门语言, 毕竟手写易语言的文本格式太扯了, 肯定是用另一种表达生成易语言的, 那能换一门语言的时候, 为什么不用 C# 呢?
|
|
|
+
|
|
|
+综合来讲, 现在唯一能做的, 就是用易语言做一个易语言的虚拟机, 但是众所周知易语言语法已经很古老了, 我绝对没有勇气完全用易语言实现易语言的解释器, 现在版本的易语言写起来太无聊了. 第一篇第二篇实际上我曾经用 Python 实现过, 约 200 行就能完成, 但是在易语言里花了 844 行, 第三篇我没有用其他语言做过, 但是目测用 Python 300 行就够了, 而易语言用了 1359 行. 我曾见过有人用 Python 实现了 lc3 虚拟机, 大概花了 688 行, 按这个比例光虚拟机部分大约在易语言里需要两千八百行, 语法前端估计又要三四千行. 这样又回到了扩展语法, 而上面分析看来扩展语法是很麻烦的.
|
|
|
|
|
|
+关于扩展语法与现有 IDE 兼容, 如果你有任何解决问题的想法, 请留言告知.
|
|
|
+只要能扩展语法, 我可以先用旧易语言扩展语法, 扩展差不多了就在其他语言用 socket 接口把 llvm 的相关操作封装起来, 让扩展后的易语言通过 socket 调用, 最终勉强还算是`使用易语言编译易语言`.
|
|
|
|
|
|
|
|
|
-## 函数实现
|
|
|
+## 操作分解
|
|
|
|
|
|
在虚拟机中, 我自己写的代码可以随意操作逻辑, 但是到 llvm 层面, 就得自己新加逻辑来控制常量匹配了. 以如下代码举例:
|
|
|
|
|
@@ -54,23 +64,25 @@ double f(double args[], int args_count) {
|
|
|
|
|
|
```
|
|
|
|
|
|
-然后这门语言除了函数就没东西了, 就这样
|
|
|
+然后这门语言除了函数就没东西了, 就这样.
|
|
|
|
|
|
-## 未来
|
|
|
+归纳一下用到的功能
|
|
|
+
|
|
|
+- 加减乘除
|
|
|
+- 语言内部函数调用
|
|
|
+- 判断
|
|
|
+- 外部 C 函数, printf
|
|
|
+
|
|
|
+> 实际上再加点关键词, 就可以实现 lisp 了
|
|
|
+
|
|
|
+## AST 导出
|
|
|
|
|
|
-与其他方案对比后, 如果 llvm 的效果很好, 接下来就可以着手
|
|
|
+没什么好说的, 手写了一个按 JSON 格式输出 AST 的函数, 这是最后的荣耀, 最后的完全使用易语言标准库完成东西
|
|
|
|
|
|
-0. 使用 Antla 的易语言解析器
|
|
|
-1. 使用易语言编写的易语言语法扩展工具
|
|
|
-2. 使用扩展后的易语言书写语法扩展工具
|
|
|
-3. 交替使用流程1/2得到的新易语言, 这里称之为 nelang
|
|
|
-4. 使用 nelang, 书写生成 nelang 在 llvm IR 的工具
|
|
|
-5. 使用以 llvm 编译后的静态文件将 nelang AST 生成 llvm IR
|
|
|
-6. 使用 nelang 补全 nelang 的标准库
|
|
|
-7. 至此 nelang 可以脱离原版易语言, 实现自举, 得益于 llvm, 现在 nelang 可以运行在三大系统, 多种架构了.
|
|
|
+## LLVM IR 生成
|
|
|
|
|
|
-这个科学计算器语言就告一段落了, 到现在我还没有给它起一个名字(
|
|
|
+> python3.9
|
|
|
|
|
|
-### 可以从本节到达的其他方向
|
|
|
+```python
|
|
|
|
|
|
-读过这四篇之后, 你应该可以很简单地把易语言子集静态编译出去了, 如果你感兴趣的话, 不如来试试?
|
|
|
+```
|