Skip to content

Commit b5c3273

Browse files
committed
Implement range() and object()
* Add range object and range iterator * Change calling parameters for UnpackTuple to check for empty kwargs * Add Bool.__index__ * Add IndexInt to return int and change Index to return Int * Fix FOR_ITER
1 parent 2a65fbd commit b5c3273

File tree

9 files changed

+135
-14
lines changed

9 files changed

+135
-14
lines changed

builtin/builtin.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ func init() {
7777
"int": py.IntType, // FIXME LongType?
7878
"list": py.ListType,
7979
// "map": py.MapType,
80-
// "object": py.BaseObjectType,
81-
// "range": py.RangeType,
80+
"object": py.BaseObjectType,
81+
"range": py.RangeType,
8282
// "reversed": py.ReversedType,
8383
"set": py.SetType,
8484
// "slice": py.SliceType,
@@ -114,7 +114,7 @@ equivalent to (x**y) % z, but may be more efficient (e.g. for ints).`
114114
func builtin_pow(self py.Object, args py.Tuple) py.Object {
115115
var v, w, z py.Object
116116
z = py.None
117-
py.UnpackTuple(args, "pow", 2, 3, &v, &w, &z)
117+
py.UnpackTuple(args, nil, "pow", 2, 3, &v, &w, &z)
118118
return py.Pow(v, w, z)
119119
}
120120

@@ -137,7 +137,7 @@ func builtin_round(self py.Object, args py.Tuple, kwargs py.StringDict) py.Objec
137137
ndigits = py.Int(0)
138138
// var kwlist = []string{"number", "ndigits"}
139139
// FIXME py.ParseTupleAndKeywords(args, kwargs, "O|O:round", kwlist, &number, &ndigits)
140-
py.UnpackTuple(args, "round", 1, 2, &number, &ndigits)
140+
py.UnpackTuple(args, nil, "round", 1, 2, &number, &ndigits)
141141

142142
numberRounder, ok := number.(py.I__round__)
143143
if !ok {

py/args.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,9 +512,14 @@ func checkNumberOfArgs(name string, nargs, nresults, min, max int) {
512512
// Unpack the args tuple into the results
513513
//
514514
// Up to the caller to set default values
515-
func UnpackTuple(args Tuple, name string, min int, max int, results ...*Object) {
515+
func UnpackTuple(args Tuple, kwargs StringDict, name string, min int, max int, results ...*Object) {
516+
if len(kwargs) != 0 {
517+
// FIXME type error
518+
panic(fmt.Sprintf("TypeError: %s() does not take keyword arguments", name))
519+
}
520+
516521
// Check number of arguments
517-
checkNumberOfArgs(name, len(args), min, max, len(results))
522+
checkNumberOfArgs(name, len(args), len(results), min, max)
518523

519524
// Copy the results in
520525
for i := range args {

py/bool.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,13 @@ func (a Bool) M__bool__() Object {
2020
return a
2121
}
2222

23+
func (a Bool) M__index__() Int {
24+
if a {
25+
return Int(1)
26+
}
27+
return Int(0)
28+
}
29+
2330
// Check interface is satisfied
2431
var _ I__bool__ = Bool(false)
32+
var _ I__index__ = Bool(false)

py/float.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ func (a Float) M__complex__() Object {
219219
func (a Float) M__round__(digitsObj Object) Object {
220220
digits := 0
221221
if digitsObj != None {
222-
digits = Index(digitsObj)
222+
digits = IndexInt(digitsObj)
223223
}
224224
scale := Float(math.Pow(10, float64(digits)))
225225
return scale * Float(math.Floor(float64(a)/float64(scale)))

py/int.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ var IntType = NewType("int", "int(x=0) -> integer\nint(x, base=10) -> integer\n\
1111

1212
type Int int64
1313

14+
const (
15+
// Maximum possible Int
16+
IntMax = 1<<63 - 1
17+
// Minimum possible Int
18+
IntMin = -IntMax - 1
19+
)
20+
1421
// Type of this Int object
1522
func (o Int) Type() *Type {
1623
return IntType
@@ -306,9 +313,8 @@ func (a Int) M__bool__() Object {
306313
return True
307314
}
308315

309-
func (a Int) M__index__() int {
310-
// FIXME moan if it overflows an int
311-
return int(a)
316+
func (a Int) M__index__() Int {
317+
return a
312318
}
313319

314320
func (a Int) M__int__() Object {

py/internal.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ func MakeBool(a Object) Object {
3636
return True
3737
}
3838

39-
// Index the python Object returning an int
39+
// Index the python Object returning an Int
4040
//
4141
// Will raise TypeError if Index can't be run on this object
42-
func Index(a Object) int {
42+
func Index(a Object) Int {
4343
A, ok := a.(I__index__)
4444
if ok {
4545
return A.M__index__()
@@ -49,6 +49,24 @@ func Index(a Object) int {
4949
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for index: '%s'", a.Type().Name))
5050
}
5151

52+
// Index the python Object returning an int
53+
//
54+
// Will raise TypeError if Index can't be run on this object
55+
//
56+
// or IndexError if the Int won't fit!
57+
func IndexInt(a Object) int {
58+
i := Index(a)
59+
intI := int(i)
60+
61+
// Int might not fit in an int
62+
if Int(intI) != i {
63+
// FIXME IndexError
64+
panic(fmt.Sprintf("IndexError: cannot fit %d into an index-sized integer", i))
65+
}
66+
67+
return intI
68+
}
69+
5270
// Return the result of not a
5371
func Not(a Object) Object {
5472
switch MakeBool(a) {

py/py.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ type I__round__ interface {
879879

880880
// object.__index__(self)
881881
type I__index__ interface {
882-
M__index__() int
882+
M__index__() Int
883883
}
884884

885885
// Int, Float and Complex should satisfy this

py/range.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Range object
2+
3+
package py
4+
5+
// A python Range object
6+
// FIXME one day support BigInts too!
7+
type Range struct {
8+
Start Int
9+
Stop Int
10+
Step Int
11+
//Length Object
12+
}
13+
14+
// A python Range iterator
15+
type RangeIterator struct {
16+
Range
17+
Index Int
18+
}
19+
20+
var RangeType = NewTypeX("range", `range(stop) -> range object
21+
range(start, stop[, step]) -> range object
22+
23+
Return a virtual sequence of numbers from start to stop by step.`,
24+
RangeNew, nil)
25+
26+
var RangeIteratorType = NewType("range_iterator", `range_iterator object`)
27+
28+
// Type of this object
29+
func (o *Range) Type() *Type {
30+
return RangeType
31+
}
32+
33+
// Type of this object
34+
func (o *RangeIterator) Type() *Type {
35+
return RangeIteratorType
36+
}
37+
38+
// RangeNew
39+
func RangeNew(metatype *Type, args Tuple, kwargs StringDict) Object {
40+
var start Object
41+
var stop Object
42+
var step Object = Int(1)
43+
UnpackTuple(args, kwargs, "range", 1, 3, &start, &stop, &step)
44+
if len(args) == 1 {
45+
return &Range{
46+
Start: Int(0),
47+
Stop: Index(start),
48+
Step: Int(1),
49+
}
50+
}
51+
return &Range{
52+
Start: Index(start),
53+
Stop: Index(stop),
54+
Step: Index(step),
55+
}
56+
}
57+
58+
// Make a range iterator from a range
59+
func (r *Range) M__iter__() Object {
60+
return &RangeIterator{
61+
Range: *r,
62+
Index: r.Start,
63+
}
64+
}
65+
66+
// Range iterator
67+
func (it *RangeIterator) M__iter__() Object {
68+
return it
69+
}
70+
71+
// Range iterator next
72+
func (it *RangeIterator) M__next__() Object {
73+
r := it.Index
74+
if r >= it.Stop {
75+
panic(StopIteration)
76+
}
77+
it.Index++
78+
return r
79+
}
80+
81+
// Check interface is satisfied
82+
var _ I__iter__ = (*Range)(nil)
83+
var _ I_iterator = (*RangeIterator)(nil)

vm/eval.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,8 @@ func do_FOR_ITER(vm *Vm, delta int32) {
666666
}
667667
}
668668
}()
669-
it := vm.TOP().(*py.Iterator)
669+
// FIXME should look in instance dictionary
670+
it := vm.TOP().(py.I__next__)
670671
r := it.M__next__()
671672
vm.PUSH(r)
672673
}

0 commit comments

Comments
 (0)