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+
funcNeg(aObject) Object{
16+
A, ok:=a.(I__neg__)
17+
ifok{
18+
res:=A.M__neg__()
19+
ifres!=NotImplemented{
20+
returnres
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+
funcPos(aObject) Object{
32+
A, ok:=a.(I__pos__)
33+
ifok{
34+
res:=A.M__pos__()
35+
ifres!=NotImplemented{
36+
returnres
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+
funcAbs(aObject) Object{
48+
A, ok:=a.(I__abs__)
49+
ifok{
50+
res:=A.M__abs__()
51+
ifres!=NotImplemented{
52+
returnres
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
63+
funcInvert(aObject) Object{
64+
A, ok:=a.(I__invert__)
65+
ifok{
66+
res:=A.M__invert__()
67+
ifres!=NotImplemented{
68+
returnres
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+
funcMakeComplex(aObject) Object{
80+
A, ok:=a.(I__complex__)
81+
ifok{
82+
res:=A.M__complex__()
83+
ifres!=NotImplemented{
84+
returnres
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+
funcMakeInt(aObject) Object{
96+
A, ok:=a.(I__int__)
97+
ifok{
98+
res:=A.M__int__()
99+
ifres!=NotImplemented{
100+
returnres
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+
funcMakeFloat(aObject) Object{
112+
A, ok:=a.(I__float__)
113+
ifok{
114+
res:=A.M__float__()
115+
ifres!=NotImplemented{
116+
returnres
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
return0, false
3838
}
3939

40+
func (aComplex) M__neg__() Object{
41+
return-a
42+
}
43+
44+
func (aComplex) M__pos__() Object{
45+
returna
46+
}
47+
48+
func (aComplex) M__abs__() Object{
49+
returnFloat(cmplx.Abs(complex128(a)))
50+
}
51+
4052
func (aComplex) M__add__(otherObject) Object{
4153
ifb, ok:=convertToComplex(other); ok{
4254
returnComplex(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
return0, false
3737
}
3838

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

197+
func (aFloat) M__bool__() Object{
198+
ifa==0{
199+
returnFalse
200+
}
201+
returnTrue
202+
}
203+
204+
func (aFloat) M__int__() Object{
205+
returnInt(a)
206+
}
207+
208+
func (aFloat) M__float__() Object{
209+
returna
210+
}
211+
212+
func (aFloat) M__complex__() Object{
213+
ifr, ok:=convertToComplex(a); ok{
214+
returnr
215+
}
216+
panic("convertToComplex failed")
217+
}
218+
219+
func (aFloat) M__round__(digitsObjObject) Object{
220+
digits:=0
221+
ifdigitsObj!=None{
222+
digits=Index(digitsObj)
223+
ifdigits<0{
224+
returnFloat(0)
225+
}
226+
}
227+
scale:=Float(math.Pow(10, float64(digits)))
228+
returnscale*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 (aInt) M__neg__() Object{
53+
return-a
54+
}
55+
56+
func (aInt) M__pos__() Object{
57+
returna
58+
}
59+
60+
func (aInt) M__abs__() Object{
61+
ifa<0{
62+
return-a
63+
}
64+
returna
65+
}
66+
67+
func (aInt) M__invert__() Object{
68+
return^a
69+
}
70+
5271
func (aInt) M__add__(otherObject) Object{
5372
ifb, ok:=convertToInt(other); ok{
5473
returnInt(a+b)
@@ -279,6 +298,43 @@ func (a Int) M__ior__(other Object) Object{
279298
returna.M__or__(other)
280299
}
281300

301+
func (aInt) M__bool__() Object{
302+
ifa==0{
303+
returnFalse
304+
}
305+
returnTrue
306+
}
307+
308+
func (aInt) M__index__() int{
309+
// FIXME moan if it overflows an int
310+
returnint(a)
311+
}
312+
313+
func (aInt) M__int__() Object{
314+
returna
315+
}
316+
317+
func (aInt) M__float__() Object{
318+
ifr, ok:=convertToFloat(a); ok{
319+
returnr
320+
}
321+
panic("convertToFloat failed")
322+
}
323+
324+
func (aInt) M__complex__() Object{
325+
ifr, ok:=convertToComplex(a); ok{
326+
returnr
327+
}
328+
panic("convertToComplex failed")
329+
}
330+
331+
func (aInt) M__round__(digitsObject) Object{
332+
returnInt(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+
funcMakeBool(aObject) Object{
18+
A, ok:=a.(I__bool__)
19+
ifok{
20+
res:=A.M__bool__()
21+
ifres!=NotImplemented{
22+
returnres
23+
}
24+
}
25+
26+
B, ok:=a.(I__len__)
27+
ifok{
28+
res:=B.M__len__()
29+
ifres!=NotImplemented{
30+
returnMakeBool(res)
31+
}
32+
}
33+
34+
returnTrue
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+
funcIndex(aObject) int{
41+
A, ok:=a.(I__index__)
42+
ifok{
43+
returnA.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
funcdo_UNARY_POSITIVE(vm*Vm, argint32){
89-
vm.NotImplemented("UNARY_POSITIVE", arg)
89+
vm.PUSH(py.Pos(vm.POP()))
9090
}
9191

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

9797
// Implements TOS = not TOS.
9898
funcdo_UNARY_NOT(vm*Vm, argint32){
99-
vm.NotImplemented("UNARY_NOT", arg)
99+
a:=py.MakeBool(vm.POP())
100+
switcha{
101+
casepy.False:
102+
vm.PUSH(py.True)
103+
casepy.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
funcdo_UNARY_INVERT(vm*Vm, argint32){
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)