Skip to content

Commit 17013ce

Browse files
committed
Implement STORE_SUBSCR and SetItem and first attempt at attribute lookup
1 parent 3fd76bb commit 17013ce

File tree

4 files changed

+114
-21
lines changed

4 files changed

+114
-21
lines changed

builtin/builtin.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ const build_class_doc = `__build_class__(func, name, *bases, metaclass=None, **k
153153
Internal helper function used by the class statement.`
154154

155155
func builtin___build_class__(self py.Object, args py.Tuple, kwargs py.StringDict) py.Object {
156+
fmt.Printf("__build_class__(self=%#v, args=%#v, kwargs=%#v\n", self, args, kwargs)
156157
var prep, cell, cls py.Object
157158
var mkw, ns py.StringDict
158159
var meta, winner *py.Type
@@ -207,7 +208,7 @@ func builtin___build_class__(self py.Object, args py.Tuple, kwargs py.StringDict
207208
}
208209
// else: meta is not a class, so we cannot do the metaclass
209210
// calculation, so we will use the explicitly given object as it is
210-
prep = meta.Type().Methods["___prepare__"]
211+
prep = meta.Type().Dict["___prepare__"] // FIXME should be using _PyObject_GetAttr
211212
if prep == nil {
212213
ns = py.NewStringDict()
213214
} else {
@@ -227,5 +228,6 @@ func builtin___build_class__(self py.Object, args py.Tuple, kwargs py.StringDict
227228
c.Set(cls)
228229
}
229230
}
231+
fmt.Printf("Globals = %v, Locals = %v\n", fn.Globals, ns)
230232
return cls
231233
}

py/internal.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,24 @@ func Call(fn Object, args Tuple, kwargs StringDict) Object {
7575
// FIXME should be TypeError
7676
panic(fmt.Sprintf("TypeError: '%s' object is not callable", fn.Type().Name))
7777
}
78+
79+
// GetItem
80+
func GetItem(self Object, key Object) Object {
81+
if I, ok := self.(I__getitem__); ok {
82+
return I.M__getitem__(key)
83+
}
84+
// FIXME should be TypeError
85+
panic(fmt.Sprintf("TypeError: '%s' object is not subscriptable", self.Type().Name))
86+
}
87+
88+
// SetItem
89+
func SetItem(self Object, key Object, value Object) Object {
90+
if I, ok := self.(I__setitem__); ok {
91+
return I.M__setitem__(key, value)
92+
} else if res, ok := TypeCall2(self, "__setitem__", key, value); ok {
93+
return res
94+
}
95+
96+
// FIXME should be TypeError
97+
panic(fmt.Sprintf("TypeError: '%s' object does not support item assignment", self.Type().Name))
98+
}

py/type.go

Lines changed: 81 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,24 +65,24 @@ const (
6565
)
6666

