def hanlder(self):
classmembers = self.guessClassmember(klass)
for func in klass.findall('./Stmt/Function/'):
if self.isClassMethod(func):
continue
for assattr in func.findall('.//Assign/AssAttr'):
if self.isClassMemberAssign(assattr, classmembers):
print 'defined at', classmembers[assattr.attrib['attrname']].attrib['lineno']
print 'substitute at', assattr.attrib['lineno']
と書いていたのを
def calc(self):
classmembers = self.guessClassmember(klass)
for func in self.wait('.//Class/Stmt/Function/'):
if self.isClassMethod(func):
continue
for assattr in self.wait('.//Class/Stmt/Function//Assign/AssAttr'):
if self.isClassMemberAssign(assattr, classmembers):
print 'defined at', classmembers[assattr.attrib['attrname']].attrib['lineno']
print 'substitute at', assattr.attrib['lineno']
とかしたい。self.waitは実際にはxpath文字列じゃなくてxpathを与えて作ったhandlerにしないと、methodの評価のタイミングが呼び出されたときなので、xpathがvisitにわたらないので駄目かな?あ~でもcalcに制御がわたってwaitを読んだときにcalcから抜けてhandlerのcallbackでyieldしてforに戻ってくる構造だからなぁ。
pollingするための口と、pollした結果どのhandlerをfireするか決めればいいのか。pollingするとほかのruleのcalcを呼ぶ可能性がある。ひとひねりしないとpollingされる関数が再帰してstack over flowだ。multithreadで書くほうが自然に思えてきた。実際にvisitするobjectがいるthreadがproducerで、handerを登録するruleがいる側がconsumerだ。といいつつも、次にvisitするものは何かをconsumerから教えてもらわないといけない。(ここがyieldになる。)
yieldが戻り先から値を返してくれるとwaitのかわりにyieldしてあげればらくに書けそう。yieldでxpathを受け取り、見つかったときにその関数(calc)を、見つかったnodeとともに返してあげればいい。すくなくとも2.4だとできないのでyieldから戻ってきたときに持たせるvalueを書き込むスペースを用意してあげることになる。美しくないが、複雑なコントロールフローを作るよりはましだ。しかしfor文が
while True:
yield ".//Stmt"
r = getresult()
#do something with r here.
こんな感じになってしまうだろう。かなり個人的な趣味をいうと、PEPで提案されているyieldの括弧のつけ方はきらいだなぁ。yield(42)とかのほうがいい。関数呼び出しっぽいが。しかしexception関係といい、2.4のgeneratorは微妙だね。
あとxpathに先読み否定(要はclassmethodをチェックさせたい)とかあるともうちょっとエレガントになる。まあ、蛇足ですが。
0 件のコメント:
コメントを投稿