@@ -85,6 +85,13 @@ func (vm *Vm) EXTEND(items py.Tuple) {
8585 vm .frame .Stack = append (vm .frame .Stack , items ... )
8686}
8787
88+ // Push items to top of vm stack in reverse order
89+ func (vm * Vm ) EXTEND_REVERSED (items py.Tuple ) {
90+ start := len (vm .frame .Stack )
91+ vm .frame .Stack = append (vm .frame .Stack , items ... )
92+ py .Tuple (vm .frame .Stack [start :]).Reverse ()
93+ }
94+
8895// Adds a traceback to the exc passed in for the current vm state
8996func (vm * Vm ) AddTraceback (exc * py.ExceptionInfo ) {
9097 exc .Traceback = & py.Traceback {
@@ -473,7 +480,11 @@ func do_STORE_SUBSCR(vm *Vm, arg int32) {
473480// Implements del TOS1[TOS].
474481func do_DELETE_SUBSCR (vm * Vm , arg int32 ) {
475482 defer vm .CheckException ()
476- vm .NotImplemented ("DELETE_SUBSCR" , arg )
483+ sub := vm .TOP ()
484+ container := vm .SECOND ()
485+ vm .DROPN (2 )
486+ /* del v[w] */
487+ py .DelItem (container , sub )
477488}
478489
479490// Miscellaneous opcodes.
@@ -513,6 +524,52 @@ func do_CONTINUE_LOOP(vm *Vm, target int32) {
513524 vm .frame .Lasti = vm .frame .Block .Handler
514525}
515526
527+ // Iterate v argcnt times and store the results on the stack (via decreasing
528+ // sp). Return 1 for success, 0 if error.
529+ //
530+ // If argcntafter == -1, do a simple unpack. If it is >= 0, do an unpack
531+ // with a variable target.
532+ func unpack_iterable (vm * Vm , v py.Object , argcnt int , argcntafter int , sp int ) {
533+ it := py .Iter (v )
534+ i := 0
535+ for i = 0 ; i < argcnt ; i ++ {
536+ w , finished := py .Next (it )
537+ if finished != nil {
538+ /* Iterator done, via error or exhaustion. */
539+ panic (py .ExceptionNewf (py .ValueError , "need more than %d value(s) to unpack" , i ))
540+ }
541+ sp --
542+ vm .frame .Stack [sp ] = w
543+ }
544+
545+ if argcntafter == - 1 {
546+ /* We better have exhausted the iterator now. */
547+ _ , finished := py .Next (it )
548+ if finished != nil {
549+ return
550+ }
551+ panic (py .ExceptionNewf (py .ValueError , "too many values to unpack (expected %d)" , argcnt ))
552+ }
553+
554+ l := py .SequenceList (it )
555+ sp --
556+ vm .frame .Stack [sp ] = l
557+ i ++
558+
559+ ll := l .Len ()
560+ if ll < argcntafter {
561+ panic (py .ExceptionNewf (py .ValueError , "need more than %d values to unpack" , argcnt + ll ))
562+ }
563+
564+ /* Pop the "after-variable" args off the list. */
565+ for j := argcntafter ; j > 0 ; j -- {
566+ sp --
567+ vm .frame .Stack [sp ] = l .M__getitem__ (py .Int (ll - j ))
568+ }
569+ /* Resize the list. */
570+ l .Resize (ll - argcntafter )
571+ }
572+
516573// Implements assignment with a starred target: Unpacks an iterable in
517574// TOS into individual values, where the total number of values can be
518575// smaller than the number of items in the iterable: one the new
@@ -523,7 +580,13 @@ func do_CONTINUE_LOOP(vm *Vm, target int32) {
523580// resulting values are put onto the stack right-to-left.
524581func do_UNPACK_EX (vm * Vm , counts int32 ) {
525582 defer vm .CheckException ()
526- vm .NotImplemented ("UNPACK_EX" , counts )
583+ before := int (counts & 0xFF )
584+ after := int (counts >> 8 )
585+ totalargs := 1 + before + after
586+ seq := vm .POP ()
587+ sp := len (vm .frame .Stack )
588+ vm .EXTEND (make ([]py.Object , totalargs ))
589+ unpack_iterable (vm , seq , before , after , sp + totalargs )
527590}
528591
529592// Calls set.add(TOS1[-i], TOS). Used to implement set comprehensions.
@@ -571,23 +634,21 @@ func do_RETURN_VALUE(vm *Vm, arg int32) {
571634
572635// Pops TOS and delegates to it as a subiterator from a generator.
573636func do_YIELD_FROM (vm * Vm , arg int32 ) {
574- defer func () {
575- if r := recover (); r != nil {
576- if vm .catchStopIteration (r ) {
577- // No extra action needed
578- }
579- }
580- }()
637+ defer vm .CheckException ()
581638
582639 var retval py.Object
640+ var finished py.Object
583641 u := vm .POP ()
584642 x := vm .TOP ()
585643 // send u to x
586644 if u == py .None {
587- retval = py .Next (x )
645+ retval , finished = py .Next (x )
588646 } else {
589647 retval = py .Send (x , u )
590648 }
649+ if finished != nil {
650+ return
651+ }
591652 // x remains on stack, retval is value to be yielded
592653 // FIXME vm.frame.Stacktop = stack_pointer
593654 //why = exitYield
@@ -756,19 +817,16 @@ func do_DELETE_NAME(vm *Vm, namei int32) {
756817func do_UNPACK_SEQUENCE (vm * Vm , count int32 ) {
757818 defer vm .CheckException ()
758819 it := vm .POP ()
759- i := count
760- items := make (py.Tuple , count )
761- py .Iterate (it , func (item py.Object ) {
762- i --
763- if i < 0 {
764- panic (py .ExceptionNewf (py .ValueError , "Too many values to unpack (expected %d)" , count ))
765- }
766- items [i ] = item
767- })
768- if i != 0 {
769- panic (py .ExceptionNewf (py .ValueError , "Need more than %d values to unpack (expected %d)" , count - i , count ))
820+ args := int (count )
821+ if tuple , ok := it .(py.Tuple ); ok && len (tuple ) == args {
822+ vm .EXTEND_REVERSED (tuple )
823+ } else if list , ok := it .(* py.List ); ok && list .Len () == args {
824+ vm .EXTEND_REVERSED (list .Items )
825+ } else {
826+ sp := len (vm .frame .Stack )
827+ vm .EXTEND (make ([]py.Object , args ))
828+ unpack_iterable (vm , it , args , - 1 , sp + args )
770829 }
771- vm .EXTEND (items )
772830}
773831
774832// Implements TOS.name = TOS1, where namei is the index of name in
@@ -1018,16 +1076,14 @@ func do_JUMP_ABSOLUTE(vm *Vm, target int32) {
10181076// iterator indicates it is exhausted TOS is popped, and the bytecode
10191077// counter is incremented by delta.
10201078func do_FOR_ITER (vm * Vm , delta int32 ) {
1021- defer func () {
1022- if r := recover (); r != nil {
1023- if vm .catchStopIteration (r ) {
1024- vm .DROP ()
1025- vm .frame .Lasti += delta
1026- }
1027- }
1028- }()
1029- r := py .Next (vm .TOP ())
1030- vm .PUSH (r )
1079+ defer vm .CheckException ()
1080+ r , finished := py .Next (vm .TOP ())
1081+ if finished != nil {
1082+ vm .DROP ()
1083+ vm .frame .Lasti += delta
1084+ } else {
1085+ vm .PUSH (r )
1086+ }
10311087}
10321088
10331089// Loads the global named co_names[namei] onto the stack.
0 commit comments