Created
August 11, 2011 22:09
-
-
Save slingamn/1140929 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ezio/Ezio.h b/ezio/Ezio.h | |
index 7ff33f1..917fd9f 100644 | |
--- a/ezio/Ezio.h | |
+++ b/ezio/Ezio.h | |
@@ -54,27 +54,6 @@ static void array_xdecref(Py_ssize_t num_vars, PyObject *vars[]) { | |
} | |
} | |
-/** | |
- Basic RAII for PyObject*'s; store a pointer and a new reference, ensure | |
- that the new reference is removed on function exit by putting an XDECREF | |
- in the destructor. This is used to implement #set, but not to implement, e.g., | |
- function arguments or the temporary variables in for loops. | |
- */ | |
-class PySmartPointer { | |
- public: | |
- // this value can be NULL and always requires a NULL test before use | |
- PyObject *referent; | |
- PySmartPointer() : referent(NULL) {} | |
- PySmartPointer(PyObject *referent) : referent(referent) {} | |
- ~PySmartPointer() { Py_XDECREF(referent); } | |
- // we could overload the assignment operator here, but we don't really need the magic: | |
- // the only value being added here is the destructor. | |
- void set_referent(PyObject *new_referent) { | |
- Py_XDECREF(referent); | |
- referent = new_referent; | |
- } | |
-}; | |
- | |
namespace ezio_templates { | |
/** Base C++ class for all templates. */ | |
diff --git a/ezio/compiler.py b/ezio/compiler.py | |
index ccb0f83..144fc7e 100644 | |
--- a/ezio/compiler.py | |
+++ b/ezio/compiler.py | |
@@ -754,6 +754,7 @@ class CodeGenerator(LineBufferMixin, NodeVisitor): | |
# semantics; a local variable is scoped to its enclosing function, not to any smaller | |
# block. | |
self.assignment_targets = LineBufferMixin() | |
+ self.assignment_cleanup = LineBufferMixin() | |
self.assignment_namespace = {} | |
self.add_fixup(self.assignment_targets) | |
self.namespaces.append(self.assignment_namespace) | |
@@ -766,9 +767,13 @@ class CodeGenerator(LineBufferMixin, NodeVisitor): | |
self.namespaces.append(arg_namespace) | |
for stmt in function_def.body: | |
self.visit(stmt) | |
+ # insert the fixup to clean up assignments | |
+ self.add_fixup(self.assignment_cleanup) | |
# XXX Py_None is being used as a C-truthy sentinel for success | |
self.add_line("return Py_None;") | |
self.add_line('%s:' % exception_handler) | |
+ # insert the cleanup fixup *again* | |
+ self.add_fixup(self.assignment_cleanup) | |
self.add_line("return NULL;") | |
self.indent -= 1 | |
# remove the argument and assignment namespaces: | |
@@ -1301,9 +1306,9 @@ class CodeGenerator(LineBufferMixin, NodeVisitor): | |
if name_status == 'SMART_POINTER': | |
# generate a NameError for uninitialized use of a #set variable: | |
- self.add_line('if (!%s.referent) { PyErr_SetString(PyExc_NameError, "%s"); goto %s; }' % | |
+ self.add_line('if (!%s) { PyErr_SetString(PyExc_NameError, "%s"); goto %s; }' % | |
(name, name, self.exception_handler_stack[-1])) | |
- return '%s.referent' % (name,) | |
+ return name | |
if name_status == 'SELF': | |
# generate a NameError if we have no wrapped object: | |
@@ -1671,12 +1676,16 @@ class CodeGenerator(LineBufferMixin, NodeVisitor): | |
target_name = target.id | |
name_status = self._get_name_status(target_name) | |
- assert name_status in ('SMART_POINTER', None), 'Cannot assign to a native name.' | |
if name_status is None: | |
# add a declaration of the requisite smart pointer | |
- self.assignment_targets.add_line('PySmartPointer %s;' % (target_name,)) | |
+ self.assignment_targets.add_line('PyObject *%s = NULL;' % (target_name,)) | |
self.assignment_namespace[target_name] = 'SMART_POINTER' | |
+ self.assignment_cleanup.add_line('Py_XDECREF(%s);' % (target_name,)) | |
+ elif name_status == 'NATIVE': | |
+ # XXX check that this is an argument | |
+ self.assignment_targets.add_line('Py_INCREF(%s);' % (target_name,)) | |
+ self.assignment_cleanup.add_line('Py_XDECREF(%s);' % (target_name,)) | |
with self.block_scope(): | |
tempvar = self._make_tempvar() | |
@@ -1685,7 +1694,7 @@ class CodeGenerator(LineBufferMixin, NodeVisitor): | |
# smart pointers always contain a new reference: | |
if not new_ref: | |
self.add_line('Py_INCREF(%s);' % (tempvar,)) | |
- self.add_line('%s.set_referent(%s);' % (target_name, tempvar,)) | |
+ self.add_line('Py_XDECREF(%s); %s = %s;' % (target_name, target_name, tempvar,)) | |
def visit_With(self, with_node, variable_name=None): | |
"""Compile the with statement. See caveats below.""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment