-
Notifications
You must be signed in to change notification settings - Fork 647
Implement generator.throw() #369
base: master
Are you sure you want to change the base?
Conversation
compiler/expr_visitor.py
Outdated
@@ -379,6 +379,10 @@ def visit_Yield(self, node): | |||
self.writer.write('return {}, nil'.format(value.expr)) | |||
self.writer.write_label(resume_label) | |||
result = self.block.alloc_temp() | |||
self.writer.write(textwrap.dedent("""\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trotterdylan not sure if try/except
block is able to catch this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you want to do:
if πRaised != nil {
πE = πRaised
πRaised = nil
if πE != nil {
continue
}
}
You could also merge the write() call below into this:
self.writer.write_tmpl(textwrap.dedent("""\
if πRaised != nil {
\tπE = πRaised
\tπRaised = nil
\tif πE != nil {
\t\tcontinue
\t}
}
$result = πSent"""), result=result.name)
runtime/generator.go
Outdated
raised = f.RaiseType(TypeErrorType, "can't send non-None value to a just-started generator") | ||
} else { | ||
func (g *Generator) resume(f *Frame, sendValue *Object, raisedValue *BaseException) (*Object, *BaseException) { | ||
if raisedValue == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@trotterdylan do we still need to update g.state
while having throw
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think you can remove this check and update g.state normally for throw.
@trotterdylan what is the best approach to test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
edit: sorry, accidentally submitted before I was finished
Thinking about this some more, maybe it's better to test in testing/generator_test.py instead of trying to do this in a stmt_test.py.
compiler/stmt.py
Outdated
@@ -590,9 +590,14 @@ def visit_function_inline(self, node): | |||
self.writer.write('var πE *πg.BaseException; _ = πE') | |||
if func_block.is_generator: | |||
self.writer.write( | |||
'return πg.NewGenerator(πF, func(πSent *πg.Object) ' | |||
'return πg.NewGenerator(πF, ' | |||
'func(πSent *πg.Object, πRaised *πg.BaseException) ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe call it πThrown
compiler/expr_visitor.py
Outdated
@@ -379,6 +379,10 @@ def visit_Yield(self, node): | |||
self.writer.write('return {}, nil'.format(value.expr)) | |||
self.writer.write_label(resume_label) | |||
result = self.block.alloc_temp() | |||
self.writer.write(textwrap.dedent("""\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you want to do:
if πRaised != nil {
πE = πRaised
πRaised = nil
if πE != nil {
continue
}
}
You could also merge the write() call below into this:
self.writer.write_tmpl(textwrap.dedent("""\
if πRaised != nil {
\tπE = πRaised
\tπRaised = nil
\tif πE != nil {
\t\tcontinue
\t}
}
$result = πSent"""), result=result.name)
runtime/generator.go
Outdated
|
||
func generatorThrow(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) { | ||
argc := len(args) | ||
if argc == 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can leave out the argc == 1
and argc > 4
checks here. If argc < 2 || argc > 4
then the checkMethodArgs will fail because it won't match expectedTypes. The error message isn't ideal in that case, but I think the simplicity warrants it.
runtime/generator.go
Outdated
raised = f.RaiseType(TypeErrorType, "can't send non-None value to a just-started generator") | ||
} else { | ||
func (g *Generator) resume(f *Frame, sendValue *Object, raisedValue *BaseException) (*Object, *BaseException) { | ||
if raisedValue == nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think you can remove this check and update g.state normally for throw.
@trotterdylan generator cannot catch the thrown exception, I should check more. |
@trotterdylan sorry for the long delay. so the problem is
and Grumpy generated code:
it seems OK to me, do you see anything improper? |
No description provided.