首页 > 解决方案 > 如何编译一个小的 DSL?

问题描述

我正在为 Python (3.x) 中的应用程序编写一个小的领域特定语言。目前该语言使用 Python 的解释器来运行脚本,但是我希望能够将代码编译成 Python 的字节码,以便我可以将它作为普通的 Python 模块导入。

有没有什么方法可以实现这一点,而无需将我的 DSL 代码转换为 Python 语法的步骤?

标签: pythondsl

解决方案


为了编译成 Python 的字节码,你默认需要两(三)个东西:

  1. 可以根据Python 语法解析的兼容 Python 代码

    如果不是为了使用,那么至少要与 AST 进行比较,如果你正确生成它,如果有东西丢失等等

(1.5) 您的 DSL 拆分为抽象语法树 (AST) - 这是 Python 在您运行(即甚至导入)代码/文件时默认执行的操作。

  1. Python 的 VM 字节码编译器

您可以做的是将您的 DSL“编译”(翻译)为 AST 或正确的 Python 代码,然后您可以从那里使 Python 解释器(用于代码)或 Python 编译器(用于 AST)做您想做的事情,例如调用Python 的 C API 即使用 Python 作为 C 库,而不是将解释器作为二进制文件调用。

对于 C API从这里开始,但目前我找不到编译器的任何参考,因此以“虚拟”方式,您可以简单地包含compile.h警告),然后使用compile.c库中公开的函数。

如果没有,您将需要手动编译 Python(甚至可能对其进行修补),因此这些符号会被公开并且您可以使用它们。但是,这种方法有一个问题,那就是 - 不使用公共 Python 的 C API 最终可能会破坏您的功能(符号可能会更改名称、功能或干脆消失),因此如果选择这种方法,请编写测试并使用特定的提交,所以您“密封”您使用的版本,并在一段时间后提交,运行测试并查看它是否中断(然后修复)。

此外,这是一个混乱的话题,因为没有很多人尝试更改或至少访问默认编译器,但是:

除此之外,请尝试联系 CPython 和 PyPy 维护者:

就像 PyPy 进行即时编译一样。但是 afaik他们的代码没有漂亮的界面,所以tar这里grep -r '<keyword [keyword ...]> <file or folder>是你的助手。


推荐阅读