Python.use(better, src=”PyPy”) #003: クラス pycodegen.Expression
|中級篇|
Python.use(better, src=”PyPy”) # ソースコードの歩き方《復刻版》
ソースコードの歩き方《PyPy1.2》
PyPy1.2 のリリースを機に、PyPy1.1 版を再構成したものです。
※ compiler の傘下にあるモジュールは、PyPy1.1.0 からの変更はありません。
クラス pycodegen.Expression
この先で迷子にならないように、謎を解く鍵を確認しておきます。
$ cat compiler/pycodegen.py
...
def compile(source, filename, mode, flags=None, dont_inherit=None):
...
gen = Expression(source, filename)
...
gen.compile()
# この行間を読み解くのが秘訣 (@.@)
return gen.code
メソッド呼び出し compile() をリターン値にはせずに、属性 .code を参照しているので、メソッド呼び出しの「副作用」が謎を解く鍵になります。そこで、メソッド compile の本体に歩を進めると、
$ cat compiler/pycodegen.py ... class Expression(AbstractCompileMode): mode = "eval" def compile(self): tree = self._get_tree() gen = ExpressionCodeGenerator(tree) self.code = gen.getCode()
確かに、属性 .code を再設定しているのが分かります。
《TIPS》コードの行間を読む:副作用を前提にしたコードは読み辛く、バグの温床になりがちです。その一方で、副作用を暗示した「阿吽の呼吸」を読み解く術も必要です。「アマ」グラマーには諸手を挙げてお勧めできませんが、「プロ」グラマーには「匠」を凝らす術が求められる場面も少なくありません。コードの行間を読めるようになると、ひと味違うプログラミングの「醍醐味」を堪能できるようになります。□
■ 新たな謎の組織(ExpressionCodeGenerator)と出生の秘密
しかし、これですべての謎が解明された訳ではありません。ようやく追いつめた実行犯の背後には、謎の組織 ExpressionCodeGenerator の存在が…。よくある連続ドラマの展開にも似ています。ここでは、副作用をもたらす源泉が、新たな登場人物 gen の背後 getCode に隠されているのが分かります。そして、物語は新たな展開へと続きます。
ところが、その謎解きには新たな鍵 tree が必要です。しかも、その鍵を得るのは、自分 self が属する組織(クラス)を知る必要があります。メソッド _get_tree は、どこに隠されているのでしょう。実は、その鍵は自身のルーツ(先祖)にありました。つまり、親クラス AbstractCompileMode から継承した資産の中に隠されていたのです。
$ cat compiler/pycodegen.py ... class AbstractCompileMode: mode = None # defined by subclass def __init__(self, source, filename): self.source = source self.filename = filename self.code = None def _get_tree(self): tree = parse(self.source, self.mode) misc.set_filename(self.filename, tree) syntax.check(tree) return tree def compile(self): pass # implemented by subclass def getCode(self): return self.code
↑TOP
》作業中です《