class IntNode(ConstNode):
type = PyrexTypes.c_long_type
+ def analyse_types(self, env):
+ self.entry = env.get_py_num(self.value)
+
+ def coerce_to(self, dst_type, env):
+ # Arrange for a Python version of the string to be pre-allocated
+ # when coercing to a Python type.
+ if dst_type.is_pyobject:
+ self.type = PyrexTypes.py_object_type
+ # We still need to perform normal coerce_to processing on the
+ # result, because we might be coercing to an extension type,
+ # in which case a type test node will be needed.
+ return ConstNode.coerce_to(self, dst_type, env)
+
+ def calculate_result_code(self):
+ if self.type.is_pyobject:
+ return self.entry.cname
+ else:
+ return str(self.value)
class FloatNode(ConstNode):
type = PyrexTypes.c_double_type
def unop_node(pos, operator, operand):
# Construct unnop node of appropriate class for
# given operator.
+ if isinstance(operand, IntNode) and operator == '-':
+ return IntNode(pos = operand.pos, value = -int(operand.value))
return unop_node_classes[operator](pos,
operator = operator,
operand = operand)
if self.type.is_pyobject:
test_result = self.temp_bool.result_code
code.putln(
- "%s = PyObject_IsTrue(%s); %s" % (
+ "%s = __Pyx_PyObject_IsTrue(%s); %s" % (
test_result,
self.operand1.py_result(),
code.error_goto_if_neg(test_result, self.pos)))
code.putln("")
code.putln("/* Implementation of %s */" % env.qualified_name)
self.generate_const_definitions(env, code)
+ self.generate_interned_num_decls(env, code)
self.generate_interned_name_decls(env, code)
self.generate_py_string_decls(env, code)
self.generate_cached_builtins_decls(env, code)
code.error_goto(self.pos)));
def generate_intern_code(self, env, code):
+ for entry in env.pynum_entries:
+ code.putln("%s = PyInt_FromLong(%s); %s;" % (
+ entry.cname,
+ entry.init,
+ code.error_goto_if_null(entry.cname, self.pos)))
if env.intern_map:
env.use_utility_code(Nodes.init_intern_tab_utility_code);
code.putln(
methtab_prefix = pyrex_prefix + "methods_"
memtab_prefix = pyrex_prefix + "members_"
interned_prefix = pyrex_prefix + "n_"
+interned_num_prefix = pyrex_prefix + "num_"
objstruct_prefix = pyrex_prefix + "obj_"
typeptr_prefix = pyrex_prefix + "ptype_"
prop_set_prefix = pyrex_prefix + "setprop_"
for entry in entries:
code.putln(
"static PyObject *%s;" % entry.pystring_cname)
+
+ def generate_interned_num_decls(self, env, code):
+ # Flush accumulated interned nums from the global scope
+ # and generate declarations for them.
+ genv = env.global_scope()
+ entries = genv.interned_nums
+ if entries:
+ code.putln("")
+ for entry in entries:
+ code.putln(
+ "static PyObject *%s;" % entry.cname)
+ del entries[:]
def generate_cached_builtins_decls(self, env, code):
entries = env.builtin_scope().undeclared_cached_entries
# Code for nested function definitions would go here
# if we supported them, which we probably won't.
# ----- Top-level constants used by this function
+ self.generate_interned_num_decls(lenv, code)
self.generate_interned_name_decls(lenv, code)
self.generate_py_string_decls(lenv, code)
self.generate_cached_builtins_decls(lenv, code)
# free_temp_entries [Entry] Temp variables currently unused
# temp_counter integer Counter for naming temp vars
# cname_to_entry {string : Entry} Temp cname to entry mapping
+ # int_to_entry {int : Entry} Temp cname to entry mapping
# pow_function_used boolean The C pow() function is used
# return_type PyrexType or None Return type of function owning scope
# is_py_class_scope boolean Is a Python class scope
self.cname_to_entry = {}
self.pow_function_used = 0
self.string_to_entry = {}
+ self.num_to_entry = {}
self.pystring_entries = []
def __str__(self):
entry.pystring_cname = entry.cname + "p"
self.pystring_entries.append(entry)
self.global_scope().all_pystring_entries.append(entry)
+
+ def add_py_num(self, value):
+ # Add an entry for an int constant.
+ cname = "%s%s" % (Naming.interned_num_prefix, value)
+ cname = cname.replace('-', 'neg_').replace('.','_')
+ entry = Entry("", cname, c_long_type, init = value)
+ entry.used = 1
+ entry.is_interned = 1
+ self.const_entries.append(entry)
+ self.interned_nums.append(entry)
+ return entry
+
+ def get_py_num(self, value):
+ # Get entry for int constant. Returns an existing
+ # one if possible, otherwise creates a new one.
+ genv = self.global_scope()
+ entry = genv.num_to_entry.get(value)
+ if not entry:
+ entry = genv.add_py_num(value)
+ genv.num_to_entry[value] = entry
+ genv.pynum_entries.append(entry)
+ return entry
def new_const_cname(self):
# Create a new globally-unique name for a constant.
self.cimported_modules = []
self.intern_map = {}
self.interned_names = []
+ self.interned_nums = []
self.all_pystring_entries = []
self.types_imported = {}
+ self.pynum_entries = []
def qualifying_scope(self):
return self.parent_module