8000 Implement Neg, Pos, Abs, Invert, MakeBool/Int/Float/Complex and Index · go-python/gpython@44e760e · GitHub
[go: up one dir, main page]

Skip to content

Commit 44e760e

Browse files
committed
Implement Neg, Pos, Abs, Invert, MakeBool/Int/Float/Complex and Index
1 parent 8131a31 commit 44e760e

File tree

7 files changed

+307
-6
lines changed

7 files changed

+307
-6
lines changed

py/arithmetic.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,118 @@ import (
99
"fmt"
1010
)
1111

12+
// Neg the python Object returning an Object
13+
//
14+
// Will raise TypeError if Neg can't be run on this object
15+
func Neg(a Object) Object {
16+
A, ok := a.(I__neg__)
17+
if ok {
18+
res := A.M__neg__()
19+
if res != NotImplemented {
20+
return res
21+
}
22+
}
23+
24+
// FIXME should be TypeError
25+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for -: '%s'", a.Type().Name))
26+
}
27+
28+
// Pos the python Object returning an Object
29+
//
30+
// Will raise TypeError if Pos can't be run on this object
31+
func Pos(a Object) Object {
32+
A, ok := a.(I__pos__)
33+
if ok {
34+
res := A.M__pos__()
35+
if res != NotImplemented {
36+
return res
37+
}
38+
}
39+
40+
// FIXME should be TypeError
41+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for +: '%s'", a.Type().Name))
42+
}
43+
44+
// Abs the python Object returning an Object
45+
//
46+
// Will raise TypeError if Abs can't be run on this object
47+
func Abs(a Object) Object {
48+
A, ok := a.(I__abs__)
49+
if ok {
50+
res := A.M__abs__()
51+
if res != NotImplemented {
52+
return res
53+
}
54+
}
55+
56+
// FIXME should be TypeError
57+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for abs: '%s'", a.Type().Name))
58+
}
59+
60+
// Invert the python Object returning an Object
61+
//
62+
// Will raise TypeError if Invert can't be run on this object
9E7A 63+
func Invert(a Object) Object {
64+
A, ok := a.(I__invert__)
65+
if ok {
66+
res := A.M__invert__()
67+
if res != NotImplemented {
68+
return res
69+
}
70+
}
71+
72+
// FIXME should be TypeError
73+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for ~: '%s'", a.Type().Name))
74+
}
75+
76+
// MakeComplex the python Object returning an Object
77+
//
78+
// Will raise TypeError if MakeComplex can't be run on this object
79+
func MakeComplex(a Object) Object {
80+
A, ok := a.(I__complex__)
81+
if ok {
82+
res := A.M__complex__()
83+
if res != NotImplemented {
84+
return res
85+
}
86+
}
87+
88+
// FIXME should be TypeError
89+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for complex: '%s'", a.Type().Name))
90+
}
91+
92+
// MakeInt the python Object returning an Object
93+
//
94+
// Will raise TypeError if MakeInt can't be run on this object
95+
func MakeInt(a Object) Object {
96+
A, ok := a.(I__int__)
97+
if ok {
98+
res := A.M__int__()
99+
if res != NotImplemented {
100+
return res
101+
}
102+
}
103+
104+
// FIXME should be TypeError
105+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for int: '%s'", a.Type().Name))
106+
}
107+
108+
// MakeFloat the python Object returning an Object
109+
//
110+
// Will raise TypeError if MakeFloat can't be run on this object
111+
func MakeFloat(a Object) Object {
112+
A, ok := a.(I__float__)
113+
if ok {
114+
res := A.M__float__()
115+
if res != NotImplemented {
116+
return res
117+
}
118+
}
119+
120+
// FIXME should be TypeError
121+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for float: '%s'", a.Type().Name))
122+
}
123+
12124
// Add two python objects together returning an Object
13125
//
14126
// Will raise TypeError if can't be add can't be run on these objects

py/complex.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ func convertToComplex(other Object) (Complex, bool) {
3737
return 0, false
3838
}
3939

