Now accepts U and LL suffixes, and large integer literals are longs rather than being truncated as Python objects.
class IntNode(ConstNode):
+
+ # unsigned "" or "U"
+ # longness "" or "L" or "LL"
+
+ unsigned = ""
+ longness = ""
type = PyrexTypes.c_long_type
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.entry = env.get_py_num(self.value)
+ self.entry = env.get_py_num(self.value, self.longness)
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,
if self.type.is_pyobject:
return self.entry.cname
else:
- return str(self.value)
+ return str(self.value) + self.unsigned + self.longness
def compile_time_value(self, denv):
return int(self.value, 0)
name = letter + Rep(letter | digit)
intconst = decimal | (Str("0x") + Rep1(hexdigit))
- longconst = intconst + Str("L")
+ intsuffix = (Opt(Any("Uu")) + Opt(Any("Ll")) + Opt(Any("Ll"))) | (Opt(Any("Ll")) + Opt(Any("Ll")) + Opt(Any("Uu")))
+ intliteral = intconst + intsuffix
fltconst = (decimal_fract + Opt(exponent)) | (decimal + exponent)
imagconst = (intconst | fltconst) + Any("jJ")
return Lexicon([
(name, 'IDENT'),
- (intconst, 'INT'),
- (longconst, 'LONG'),
+ (intliteral, 'INT'),
(fltconst, 'FLOAT'),
(imagconst, 'IMAG'),
(deco, 'DECORATOR'),
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 entry.init[-1] == "L":
+ code.putln('%s = PyLong_FromString("%s", 0, 0); %s;' % (
+ entry.cname,
+ entry.init,
+ code.error_goto_if_null(entry.cname, self.pos)))
+ else:
+ code.putln("%s = PyInt_FromLong(%s); %s;" % (
+ entry.cname,
+ entry.init,
+ code.error_goto_if_null(entry.cname, self.pos)))
def generate_string_init_code(self, env, code):
if env.all_pystring_entries:
elif sy == 'INT':
value = s.systring
s.next()
- return ExprNodes.IntNode(pos, value = value)
- elif sy == 'LONG':
- value = s.systring
- s.next()
- return ExprNodes.LongNode(pos, value = value)
+ unsigned = ""
+ longness = ""
+ while value[-1] in "UuLl":
+ if value[-1] in "Ll":
+ longness += "L"
+ else:
+ unsigned += "U"
+ value = value[:-1]
+ return ExprNodes.IntNode(pos,
+ value = value,
+ unsigned = unsigned,
+ longness = longness)
elif sy == 'FLOAT':
value = s.systring
s.next()
elif isinstance(value, int):
return ExprNodes.IntNode(pos, value = rep)
elif isinstance(value, long):
- return ExprNodes.LongNode(pos, value = rep)
+ return ExprNodes.IntNode(pos, value = rep, longness = "L")
elif isinstance(value, float):
return ExprNodes.FloatNode(pos, value = rep)
elif isinstance(value, unicode):
self.interned_nums.append(entry)
return entry
- def get_py_num(self, value):
+ def get_py_num(self, value, longness):
# Get entry for int constant. Returns an existing
# one if possible, otherwise creates a new one.
+ if longness or Utils.long_literal(value):
+ value += "L"
genv = self.global_scope()
entry = genv.num_to_entry.get(value)
if not entry:
else:
append(c)
return ''.join(l)
+
+def long_literal(value):
+ if isinstance(value, basestring):
+ if len(value) < 2:
+ value = int(value)
+ elif value[0] == 0:
+ return int(value, 8)
+ elif value[1] in 'xX':
+ return int(value[2:], 16)
+ return not -2**31 <= value < 2**31
--- /dev/null
+__doc__ = """
+ >>> c_longs()
+ (1, 1L, -1L, 18446744073709551615L)
+ >>> py_longs()
+ (1, 1L, 100000000000000000000000000000000L, -100000000000000000000000000000000L)
+"""
+
+def c_longs():
+ cdef long a = 1L
+ cdef unsigned long ua = 1UL
+ cdef long long aa = 0xFFFFFFFFFFFFFFFFLL
+ cdef unsigned long long uaa = 0xFFFFFFFFFFFFFFFFULL
+
+ return a, ua, aa, uaa
+
+def py_longs():
+ return 1, 1L, 100000000000000000000000000000000, -100000000000000000000000000000000