import Symtab
import Options
from Annotate import AnnotationItem
+from Cython import Utils
from Cython.Debugging import print_call_chain
from DebugFlags import debug_disposal_code, debug_temp_alloc, \
self.result_code = self.get_constant_c_result_code()
def get_constant_c_result_code(self):
- return str(self.value) + self.unsigned + self.longness
+ value = self.value
+ if isinstance(value, basestring) and len(value) > 2:
+ # must convert C-incompatible Py3 oct/bin notations
+ if value[1] in 'oO':
+ value = value[0] + value[2:] # '0o123' => '0123'
+ elif value[1] in 'bB':
+ value = int(value[2:], 2)
+ return str(value) + self.unsigned + self.longness
def calculate_result_code(self):
return self.result_code
def calculate_constant_result(self):
- self.constant_result = int(self.value, 0)
+ self.constant_result = Utils.str_to_number(self.value)
def compile_time_value(self, denv):
- return int(self.value, 0)
+ return Utils.str_to_number(self.value)
class FloatNode(ConstNode):
type = py_object_type
def calculate_constant_result(self):
- self.constant_result = long(self.value)
+ self.constant_result = Utils.str_to_number(self.value)
def compile_time_value(self, denv):
- return long(self.value)
+ return Utils.str_to_number(self.value)
def analyse_types(self, env):
self.is_temp = 1
letter = Any("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_")
digit = Any("0123456789")
+ bindigit = Any("01")
octdigit = Any("01234567")
hexdigit = Any("0123456789ABCDEFabcdef")
indentation = Bol + Rep(Any(" \t"))
decimal_fract = (decimal + dot + Opt(decimal)) | (dot + decimal)
name = letter + Rep(letter | digit)
- intconst = decimal | (Str("0x") + Rep1(hexdigit))
+ intconst = decimal | (Str("0") + ((Any("Xx") + Rep1(hexdigit)) |
+ (Any("Oo") + Rep1(octdigit)) |
+ (Any("Bb") + Rep1(bindigit)) ))
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)
punct = Any(":,;+-*/|&<>=.%`~^?")
diphthong = Str("==", "<>", "!=", "<=", ">=", "<<", ">>", "**", "//",
"+=", "-=", "*=", "/=", "%=", "|=", "^=", "&=",
- "<<=", ">>=", "**=", "//=")
+ "<<=", ">>=", "**=", "//=", "->")
spaces = Rep1(Any(" \t\f"))
escaped_newline = Str("\\\n")
lineterm = Eol + Opt(Str("\n"))
# not_none boolean Tagged with 'not None'
# default ExprNode or None
# default_value PyObjectConst constant for default value
+ # annotation ExprNode or None Py3 function arg annotation
# is_self_arg boolean Is the "self" arg of an extension type method
# is_kw_only boolean Is a keyword-only argument
type = None
name_declarator = None
default_value = None
+ annotation = None
def analyse(self, env, nonempty = 0):
#print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
# Argument which must be a Python object (used
# for * and ** arguments).
#
- # name string
- # entry Symtab.Entry
+ # name string
+ # entry Symtab.Entry
+ # annotation ExprNode or None Py3 argument annotation
child_attrs = []
# starstar_arg PyArgDeclNode or None ** argument
# doc EncodedString or None
# body StatListNode
+ # return_type_annotation
+ # ExprNode or None the Py3 return type annotation
#
# The following subnode is constructed internally
# when the def statement is inside a Python class definition.
reqd_kw_flags_cname = "0"
is_wrapper = 0
decorators = None
+ return_type_annotation = None
entry = None
acquire_gil = 0
cfunc_type = cfunc.type
if len(self.args) != len(cfunc_type.args) or cfunc_type.has_varargs:
error(self.pos, "wrong number of arguments")
- error(declarator.pos, "previous declaration here")
+ error(cfunc.pos, "previous declaration here")
for formal_arg, type_arg in zip(self.args, cfunc_type.args):
name_declarator, type = formal_arg.analyse(cfunc.scope, nonempty=1)
if type is None or type is PyrexTypes.py_object_type or formal_arg.is_self:
cpdef p_with_gil(PyrexScanner s)
cpdef p_exception_value_clause(PyrexScanner s)
cpdef p_c_arg_list(PyrexScanner s, ctx = *, bint in_pyfunc = *, bint cmethod_flag = *,
- bint nonempty_declarators = *, bint kw_only = *)
+ bint nonempty_declarators = *, bint kw_only = *, bint annotated = *)
cpdef p_optional_ellipsis(PyrexScanner s)
-cpdef p_c_arg_decl(PyrexScanner s, ctx, in_pyfunc, bint cmethod_flag = *, bint nonempty = *, bint kw_only = *)
+cpdef p_c_arg_decl(PyrexScanner s, ctx, in_pyfunc, bint cmethod_flag = *, bint nonempty = *, bint kw_only = *, bint annotated = *)
cpdef p_api(PyrexScanner s)
cpdef p_cdef_statement(PyrexScanner s, ctx)
cpdef p_cdef_block(PyrexScanner s, ctx)
cpdef p_ctypedef_statement(PyrexScanner s, ctx)
cpdef p_decorators(PyrexScanner s)
cpdef p_def_statement(PyrexScanner s, list decorators = *)
-cpdef p_varargslist(PyrexScanner s, terminator=*)
+cpdef p_varargslist(PyrexScanner s, terminator=*, bint annotated = *)
cpdef p_py_arg_decl(PyrexScanner s)
cpdef p_class_statement(PyrexScanner s, decorators)
cpdef p_c_class_definition(PyrexScanner s, pos, ctx)
args = []
star_arg = starstar_arg = None
else:
- args, star_arg, starstar_arg = p_varargslist(s, terminator=':')
+ args, star_arg, starstar_arg = p_varargslist(
+ s, terminator=':', annotated=False)
s.expect(':')
if allow_conditional:
expr = p_simple_expr(s)
imported_names = [p_imported_name(s, is_cimport)]
while s.sy == ',':
s.next()
+ if is_parenthesized and s.sy == ')':
+ break
imported_names.append(p_imported_name(s, is_cimport))
if is_parenthesized:
s.expect(')')
exc_value = None
if s.sy != ':':
exc_type = p_simple_expr(s)
- if s.sy == ',':
+ if s.sy == ',' or (s.sy == 'IDENT' and s.systring == 'as'):
s.next()
exc_value = p_simple_expr(s)
body = p_suite(s)
elif s.sy == 'IF':
return p_IF_statement(s, ctx)
elif s.sy == 'DECORATOR':
- if ctx.level not in ('module', 'class', 'c_class', 'property', 'module_pxd', 'c_class_pxd'):
+ if ctx.level not in ('module', 'class', 'c_class', 'function', 'property', 'module_pxd', 'c_class_pxd'):
print ctx.level
s.error('decorator not allowed here')
s.level = ctx.level
c_arg_list_terminators = ('*', '**', '.', ')')
def p_c_arg_list(s, ctx = Ctx(), in_pyfunc = 0, cmethod_flag = 0,
- nonempty_declarators = 0, kw_only = 0):
+ nonempty_declarators = 0, kw_only = 0, annotated = 1):
# Comma-separated list of C argument declarations, possibly empty.
# May have a trailing comma.
args = []
is_self_arg = cmethod_flag
while s.sy not in c_arg_list_terminators:
args.append(p_c_arg_decl(s, ctx, in_pyfunc, is_self_arg,
- nonempty = nonempty_declarators, kw_only = kw_only))
+ nonempty = nonempty_declarators, kw_only = kw_only,
+ annotated = annotated))
if s.sy != ',':
break
s.next()
else:
return 0
-def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0):
+def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0,
+ kw_only = 0, annotated = 1):
pos = s.position()
not_none = 0
default = None
+ annotation = None
base_type = p_c_base_type(s, cmethod_flag, nonempty = nonempty)
declarator = p_c_declarator(s, ctx, nonempty = nonempty)
if s.sy == 'not':
if not in_pyfunc:
error(pos, "'not None' only allowed in Python functions")
not_none = 1
+ if annotated and s.sy == ':':
+ s.next()
+ annotation = p_simple_expr(s)
if s.sy == '=':
s.next()
if 'pxd' in s.level:
declarator = declarator,
not_none = not_none,
default = default,
+ annotation = annotation,
kw_only = kw_only)
def p_api(s):
s.expect(')')
if p_nogil(s):
error(s.pos, "Python function cannot be declared nogil")
+ return_type_annotation = None
+ if s.sy == '->':
+ s.next()
+ return_type_annotation = p_simple_expr(s)
doc, body = p_suite(s, Ctx(level = 'function'), with_doc = 1)
return Nodes.DefNode(pos, name = name, args = args,
star_arg = star_arg, starstar_arg = starstar_arg,
- doc = doc, body = body, decorators = decorators)
+ doc = doc, body = body, decorators = decorators,
+ return_type_annotation = return_type_annotation)
-def p_varargslist(s, terminator=')'):
- args = p_c_arg_list(s, in_pyfunc = 1, nonempty_declarators = 1)
+def p_varargslist(s, terminator=')', annotated=1):
+ args = p_c_arg_list(s, in_pyfunc = 1, nonempty_declarators = 1,
+ annotated = annotated)
star_arg = None
starstar_arg = None
if s.sy == '*':
def p_py_arg_decl(s):
pos = s.position()
name = p_ident(s)
- return Nodes.PyArgDeclNode(pos, name = name)
+ annotation = None
+ if s.sy == ':':
+ s.next()
+ annotation = p_simple_expr(s)
+ return Nodes.PyArgDeclNode(pos, name = name, annotation = annotation)
def p_class_statement(s, decorators):
# s.sy == 'class'
encoding = detect_file_encoding(source_filename)
return codecs.open(source_filename, mode=mode, encoding=encoding)
-def long_literal(value):
- if isinstance(value, basestring):
- if len(value) < 2:
- value = int(value)
- elif value[0] == 0:
- value = int(value, 8)
- elif value[1] in 'xX':
+def str_to_number(value):
+ # note: this expects a string as input that was accepted by the
+ # parser already
+ if len(value) < 2:
+ value = int(value, 0)
+ elif value[0] == '0':
+ if value[1] in 'xX':
+ # hex notation ('0x1AF')
value = int(value[2:], 16)
+ elif value[1] in 'oO':
+ # Py3 octal notation ('0o136')
+ value = int(value[2:], 8)
+ elif value[1] in 'bB':
+ # Py3 binary notation ('0b101')
+ value = int(value[2:], 2)
else:
- value = int(value)
+ # Py2 octal notation ('0136')
+ value = int(value, 8)
+ else:
+ value = int(value, 0)
+ return value
+
+def long_literal(value):
+ if isinstance(value, basestring):
+ value = str_to_number(value)
return not -2**31 <= value < 2**31
def none_or_sub(s, data):