40+
func (a Complex) M__neg__() Object {
41+
return -a
42+
}
43+
44+
func (a Complex) M__pos__() Object {
45+
return a
46+
}
47+
48+
func (a Complex) M__abs__() Object {
49+
return Float(cmplx.Abs(complex128(a)))
50+
}
51+
4052
func (a Complex) M__add__(other Object) Object {
4153
if b, ok := convertToComplex(other); ok {
4254
return Complex(a + b)

py/float.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ func convertToFloat(other Object) (Float, bool) {
3636
return 0, false
3737
}
3838

39+
func (a Float) M__neg__() Object {
40+
return -a
41+
}
42+
43+
func (a Float) M__pos__() Object {
44+
return a
45+
}
46+
47+
func (a Float) M__abs__() Object {
48+
return Float(math.Abs(float64(a)))
49+
}
50+
3951
func (a Float) M__add__(other Object) Object {
4052
if b, ok := convertToFloat(other); ok {
4153
return Float(a + b)
@@ -182,5 +194,41 @@ func (a Float) M__ipow__(other, modulus Object) Object {
182194
return a.M__pow__(other, modulus)
183195
}
184196

197+
func (a Float) M__bool__() Object {
198+
if a == 0 {
199+
return False
200+
}
201+
return True
202+
}
203+
204+
func (a Float) M__int__() Object {
205+
return Int(a)
206+
}
207+
208+
func (a Float) M__float__() Object {
209+
return a
210+
}
211+
212+
func (a Float) M__complex__() Object {
213+
if r, ok := convertToComplex(a); ok {
214+
return r
215+
}
216+
panic("convertToComplex failed")
217+
}
218+
219+
func (a Float) M__round__(digitsObj Object) Object {
220+
digits := 0
221+
if digitsObj != None {
222+
digits = Index(digitsObj)
223+
if digits < 0 {
224+
return Float(0)
225+
}
226+
}
227+
scale := Float(math.Pow(10, float64(digits)))
228+
return scale * Float(math.Floor(float64(a)/float64(scale)))
229+
}
230+
185231
// Check interface is satisfied
186232
var _ floatArithmetic = Float(0)
233+
var _ conversionBetweenTypes = Int(0)
234+
var _ I__bool__ = Int(0)

py/gen.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,10 @@ var data = Data{
3434
{Name: "neg", Title: "Neg", Operator: "-", Unary: true},
3535
{Name: "pos", Title: "Pos", Operator: "+", Unary: true},
3636
{Name: "abs", Title: "Abs", Operator: "abs", Unary: true},
37-
{Name: "invert", Title: "Invert", Operator: "invert", Unary: true},
37+
{Name: "invert", Title: "Invert", Operator: "~", Unary: true},
3838
{Name: "complex", Title: "MakeComplex", Operator: "complex", Unary: true},
3939
{Name: "int", Title: "MakeInt", Operator: "int", Unary: true},
4040
{Name: "float", Title: "MakeFloat", Operator: "float", Unary: true},
41-
{Name: "index", Title: "Index", Operator: "index", Unary: true},
4241
},
4342
BinaryOps: Ops{
4443
{Name: "add", Title: "Add", Operator: "+", Binary: true},
@@ -76,6 +75,24 @@ import (
7675
"fmt"
7776
)
7877
78+
{{ range .UnaryOps }}
79+
// {{.Title}} the python Object returning an Object
80+
//
81+
// Will raise TypeError if {{.Title}} can't be run on this object
82+
func {{.Title}}(a Object) Object {
83+
A, ok := a.(I__{{.Name}}__)
84+
if ok {
85+
res := A.M__{{.Name}}__()
86+
if res != NotImplemented {
87+
return res
88+
}
89+
}
90+
91+
// FIXME should be TypeError
92+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for {{.Operator}}: '%s'", a.Type().Name))
93+
}
94+
{{ end }}
95+
7996
{{ range .BinaryOps }}
8097
// {{.Title}} {{ if .Binary }}two{{ end }}{{ if .Ternary }}three{{ end }} python objects together returning an Object
8198
{{ if .Ternary}}//

py/int.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,25 @@ func convertToInt(other Object) (Int, bool) {
4949

5050
// FIXME overflow should promote to Long in all these functions
5151

52+
func (a Int) M__neg__() Object {
53+
return -a
54+
}
55+
56+
func (a Int) M__pos__() Object {
57+
return a
58+
}
59+
60+
func (a Int) M__abs__() Object {
61+
if a < 0 {
62+
return -a
63+
}
64+
return a
65+
}
66+
67+
func (a Int) M__invert__() Object {
68+
return ^a
69+
}
70+
5271
func (a Int) M__add__(other Object) Object {
5372
if b, ok := convertToInt(other); ok {
5473
return Int(a + b)
@@ -279,6 +298,43 @@ func (a Int) M__ior__(other Object) Object {
279298
return a.M__or__(other)
280299
}
281300

301+
func (a Int) M__bool__() Object {
302+
if a == 0 {
303+
return False
304+
}
305+
return True
306+
}
307+
308+
func (a Int) M__index__() int {
309+
// FIXME moan if it overflows an int
310+
return int(a)
311+
}
312+
313+
func (a Int) M__int__() Object {
314+
return a
315+
}
316+
317+
func (a Int) M__float__() Object {
318+
if r, ok := convertToFloat(a); ok {
319+
return r
320+
}
321+
panic("convertToFloat failed")
322+
}
323+
324+
func (a Int) M__complex__() Object {
325+
if r, ok := convertToComplex(a); ok {
326+
return r
327+
}
328+
panic("convertToComplex failed")
329+
}
330+
331+
func (a Int) M__round__(digits Object) Object {
332+
return Int(Float(a).M__round__(digits).(Float))
333+
}
334+
282335
// Check interface is satisfied
283336
var _ floatArithmetic = Int(0)
284337
var _ booleanArithmetic = Int(0)
338+
var _ conversionBetweenTypes = Int(0)
339+
var _ I__bool__ = Int(0)
340+
var _ I__index__ = Int(0)

py/internal.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Internal interface for use from Go
2+
//
3+
// See arithmetic.go for the auto generated stuff
4+
5+
package py
6+
7+
import (
8+
"fmt"
9+
)
10+
11+
// Bool is called to implement truth value testing and the built-in
12+
// operation bool(); should return False or True. When this method is
13+
// not defined, __len__() is called, if it is defined, and the object
14+
// is considered true if its result is nonzero. If a class defines
15+
// neither __len__() nor __bool__(), all its instances are considered
16+
// true.
17+
func MakeBool(a Object) Object {
18+
A, ok := a.(I__bool__)
19+
if ok {
20+
res := A.M__bool__()
21+
if res != NotImplemented {
22+
return res
23+
}
24+
}
25+
26+
B, ok := a.(I__len__)
27+
if ok {
28+
res := B.M__len__()
29+
if res != NotImplemented {
30+
return MakeBool(res)
31+
}
32+
}
33+
34+
return True
35+
}
36+
37+
// Index the python Object returning an int
38+
//
39+
// Will raise TypeError if Index can't be run on this object
40+
func Index(a Object) int {
41+
A, ok := a.(I__index__)
42+
if ok {
43+
return A.M__index__()
44+
}
45+
46+
// FIXME should be TypeError
47+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for index: '%s'", a.Type().Name))
48+
}

vm/eval.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,22 +86,30 @@ func do_DUP_TOP_TWO(vm *Vm, arg int32) {
8686

8787
// Implements TOS = +TOS.
8888
func do_UNARY_POSITIVE(vm *Vm, arg int32) {
89-
vm.NotImplemented("UNARY_POSITIVE", arg)
89+
vm.PUSH(py.Pos(vm.POP()))
9090
}
9191

9292
// Implements TOS = -TOS.
9393
func do_UNARY_NEGATIVE(vm *Vm, arg int32) {
94-
vm.NotImplemented("UNARY_NEGATIVE", arg)
94+
vm.PUSH(py.Neg(vm.POP()))
9595
}
9696

9797
// Implements TOS = not TOS.
9898
func do_UNARY_NOT(vm *Vm, arg int32) {
99-
vm.NotImplemented("UNARY_NOT", arg)
99+
a := py.MakeBool(vm.POP())
100+
switch a {
101+
case py.False:
102+
vm.PUSH(py.True)
103+
case py.True:
104+
vm.PUSH(py.False)
105+
default:
106+
panic("bool() didn't return True or False")
107+
}
100108
}
101109

102110
// Implements TOS = ~TOS.
103111
func do_UNARY_INVERT(vm *Vm, arg int32) {
104-
vm.NotImplemented("UNARY_INVERT", arg)
112+
vm.PUSH(py.Invert(vm.POP()))
105113
}
106114

107115
// Implements TOS = iter(TOS).

0 commit comments

Comments
 (0)
0