@@ -19,6 +19,19 @@ type Generator struct {
19
19
20
20
var GeneratorType = NewType ("generator" , "generator object" )
21
21
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
+
22
35
// Type of this object
23
36
func (o * Generator ) Type () * Type {
24
37
return GeneratorType
@@ -51,20 +64,7 @@ func (it *Generator) M__iter__() Object {
51
64
//
52
65
// This method is normally called implicitly, e.g. by a for loop, or by the built-in next() function.
53
66
func (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 )
68
68
}
69
69
70
70
// generator.send(value)
@@ -76,8 +76,29 @@ func (it *Generator) M__next__() Object {
76
76
// without yielding another value. When send() is called to start the
77
77
// generator, it must be called with None as the argument, because
78
78
// 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 )
81
102
}
82
103
83
104
// generator.throw(type[, value[, traceback]])
0 commit comments