Skip to content

Commit f9b0894

Browse files
committed
Implement py.DeleteAttr, py.NewStringDictSized and DELETE_ATTR, BUILD_MAP, STORE_MAP opcodes
1 parent e387540 commit f9b0894

File tree

3 files changed

+60
-3
lines changed

3 files changed

+60
-3
lines changed

‎py/dict.go‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ func NewStringDict() StringDict{
2424
returnmake(StringDict)
2525
}
2626

27+
// Make a new dictionary with reservation for n entries
28+
funcNewStringDictSized(nint) StringDict{
29+
returnmake(StringDict, n)
30+
}
31+
2732
// Copy a dictionary
2833
func (dStringDict) Copy() StringDict{
2934
e:=make(StringDict, len(d))

‎py/internal.go‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,53 @@ func SetAttr(self Object, keyObj Object, value Object) Object{
240240
panic(ExceptionNewf(TypeError, "attribute name must be string, not '%s'", self.Type().Name))
241241
}
242242

243+
// DeleteAttrString
244+
funcDeleteAttrString(selfObject, keystring){
245+
// First look in type's dictionary etc for a property that could
246+
// be set - do this before looking in the instance dictionary
247+
deleter:=self.Type().NativeGetAttrOrNil(key)
248+
ifdeleter!=nil{
249+
// Call __set__ which writes properties etc
250+
ifI, ok:=deleter.(I__delete__); ok{
251+
I.M__delete__(self)
252+
return
253+
}
254+
}
255+
256+
// If we have __delattr__ then use that
257+
ifI, ok:=self.(I__delattr__); ok{
258+
I.M__delattr__(key)
259+
return
260+
} elseif_, ok:=TypeCall1(self, "__delattr__", String(key)); ok{
261+
return
262+
}
263+
264+
// Otherwise delete the attribute from the instance dictionary
265+
// if possible
266+
ifI, ok:=self.(IGetDict); ok{
267+
dict:=I.GetDict()
268+
ifdict==nil{
269+
panic(ExceptionNewf(SystemError, "nil Dict in %s", self.Type().Name))
270+
}
271+
if_, ok:=dict[key]; ok{
272+
delete(dict, key)
273+
return
274+
}
275+
}
276+
277+
// If not blow up
278+
panic(ExceptionNewf(AttributeError, "'%s' object has no attribute '%s'", self.Type().Name, key))
279+
}
280+
281+
// DeleteAttr
282+
funcDeleteAttr(selfObject, keyObjObject){
283+
ifkey, ok:=keyObj.(String); ok{
284+
DeleteAttrString(self, string(key))
285+
return
286+
}
287+
panic(ExceptionNewf(TypeError, "attribute name must be string, not '%s'", self.Type().Name))
288+
}
289+
243290
// Call __next__ for the python object
244291
funcNext(selfObject) Object{
245292
ifI, ok:=self.(I__next__); ok{

‎vm/eval.go‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ func do_STORE_ATTR(vm *Vm, namei int32){
727727
// Implements del TOS.name, using namei as index into co_names.
728728
funcdo_DELETE_ATTR(vm*Vm, nameiint32){
729729
defervm.CheckException()
730-
vm.NotImplemented("DELETE_ATTR", namei)
730+
py.DeleteAttrString(vm.POP(), vm.frame.Code.Names[namei])
731731
}
732732

733733
// Works as STORE_NAME, but stores the name as a global.
@@ -786,7 +786,7 @@ func do_BUILD_LIST(vm *Vm, count int32){
786786
// pre-sized to hold count entries.
787787
funcdo_BUILD_MAP(vm*Vm, countint32){
788788
defervm.CheckException()
789-
vm.NotImplemented("BUILD_MAP", count)
789+
vm.PUSH(py.NewStringDictSized(int(count)))
790790
}
791791

792792
// Replaces TOS with getattr(TOS, co_names[namei]).
@@ -988,7 +988,12 @@ func do_SETUP_FINALLY(vm *Vm, delta int32){
988988
// while leaving the dictionary on the stack.
989989
funcdo_STORE_MAP(vm*Vm, argint32){
990990
defervm.CheckException()
991-
vm.NotImplemented("STORE_MAP", arg)
991+
key:=string(vm.TOP().(py.String)) // FIXME
992+
value:=vm.SECOND()
993+
dictObj:=vm.THIRD()
994+
vm.DROPN(2)
995+
dict:=dictObj.(py.StringDict)
996+
dict[key] =value
992997
}
993998

994999
// Pushes a reference to the local co_varnames[var_num] onto the stack.

0 commit comments

Comments
(0)