@@ -19,6 +19,19 @@ type Generator struct {
1919
2020var GeneratorType = NewType ("generator" , "generator object" )
2121
22+ func init () {
23+ // FIXME would like to do this with introspection
24+ GeneratorType .Dict ["send" ] = NewMethod ("send" , func (self Object , value Object ) Object {
25+ return self .(* Generator ).Send (value )
26+ }, 0 , "send(arg) -> send 'arg' into generator,\n return next yielded value or raise StopIteration." )
27+ GeneratorType .Dict ["throw" ] = NewMethod ("throw" , func (self Object , args Tuple , kwargs StringDict ) Object {
28+ return self .(* Generator ).Throw (args , kwargs )
29+ }, 0 , "throw(typ[,val[,tb]]) -> raise exception in generator,\n return next yielded value or raise StopIteration." )
30+ GeneratorType .Dict ["close" ] = NewMethod ("close" , func (self Object ) Object {
31+ return self .(* Generator ).Close ()
32+ }, 0 , "close() -> raise GeneratorExit inside generator." )
33+ }
34+
2235// Type of this object
2336func (o * Generator ) Type () * Type {
2437 return GeneratorType
@@ -51,20 +64,7 @@ func (it *Generator) M__iter__() Object {
5164//
5265// This method is normally called implicitly, e.g. by a for loop, or by the built-in next() function.
5366func (it * Generator ) M__next__ () Object {
54- it .Running = true
55- res , err := RunFrame (it .Frame )
56- it .Running = false
57- // Push a None on the stack for next time
58- // FIXME this value is the one sent by Send
59- it .Frame .Stack = append (it .Frame .Stack , None )
60- if err != nil {
61- // Propagate the error
62- panic (err )
63- }
64- if it .Frame .Yielded {
65- return res
66- }
67- panic (StopIteration )
67+ return it .Send (None )
6868}
6969
7070// generator.send(value)
@@ -76,8 +76,29 @@ func (it *Generator) M__next__() Object {
7676// without yielding another value. When send() is called to start the
7777// generator, it must be called with None as the argument, because
7878// there is no yield expression that could receive the value.
79- func (it * Generator ) Send (value Object ) Object {
80- panic ("generator send not implemented" )
79+ func (it * Generator ) Send (arg Object ) Object {
80+ if it .Running {
81+ panic (ExceptionNewf (ValueError , "generator already executing" ))
82+ }
83+ if it .Frame .Lasti == 0 {
84+ if arg != None {
85+ panic (ExceptionNewf (TypeError , "can't send non-None value to a just-started generator" ))
86+ }
87+ } else {
88+ // Push arg onto the frame's value stack
89+ it .Frame .Stack = append (it .Frame .Stack , arg )
90+ }
91+ it .Running = true
92+ res , err := RunFrame (it .Frame )
93+ it .Running = false
94+ if err != nil {
95+ // Propagate the error
96+ panic (err )
97+ }
98+ if it .Frame .Yielded {
99+ return res
100+ }
101+ panic (StopIteration )
81102}
82103
83104// generator.throw(type[, value[, traceback]])
0 commit comments