'all_the_rest',
'pystring_table',
'cached_builtins',
+ 'cached_constants',
'init_globals',
'init_module',
'cleanup_globals',
w.enter_cfunc_scope()
w.putln("static int __Pyx_InitCachedBuiltins(void) {")
-
+ w = self.parts['cached_constants']
+ w.enter_cfunc_scope()
+ w.putln("")
+ w.putln("static int __Pyx_InitCachedConstants(void) {")
+ w.put_setup_refcount_context("__Pyx_InitCachedConstants")
+
w = self.parts['init_globals']
w.enter_cfunc_scope()
w.putln("")
if Options.cache_builtins:
w = self.parts['cached_builtins']
w.putln("return 0;")
- w.put_label(w.error_label)
- w.putln("return -1;")
+ if w.label_used(w.error_label):
+ w.put_label(w.error_label)
+ w.putln("return -1;")
w.putln("}")
w.exit_cfunc_scope()
+ w = self.parts['cached_constants']
+ w.put_finish_refcount_context()
+ w.putln("return 0;")
+ if w.label_used(w.error_label):
+ w.put_label(w.error_label)
+ w.put_finish_refcount_context()
+ w.putln("return -1;")
+ w.putln("}")
+ w.exit_cfunc_scope()
+
w = self.parts['init_globals']
w.putln("return 0;")
- w.put_label(w.error_label)
- w.putln("return -1;")
+ if w.label_used(w.error_label):
+ w.put_label(w.error_label)
+ w.putln("return -1;")
w.putln("}")
w.exit_cfunc_scope()
# constant handling at code generation time
+ def get_cached_constants_writer(self):
+ return self.parts['cached_constants']
+
+ def get_globals_cleanup_writer(self):
+ return self.parts['cleanup_globals']
+
def get_int_const(self, str_value, longness=False):
longness = bool(longness)
try:
c = self.new_int_const(str_value, longness)
return c
- def get_py_const(self, type):
+ def get_py_const(self, type, prefix=''):
# create a new Python object constant
- return self.new_py_const(type)
+ return self.new_py_const(type, prefix)
def get_string_const(self, text):
# return a C string constant, creating a new one if necessary
self.int_const_index[(value, longness)] = c
return c
- def new_py_const(self, type):
- cname = self.new_const_cname()
+ def new_py_const(self, type, prefix=''):
+ cname = self.new_const_cname(prefix)
c = PyObjectConst(cname, type)
self.py_constants.append(c)
return c
def get_py_num(self, str_value, longness):
return self.globalstate.get_int_const(str_value, longness).cname
+ def get_py_const(self, type, prefix=''):
+ return self.globalstate.get_py_const(type, prefix).cname
+
def get_string_const(self, text):
return self.globalstate.get_string_const(text).cname
def intern_identifier(self, text):
return self.get_py_string_const(text, identifier=True)
+ def get_cached_constants_writer(self):
+ return self.globalstate.get_cached_constants_writer()
+
+ def get_globals_cleanup_writer(self):
+ return self.globalstate.get_globals_cleanup_writer()
+
# code generation
def putln(self, code = "", safe=False):
self.is_literal = 1
else:
SequenceNode.analyse_types(self, env, skip_children)
+ for child in self.args:
+ if not child.is_literal:
+ break
+ else:
+ self.is_temp = 0
+ self.is_literal = 1
def calculate_result_code(self):
if len(self.args) > 0:
- error(self.pos, "Positive length tuples must be constructed.")
+ return self.result_code
else:
return Naming.empty_tuple
if len(self.args) == 0:
# result_code is Naming.empty_tuple
return
+ if self.is_literal:
+ # non-empty cached tuple => result is global constant,
+ # creation code goes into separate code writer
+ self.result_code = code.get_py_const(py_object_type, 'tuple_')
+ if Options.generate_cleanup_code >= 2:
+ cleanup_writer = code.get_globals_cleanup_writer()
+ cleanup_writer.put_xdecref_clear(self.result(), py_object_type, nanny=False)
+ code = code.get_cached_constants_writer()
+ code.mark_pos(self.pos)
+
code.putln(
"%s = PyTuple_New(%s); %s" % (
self.result(),
i,
arg.py_result()))
code.put_giveref(arg.py_result())
+ if self.is_literal:
+ code.put_giveref(self.py_result())
def generate_subexpr_disposal_code(self, code):
# We call generate_post_assignment_code here instead