Skip to content

Commit 60dd952

Browse files
committed
Make Iter() and Iterator type and implement GET_ITER, FOR_ITER, BUILD_LIST/TUPLE
1 parent acc6057 commit 60dd952

File tree

6 files changed

+109
-8
lines changed

6 files changed

+109
-8
lines changed

‎py/arithmetic.go‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,22 @@ func MakeFloat(a Object) Object{
133133
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for float: '%s'", a.Type().Name))
134134
}
135135

136+
// Iter the python Object returning an Object
137+
//
138+
// Will raise TypeError if Iter can't be run on this object
139+
funcIter(aObject) Object{
140+
141+
ifA, ok:=a.(I__iter__); ok{
142+
res:=A.M__iter__()
143+
ifres!=NotImplemented{
144+
returnres
145+
}
146+
}
147+
148+
// FIXME should be TypeError
149+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for iter: '%s'", a.Type().Name))
150+
}
151+
136152
// Add two python objects together returning an Object
137153
//
138154
// Will raise TypeError if can't be add can't be run on these objects

‎py/gen.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var data = Data{
4040
{Name: "complex", Title: "MakeComplex", Operator: "complex", Unary: true, Conversion: "Complex"},
4141
{Name: "int", Title: "MakeInt", Operator: "int", Unary: true, Conversion: "Int"},
4242
{Name: "float", Title: "MakeFloat", Operator: "float", Unary: true, Conversion: "Float"},
43+
{Name: "iter", Title: "Iter", Operator: "iter", Unary: true},
4344
},
4445
BinaryOps: Ops{
4546
{Name: "add", Title: "Add", Operator: "+", Binary: true},

‎py/list.go‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,25 @@ type List []Object
1010
func (oList) Type() *Type{
1111
returnListType
1212
}
13+
14+
func (tList) M__len__() Object{
15+
returnInt(len(t))
16+
}
17+
18+
func (tList) M__bool__() Object{
19+
iflen(t) >0{
20+
returnTrue
21+
}
22+
returnFalse
23+
}
24+
25+
func (tList) M__iter__() Object{
26+
returnNewIterator(t)
27+
}
28+
29+
// Check interface is satisfied
30+
var_I__len__=List(nil)
31+
var_I__bool__=List(nil)
32+
var_I__iter__=List(nil)
33+
34+
// var _ richComparison = List(nil)

‎py/py.go‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,17 @@ type I__iter__ interface{
546546
M__iter__() Object
547547
}
548548

549+
// The next method for iterators
550+
typeI__next__interface{
551+
M__next__() Object
552+
}
553+
554+
// Interface all iterators must satisfy
555+
typeI_iteratorinterface{
556+
I__iter__
557+
I__next__
558+
}
559+
549560
// Called (if present) by the reversed() built-in to implement reverse
550561
// iteration. It should return a new iterator object that iterates
551562
// over all the objects in the container in reverse order.

‎py/tuple.go‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,25 @@ type Tuple []Object
1010
func (oTuple) Type() *Type{
1111
returnTupleType
1212
}
13+
14+
func (tTuple) M__len__() Object{
15+
returnInt(len(t))
16+
}
17+
18+
func (tTuple) M__bool__() Object{
19+
iflen(t) >0{
20+
returnTrue
21+
}
22+
returnFalse
23+
}
24+
25+
func (tTuple) M__iter__() Object{
26+
returnNewIterator(t)
27+
}
28+
29+
// Check interface is satisfied
30+
var_I__len__=Tuple(nil)
31+
var_I__bool__=Tuple(nil)
32+
var_I__iter__=Tuple(nil)
33+
34+
// var _ richComparison = Tuple(nil)

‎vm/eval.go‎

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,27 +87,27 @@ func do_DUP_TOP_TWO(vm *Vm, arg int32){
8787

8888
// Implements TOS = +TOS.
8989
funcdo_UNARY_POSITIVE(vm*Vm, argint32){
90-
vm.PUSH(py.Pos(vm.POP()))
90+
vm.SET_TOP(py.Pos(vm.TOP()))
9191
}
9292

9393
// Implements TOS = -TOS.
9494
funcdo_UNARY_NEGATIVE(vm*Vm, argint32){
95-
vm.PUSH(py.Neg(vm.POP()))
95+
vm.SET_TOP(py.Neg(vm.TOP()))
9696
}
9797

9898
// Implements TOS = not TOS.
9999
funcdo_UNARY_NOT(vm*Vm, argint32){
100-
vm.PUSH(py.Not(vm.POP()))
100+
vm.SET_TOP(py.Not(vm.TOP()))
101101
}
102102

103103
// Implements TOS = ~TOS.
104104
funcdo_UNARY_INVERT(vm*Vm, argint32){
105-
vm.PUSH(py.Invert(vm.POP()))
105+
vm.SET_TOP(py.Invert(vm.TOP()))
106106
}
107107

108108
// Implements TOS = iter(TOS).
109109
funcdo_GET_ITER(vm*Vm, argint32){
110-
vm.NotImplemented("GET_ITER", arg)
110+
vm.SET_TOP(py.Iter(vm.TOP()))
111111
}
112112

113113
// Binary operations remove the top of the stack (TOS) and the second
@@ -315,7 +315,10 @@ func do_PRINT_EXPR(vm *Vm, arg int32){
315315

316316
// Terminates a loop due to a break statement.
317317
funcdo_BREAK_LOOP(vm*Vm, argint32){
318+
// Jump
318319
vm.frame.Lasti=vm.frame.Block.Handler
320+
// Reset the stack (FIXME?)
321+
vm.stack=vm.stack[:vm.frame.Block.Level]
319322
vm.frame.PopBlock()
320323
}
321324

@@ -505,7 +508,13 @@ func do_LOAD_NAME(vm *Vm, namei int32){
505508
// Creates a tuple consuming count items from the stack, and pushes
506509
// the resulting tuple onto the stack.
507510
funcdo_BUILD_TUPLE(vm*Vm, countint32){
508-
vm.NotImplemented("BUILD_TUPLE", count)
511+
tuple:=make(py.Tuple, count)
512+
p:=len(vm.stack) -int(count)
513+
fori:=rangetuple{
514+
tuple[i] =vm.stack[p+i]
515+
}
516+
vm.DROPN(int(count))
517+
vm.PUSH(tuple)
509518
}
510519

511520
// Works as BUILD_TUPLE, but creates a set.
@@ -515,7 +524,13 @@ func do_BUILD_SET(vm *Vm, count int32){
515524

516525
// Works as BUILD_TUPLE, but creates a list.
517526
funcdo_BUILD_LIST(vm*Vm, countint32){
518-
vm.NotImplemented("BUILD_LIST", count)
527+
list:=make(py.List, count)
528+
p:=len(vm.stack) -int(count)
529+
fori:=rangelist{
530+
list[i] =vm.stack[p+i]
531+
}
532+
vm.DROPN(int(count))
533+
vm.PUSH(list)
519534
}
520535

521536
// Pushes a new dictionary object onto the stack. The dictionary is
@@ -619,7 +634,21 @@ func do_JUMP_ABSOLUTE(vm *Vm, target int32){
619634
// iterator indicates it is exhausted TOS is popped, and the bytecode
620635
// counter is incremented by delta.
621636
funcdo_FOR_ITER(vm*Vm, deltaint32){
622-
vm.NotImplemented("FOR_ITER", delta)
637+
deferfunc(){
638+
ifr:=recover(); r!=nil{
639+
ifex, ok:=r.(*py.Exception); ok&&ex==py.StopIteration{
640+
// StopIteration raised
641+
vm.DROP()
642+
vm.frame.Lasti+=delta
643+
} else{
644+
// re-raise the panic
645+
panic(r)
646+
}
647+
}
648+
}()
649+
it:=vm.TOP().(*py.Iterator)
650+
r:=it.M__next__()
651+
vm.PUSH(r)
623652
}
624653

625654
// Loads the global named co_names[namei] onto the stack.

0 commit comments

Comments
(0)