12

我想破解 Python 解释器并尝试创建一个小的 DSL 。有没有我可以做类似这个理论代码的模块(类似于 LINQ 表达式树)?

expression_tree = Function(
    Print(
        String('Hello world!')
    )
 )
compile_to_bytecode(expression_tree)

还是只生成 Python 源代码会更容易?使用 C 或 SWIG 或 Cython 可以使这更容易吗?

4

6 回答 6

12

正如另一个答案所暗示的那样,通过ast树并将树编译成字节码可能是最简单的;生成源并编译它们,几乎一样好。

但是,要探索较低级别的方法,请查看此页面中的链接;我发现byteplay特别有用(目前在 2.6 和 3.* 上都不起作用,只有 2.4 或 2.5,但我认为为 2.6 修复它应该很容易,正如目前在其跟踪器中所讨论的那样)。我没有使用过 Phil Eby 的类似功能的BytecodeAssembler,但考虑到作者的声誉,我相信它值得一试!

于 2009-09-27T00:35:35.437 回答
5

在 Python 2.X 中,您通常会使用compiler模块及其ast子模块来处理此问题(但请注意,此模块自 2.6 版以来已弃用)。在 Python 3.X 中,您只需使用ast.

两者都提供了一个compile()函数,该函数将从源代码/AST 转换为“可以由exec语句或eval().

于 2009-09-26T20:07:24.780 回答
2

生成 Python 代码并运行它更容易。如果你这样做,你也可以更容易地调试它,因为调试器有实际的源来显示。另请参阅 Python 杂志 7 月刊中的 Malte Borchs 文章,他在其中谈到了这一点。

于 2009-09-26T21:11:44.930 回答
1

Fernando Meyer 最近写了一篇博文,解释如何使用该# coding指令来指定您自己的 Python 扩展。示例(实际的格式定义在pyspec.pytokenizer.py中):

# coding: pyspec

class Bow:
    def shot(self):
        print "got shot"

    def score(self):
        return 5

describe Bowling:
    it "should score 0 for gutter game":
        bowling = Bow()
        bowling.shot()
        assert that bowling.score.should_be(5)
于 2009-09-26T20:25:00.300 回答
1

更新 Python3 - 还有非常有趣的 assembler zachariahreed/byteasm

实际上是 Py3 中唯一为我工作的人。它有非常漂亮和干净的 API:

>>> import byteasm, dis
>>> b = byteasm.FunctionBuilder()
>>> b.add_positional_arg('x')
>>> b.emit_load_const('Hello!')
>>> b.emit_load_fast('x')
>>> b.emit_build_tuple(2)
>>> b.emit_return_value()
>>> f = b.make('f')
>>> f
<function f at 0xb7012a4c>
>>> dis.dis(f)
  1           0 LOAD_CONST               0 ('Hello!')
              3 LOAD_FAST                0 (x)
              6 BUILD_TUPLE              2
              9 RETURN_VALUE
>>> f(108)
('Hello!', 108)
于 2016-07-21T16:23:55.667 回答
0

查看此处的反汇编模块:

http://docs.python.org/library/dis.html

于 2009-09-26T20:02:45.067 回答