Hatena::ブログ(Diary)

西尾泰和のはてなダイアリー

2010-08-24

Pythonいじり

オブジェクトの生成を表示させようとして予期せず対話的に入力したトークンが出るようになったRubyいじりなんだけども、これって「プログラミング言語はコードの文字列からトークン列、構文木バイトコードを経て実行されている」って授業をする際に実際に実物を見ながら実行できていいんじゃないかなーなどと考えて、で、こうなった。

build$ PYTHON_AUTODIS=1 ./python.exe
Python 2.7rc2+ (trunk:82245M, Aug 24 2010, 23:25:27) 
[GCC 4.2.1 (Apple Inc. build 5659)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1
===== DIS =====
  1           0 LOAD_CONST               0 (1)
              3 PRINT_EXPR          
              4 LOAD_CONST               1 (None)
              7 RETURN_VALUE        
===== END DIS =====
1
>>> x = 1  
===== DIS =====
  1           0 LOAD_CONST               0 (1)
              3 STORE_NAME               0 (x)
              6 LOAD_CONST               1 (None)
              9 RETURN_VALUE        
===== END DIS =====
>>> x + 1
===== DIS =====
  1           0 LOAD_NAME                0 (x)
              3 LOAD_CONST               0 (1)
              6 BINARY_ADD          
              7 PRINT_EXPR          
              8 LOAD_CONST               1 (None)
             11 RETURN_VALUE        
===== END DIS =====
2

うむうむ。いい感じ。

しかし構文木の表示はうまくいかなかった。

>>> 1
===== AST =====
<_ast.Interactive object at 0x100492150>
===== END AST =====
1

こんな感じになって欲しかったんだけどね。

>>> import compiler
>>> compiler.parse("1")
Module(None, Stmt([Discard(Const(1))]))
>>> compiler.parse("x = 1")
Module(None, Stmt([Assign([AssName('x', 'OP_ASSIGN')], Const(1))]))
>>> compiler.parse("x + 1")
Module(None, Stmt([Discard(Add((Name('x'), Const(1))))]))

変更点はこちら: http://gist.github.com/547651

run_modに渡ってくる内部の構文木はcompiler.parseとかで作れる見やすい構文木じゃないってことなんだな。どうやって間をつなぐか、それとも内部構文木になる前の文字列から直接つくるか。後者が楽だと思うかも知れないけど、斜め読みした感じだと1行入力されるごとにトークナイザがそれを刻んでしまうので誰も入力された文字列の全体を持ってない。自前で取っておくようにするかなぁ。

まあ、続きはまた今度。