From: Thomas Hunger Date: Wed, 19 Sep 2007 13:40:17 +0000 (+0200) Subject: Changed the assigment code generator to emit X-Git-Tag: 0.9.6.14~29^2~139 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=1c9be2fcc721674e5a2a70d8d1022426fb6ff514;p=cython.git Changed the assigment code generator to emit a direct change of a classes tp_dict instead of SetAttr if assignment code is executed in a class body. To tell the code generator that we have a class entry, entry has a new attribute "is_member". --- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 31ad5379..aa147d11 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -814,24 +814,45 @@ class NameNode(AtomicExprNode): entry = self.entry if entry is None: return # There was an error earlier + + # is_pyglobal seems to be True for module level-globals only. + # We use this to access class->tp_dict if necessary. if entry.is_pyglobal: namespace = self.entry.namespace_cname - if Options.intern_names: - code.put_error_if_neg(self.pos, - 'PyObject_SetAttr(%s, %s, %s)' % ( - namespace, - entry.interned_cname, - rhs.py_result())) - else: - code.put_error_if_neg(self.pos, - 'PyObject_SetAttrString(%s, "%s", %s)' % ( - namespace, - entry.name, - rhs.py_result())) - if debug_disposal_code: - print "NameNode.generate_assignment_code:" - print "...generating disposal code for", rhs - rhs.generate_disposal_code(code) + if entry.is_member: + # if we entry is a member we have to cheat: SetAttr does not work + # on types, so we create a descriptor which is then added to tp_dict + if Options.intern_names: + code.put_error_if_neg(self.pos, + 'PyDict_SetItem(%s->tp_dict, %s, %s)' % ( + namespace, + entry.interned_cname, + rhs.py_result())) + else: + code.put_error_if_neg(self.pos, + 'PyDict_SetItemString(%s->tp_dict, %s, %s)' % ( + namespace, + entry.name, + rhs.py_result())) + + else: + if Options.intern_names: + code.put_error_if_neg(self.pos, + 'PyObject_SetAttr(%s, %s, %s)' % ( + namespace, + entry.interned_cname, + rhs.py_result())) + else: + code.put_error_if_neg(self.pos, + 'PyObject_SetAttrString(%s, "%s", %s)' % ( + namespace, + entry.name, + rhs.py_result())) + if debug_disposal_code: + print "NameNode.generate_assignment_code:" + print "...generating disposal code for", rhs + rhs.generate_disposal_code(code) + else: if self.type.is_pyobject: #print "NameNode.generate_assignment_code: to", self.name ### diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 2f0c0c3e..9279282e 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -30,6 +30,7 @@ class Entry: # or class attribute during # class construction # is_special boolean Is a special class method + # is_member boolean Is an assigned class member # is_variable boolean Is a variable # is_cfunction boolean Is a C function # is_cmethod boolean Is a C method of an extension type @@ -72,6 +73,7 @@ class Entry: is_cglobal = 0 is_pyglobal = 0 is_special = 0 + is_member = 0 is_variable = 0 is_cfunction = 0 is_cmethod = 0 @@ -979,10 +981,7 @@ class ClassScope(Scope): return self.outer_scope.add_string_const(value) def lookup(self, name): - print "*** Looking for", name, "in ClassScope", self - print self.entries res = Scope.lookup(self, name) - print "got", res, res.type return res @@ -1095,7 +1094,10 @@ class CClassScope(ClassScope): # Add an entry for a class attribute. entry = Scope.declare_var(self, name, type, pos, cname, visibility, is_cdef) - entry.is_pyglobal = 1 + entry.is_member = 1 + entry.is_pyglobal = 1 # xxx: is_pyglobal changes behaviour in so many places that + # I keep it in for now. is_member should be enough + # later on entry.namespace_cname = "(PyObject *)%s" % self.parent_type.typeptr_cname if Options.intern_names: entry.interned_cname = self.intern(name)