6767
type Type struct {
68-
ObjectType *Type // Type of this object
69-
Name string // For printing, in format "<module>.<name>"
70-
Doc string // Documentation string
71-
Methods StringDict // *PyMethodDef
72-
Members StringDict // *PyMemberDef
68+
ObjectType *Type // Type of this object
69+
Name string // For printing, in format "<module>.<name>"
70+
Doc string // Documentation string
71+
// Methods StringDict // *PyMethodDef
72+
// Members StringDict // *PyMemberDef
7373
// Getset *PyGetSetDef
74-
Base *Type
75-
Dict StringDict
76-
Dictoffset int
77-
Bases Tuple
78-
Mro Tuple // method resolution order
74+
Base *Type
75+
Dict StringDict
76+
// Dictoffset int
77+
Bases Tuple
78+
Mro Tuple // method resolution order
7979
// Cache Object
80-
Subclasses Tuple
81-
Weaklist Tuple
82-
New func(metatype *Type, args Tuple, kwargs StringDict) *Type
83-
Init func(self Object, args Tuple, kwargs StringDict)
84-
Flags int // Flags to define presence of optional/expanded features
85-
Qualname string
80+
// Subclasses Tuple
81+
// Weaklist Tuple
82+
New func(metatype *Type, args Tuple, kwargs StringDict) *Type
83+
Init func(self Object, args Tuple, kwargs StringDict)
84+
Flags int // Flags to define presence of optional/expanded features
85+
Qualname string
8686

8787
/*
8888
Py_ssize_t tp_basicsize, tp_itemsize; // For allocation
@@ -322,6 +322,68 @@ func (t *Type) Lookup(name string) Object {
322322
return res
323323
}
324324

325+
// Get an attribute from the type
326+
//
327+
// FIXME this isn't totally correct!
328+
// as we are ignoring getattribute etc
329+
// See _PyObject_GenericGetAttrWithDict in object.c
330+
func (t *Type) GetMethod(name string) Object {
331+
// Look in instance dictionary first
332+
if res, ok := t.Dict[name]; ok {
333+
return res
334+
}
335+
// Then look in type Dict
336+
if res, ok := t.Type().Dict[name]; ok {
337+
return res
338+
}
339+
return t.Lookup(name)
340+
}
341+
342+
// Calls method on name
343+
//
344+
// If method not found returns (nil, false)
345+
//
346+
// If method found returns (object, true)
347+
//
348+
// May raise exceptions if calling the method failed
349+
func (t *Type) CallMethod(name string, args Tuple, kwargs StringDict) (Object, bool) {
350+
fn := t.GetMethod(name)
351+
if fn == nil {
352+
return nil, false
353+
}
354+
return Call(fn, args, kwargs), true
355+
}
356+
357+
// Calls a type method on obj
358+
//
359+
// If obj isnt a *Type or the method isn't found on it returns (nil, false)
360+
//
361+
// Otherwise returns (object, true)
362+
//
363+
// May raise exceptions if calling the method fails
364+
func TypeCall(self Object, name string, args Tuple, kwargs StringDict) (Object, bool) {
365+
t, ok := self.(*Type)
366+
if !ok {
367+
return nil, false
368+
}
369+
return t.CallMethod(name, args, kwargs)
370+
}
371+
372+
// Calls TypeCall with 0 arguments
373+
func TypeCall0(self Object, name string) (Object, bool) {
374+
return TypeCall(self, name, nil, nil)
375+
}
376+
377+
// Calls TypeCall with 1 argument
378+
func TypeCall1(self Object, name string, arg Object) (Object, bool) {
379+
return TypeCall(self, name, Tuple{arg}, nil)
380+
}
381+
382+
// Calls TypeCall with 2 arguments
383+
func TypeCall2(self Object, name string, arg1, arg2 Object) (Object, bool) {
384+
return TypeCall(self, name, Tuple{arg1, arg2}, nil)
385+
}
386+
325387
// Internal routines to do a method lookup in the type
326388
// without looking in the instance dictionary
327389
// (so we can't use PyObject_GetAttr) but still binding
@@ -950,6 +1012,7 @@ func (t *Type) Alloc() *Type {
9501012

9511013
// Create a new type
9521014
func TypeNew(metatype *Type, args Tuple, kwargs StringDict) *Type {
1015+
fmt.Printf("TypeNew(type=%q, args=%v, kwargs=%v\n", metatype.Name, args, kwargs)
9531016
var nameObj, basesObj, orig_dictObj Object
9541017
var new_type, base, winner *Type
9551018
// PyHeapTypeObject et;
@@ -1159,10 +1222,11 @@ func TypeNew(metatype *Type, args Tuple, kwargs StringDict) *Type {
11591222

11601223
// Initialize tp_dict from passed-in dict
11611224
new_type.Dict = dict
1225+
fmt.Printf("New type dict is %v\n", dict)
11621226

11631227
// Set __module__ in the dict
11641228
if _, ok := dict["__module__"]; !ok {
1165-
fmt.Printf("FIXME neet to get the current vm globals somehow\n")
1229+
fmt.Printf("*** FIXME need to get the current vm globals somehow\n")
11661230
// tmp = PyEval_GetGlobals()
11671231
// if tmp != nil {
11681232
// tmp, ok := tmp["__name__"]

vm/eval.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,12 @@ func do_INPLACE_OR(vm *Vm, arg int32) {
308308

309309
// Implements TOS1[TOS] = TOS2.
310310
func do_STORE_SUBSCR(vm *Vm, arg int32) {
311-
vm.NotImplemented("STORE_SUBSCR", arg)
311+
w := vm.TOP()
312+
v := vm.SECOND()
313+
u := vm.THIRD()
314+
vm.DROPN(3)
315+
// v[w] = u
316+
py.SetItem(v, w, u)
312317
}
313318

314319
// Implements del TOS1[TOS].
@@ -976,9 +981,10 @@ func Run(globals, locals py.StringDict, code *py.Code) (res py.Object, err error
976981
default:
977982
err = errors.New(fmt.Sprintf("Unknown error '%s'", x))
978983
}
984+
fmt.Printf("*** Exception raised %v\n", r)
985+
// Dump the goroutine stack
986+
debug.PrintStack()
979987
}
980-
// Dump the goroutine stack
981-
debug.PrintStack()
982988
}()
983989
vm.PushFrame(globals, locals, code)
984990

0 commit comments

Comments
 (0)