2009-09-26 14 views
10

Tôi muốn hack xung quanh với trình thông dịch Python và thử tạo một DSL nhỏ. Có bất kỳ mô-đun mà tôi có thể làm một cái gì đó như mã lý thuyết này (tương tự như cây biểu hiện LINQ)?Có cách nào để tạo mã bytecode bằng Python không?

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

Hoặc sẽ dễ dàng hơn khi chỉ tạo mã nguồn Python? Điều này có thể được thực hiện dễ dàng hơn bằng cách sử dụng C hoặc SWIG hoặc Cython?

+0

Với sức mạnh biểu cảm to lớn của các ngôn ngữ OO (đặc biệt là Python) DSL là khá ngớ ngẩn. Chỉ cần viết Python. Nếu bạn cung cấp cho mình các định nghĩa lớp tốt, bạn có một Python "giống như DSL" và không cần điều này. –

Trả lời

10

Làm việc qua ast và biên dịch cây thành bytecode, như một câu trả lời khác gợi ý, có lẽ là đơn giản nhất; tạo ra các nguồn và biên dịch chúng, gần như là tốt.

Tuy nhiên, để khám phá các cách tiếp cận cấp thấp hơn, hãy xem các liên kết từ this page; Tôi đã tìm thấy byteplay đặc biệt hữu ích (hiện không hoạt động trên 2,6 cũng không 3. *, chỉ có 2,4 hoặc 2,5, nhưng tôi nghĩ rằng sửa chữa nó cho 2,6 nên được dễ dàng, như hiện đang thảo luận trong theo dõi của nó). Tôi đã không sử dụng tính năng tương tự như vậy của Phil Eby BytecodeAssembler, nhưng với danh tiếng của tác giả tôi chắc chắn nó đáng để kiểm tra nó!

+0

+1 Liên kết đẹp :) –

+0

Câu trả lời tuyệt vời như mọi khi. :-) –

0

Kiểm tra các mô-đun disassembler tìm thấy ở đây:

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

+0

Điều duy nhất là tôi muốn lắp ráp bytecode, không * dis * lắp ráp nó. :-) –

+0

ahh điểm tốt, xin lỗi mà;) Tuy nhiên điều tốt đẹp về mô-đun tháo rời là nó cho phép bạn nhìn vào bytecode được tạo ra cũng như đưa ra các chi tiết cụ thể cho các hướng dẫn bytecode. – Nope

5

Trong Python 2.x, bạn sẽ thường tiếp cận này với compiler moduleast sub-mô-đun của nó (nhưng lưu ý mô-đun này không được chấp kể từ phiên bản 2.6). Trong Python 3.X, bạn sẽ chỉ sử dụng ast.

Cả hai đều cung cấp chức năng compile() sẽ chuyển từ nguồn/AST thành "đối tượng mã có thể được thực hiện bởi câu lệnh exec hoặc eval()".

1

Fernando Meyer recently wrote a blog post giải thích cách sử dụng chỉ thị # coding để chỉ định các tiện ích mở rộng của riêng bạn cho Python. Ví dụ (định nghĩa định dạng thực tế là trong 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) 
2

Nó dễ dàng hơn để tạo ra mã Python và chạy nó. Nếu bạn làm điều đó bạn cũng có thể gỡ lỗi nó dễ dàng hơn vì có nguồn thực sự cho trình gỡ lỗi hiển thị. Xem thêm bài báo của Malte Borchs trong số tháng 7 của tạp chí Python, nơi anh nói về điều này trong số những thứ khác.

1

Cập nhật cho Python3 - cũng có trình biên tập rất thú vị zachariahreed/byteasm.

Thực ra, người duy nhất làm việc cho tôi ở Py3. Nó có rất tốt đẹp & API sạch:

>>> 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)