@@ -263,7 +263,7 @@ func (exec *Execution) assign(target Expression, value Value, env *Env) error {
263263 if fn .Private && ! exec .isCurrentReceiver (obj ) {
264264 return exec .errorAt (t .Pos (), "private method %s" , setterName )
265265 }
266- _ , err := exec .callFunction (fn , obj , []Value {value }, nil , t .Pos ())
266+ _ , err := exec .callFunction (fn , obj , []Value {value }, nil , NewNil (), t .Pos ())
267267 return err
268268 }
269269 if _ , hasGetter := obj .Instance ().Class .Methods [t .Property ]; hasGetter {
@@ -278,7 +278,7 @@ func (exec *Execution) assign(target Expression, value Value, env *Env) error {
278278 if fn .Private && ! exec .isCurrentReceiver (obj ) {
279279 return exec .errorAt (t .Pos (), "private method %s" , setterName )
280280 }
281- _ , err := exec .callFunction (fn , obj , []Value {value }, nil , t .Pos ())
281+ _ , err := exec .callFunction (fn , obj , []Value {value }, nil , NewNil (), t .Pos ())
282282 return err
283283 }
284284 if _ , hasGetter := cl .ClassMethods [t .Property ]; hasGetter {
@@ -531,6 +531,8 @@ func (exec *Execution) evalExpressionWithAuto(expr Expression, env *Env, autoCal
531531 return exec .evalCallExpr (e , env )
532532 case * BlockLiteral :
533533 return exec .evalBlockLiteral (e , env )
534+ case * YieldExpr :
535+ return exec .evalYield (e , env )
534536 default :
535537 return NewNil (), exec .errorAt (expr .Pos (), "unsupported expression" )
536538 }
@@ -556,10 +558,7 @@ func (exec *Execution) invokeCallable(callee Value, receiver Value, args []Value
556558 switch callee .Kind () {
557559 case KindFunction :
558560 fn := callee .Function ()
559- if block .Kind () != KindNil {
560- return NewNil (), exec .errorAt (pos , "script functions do not accept blocks" )
561- }
562- return exec .callFunction (fn , receiver , args , kwargs , pos )
561+ return exec .callFunction (fn , receiver , args , kwargs , block , pos )
563562 case KindBuiltin :
564563 result , err := callee .Builtin ().Fn (exec , receiver , args , kwargs , block )
565564 if err != nil {
@@ -571,11 +570,12 @@ func (exec *Execution) invokeCallable(callee Value, receiver Value, args []Value
571570 }
572571}
573572
574- func (exec * Execution ) callFunction (fn * ScriptFunction , receiver Value , args []Value , kwargs map [string ]Value , pos Position ) (Value , error ) {
573+ func (exec * Execution ) callFunction (fn * ScriptFunction , receiver Value , args []Value , kwargs map [string ]Value , block Value , pos Position ) (Value , error ) {
575574 callEnv := newEnv (fn .Env )
576575 if receiver .Kind () != KindNil {
577576 callEnv .Define ("self" , receiver )
578577 }
578+ callEnv .Define ("__block__" , block )
579579 if err := exec .bindFunctionArgs (fn , callEnv , args , kwargs , pos ); err != nil {
580580 return NewNil (), err
581581 }
@@ -729,6 +729,22 @@ func (exec *Execution) callBlock(block Value, args []Value) (Value, error) {
729729 return val , nil
730730}
731731
732+ func (exec * Execution ) evalYield (expr * YieldExpr , env * Env ) (Value , error ) {
733+ block , ok := env .Get ("__block__" )
734+ if ! ok || block .Kind () == KindNil {
735+ return NewNil (), exec .errorAt (expr .Pos (), "no block given" )
736+ }
737+ var args []Value
738+ for _ , arg := range expr .Args {
739+ val , err := exec .evalExpression (arg , env )
740+ if err != nil {
741+ return NewNil (), err
742+ }
743+ args = append (args , val )
744+ }
745+ return exec .callBlock (block , args )
746+ }
747+
732748func (exec * Execution ) evalRangeExpr (expr * RangeExpr , env * Env ) (Value , error ) {
733749 startVal , err := exec .evalExpression (expr .Start , env )
734750 if err != nil {
@@ -829,13 +845,10 @@ func (exec *Execution) getMember(obj Value, property string, pos Position) (Valu
829845 cl := obj .Class ()
830846 if property == "new" {
831847 return NewAutoBuiltin (cl .Name + ".new" , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
832- if block .Kind () != KindNil {
833- return NewNil (), fmt .Errorf ("script functions do not accept blocks" )
834- }
835848 inst := & Instance {Class : cl , Ivars : make (map [string ]Value )}
836849 instVal := NewInstance (inst )
837850 if initFn , ok := cl .Methods ["initialize" ]; ok {
838- if _ , err := exec .callFunction (initFn , instVal , args , kwargs , pos ); err != nil {
851+ if _ , err := exec .callFunction (initFn , instVal , args , kwargs , block , pos ); err != nil {
839852 return NewNil (), err
840853 }
841854 }
@@ -847,10 +860,7 @@ func (exec *Execution) getMember(obj Value, property string, pos Position) (Valu
847860 return NewNil (), exec .errorAt (pos , "private method %s" , property )
848861 }
849862 return NewAutoBuiltin (cl .Name + "." + property , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
850- if block .Kind () != KindNil {
851- return NewNil (), fmt .Errorf ("script functions do not accept blocks" )
852- }
853- return exec .callFunction (fn , obj , args , kwargs , pos )
863+ return exec .callFunction (fn , obj , args , kwargs , block , pos )
854864 }), nil
855865 }
856866 if val , ok := cl .ClassVars [property ]; ok {
@@ -867,10 +877,7 @@ func (exec *Execution) getMember(obj Value, property string, pos Position) (Valu
867877 return NewNil (), exec .errorAt (pos , "private method %s" , property )
868878 }
869879 return NewAutoBuiltin (inst .Class .Name + "#" + property , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
870- if block .Kind () != KindNil {
871- return NewNil (), fmt .Errorf ("script functions do not accept blocks" )
872- }
873- return exec .callFunction (fn , obj , args , kwargs , pos )
880+ return exec .callFunction (fn , obj , args , kwargs , block , pos )
874881 }), nil
875882 }
876883 if val , ok := inst .Ivars [property ]; ok {
@@ -1149,7 +1156,7 @@ func arrayMember(array Value, property string) (Value, error) {
11491156 return NewInt (int64 (len (receiver .Array ()))), nil
11501157 }), nil
11511158 case "each" :
1152- return NewBuiltin ("array.each" , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
1159+ return NewAutoBuiltin ("array.each" , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
11531160 if block .Block () == nil {
11541161 return NewNil (), fmt .Errorf ("array.each requires a block" )
11551162 }
@@ -1161,7 +1168,7 @@ func arrayMember(array Value, property string) (Value, error) {
11611168 return receiver , nil
11621169 }), nil
11631170 case "map" :
1164- return NewBuiltin ("array.map" , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
1171+ return NewAutoBuiltin ("array.map" , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
11651172 if block .Block () == nil {
11661173 return NewNil (), fmt .Errorf ("array.map requires a block" )
11671174 }
@@ -1177,7 +1184,7 @@ func arrayMember(array Value, property string) (Value, error) {
11771184 return NewArray (result ), nil
11781185 }), nil
11791186 case "select" :
1180- return NewBuiltin ("array.select" , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
1187+ return NewAutoBuiltin ("array.select" , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
11811188 if block .Block () == nil {
11821189 return NewNil (), fmt .Errorf ("array.select requires a block" )
11831190 }
@@ -1195,7 +1202,7 @@ func arrayMember(array Value, property string) (Value, error) {
11951202 return NewArray (out ), nil
11961203 }), nil
11971204 case "reduce" :
1198- return NewBuiltin ("array.reduce" , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
1205+ return NewAutoBuiltin ("array.reduce" , func (exec * Execution , receiver Value , args []Value , kwargs map [string ]Value , block Value ) (Value , error ) {
11991206 if block .Block () == nil {
12001207 return NewNil (), fmt .Errorf ("array.reduce requires a block" )
12011208 }
0 commit comments