self.closure_temps = ClosureTempAllocator(scope)
-class IntConst(object):
- """Global info about a Python integer constant held by GlobalState.
+class NumConst(object):
+ """Global info about a Python number constant held by GlobalState.
+
+ cname string
+ value string
+ py_type string int, long, float
+ value_code string evaluation code if different from value
"""
- # cname string
- # value int
- # is_long boolean
- def __init__(self, cname, value, is_long):
+ def __init__(self, cname, value, py_type, value_code=None):
self.cname = cname
self.value = value
- self.is_long = is_long
+ self.py_type = py_type
+ self.value_code = value_code or value
+
class PyObjectConst(object):
"""Global info about a generic constant held by GlobalState.
self.cname = cname
self.type = type
+
cython.declare(possible_unicode_identifier=object, possible_bytes_identifier=object,
replace_identifier=object, find_alphanums=object)
possible_unicode_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
self.const_cnames_used = {}
self.string_const_index = {}
self.pyunicode_ptr_const_index = {}
- self.int_const_index = {}
+ self.num_const_index = {}
self.py_constants = []
assert writer.globalstate is None
return self.parts['cached_constants']
def get_int_const(self, str_value, longness=False):
- longness = bool(longness)
+ py_type = longness and 'long' or 'int'
try:
- c = self.int_const_index[(str_value, longness)]
+ c = self.num_const_index[(str_value, py_type)]
except KeyError:
- c = self.new_int_const(str_value, longness)
+ c = self.new_num_const(str_value, py_type)
+ return c
+
+ def get_float_const(self, str_value, value_code):
+ try:
+ c = self.num_const_index[(str_value, 'float')]
+ except KeyError:
+ c = self.new_num_const(str_value, 'float', value_code)
return c
def get_py_const(self, type, prefix='', cleanup_level=None):
self.string_const_index[byte_string] = c
return c
- def new_int_const(self, value, longness):
- cname = self.new_int_const_cname(value, longness)
- c = IntConst(cname, value, longness)
- self.int_const_index[(value, longness)] = c
+ def new_num_const(self, value, py_type, value_code=None):
+ cname = self.new_num_const_cname(value, py_type)
+ c = NumConst(cname, value, py_type, value_code)
+ self.num_const_index[(value, py_type)] = c
return c
def new_py_const(self, type, prefix=''):
value = bytes_value.decode('ASCII', 'ignore')
return self.new_const_cname(value=value)
- def new_int_const_cname(self, value, longness):
- if longness:
+ def new_num_const_cname(self, value, py_type):
+ prefix = Naming.interned_int_prefix
+ if py_type == 'long':
value += 'L'
- cname = "%s%s" % (Naming.interned_num_prefix, value)
- cname = cname.replace('-', 'neg_').replace('.','_')
+ elif py_type == 'float':
+ prefix = Naming.interned_float_prefix
+ cname = "%s%s" % (prefix, value)
+ cname = cname.replace('-', 'neg_').replace('.', '_')
return cname
def new_const_cname(self, prefix='', value=''):
def generate_const_declarations(self):
self.generate_string_constants()
- self.generate_int_constants()
+ self.generate_num_constants()
self.generate_object_constant_decls()
def generate_object_constant_decls(self):
Naming.stringtab_cname,
init_globals.error_goto(self.module_pos)))
- def generate_int_constants(self):
- consts = [ (len(c.value), c.value, c.is_long, c)
- for c in self.int_const_index.values() ]
+ def generate_num_constants(self):
+ consts = [(c.py_type, len(c.value), c.value, c.value_code, c)
+ for c in self.num_const_index.values()]
consts.sort()
decls_writer = self.parts['decls']
- for _, value, longness, c in consts:
+ init_globals = self.parts['init_globals']
+ for py_type, _, value, value_code, c in consts:
cname = c.cname
decls_writer.putln("static PyObject *%s;" % cname)
- if longness:
+ if py_type == 'float':
+ function = '%s = PyFloat_FromDouble(%s); %s;'
+ elif py_type == 'long':
function = '%s = PyLong_FromString((char *)"%s", 0, 0); %s;'
elif Utils.long_literal(value):
function = '%s = PyInt_FromString((char *)"%s", 0, 0); %s;'
else:
function = "%s = PyInt_FromLong(%s); %s;"
- init_globals = self.parts['init_globals']
init_globals.putln(function % (
- cname,
- value,
+ cname, value_code,
init_globals.error_goto_if_null(cname, self.module_pos)))
# The functions below are there in a transition phase only
# constant handling
- def get_py_num(self, str_value, longness):
+ def get_py_int(self, str_value, longness):
return self.globalstate.get_int_const(str_value, longness).cname
+ def get_py_float(self, str_value, value_code):
+ return self.globalstate.get_float_const(str_value, value_code).cname
+
def get_py_const(self, type, prefix='', cleanup_level=None):
return self.globalstate.get_py_const(type, prefix, cleanup_level).cname
if self.type.is_pyobject:
# pre-allocate a Python version of the number
plain_integer_string = self.value_as_c_integer_string(plain_digits=True)
- self.result_code = code.get_py_num(plain_integer_string, self.longness)
+ self.result_code = code.get_py_int(plain_integer_string, self.longness)
else:
self.result_code = self.get_constant_c_result_code()
def compile_time_value(self, denv):
return float(self.value)
+ def coerce_to(self, dst_type, env):
+ if dst_type.is_pyobject and self.type.is_float:
+ return FloatNode(
+ self.pos, value=self.value,
+ constant_result=self.constant_result,
+ type=Builtin.float_type)
+ return ConstNode.coerce_to(self, dst_type, env)
+
def calculate_result_code(self):
+ return self.result_code
+
+ def as_c_constant(self):
strval = self.value
assert isinstance(strval, (str, unicode))
cmpval = repr(float(strval))
else:
return strval
+ def generate_evaluation_code(self, code):
+ if self.type.is_pyobject:
+ self.result_code = code.get_py_float(
+ self.value, self.as_c_constant())
+ else:
+ self.result_code = self.as_c_constant()
+
class BytesNode(ConstNode):
# A char* or bytes literal