2009-09-26 4 views
10

저는 파이썬 인터프리터를 해킹하고 작은 DSL을 만들려고합니다. 이 이론적 인 코드 (LINQ 표현식 트리와 유사)와 같은 것을 할 수있는 모듈이 있습니까?프로그래밍 방식으로 파이썬 바이트 코드를 생성 할 수있는 방법이 있습니까?

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

아니면 그냥 파이썬 소스 코드를 생성하는 것이 더 쉬울까요? C 또는 SWIG 또는 Cython을 사용하면 더 쉽게 만들 수 있습니까? 디스어셈블러 모듈 밖으로

+0

: 그것은 아주 좋은 & 깨끗한 API를 가지고있다. 그냥 파이썬을 작성하십시오. 좋은 클래스 정의를 제공한다면 "DSL과 비슷한"파이썬이 필요하며 필요하지 않습니다. –

답변

10

ast을 통해 작업하고 트리를 바이트 코드로 컴파일하는 것은 다른 대답에서 알 수 있듯이, 아마도 가장 단순 할 것입니다. 소스를 생성하고 컴파일하는 것은 거의 비슷합니다.

그러나 하위 수준의 접근 방식을 탐구하려면 this page; 나는 byteplay이 특히 유용하다는 것을 발견했다. (현재 2.6이나 3에서도 작동하지 않는다. *, 2.4 또는 2.5 만, 2.6 용으로 고쳐야한다고 생각한다. 나는 필 이비 (Phil Eby)의 비슷한 기능인 BytecodeAssembler을 사용하지 않았지만 필자의 평판을 받으면 체크 아웃 할 가치가 있다고 확신한다!

+0

+1 좋은 링크 :) –

+0

언제나처럼 위대한 답. :-) –

0

확인은 여기에서 찾을 :

파이썬 2.X에서

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

+0

유일한 것은 내가 바이트 코드를 조립하고 싶지 않다는 것입니다. :-) –

+0

ahh 좋은 지적, 불쌍한 한판 승부;) 그러나 disassembler 모듈에 대한 좋은 점은 바이트 코드 지시 사항을 구체적으로 설명 할 수있을뿐 아니라 생성 된 바이트 코드도 살펴볼 수 있다는 것입니다. – Nope

5

, 당신은 일반적으로 compiler moduleast 서브 모듈이 접근 (하지만이 모듈을주의 할 버전 이후 사용되지 않습니다 2.6). Python 3.X에서는 ast 만 사용합니다.

두 가지 모두 소스/AST에서 exec 문 또는 eval() 문에 의해 실행될 수있는 코드 개체로 이동하는 compile() 함수를 제공합니다.

1

Fernando Meyer recently wrote a blog post# 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) 
2

그것은 파이썬 코드를 생성하고 실행하는 것이 더 쉽습니다. 그렇게하면 디버거가 표시 될 실제 소스가 있으므로 디버그도 더 쉽게 할 수 있습니다. Python 잡지 7 월호의 Malte Borchs 기사를 참조하십시오. 여기서 그는이 점에 대해 이야기합니다.

1

Python3 용 업데이트 - 매우 흥미로운 어셈블러 인 zachariahreed/byteasm도 있습니다.

저는 실제로 Py3에서 저만 작동합니다. (특히 파이썬) OO 언어의 엄청난 표현력을 감안할 DSL 상당히 바보

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