Skip to content

Commit 55fd328

Browse files
committed
Implement add and subtract
1 parent d30fc55 commit 55fd328

File tree

3 files changed

+142
-9
lines changed

3 files changed

+142
-9
lines changed

py/arithmetic.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Arithmetic operations
2+
3+
package py
4+
5+
import (
6+
"fmt"
7+
)
8+
9+
// Add two python objects together returning an Object
10+
//
11+
// Will raise TypeError if can't be added
12+
func Add(a, b Object) Object {
13+
// Try using a to add
14+
A, ok := a.(I__add__)
15+
if ok {
16+
res := A.M__add__(b)
17+
if res != NotImplemented {
18+
return res
19+
}
20+
}
21+
22+
// Now using b to radd if different in type to a
23+
if a.Type() != b.Type() {
24+
B, ok := b.(I__radd__)
25+
if ok {
26+
res := B.M__radd__(a)
27+
if res != NotImplemented {
28+
return res
29+
}
30+
}
31+
}
32+
33+
// FIXME should be TypeError
34+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for +: '%s' and '%s'", a.Type().Name, b.Type().Name))
35+
}
36+
37+
// Inplace add
38+
func Iadd(a, b Object) Object {
39+
A, ok := a.(I__iadd__)
40+
if ok {
41+
res := A.M__iadd__(b)
42+
if res != NotImplemented {
43+
return res
44+
}
45+
}
46+
return Add(a, b)
47+
}
48+
49+
// Subtract two python objects together returning an Object
50+
//
51+
// Will raise TypeError if can't be subtracted
52+
func Sub(a, b Object) Object {
53+
// Try using a to sub
54+
A, ok := a.(I__sub__)
55+
if ok {
56+
res := A.M__sub__(b)
57+
if res != NotImplemented {
58+
return res
59+
}
60+
}
61+
62+
// Now using b to rsub if different in type to a
63+
if a.Type() != b.Type() {
64+
B, ok := b.(I__rsub__)
65+
if ok {
66+
res := B.M__rsub__(a)
67+
if res != NotImplemented {
68+
return res
69+
}
70+
}
71+
}
72+
73+
// FIXME should be TypeError
74+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for -: '%s' and '%s'", a.Type().Name, b.Type().Name))
75+
}
76+
77+
// Inplace sub
78+
func Isub(a, b Object) Object {
79+
A, ok := a.(I__isub__)
80+
if ok {
81+
res := A.M__isub__(b)
82+
if res != NotImplemented {
83+
return res
84+
}
85+
}
86+
return Sub(a, b)
87+
}

py/int.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,41 @@ func (o *BigInt) Type() *Type {
2626

2727
// Make sure it satisfies the interface
2828
var _ Object = (*BigInt)(nil)
29+
30+
// Arithmetic
31+
32+
func (a Int) M__add__(other Object) Object {
33+
switch b := other.(type) {
34+
case Int:
35+
return Int(a + b)
36+
}
37+
return NotImplemented
38+
}
39+
40+
func (a Int) M__radd__(other Object) Object {
41+
return a.M__add__(other)
42+
}
43+
44+
func (a Int) M__iadd__(other Object) Object {
45+
return a.M__add__(other)
46+
}
47+
48+
func (a Int) M__sub__(other Object) Object {
49+
switch b := other.(type) {
50+
case Int:
51+
return Int(a - b)
52+
}
53+
return NotImplemented
54+
}
55+
56+
func (b Int) M__rsub__(other Object) Object {
57+
switch a := other.(type) {
58+
case Int:
59+
return Int(b - a)
60+
}
61+
return NotImplemented
62+
}
63+
64+
func (a Int) M__isub(other Object) Object {
65+
return a.M__sub__(other)
66+
}

vm/eval.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,17 +141,16 @@ func do_BINARY_MODULO(vm *Vm, arg int32) {
141141

142142
// Implements TOS = TOS1 + TOS.
143143
func do_BINARY_ADD(vm *Vm, arg int32) {
144-
// FIXME not a very good implementation ;-)
145-
b := vm.POP().(py.Int)
146-
a := vm.POP().(py.Int)
147-
c := a + b
148-
vm.PUSH(py.Int(c))
149-
vm.NotImplemented("BINARY_ADD", arg)
144+
b := vm.POP()
145+
a := vm.POP()
146+
vm.PUSH(py.Add(a, b))
150147
}
151148

152149
// Implements TOS = TOS1 - TOS.
153150
func do_BINARY_SUBTRACT(vm *Vm, arg int32) {
154-
vm.NotImplemented("BINARY_SUBTRACT", arg)
151+
b := vm.POP()
152+
a := vm.POP()
153+
vm.PUSH(py.Sub(a, b))
155154
}
156155

157156
// Implements TOS = TOS1[TOS].
@@ -217,12 +216,16 @@ func do_INPLACE_MODULO(vm *Vm, arg int32) {
217216

218217
// Implements in-place TOS = TOS1 + TOS.
219218
func do_INPLACE_ADD(vm *Vm, arg int32) {
220-
vm.NotImplemented("INPLACE_ADD", arg)
219+
b := vm.POP()
220+
a := vm.POP()
221+
vm.PUSH(py.Iadd(a, b))
221222
}
222223

223224
// Implements in-place TOS = TOS1 - TOS.
224225
func do_INPLACE_SUBTRACT(vm *Vm, arg int32) {
225-
vm.NotImplemented("INPLACE_SUBTRACT", arg)
226+
b := vm.POP()
227+
a := vm.POP()
228+
vm.PUSH(py.Isub(a, b))
226229
}
227230

228231
// Implements in-place TOS = TOS1 << TOS.
@@ -867,5 +870,10 @@ func Run(globals, locals py.StringDict, code *py.Code) (err error) {
867870
vm.extended = false
868871
jumpTable[opcode](vm, arg)
869872
}
873+
if len(vm.stack) != 1 {
874+
fmt.Printf("vmstack = %v\n", vm.stack)
875+
panic("vm stack should only have 1 entry on at this point")
876+
}
877+
// return vm.POP()
870878
return nil
871879
}

0 commit comments

Comments
 (0)