Commit 7148a1a7 authored by Robert Bradshaw's avatar Robert Bradshaw

Merge closures into main development branch.

parents 8d4fdaad 48d7588a
......@@ -415,7 +415,7 @@ def init_builtins():
init_builtin_structs()
global list_type, tuple_type, dict_type, set_type, frozenset_type
global bytes_type, str_type, unicode_type
global float_type, bool_type, type_type
global float_type, bool_type, type_type, complex_type
type_type = builtin_scope.lookup('type').type
list_type = builtin_scope.lookup('list').type
tuple_type = builtin_scope.lookup('tuple').type
......@@ -427,5 +427,6 @@ def init_builtins():
unicode_type = builtin_scope.lookup('unicode').type
float_type = builtin_scope.lookup('float').type
bool_type = builtin_scope.lookup('bool').type
complex_type = builtin_scope.lookup('complex').type
init_builtins()
......@@ -407,6 +407,7 @@ class GlobalState(object):
code_layout = [
'h_code',
'filename_table',
'utility_code_proto_before_types',
'numeric_typedefs', # Let these detailed individual parts stay!,
'complex_type_declarations', # as the proper solution is to make a full DAG...
......@@ -425,7 +426,6 @@ class GlobalState(object):
'cleanup_globals',
'cleanup_module',
'main_method',
'filename_table',
'utility_code_def',
'end'
]
......@@ -484,11 +484,6 @@ class GlobalState(object):
code.write('\n#line 1 "cython_utility"\n')
code.putln("")
code.putln("/* Runtime support code */")
code.putln("")
code.putln("static void %s(void) {" % Naming.fileinit_cname)
code.putln("%s = %s;" %
(Naming.filetable_cname, Naming.filenames_cname))
code.putln("}")
def finalize_main_c_code(self):
self.close_global_decls()
......
......@@ -70,7 +70,7 @@ class ControlFlow(object):
if current is None:
return (None, None)
state = current._get_pos_state_local(item, pos)
while state is None and current.incoming is not None:
while (state is None or state == (None, None)) and current.incoming is not None:
current = current.incoming
state = current._get_pos_state_local(item, pos)
if state is None:
......
......@@ -12,7 +12,8 @@ import Naming
import Nodes
from Nodes import Node
import PyrexTypes
from PyrexTypes import py_object_type, c_long_type, typecast, error_type, unspecified_type
from PyrexTypes import py_object_type, c_long_type, typecast, error_type, \
unspecified_type
from Builtin import list_type, tuple_type, set_type, dict_type, \
unicode_type, str_type, bytes_type, type_type
import Builtin
......@@ -20,6 +21,7 @@ import Symtab
import Options
from Cython import Utils
from Annotate import AnnotationItem
from Cython import Utils
from Cython.Debugging import print_call_chain
from DebugFlags import debug_disposal_code, debug_temp_alloc, \
......@@ -519,6 +521,9 @@ class ExprNode(Node):
for sub in self.subexpr_nodes():
sub.free_temps(code)
def generate_function_definitions(self, env, code):
pass
# ---------------- Annotation ---------------------
def annotate(self, code):
......@@ -827,16 +832,23 @@ class IntNode(ConstNode):
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):
......@@ -1056,10 +1068,10 @@ class LongNode(AtomicExprNode):
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
......@@ -1289,7 +1301,7 @@ class NameNode(AtomicExprNode):
else:
type = py_object_type
self.entry = env.declare_var(self.name, type, self.pos)
env.control_flow.set_state(self.pos, (self.name, 'initalized'), True)
env.control_flow.set_state(self.pos, (self.name, 'initialized'), True)
env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment')
if self.entry.is_declared_generic:
self.result_ctype = py_object_type
......@@ -1434,13 +1446,13 @@ class NameNode(AtomicExprNode):
elif entry.is_local and False:
# control flow not good enough yet
assigned = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
assigned = entry.scope.control_flow.get_state((entry.name, 'initialized'), self.pos)
if assigned is False:
error(self.pos, "local variable '%s' referenced before assignment" % entry.name)
elif not Options.init_local_none and assigned is None:
code.putln('if (%s == 0) { PyErr_SetString(PyExc_UnboundLocalError, "%s"); %s }' %
(entry.cname, entry.name, code.error_goto(self.pos)))
entry.scope.control_flow.set_state(self.pos, (entry.name, 'initalized'), True)
entry.scope.control_flow.set_state(self.pos, (entry.name, 'initialized'), True)
def generate_assignment_code(self, rhs, code):
#print "NameNode.generate_assignment_code:", self.name ###
......@@ -1502,19 +1514,20 @@ class NameNode(AtomicExprNode):
rhs.make_owned_reference(code)
if entry.is_cglobal:
code.put_gotref(self.py_result())
if self.use_managed_ref and not self.lhs_of_first_assignment:
if entry.is_local and not Options.init_local_none:
initalized = entry.scope.control_flow.get_state((entry.name, 'initalized'), self.pos)
if initalized is True:
if not self.lhs_of_first_assignment:
if entry.is_local and not Options.init_local_none:
initialized = entry.scope.control_flow.get_state((entry.name, 'initialized'), self.pos)
if initialized is True:
code.put_decref(self.result(), self.ctype())
elif initialized is None:
code.put_xdecref(self.result(), self.ctype())
else:
code.put_decref(self.result(), self.ctype())
elif initalized is None:
code.put_xdecref(self.result(), self.ctype())
else:
code.put_decref(self.result(), self.ctype())
if self.use_managed_ref:
if entry.is_cglobal:
code.put_giveref(rhs.py_result())
code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
code.putln('%s = %s;' % (self.result(),
rhs.result_as(self.ctype())))
if debug_disposal_code:
print("NameNode.generate_assignment_code:")
print("...generating post-assignment code for %s" % rhs)
......@@ -3916,21 +3929,71 @@ class ListNode(SequenceNode):
# generate_evaluation_code which will do that.
class ComprehensionNode(ExprNode):
class ScopedExprNode(ExprNode):
# Abstract base class for ExprNodes that have their own local
# scope, such as generator expressions.
#
# expr_scope Scope the inner scope of the expression
subexprs = []
expr_scope = None
def analyse_types(self, env):
# nothing to do here, the children will be analysed separately
pass
def analyse_expressions(self, env):
# nothing to do here, the children will be analysed separately
pass
def analyse_scoped_expressions(self, env):
# this is called with the expr_scope as env
pass
def init_scope(self, outer_scope, expr_scope=None):
self.expr_scope = expr_scope
class ComprehensionNode(ScopedExprNode):
subexprs = ["target"]
child_attrs = ["loop", "append"]
# leak loop variables or not? non-leaking Py3 behaviour is
# default, except for list comprehensions where the behaviour
# differs in Py2 and Py3 (see Parsing.py)
has_local_scope = True
def infer_type(self, env):
return self.target.infer_type(env)
def analyse_declarations(self, env):
self.append.target = self # this is used in the PyList_Append of the inner loop
self.loop.analyse_declarations(env)
self.init_scope(env)
if self.expr_scope is not None:
self.loop.analyse_declarations(self.expr_scope)
else:
self.loop.analyse_declarations(env)
def init_scope(self, outer_scope, expr_scope=None):
if expr_scope is not None:
self.expr_scope = expr_scope
elif self.has_local_scope:
self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope)
else:
self.expr_scope = None
def analyse_types(self, env):
self.target.analyse_expressions(env)
self.type = self.target.type
self.loop.analyse_expressions(env)
if not self.has_local_scope:
self.loop.analyse_expressions(env)
def analyse_expressions(self, env):
self.analyse_types(env)
def analyse_scoped_expressions(self, env):
if self.has_local_scope:
self.loop.analyse_expressions(env)
def may_be_none(self):
return False
......@@ -3948,20 +4011,20 @@ class ComprehensionNode(ExprNode):
self.loop.annotate(code)
class ComprehensionAppendNode(ExprNode):
class ComprehensionAppendNode(Node):
# Need to be careful to avoid infinite recursion:
# target must not be in child_attrs/subexprs
subexprs = ['expr']
child_attrs = ['expr']
type = PyrexTypes.c_int_type
def analyse_types(self, env):
self.expr.analyse_types(env)
def analyse_expressions(self, env):
self.expr.analyse_expressions(env)
if not self.expr.type.is_pyobject:
self.expr = self.expr.coerce_to_pyobject(env)
self.is_temp = 1
def generate_result_code(self, code):
def generate_execution_code(self, code):
if self.target.type is list_type:
function = "PyList_Append"
elif self.target.type is set_type:
......@@ -3969,33 +4032,115 @@ class ComprehensionAppendNode(ExprNode):
else:
raise InternalError(
"Invalid type for comprehension node: %s" % self.target.type)
code.putln("%s = %s(%s, (PyObject*)%s); %s" %
(self.result(),
function,
self.target.result(),
self.expr.result(),
code.error_goto_if(self.result(), self.pos)))
self.expr.generate_evaluation_code(code)
code.putln(code.error_goto_if("%s(%s, (PyObject*)%s)" % (
function,
self.target.result(),
self.expr.result()
), self.pos))
self.expr.generate_disposal_code(code)
self.expr.free_temps(code)
def generate_function_definitions(self, env, code):
self.expr.generate_function_definitions(env, code)
def annotate(self, code):
self.expr.annotate(code)
class DictComprehensionAppendNode(ComprehensionAppendNode):
subexprs = ['key_expr', 'value_expr']
child_attrs = ['key_expr', 'value_expr']
def analyse_types(self, env):
self.key_expr.analyse_types(env)
def analyse_expressions(self, env):
self.key_expr.analyse_expressions(env)
if not self.key_expr.type.is_pyobject:
self.key_expr = self.key_expr.coerce_to_pyobject(env)
self.value_expr.analyse_types(env)
self.value_expr.analyse_expressions(env)
if not self.value_expr.type.is_pyobject:
self.value_expr = self.value_expr.coerce_to_pyobject(env)
self.is_temp = 1
def generate_execution_code(self, code):
self.key_expr.generate_evaluation_code(code)
self.value_expr.generate_evaluation_code(code)
code.putln(code.error_goto_if("PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s)" % (
self.target.result(),
self.key_expr.result(),
self.value_expr.result()
), self.pos))
self.key_expr.generate_disposal_code(code)
self.key_expr.free_temps(code)
self.value_expr.generate_disposal_code(code)
self.value_expr.free_temps(code)
def generate_function_definitions(self, env, code):
self.key_expr.generate_function_definitions(env, code)
self.value_expr.generate_function_definitions(env, code)
def annotate(self, code):
self.key_expr.annotate(code)
self.value_expr.annotate(code)
class GeneratorExpressionNode(ScopedExprNode):
# A generator expression, e.g. (i for i in range(10))
#
# Result is a generator.
#
# loop ForStatNode the for-loop, containing a YieldExprNode
child_attrs = ["loop"]
type = py_object_type
def analyse_declarations(self, env):
self.init_scope(env)
self.loop.analyse_declarations(self.expr_scope)
def init_scope(self, outer_scope, expr_scope=None):
if expr_scope is not None:
self.expr_scope = expr_scope
else:
self.expr_scope = Symtab.GeneratorExpressionScope(outer_scope)
def analyse_types(self, env):
self.is_temp = True
def analyse_scoped_expressions(self, env):
self.loop.analyse_expressions(env)
def may_be_none(self):
return False
def annotate(self, code):
self.loop.annotate(code)
class InlinedGeneratorExpressionNode(GeneratorExpressionNode):
# An inlined generator expression for which the result is
# calculated inside of the loop. This will only be created by
# transforms when replacing builtin calls on generator
# expressions.
#
# loop ForStatNode the for-loop, not containing any YieldExprNodes
# result_node ResultRefNode the reference to the result value temp
# orig_func String the name of the builtin function this node replaces
child_attrs = ["loop"]
def analyse_types(self, env):
self.type = self.result_node.type
self.is_temp = True
def coerce_to(self, dst_type, env):
if self.orig_func == 'sum' and dst_type.is_numeric:
# we can optimise by dropping the aggregation variable into C
self.result_node.type = self.type = dst_type
return self
return GeneratorExpressionNode.coerce_to(self, dst_type, env)
def generate_result_code(self, code):
code.putln("%s = PyDict_SetItem(%s, (PyObject*)%s, (PyObject*)%s); %s" %
(self.result(),
self.target.result(),
self.key_expr.result(),
self.value_expr.result(),
code.error_goto_if(self.result(), self.pos)))
self.result_node.result_code = self.result()
self.loop.generate_execution_code(code)
class SetNode(ExprNode):
......@@ -4240,6 +4385,32 @@ class ClassNode(ExprNode):
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.py_result())
class BoundMethodNode(ExprNode):
# Helper class used in the implementation of Python
# class definitions. Constructs an bound method
# object from a class and a function.
#
# function ExprNode Function object
# self_object ExprNode self object
subexprs = ['function']
def analyse_types(self, env):
self.function.analyse_types(env)
self.type = py_object_type
self.is_temp = 1
gil_message = "Constructing an bound method"
def generate_result_code(self, code):
code.putln(
"%s = PyMethod_New(%s, %s, (PyObject*)%s->ob_type); %s" % (
self.result(),
self.function.py_result(),
self.self_object.py_result(),
self.self_object.py_result(),
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.py_result())
class UnboundMethodNode(ExprNode):
# Helper class used in the implementation of Python
......@@ -4272,32 +4443,108 @@ class UnboundMethodNode(ExprNode):
code.put_gotref(self.py_result())
class PyCFunctionNode(AtomicExprNode):
class PyCFunctionNode(ExprNode):
# Helper class used in the implementation of Python
# class definitions. Constructs a PyCFunction object
# from a PyMethodDef struct.
#
# pymethdef_cname string PyMethodDef structure
# self_object ExprNode or None
# binding bool
subexprs = []
self_object = None
binding = False
type = py_object_type
is_temp = 1
def analyse_types(self, env):
pass
if self.binding:
env.use_utility_code(binding_cfunc_utility_code)
def may_be_none(self):
return False
gil_message = "Constructing Python function"
def self_result_code(self):
if self.self_object is None:
self_result = "NULL"
else:
self_result = self.self_object.py_result()
return self_result
def generate_result_code(self, code):
if self.binding:
constructor = "%s_New" % Naming.binding_cfunc
else:
constructor = "PyCFunction_New"
code.putln(
"%s = PyCFunction_New(&%s, 0); %s" % (
"%s = %s(&%s, %s); %s" % (
self.result(),
constructor,
self.pymethdef_cname,
self.self_result_code(),
code.error_goto_if_null(self.result(), self.pos)))
code.put_gotref(self.py_result())
class InnerFunctionNode(PyCFunctionNode):
# Special PyCFunctionNode that depends on a closure class
#
binding = True
def self_result_code(self):
return "((PyObject*)%s)" % Naming.cur_scope_cname
class LambdaNode(InnerFunctionNode):
# Lambda expression node (only used as a function reference)
#
# args [CArgDeclNode] formal arguments
# star_arg PyArgDeclNode or None * argument
# starstar_arg PyArgDeclNode or None ** argument
# lambda_name string a module-globally unique lambda name
# result_expr ExprNode
# def_node DefNode the underlying function 'def' node
child_attrs = ['def_node']
def_node = None
name = StringEncoding.EncodedString('<lambda>')
def analyse_declarations(self, env):
#self.def_node.needs_closure = self.needs_closure
self.def_node.analyse_declarations(env)
self.pymethdef_cname = self.def_node.entry.pymethdef_cname
env.add_lambda_def(self.def_node)
class YieldExprNode(ExprNode):
# Yield expression node
#
# arg ExprNode the value to return from the generator
# label_name string name of the C label used for this yield
subexprs = ['arg']
type = py_object_type
def analyse_types(self, env):
self.is_temp = 1
if self.arg is not None:
self.arg.analyse_types(env)
if not self.arg.type.is_pyobject:
self.arg = self.arg.coerce_to_pyobject(env)
error(self.pos, "Generators are not supported")
def generate_result_code(self, code):
self.label_name = code.new_label('resume_from_yield')
code.use_label(self.label_name)
code.putln("/* FIXME: save temporary variables */")
code.putln("/* FIXME: return from function, yielding value */")
code.put_label(self.label_name)
code.putln("/* FIXME: restore temporary variables and */")
code.putln("/* FIXME: extract sent value from closure */")
#-------------------------------------------------------------------
#
# Unary operator nodes
......@@ -7186,3 +7433,62 @@ proto="""
#define UNARY_NEG_WOULD_OVERFLOW(x) \
(((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
""")
binding_cfunc_utility_code = UtilityCode(
proto="""
#define %(binding_cfunc)s_USED 1
typedef struct {
PyCFunctionObject func;
} %(binding_cfunc)s_object;
PyTypeObject %(binding_cfunc)s_type;
PyTypeObject *%(binding_cfunc)s = NULL;
PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module); /* proto */
#define %(binding_cfunc)s_New(ml, self) %(binding_cfunc)s_NewEx(ml, self, NULL)
int %(binding_cfunc)s_init(void); /* proto */
""" % Naming.__dict__,
impl="""
PyObject *%(binding_cfunc)s_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) {
%(binding_cfunc)s_object *op = PyObject_GC_New(%(binding_cfunc)s_object, %(binding_cfunc)s);
if (op == NULL)
return NULL;
op->func.m_ml = ml;
Py_XINCREF(self);
op->func.m_self = self;
Py_XINCREF(module);
op->func.m_module = module;
_PyObject_GC_TRACK(op);
return (PyObject *)op;
}
static void %(binding_cfunc)s_dealloc(%(binding_cfunc)s_object *m) {
_PyObject_GC_UNTRACK(m);
Py_XDECREF(m->func.m_self);
Py_XDECREF(m->func.m_module);
PyObject_GC_Del(m);
}
static PyObject *%(binding_cfunc)s_descr_get(PyObject *func, PyObject *obj, PyObject *type) {
if (obj == Py_None)
obj = NULL;
return PyMethod_New(func, obj, type);
}
int %(binding_cfunc)s_init(void) {
%(binding_cfunc)s_type = PyCFunction_Type;
%(binding_cfunc)s_type.tp_name = "cython_binding_builtin_function_or_method";
%(binding_cfunc)s_type.tp_dealloc = (destructor)%(binding_cfunc)s_dealloc;
%(binding_cfunc)s_type.tp_descr_get = %(binding_cfunc)s_descr_get;
if (PyType_Ready(&%(binding_cfunc)s_type) < 0) {
return -1;
}
%(binding_cfunc)s = &%(binding_cfunc)s_type;
return 0;
}
""" % Naming.__dict__)
......@@ -14,6 +14,7 @@ def make_lexicon():
letter = Any("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_")
digit = Any("0123456789")
bindigit = Any("01")
octdigit = Any("01234567")
hexdigit = Any("0123456789ABCDEFabcdef")
indentation = Bol + Rep(Any(" \t"))
......@@ -24,7 +25,9 @@ def make_lexicon():
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)
......@@ -72,7 +75,7 @@ def make_lexicon():
punct = Any(":,;+-*/|&<>=.%`~^?")
diphthong = Str("==", "<>", "!=", "<=", ">=", "<<", ">>", "**", "//",
"+=", "-=", "*=", "/=", "%=", "|=", "^=", "&=",
"<<=", ">>=", "**=", "//=")
"<<=", ">>=", "**=", "//=", "->")
spaces = Rep1(Any(" \t\f"))
escaped_newline = Str("\\\n")
lineterm = Eol + Opt(Str("\n"))
......
......@@ -136,11 +136,13 @@ class Context(object):
_specific_post_parse,
InterpretCompilerDirectives(self, self.compiler_directives),
_align_function_definitions,
MarkClosureVisitor(self),
ConstantFolding(),
FlattenInListTransform(),
WithTransform(self),
DecoratorTransform(self),
AnalyseDeclarationsTransform(self),
CreateClosureClasses(self),
AutoTestDictTransform(self),
EmbedSignature(self),
EarlyReplaceBuiltinCalls(self),
......
......@@ -270,11 +270,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code = globalstate['all_the_rest']
self.generate_cached_builtins_decls(env, code)
# generate lambda function definitions
for node in env.lambda_defs:
node.generate_function_definitions(env, code)
# generate normal function definitions
self.body.generate_function_definitions(env, code)
code.mark_pos(None)
self.generate_typeobj_definitions(env, code)
self.generate_method_table(env, code)
self.generate_filename_init_prototype(code)
if env.has_import_star:
self.generate_import_star(env, code)
self.generate_pymoduledef_struct(env, code)
......@@ -545,6 +548,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
#define PyBytes_Repr PyString_Repr
#define PyBytes_Concat PyString_Concat
#define PyBytes_ConcatAndDel PyString_ConcatAndDel
#define PySet_Check(obj) PyObject_TypeCheck(obj, &PySet_Type)
#define PyFrozenSet_Check(obj) PyObject_TypeCheck(obj, &PyFrozenSet_Type)
#endif
#ifndef PySet_CheckExact
# define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type)
#endif
#if PY_MAJOR_VERSION >= 3
......@@ -580,7 +589,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.put("""
#if PY_MAJOR_VERSION >= 3
#define PyMethod_New(func, self, klass) PyInstanceMethod_New(func)
#define PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func))
#endif
#if PY_VERSION_HEX < 0x02050000
......@@ -631,7 +640,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('static int %s = 0;' % Naming.clineno_cname)
code.putln('static const char * %s= %s;' % (Naming.cfilenm_cname, Naming.file_c_macro))
code.putln('static const char *%s;' % Naming.filename_cname)
code.putln('static const char **%s;' % Naming.filetable_cname)
# XXX this is a mess
for utility_code in PyrexTypes.c_int_from_py_function.specialize_list:
......@@ -658,13 +666,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_filename_table(self, code):
code.putln("")
code.putln("static const char *%s[] = {" % Naming.filenames_cname)
code.putln("static const char *%s[] = {" % Naming.filetable_cname)
if code.globalstate.filename_list:
for source_desc in code.globalstate.filename_list:
filename = os.path.basename(source_desc.get_filenametable_entry())
escaped_filename = filename.replace("\\", "\\\\").replace('"', r'\"')
code.putln('"%s",' %
escaped_filename)
code.putln('"%s",' % escaped_filename)
else:
# Some C compilers don't like an empty array
code.putln("0")
......@@ -1003,7 +1010,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type.vtabslot_cname,
struct_type_cast, type.vtabptr_cname))
for entry in py_attrs:
if entry.name == "__weakref__":
if scope.is_internal or entry.name == "__weakref__":
# internal classes do not need None inits
code.putln("p->%s = 0;" % entry.cname)
else:
code.put_init_var_to_py_none(entry, "p->%s", nanny=False)
......@@ -1584,10 +1592,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(
"};")
def generate_filename_init_prototype(self, code):
code.putln("");
code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname)
def generate_import_star(self, env, code):
env.use_utility_code(streq_utility_code)
code.putln()
......@@ -1678,11 +1682,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("__pyx_refnanny = __Pyx_RefNanny->SetupContext(\"%s\", __LINE__, __FILE__);"% header3)
code.putln("#endif")
self.generate_filename_init_call(code)
code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos)));
code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
code.putln("#ifdef %s_USED" % Naming.binding_cfunc)
code.putln("if (%s_init() < 0) %s" % (Naming.binding_cfunc, code.error_goto(self.pos)))
code.putln("#endif")
code.putln("/*--- Library function declarations ---*/")
env.generate_library_function_declarations(code)
......@@ -1816,9 +1822,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
module_is_main = "%s%s" % (Naming.module_is_main, self.full_module_name.replace('.', '__'))
code.globalstate.use_utility_code(main_method.specialize(module_name=env.module_name, module_is_main=module_is_main))
def generate_filename_init_call(self, code):
code.putln("%s();" % Naming.fileinit_cname)
def generate_pymoduledef_struct(self, env, code):
if env.doc:
doc = "__Pyx_DOCSTR(%s)" % code.get_string_const(env.doc)
......
......@@ -44,6 +44,9 @@ vtabptr_prefix = pyrex_prefix + "vtabptr_"
vtabstruct_prefix = pyrex_prefix + "vtabstruct_"
opt_arg_prefix = pyrex_prefix + "opt_args_"
convert_func_prefix = pyrex_prefix + "convert_"
closure_scope_prefix = pyrex_prefix + "scope_"
closure_class_prefix = pyrex_prefix + "scope_struct_"
lambda_func_prefix = pyrex_prefix + "lambda_"
module_is_main = pyrex_prefix + "module_is_main_"
args_cname = pyrex_prefix + "args"
......@@ -56,8 +59,6 @@ dummy_cname = pyrex_prefix + "dummy"
filename_cname = pyrex_prefix + "filename"
modulename_cname = pyrex_prefix + "modulename"
filetable_cname = pyrex_prefix + "f"
filenames_cname = pyrex_prefix + "filenames"
fileinit_cname = pyrex_prefix + "init_filenames"
intern_tab_cname = pyrex_prefix + "intern_tab"
kwds_cname = pyrex_prefix + "kwds"
lineno_cname = pyrex_prefix + "lineno"
......@@ -83,10 +84,14 @@ pymoduledef_cname = pyrex_prefix + "moduledef"
optional_args_cname = pyrex_prefix + "optional_args"
import_star = pyrex_prefix + "import_star"
import_star_set = pyrex_prefix + "import_star_set"
outer_scope_cname= pyrex_prefix + "outer_scope"
cur_scope_cname = pyrex_prefix + "cur_scope"
enc_scope_cname = pyrex_prefix + "enc_scope"
frame_cname = pyrex_prefix + "frame"
frame_code_cname = pyrex_prefix + "frame_code"
binding_cfunc = pyrex_prefix + "binding_PyCFunctionType"
genexpr_id_ref = 'genexpr'
line_c_macro = "__LINE__"
......
......@@ -18,7 +18,7 @@ import Naming
import PyrexTypes
import TypeSlots
from PyrexTypes import py_object_type, error_type, CFuncType
from Symtab import ModuleScope, LocalScope, GeneratorLocalScope, \
from Symtab import ModuleScope, LocalScope, ClosureScope, \
StructOrUnionScope, PyClassScope, CClassScope, CppClassScope
from Cython.Utils import open_new_file, replace_suffix
from Code import UtilityCode
......@@ -634,6 +634,7 @@ class CArgDeclNode(Node):
# accept_none boolean Resolved boolean for not_none/or_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_type_arg boolean Is the "class" arg of an extension type classmethod
# is_kw_only boolean Is a keyword-only argument
......@@ -646,6 +647,7 @@ class CArgDeclNode(Node):
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 ###
......@@ -1178,9 +1180,13 @@ class FuncDefNode(StatNode, BlockNode):
while genv.is_py_class_scope or genv.is_c_class_scope:
genv = env.outer_scope
if self.needs_closure:
lenv = GeneratorLocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
lenv = ClosureScope(name=self.entry.name,
outer_scope = genv,
scope_name=self.entry.cname)
else:
lenv = LocalScope(name = self.entry.name, outer_scope = genv, parent_scope = env)
lenv = LocalScope(name=self.entry.name,
outer_scope=genv,
parent_scope=env)
lenv.return_type = self.return_type
type = self.entry.type
if type.is_cfunction:
......@@ -1193,6 +1199,17 @@ class FuncDefNode(StatNode, BlockNode):
import Buffer
lenv = self.local_scope
if lenv.is_closure_scope:
outer_scope_cname = "%s->%s" % (Naming.cur_scope_cname,
Naming.outer_scope_cname)
else:
outer_scope_cname = Naming.outer_scope_cname
lenv.mangle_closure_cnames(outer_scope_cname)
# Generate closure function definitions
self.body.generate_function_definitions(lenv, code)
# generate lambda function definitions
for node in lenv.lambda_defs:
node.generate_function_definitions(lenv, code)
is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
self.entry.scope.is_c_class_scope)
......@@ -1218,27 +1235,32 @@ class FuncDefNode(StatNode, BlockNode):
self.generate_cached_builtins_decls(lenv, code)
# ----- Function header
code.putln("")
with_pymethdef = self.needs_assignment_synthesis(env, code)
if self.py_func:
self.py_func.generate_function_header(code,
with_pymethdef = env.is_py_class_scope,
with_pymethdef = with_pymethdef,
proto_only=True)
self.generate_function_header(code,
with_pymethdef = env.is_py_class_scope)
with_pymethdef = with_pymethdef)
# ----- Local variable declarations
lenv.mangle_closure_cnames(Naming.cur_scope_cname)
if lenv.is_closure_scope:
code.put(lenv.scope_class.type.declaration_code(Naming.cur_scope_cname))
code.putln(";")
elif env.is_closure_scope:
code.put(env.scope_class.type.declaration_code(Naming.outer_scope_cname))
code.putln(";")
self.generate_argument_declarations(lenv, code)
if self.needs_closure:
code.putln("/* TODO: declare and create scope object */")
code.put_var_declarations(lenv.var_entries)
for entry in lenv.var_entries:
if not entry.in_closure:
code.put_var_declaration(entry)
init = ""
if not self.return_type.is_void:
if self.return_type.is_pyobject:
init = " = NULL"
code.putln(
"%s%s;" %
(self.return_type.declaration_code(
Naming.retval_cname),
init))
(self.return_type.declaration_code(Naming.retval_cname),
init))
tempvardecl_code = code.insertion_point()
self.generate_keyword_list(code)
if profile:
......@@ -1250,20 +1272,52 @@ class FuncDefNode(StatNode, BlockNode):
if acquire_gil:
env.use_utility_code(force_init_threads_utility_code)
code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
# ----- Automatic lead-ins for certain special functions
# ----- set up refnanny
if not lenv.nogil:
code.put_setup_refcount_context(self.entry.name)
if profile:
code.put_trace_call(self.entry.name, self.pos)
# ----- Automatic lead-ins for certain special functions
if is_getbuffer_slot:
self.getbuffer_init(code)
# ----- Create closure scope object
if self.needs_closure:
code.putln("%s = (%s)%s->tp_new(%s, %s, NULL);" % (
Naming.cur_scope_cname,
lenv.scope_class.type.declaration_code(''),
lenv.scope_class.type.typeptr_cname,
lenv.scope_class.type.typeptr_cname,
Naming.empty_tuple))
code.putln("if (unlikely(!%s)) {" % Naming.cur_scope_cname)
if is_getbuffer_slot:
self.getbuffer_error_cleanup(code)
if not lenv.nogil:
code.put_finish_refcount_context()
# FIXME: what if the error return value is a Python value?
code.putln("return %s;" % self.error_value())
code.putln("}")
code.put_gotref(Naming.cur_scope_cname)
# Note that it is unsafe to decref the scope at this point.
if env.is_closure_scope:
code.putln("%s = (%s)%s;" % (
outer_scope_cname,
env.scope_class.type.declaration_code(''),
Naming.self_cname))
if self.needs_closure:
# inner closures own a reference to their outer parent
code.put_incref(outer_scope_cname, env.scope_class.type)
code.put_giveref(outer_scope_cname)
# ----- Trace function call
if profile:
# this looks a bit late, but if we don't get here due to a
# fatal error before hand, it's not really worth tracing
code.put_trace_call(self.entry.name, self.pos)
# ----- Fetch arguments
self.generate_argument_parsing_code(env, code)
# If an argument is assigned to in the body, we must
# incref it to properly keep track of refcounts.
for entry in lenv.arg_entries:
if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
code.put_var_incref(entry)
if entry.type.is_pyobject:
if entry.assignments and not entry.in_closure:
code.put_var_incref(entry)
# ----- Initialise local variables
for entry in lenv.var_entries:
if entry.type.is_pyobject and entry.init_to_none and entry.used:
......@@ -1271,15 +1325,20 @@ class FuncDefNode(StatNode, BlockNode):
# ----- Initialise local buffer auxiliary variables
for entry in lenv.var_entries + lenv.arg_entries:
if entry.type.is_buffer and entry.buffer_aux.buffer_info_var.used:
code.putln("%s.buf = NULL;" % entry.buffer_aux.buffer_info_var.cname)
code.putln("%s.buf = NULL;" %
entry.buffer_aux.buffer_info_var.cname)
# ----- Check and convert arguments
self.generate_argument_type_tests(code)
# ----- Acquire buffer arguments
for entry in lenv.arg_entries:
if entry.type.is_buffer:
Buffer.put_acquire_arg_buffer(entry, code, self.pos)
# ----- Function body
Buffer.put_acquire_arg_buffer(entry, code, self.pos)
# -------------------------
# ----- Function body -----
# -------------------------
self.body.generate_execution_code(code)
# ----- Default return value
code.putln("")
if self.return_type.is_pyobject:
......@@ -1330,10 +1389,7 @@ class FuncDefNode(StatNode, BlockNode):
if err_val is None and default_retval:
err_val = default_retval
if err_val is not None:
code.putln(
"%s = %s;" % (
Naming.retval_cname,
err_val))
code.putln("%s = %s;" % (Naming.retval_cname, err_val))
if is_getbuffer_slot:
self.getbuffer_error_cleanup(code)
......@@ -1356,15 +1412,25 @@ class FuncDefNode(StatNode, BlockNode):
code.put_label(code.return_from_error_cleanup_label)
if not Options.init_local_none:
for entry in lenv.var_entries:
if lenv.control_flow.get_state((entry.name, 'initalized')) is not True:
if lenv.control_flow.get_state((entry.name, 'initialized')) is not True:
entry.xdecref_cleanup = 1
code.put_var_decrefs(lenv.var_entries, used_only = 1)
for entry in lenv.var_entries:
if entry.type.is_pyobject:
if entry.used and not entry.in_closure:
code.put_var_decref(entry)
elif entry.in_closure and self.needs_closure:
code.put_giveref(entry.cname)
# Decref any increfed args
for entry in lenv.arg_entries:
if entry.type.is_pyobject and lenv.control_flow.get_state((entry.name, 'source')) != 'arg':
code.put_var_decref(entry)
# code.putln("/* TODO: decref scope object */")
if entry.type.is_pyobject:
if entry.in_closure:
code.put_var_giveref(entry)
elif entry.assignments:
code.put_var_decref(entry)
if self.needs_closure:
code.put_decref(Naming.cur_scope_cname, lenv.scope_class.type)
# ----- Return
# This code is duplicated in ModuleNode.generate_module_init_func
if not lenv.nogil:
......@@ -1616,6 +1682,9 @@ class CFuncDefNode(FuncDefNode):
self.analyse_default_values(env)
self.acquire_gil = self.need_gil_acquisition(self.local_scope)
def needs_assignment_synthesis(self, env, code=None):
return False
def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
arg_decls = []
type = self.type
......@@ -1736,10 +1805,13 @@ class PyArgDeclNode(Node):
# 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 = []
def generate_function_definitions(self, env, code):
self.entry.generate_function_definitions(env, code)
class DecoratorNode(Node):
# A decorator
......@@ -1752,12 +1824,15 @@ class DefNode(FuncDefNode):
# A Python function definition.
#
# name string the Python name of the function
# lambda_name string the internal name of a lambda 'function'
# decorators [DecoratorNode] list of decorators
# args [CArgDeclNode] formal arguments
# star_arg PyArgDeclNode or None * argument
# 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.
......@@ -1766,12 +1841,14 @@ class DefNode(FuncDefNode):
child_attrs = ["args", "star_arg", "starstar_arg", "body", "decorators"]
lambda_name = None
assmt = None
num_kwonly_args = 0
num_required_kw_args = 0
reqd_kw_flags_cname = "0"
is_wrapper = 0
decorators = None
return_type_annotation = None
entry = None
acquire_gil = 0
self_in_stararg = 0
......@@ -1866,7 +1943,10 @@ class DefNode(FuncDefNode):
self.is_staticmethod = False
self.analyse_argument_types(env)
self.declare_pyfunction(env)
if self.name == '<lambda>':
self.declare_lambda_function(env)
else:
self.declare_pyfunction(env)
self.analyse_signature(env)
self.return_type = self.entry.signature.return_type()
self.create_local_scope(env)
......@@ -2016,10 +2096,10 @@ class DefNode(FuncDefNode):
def declare_pyfunction(self, env):
#print "DefNode.declare_pyfunction:", self.name, "in", env ###
name = self.name
entry = env.lookup_here(self.name)
entry = env.lookup_here(name)
if entry and entry.type.is_cfunction and not self.is_wrapper:
warning(self.pos, "Overriding cdef method with def method.", 5)
entry = env.declare_pyfunction(self.name, self.pos)
entry = env.declare_pyfunction(name, self.pos)
self.entry = entry
prefix = env.scope_prefix
entry.func_cname = \
......@@ -2033,14 +2113,27 @@ class DefNode(FuncDefNode):
else:
entry.doc = None
def declare_lambda_function(self, env):
name = self.name
prefix = env.scope_prefix
func_cname = \
Naming.lambda_func_prefix + u'funcdef' + prefix + self.lambda_name
entry = env.declare_lambda_function(func_cname, self.pos)
entry.pymethdef_cname = \
Naming.lambda_func_prefix + u'methdef' + prefix + self.lambda_name
entry.qualified_name = env.qualify_name(self.lambda_name)
entry.doc = None
self.entry = entry
def declare_arguments(self, env):
for arg in self.args:
if not arg.name:
error(arg.pos, "Missing argument name")
else:
env.control_flow.set_state((), (arg.name, 'source'), 'arg')
env.control_flow.set_state((), (arg.name, 'initialized'), True)
if arg.needs_conversion:
arg.entry = env.declare_var(arg.name, arg.type, arg.pos)
env.control_flow.set_state((), (arg.name, 'source'), 'arg')
env.control_flow.set_state((), (arg.name, 'initalized'), True)
if arg.type.is_pyobject:
arg.entry.init = "0"
arg.entry.init_to_none = 0
......@@ -2067,21 +2160,39 @@ class DefNode(FuncDefNode):
entry.init_to_none = 0
entry.xdecref_cleanup = 1
arg.entry = entry
env.control_flow.set_state((), (arg.name, 'initalized'), True)
env.control_flow.set_state((), (arg.name, 'initialized'), True)
def analyse_expressions(self, env):
self.local_scope.directives = env.directives
self.analyse_default_values(env)
if env.is_py_class_scope:
if self.needs_assignment_synthesis(env):
# Shouldn't we be doing this at the module level too?
self.synthesize_assignment_node(env)
def needs_assignment_synthesis(self, env, code=None):
# Should enable for module level as well, that will require more testing...
if env.is_module_scope:
if code is None:
return env.directives['binding']
else:
return code.globalstate.directives['binding']
return env.is_py_class_scope or env.is_closure_scope
def synthesize_assignment_node(self, env):
import ExprNodes
self.assmt = SingleAssignmentNode(self.pos,
lhs = ExprNodes.NameNode(self.pos, name = self.name),
if env.is_py_class_scope:
rhs = ExprNodes.UnboundMethodNode(self.pos,
function = ExprNodes.PyCFunctionNode(self.pos,
pymethdef_cname = self.entry.pymethdef_cname)))
pymethdef_cname = self.entry.pymethdef_cname))
elif env.is_closure_scope:
rhs = ExprNodes.InnerFunctionNode(
self.pos, pymethdef_cname = self.entry.pymethdef_cname)
else:
rhs = ExprNodes.PyCFunctionNode(
self.pos, pymethdef_cname = self.entry.pymethdef_cname, binding = env.directives['binding'])
self.assmt = SingleAssignmentNode(self.pos,
lhs = ExprNodes.NameNode(self.pos, name = self.name),
rhs = rhs)
self.assmt.analyse_declarations(env)
self.assmt.analyse_expressions(env)
......@@ -2136,7 +2247,7 @@ class DefNode(FuncDefNode):
if arg.is_generic: # or arg.needs_conversion:
if arg.needs_conversion:
code.putln("PyObject *%s = 0;" % arg.hdr_cname)
else:
elif not arg.entry.in_closure:
code.put_var_declaration(arg.entry)
def generate_keyword_list(self, code):
......@@ -2213,6 +2324,19 @@ class DefNode(FuncDefNode):
else:
code.put_var_decref(self.starstar_arg.entry)
code.putln('__Pyx_AddTraceback("%s");' % self.entry.qualified_name)
# The arguments are put into the closure one after the
# other, so when type errors are found, all references in
# the closure instance must be properly ref-counted to
# facilitate generic closure instance deallocation. In
# the case of an argument type error, it's best to just
# DECREF+clear the already handled references, as this
# frees their references as early as possible.
for arg in self.args:
if arg.type.is_pyobject and arg.entry.in_closure:
code.put_var_xdecref_clear(arg.entry)
if self.needs_closure:
code.put_decref(Naming.cur_scope_cname, self.local_scope.scope_class.type)
code.put_finish_refcount_context()
code.putln("return %s;" % self.error_value())
if code.label_used(end_label):
code.put_label(end_label)
......@@ -2221,7 +2345,10 @@ class DefNode(FuncDefNode):
if arg.type.is_pyobject:
if arg.is_generic:
item = PyrexTypes.typecast(arg.type, PyrexTypes.py_object_type, item)
code.putln("%s = %s;" % (arg.entry.cname, item))
entry = arg.entry
code.putln("%s = %s;" % (entry.cname, item))
if entry.in_closure:
code.put_var_incref(entry)
else:
func = arg.type.from_py_function
if func:
......@@ -2283,7 +2410,7 @@ class DefNode(FuncDefNode):
self.star_arg.entry.cname))
if self.starstar_arg:
code.putln("{")
code.put_decref(self.starstar_arg.entry.cname, py_object_type)
code.put_decref_clear(self.starstar_arg.entry.cname, py_object_type)
code.putln("return %s;" % self.error_value())
code.putln("}")
else:
......@@ -2619,11 +2746,16 @@ class DefNode(FuncDefNode):
code.putln('}')
def generate_argument_conversion_code(self, code):
# Generate code to convert arguments from
# signature type to declared type, if needed.
# Generate code to convert arguments from signature type to
# declared type, if needed. Also copies signature arguments
# into closure fields.
for arg in self.args:
if arg.needs_conversion:
self.generate_arg_conversion(arg, code)
elif arg.entry.in_closure:
code.putln('%s = %s;' % (arg.entry.cname, arg.hdr_cname))
if arg.type.is_pyobject:
code.put_var_incref(arg.entry)
def generate_arg_conversion(self, arg, code):
# Generate conversion code for one argument.
......@@ -3098,6 +3230,9 @@ class ExprStatNode(StatNode):
self.expr.generate_disposal_code(code)
self.expr.free_temps(code)
def generate_function_definitions(self, env, code):
self.expr.generate_function_definitions(env, code)
def annotate(self, code):
self.expr.annotate(code)
......@@ -3216,6 +3351,9 @@ class SingleAssignmentNode(AssignmentNode):
def generate_assignment_code(self, code):
self.lhs.generate_assignment_code(self.rhs, code)
def generate_function_definitions(self, env, code):
self.rhs.generate_function_definitions(env, code)
def annotate(self, code):
self.lhs.annotate(code)
self.rhs.annotate(code)
......@@ -3269,6 +3407,9 @@ class CascadedAssignmentNode(AssignmentNode):
self.rhs.generate_disposal_code(code)
self.rhs.free_temps(code)
def generate_function_definitions(self, env, code):
self.rhs.generate_function_definitions(env, code)
def annotate(self, code):
for i in range(len(self.lhs_list)):
lhs = self.lhs_list[i].annotate(code)
......@@ -3312,6 +3453,10 @@ class ParallelAssignmentNode(AssignmentNode):
for stat in self.stats:
stat.generate_assignment_code(code)
def generate_function_definitions(self, env, code):
for stat in self.stats:
stat.generate_function_definitions(env, code)
def annotate(self, code):
for stat in self.stats:
stat.annotate(code)
......@@ -3437,7 +3582,7 @@ class InPlaceAssignmentNode(AssignmentNode):
indices = indices,
is_temp = self.dup.is_temp)
else:
assert False
assert False, "Unsupported node: %s" % type(self.lhs)
self.lhs = target_lhs
return self.dup
......@@ -3523,6 +3668,11 @@ class PrintStatNode(StatNode):
self.stream.generate_disposal_code(code)
self.stream.free_temps(code)
def generate_function_definitions(self, env, code):
if self.stream:
self.stream.generate_function_definitions(env, code)
self.arg_tuple.generate_function_definitions(env, code)
def annotate(self, code):
if self.stream:
self.stream.annotate(code)
......@@ -3717,6 +3867,10 @@ class ReturnStatNode(StatNode):
for cname, type in code.funcstate.temps_holding_reference():
code.put_decref_clear(cname, type)
code.put_goto(code.return_label)
def generate_function_definitions(self, env, code):
if self.value is not None:
self.value.generate_function_definitions(env, code)
def annotate(self, code):
if self.value:
......@@ -3775,6 +3929,14 @@ class RaiseStatNode(StatNode):
code.putln(
code.error_goto(self.pos))
def generate_function_definitions(self, env, code):
if self.exc_type is not None:
self.exc_type.generate_function_definitions(env, code)
if self.exc_value is not None:
self.exc_value.generate_function_definitions(env, code)
if self.exc_tb is not None:
self.exc_tb.generate_function_definitions(env, code)
def annotate(self, code):
if self.exc_type:
self.exc_type.annotate(code)
......@@ -3849,6 +4011,11 @@ class AssertStatNode(StatNode):
self.cond.free_temps(code)
code.putln("#endif")
def generate_function_definitions(self, env, code):
self.cond.generate_function_definitions(env, code)
if self.value is not None:
self.value.generate_function_definitions(env, code)
def annotate(self, code):
self.cond.annotate(code)
if self.value:
......@@ -3895,6 +4062,12 @@ class IfStatNode(StatNode):
code.putln("}")
code.put_label(end_label)
def generate_function_definitions(self, env, code):
for clause in self.if_clauses:
clause.generate_function_definitions(env, code)
if self.else_clause is not None:
self.else_clause.generate_function_definitions(env, code)
def annotate(self, code):
for if_clause in self.if_clauses:
if_clause.annotate(code)
......@@ -3939,6 +4112,10 @@ class IfClauseNode(Node):
code.put_goto(end_label)
code.putln("}")
def generate_function_definitions(self, env, code):
self.condition.generate_function_definitions(env, code)
self.body.generate_function_definitions(env, code)
def annotate(self, code):
self.condition.annotate(code)
self.body.annotate(code)
......@@ -3959,6 +4136,11 @@ class SwitchCaseNode(StatNode):
code.putln("case %s:" % cond.result())
self.body.generate_execution_code(code)
code.putln("break;")
def generate_function_definitions(self, env, code):
for cond in self.conditions:
cond.generate_function_definitions(env, code)
self.body.generate_function_definitions(env, code)
def annotate(self, code):
for cond in self.conditions:
......@@ -3984,6 +4166,13 @@ class SwitchStatNode(StatNode):
code.putln("break;")
code.putln("}")
def generate_function_definitions(self, env, code):
self.test.generate_function_definitions(env, code)
for case in self.cases:
case.generate_function_definitions(env, code)
if self.else_clause is not None:
self.else_clause.generate_function_definitions(env, code)
def annotate(self, code):
self.test.annotate(code)
for case in self.cases:
......@@ -4044,6 +4233,12 @@ class WhileStatNode(LoopNode, StatNode):
code.putln("}")
code.put_label(break_label)
def generate_function_definitions(self, env, code):
self.condition.generate_function_definitions(env, code)
self.body.generate_function_definitions(env, code)
if self.else_clause is not None:
self.else_clause.generate_function_definitions(env, code)
def annotate(self, code):
self.condition.annotate(code)
self.body.annotate(code)
......@@ -4125,6 +4320,13 @@ class ForInStatNode(LoopNode, StatNode):
self.iterator.generate_disposal_code(code)
self.iterator.free_temps(code)
def generate_function_definitions(self, env, code):
self.target.generate_function_definitions(env, code)
self.iterator.generate_function_definitions(env, code)
self.body.generate_function_definitions(env, code)
if self.else_clause is not None:
self.else_clause.generate_function_definitions(env, code)
def annotate(self, code):
self.target.annotate(code)
self.iterator.annotate(code)
......@@ -4314,13 +4516,23 @@ class ForFromStatNode(LoopNode, StatNode):
'>=': ("", "--"),
'>' : ("-1", "--")
}
def generate_function_definitions(self, env, code):
self.target.generate_function_definitions(env, code)
self.bound1.generate_function_definitions(env, code)
self.bound2.generate_function_definitions(env, code)
if self.step is not None:
self.step.generate_function_definitions(env, code)
self.body.generate_function_definitions(env, code)
if self.else_clause is not None:
self.else_clause.generate_function_definitions(env, code)
def annotate(self, code):
self.target.annotate(code)
self.bound1.annotate(code)
self.bound2.annotate(code)
if self.step:
self.bound2.annotate(code)
self.step.annotate(code)
self.body.annotate(code)
if self.else_clause:
self.else_clause.annotate(code)
......@@ -4475,6 +4687,13 @@ class TryExceptStatNode(StatNode):
code.continue_label = old_continue_label
code.error_label = old_error_label
def generate_function_definitions(self, env, code):
self.body.generate_function_definitions(env, code)
for except_clause in self.except_clauses:
except_clause.generate_function_definitions(env, code)
if self.else_clause is not None:
self.else_clause.generate_function_definitions(env, code)
def annotate(self, code):
self.body.annotate(code)
for except_node in self.except_clauses:
......@@ -4614,6 +4833,11 @@ class ExceptClauseNode(Node):
code.putln(
"}")
def generate_function_definitions(self, env, code):
if self.target is not None:
self.target.generate_function_definitions(env, code)
self.body.generate_function_definitions(env, code)
def annotate(self, code):
if self.pattern:
self.pattern.annotate(code)
......@@ -4686,6 +4910,7 @@ class TryFinallyStatNode(StatNode):
code.putln(
"}")
temps_to_clean_up = code.funcstate.all_free_managed_temps()
code.mark_pos(self.finally_clause.pos)
code.putln(
"/*finally:*/ {")
cases_used = []
......@@ -4761,6 +4986,10 @@ class TryFinallyStatNode(StatNode):
code.putln(
"}")
def generate_function_definitions(self, env, code):
self.body.generate_function_definitions(env, code)
self.finally_clause.generate_function_definitions(env, code)
def put_error_catcher(self, code, error_label, i, catch_label, temps_to_clean_up):
code.globalstate.use_utility_code(restore_exception_utility_code)
code.putln(
......
......@@ -995,8 +995,9 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
if not function.is_name:
return False
entry = self.current_env().lookup(function.name)
if not entry or getattr(entry, 'scope', None) is not Builtin.builtin_scope:
if entry and getattr(entry, 'scope', None) is not Builtin.builtin_scope:
return False
# if entry is None, it's at least an undeclared name, so likely builtin
return True
def _dispatch_to_handler(self, node, function, args, kwargs=None):
......@@ -1035,58 +1036,316 @@ class EarlyReplaceBuiltinCalls(Visitor.EnvTransform):
# specific handlers for simple call nodes
def _handle_simple_function_set(self, node, pos_args):
"""Replace set([a,b,...]) by a literal set {a,b,...} and
set([ x for ... ]) by a literal { x for ... }.
def _handle_simple_function_float(self, node, pos_args):
if len(pos_args) == 0:
return ExprNodes.FloatNode(node.pos, value='0.0')
if len(pos_args) > 1:
self._error_wrong_arg_count('float', node, pos_args, 1)
return node
class YieldNodeCollector(Visitor.TreeVisitor):
def __init__(self):
Visitor.TreeVisitor.__init__(self)
self.yield_stat_nodes = {}
self.yield_nodes = []
visit_Node = Visitor.TreeVisitor.visitchildren
def visit_YieldExprNode(self, node):
self.yield_nodes.append(node)
self.visitchildren(node)
def visit_ExprStatNode(self, node):
self.visitchildren(node)
if node.expr in self.yield_nodes:
self.yield_stat_nodes[node.expr] = node
def __visit_GeneratorExpressionNode(self, node):
# enable when we support generic generator expressions
#
# everything below this node is out of scope
pass
def _find_single_yield_expression(self, node):
collector = self.YieldNodeCollector()
collector.visitchildren(node)
if len(collector.yield_nodes) != 1:
return None, None
yield_node = collector.yield_nodes[0]
try:
return (yield_node.arg, collector.yield_stat_nodes[yield_node])
except KeyError:
return None, None
def _handle_simple_function_all(self, node, pos_args):
"""Transform
_result = all(x for L in LL for x in L)
into
for L in LL:
for x in L:
if not x:
_result = False
break
else:
continue
break
else:
_result = True
"""
arg_count = len(pos_args)
if arg_count == 0:
return ExprNodes.SetNode(node.pos, args=[],
type=Builtin.set_type)
if arg_count > 1:
return node
iterable = pos_args[0]
if isinstance(iterable, (ExprNodes.ListNode, ExprNodes.TupleNode)):
return ExprNodes.SetNode(node.pos, args=iterable.args)
elif isinstance(iterable, ExprNodes.ComprehensionNode) and \
isinstance(iterable.target, (ExprNodes.ListNode,
ExprNodes.SetNode)):
iterable.target = ExprNodes.SetNode(node.pos, args=[])
iterable.pos = node.pos
return iterable
return self._transform_any_all(node, pos_args, False)
def _handle_simple_function_any(self, node, pos_args):
"""Transform
_result = any(x for L in LL for x in L)
into
for L in LL:
for x in L:
if x:
_result = True
break
else:
continue
break
else:
_result = False
"""
return self._transform_any_all(node, pos_args, True)
def _transform_any_all(self, node, pos_args, is_any):
if len(pos_args) != 1:
return node
if not isinstance(pos_args[0], ExprNodes.GeneratorExpressionNode):
return node
gen_expr_node = pos_args[0]
loop_node = gen_expr_node.loop
yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node)
if yield_expression is None:
return node
def _handle_simple_function_dict(self, node, pos_args):
"""Replace dict([ (a,b) for ... ]) by a literal { a:b for ... }.
if is_any:
condition = yield_expression
else:
condition = ExprNodes.NotNode(yield_expression.pos, operand = yield_expression)
result_ref = UtilNodes.ResultRefNode(pos=node.pos, type=PyrexTypes.c_bint_type)
test_node = Nodes.IfStatNode(
yield_expression.pos,
else_clause = None,
if_clauses = [ Nodes.IfClauseNode(
yield_expression.pos,
condition = condition,
body = Nodes.StatListNode(
node.pos,
stats = [
Nodes.SingleAssignmentNode(
node.pos,
lhs = result_ref,
rhs = ExprNodes.BoolNode(yield_expression.pos, value = is_any,
constant_result = is_any)),
Nodes.BreakStatNode(node.pos)
])) ]
)
loop = loop_node
while isinstance(loop.body, Nodes.LoopNode):
next_loop = loop.body
loop.body = Nodes.StatListNode(loop.body.pos, stats = [
loop.body,
Nodes.BreakStatNode(yield_expression.pos)
])
next_loop.else_clause = Nodes.ContinueStatNode(yield_expression.pos)
loop = next_loop
loop_node.else_clause = Nodes.SingleAssignmentNode(
node.pos,
lhs = result_ref,
rhs = ExprNodes.BoolNode(yield_expression.pos, value = not is_any,
constant_result = not is_any))
Visitor.recursively_replace_node(loop_node, yield_stat_node, test_node)
return ExprNodes.InlinedGeneratorExpressionNode(
gen_expr_node.pos, loop = loop_node, result_node = result_ref,
expr_scope = gen_expr_node.expr_scope, orig_func = is_any and 'any' or 'all')
def _handle_simple_function_sum(self, node, pos_args):
"""Transform sum(genexpr) into an equivalent inlined aggregation loop.
"""
if len(pos_args) != 1:
if len(pos_args) not in (1,2):
return node
arg = pos_args[0]
if isinstance(arg, ExprNodes.ComprehensionNode) and \
isinstance(arg.target, (ExprNodes.ListNode,
ExprNodes.SetNode)):
append_node = arg.append
if isinstance(append_node.expr, (ExprNodes.TupleNode, ExprNodes.ListNode)) and \
len(append_node.expr.args) == 2:
key_node, value_node = append_node.expr.args
target_node = ExprNodes.DictNode(
pos=arg.target.pos, key_value_pairs=[])
new_append_node = ExprNodes.DictComprehensionAppendNode(
append_node.pos, target=target_node,
key_expr=key_node, value_expr=value_node)
arg.target = target_node
arg.type = target_node.type
replace_in = Visitor.RecursiveNodeReplacer(append_node, new_append_node)
return replace_in(arg)
if not isinstance(pos_args[0], ExprNodes.GeneratorExpressionNode):
return node
gen_expr_node = pos_args[0]
loop_node = gen_expr_node.loop
yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node)
if yield_expression is None:
return node
if len(pos_args) == 1:
start = ExprNodes.IntNode(node.pos, value='0', constant_result=0)
else:
start = pos_args[1]
result_ref = UtilNodes.ResultRefNode(pos=node.pos, type=PyrexTypes.py_object_type)
add_node = Nodes.SingleAssignmentNode(
yield_expression.pos,
lhs = result_ref,
rhs = ExprNodes.binop_node(node.pos, '+', result_ref, yield_expression)
)
Visitor.recursively_replace_node(loop_node, yield_stat_node, add_node)
exec_code = Nodes.StatListNode(
node.pos,
stats = [
Nodes.SingleAssignmentNode(
start.pos,
lhs = UtilNodes.ResultRefNode(pos=node.pos, expression=result_ref),
rhs = start,
first = True),
loop_node
])
return ExprNodes.InlinedGeneratorExpressionNode(
gen_expr_node.pos, loop = exec_code, result_node = result_ref,
expr_scope = gen_expr_node.expr_scope, orig_func = 'sum')
def _handle_simple_function_min(self, node, pos_args):
return self._optimise_min_max(node, pos_args, '<')
def _handle_simple_function_max(self, node, pos_args):
return self._optimise_min_max(node, pos_args, '>')
def _optimise_min_max(self, node, args, operator):
"""Replace min(a,b,...) and max(a,b,...) by explicit comparison code.
"""
if len(args) <= 1:
# leave this to Python
return node
cascaded_nodes = map(UtilNodes.ResultRefNode, args[1:])
last_result = args[0]
for arg_node in cascaded_nodes:
result_ref = UtilNodes.ResultRefNode(last_result)
last_result = ExprNodes.CondExprNode(
arg_node.pos,
true_val = arg_node,
false_val = result_ref,
test = ExprNodes.PrimaryCmpNode(
arg_node.pos,
operand1 = arg_node,
operator = operator,
operand2 = result_ref,
)
)
last_result = UtilNodes.EvalWithTempExprNode(result_ref, last_result)
for ref_node in cascaded_nodes[::-1]:
last_result = UtilNodes.EvalWithTempExprNode(ref_node, last_result)
return last_result
def _DISABLED_handle_simple_function_tuple(self, node, pos_args):
if len(pos_args) == 0:
return ExprNodes.TupleNode(node.pos, args=[], constant_result=())
# This is a bit special - for iterables (including genexps),
# Python actually overallocates and resizes a newly created
# tuple incrementally while reading items, which we can't
# easily do without explicit node support. Instead, we read
# the items into a list and then copy them into a tuple of the
# final size. This takes up to twice as much memory, but will
# have to do until we have real support for genexps.
result = self._transform_list_set_genexpr(node, pos_args, ExprNodes.ListNode)
if result is not node:
return ExprNodes.AsTupleNode(node.pos, arg=result)
return node
def _handle_simple_function_float(self, node, pos_args):
def _handle_simple_function_list(self, node, pos_args):
if len(pos_args) == 0:
return ExprNodes.FloatNode(node.pos, value='0.0')
return ExprNodes.ListNode(node.pos, args=[], constant_result=[])
return self._transform_list_set_genexpr(node, pos_args, ExprNodes.ListNode)
def _handle_simple_function_set(self, node, pos_args):
if len(pos_args) == 0:
return ExprNodes.SetNode(node.pos, args=[], constant_result=set())
return self._transform_list_set_genexpr(node, pos_args, ExprNodes.SetNode)
def _transform_list_set_genexpr(self, node, pos_args, container_node_class):
"""Replace set(genexpr) and list(genexpr) by a literal comprehension.
"""
if len(pos_args) > 1:
self._error_wrong_arg_count('float', node, pos_args, 1)
return node
return node
if not isinstance(pos_args[0], ExprNodes.GeneratorExpressionNode):
return node
gen_expr_node = pos_args[0]
loop_node = gen_expr_node.loop
yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node)
if yield_expression is None:
return node
target_node = container_node_class(node.pos, args=[])
append_node = ExprNodes.ComprehensionAppendNode(
yield_expression.pos,
expr = yield_expression,
target = ExprNodes.CloneNode(target_node))
Visitor.recursively_replace_node(loop_node, yield_stat_node, append_node)
setcomp = ExprNodes.ComprehensionNode(
node.pos,
has_local_scope = True,
expr_scope = gen_expr_node.expr_scope,
loop = loop_node,
append = append_node,
target = target_node)
append_node.target = setcomp
return setcomp
def _handle_simple_function_dict(self, node, pos_args):
"""Replace dict( (a,b) for ... ) by a literal { a:b for ... }.
"""
if len(pos_args) == 0:
return ExprNodes.DictNode(node.pos, key_value_pairs=[], constant_result={})
if len(pos_args) > 1:
return node
if not isinstance(pos_args[0], ExprNodes.GeneratorExpressionNode):
return node
gen_expr_node = pos_args[0]
loop_node = gen_expr_node.loop
yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node)
if yield_expression is None:
return node
if not isinstance(yield_expression, ExprNodes.TupleNode):
return node
if len(yield_expression.args) != 2:
return node
target_node = ExprNodes.DictNode(node.pos, key_value_pairs=[])
append_node = ExprNodes.DictComprehensionAppendNode(
yield_expression.pos,
key_expr = yield_expression.args[0],
value_expr = yield_expression.args[1],
target = ExprNodes.CloneNode(target_node))
Visitor.recursively_replace_node(loop_node, yield_stat_node, append_node)
dictcomp = ExprNodes.ComprehensionNode(
node.pos,
has_local_scope = True,
expr_scope = gen_expr_node.expr_scope,
loop = loop_node,
append = append_node,
target = target_node)
append_node.target = dictcomp
return dictcomp
# specific handlers for general call nodes
......@@ -1580,6 +1839,59 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
is_temp = False)
return ExprNodes.CastNode(node, PyrexTypes.py_object_type)
Py_type_check_func_type = PyrexTypes.CFuncType(
PyrexTypes.c_bint_type, [
PyrexTypes.CFuncTypeArg("arg", PyrexTypes.py_object_type, None)
])
def _handle_simple_function_isinstance(self, node, pos_args):
"""Replace isinstance() checks against builtin types by the
corresponding C-API call.
"""
if len(pos_args) != 2:
return node
arg, types = pos_args
temp = None
if isinstance(types, ExprNodes.TupleNode):
types = types.args
arg = temp = UtilNodes.ResultRefNode(arg)
elif types.type is Builtin.type_type:
types = [types]
else:
return node
tests = []
test_nodes = []
env = self.current_env()
for test_type_node in types:
if not test_type_node.entry:
return node
entry = env.lookup(test_type_node.entry.name)
if not entry or not entry.type or not entry.type.is_builtin_type:
return node
type_check_function = entry.type.type_check_function(exact=False)
if not type_check_function:
return node
if type_check_function not in tests:
tests.append(type_check_function)
test_nodes.append(
ExprNodes.PythonCapiCallNode(
test_type_node.pos, type_check_function, self.Py_type_check_func_type,
args = [arg],
is_temp = True,
))
def join_with_or(a,b, make_binop_node=ExprNodes.binop_node):
or_node = make_binop_node(node.pos, 'or', a, b)
or_node.type = PyrexTypes.c_bint_type
or_node.is_temp = True
return or_node
test_node = reduce(join_with_or, test_nodes).coerce_to(node.type, env)
if temp is not None:
test_node = UtilNodes.EvalWithTempExprNode(temp, test_node)
return test_node
### special methods
Pyx_tp_new_func_type = PyrexTypes.CFuncType(
......@@ -2549,9 +2861,9 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
for child_result in children.itervalues():
if type(child_result) is list:
for child in child_result:
if child.constant_result is not_a_constant:
if getattr(child, 'constant_result', not_a_constant) is not_a_constant:
return
elif child_result.constant_result is not_a_constant:
elif getattr(child_result, 'constant_result', not_a_constant) is not_a_constant:
return
# now try to calculate the real constant value
......
......@@ -74,6 +74,9 @@ directive_defaults = {
# test support
'test_assert_path_exists' : [],
'test_fail_if_path_exists' : [],
# experimental, subject to change
'binding': False,
}
# Override types possibilities above, if needed
......
......@@ -177,6 +177,7 @@ class PostParse(CythonTransform):
def visit_ModuleNode(self, node):
self.scope_type = 'module'
self.scope_node = node
self.lambda_counter = 1
self.visitchildren(node)
return node
......@@ -197,6 +198,25 @@ class PostParse(CythonTransform):
def visit_CStructOrUnionDefNode(self, node):
return self.visit_scope(node, 'struct')
def visit_LambdaNode(self, node):
# unpack a lambda expression into the corresponding DefNode
if self.scope_type != 'function':
error(node.pos,
"lambda functions are currently only supported in functions")
lambda_id = self.lambda_counter
self.lambda_counter += 1
node.lambda_name = EncodedString(u'lambda%d' % lambda_id)
body = Nodes.ReturnStatNode(
node.result_expr.pos, value = node.result_expr)
node.def_node = Nodes.DefNode(
node.pos, name=node.name, lambda_name=node.lambda_name,
args=node.args, star_arg=node.star_arg,
starstar_arg=node.starstar_arg,
body=body)
self.visitchildren(node)
return node
# cdef variables
def handle_bufferdefaults(self, decl):
if not isinstance(decl.default, DictNode):
......@@ -983,7 +1003,12 @@ property NAME:
self.visitchildren(node)
self.seen_vars_stack.pop()
return node
def visit_LambdaNode(self, node):
node.analyse_declarations(self.env_stack[-1])
self.visitchildren(node)
return node
def visit_ClassDefNode(self, node):
self.env_stack.append(node.scope)
self.visitchildren(node)
......@@ -1014,6 +1039,23 @@ property NAME:
node.analyse_declarations(self.env_stack[-1])
return node
def visit_ScopedExprNode(self, node):
node.analyse_declarations(self.env_stack[-1])
if self.seen_vars_stack:
self.seen_vars_stack.append(set(self.seen_vars_stack[-1]))
else:
self.seen_vars_stack.append(set())
self.env_stack.append(node.expr_scope)
self.visitchildren(node)
self.env_stack.pop()
self.seen_vars_stack.pop()
return node
def visit_TempResultFromStatNode(self, node):
self.visitchildren(node)
node.analyse_declarations(self.env_stack[-1])
return node
# Some nodes are no longer needed after declaration
# analysis and can be dropped. The analysis was performed
# on these nodes in a seperate recursive process from the
......@@ -1110,6 +1152,13 @@ class AnalyseExpressionsTransform(CythonTransform):
node.body.analyse_expressions(node.local_scope)
self.visitchildren(node)
return node
def visit_ScopedExprNode(self, node):
if node.expr_scope is not None:
node.expr_scope.infer_types()
node.analyse_scoped_expressions(node.expr_scope)
self.visitchildren(node)
return node
class AlignFunctionDefinitions(CythonTransform):
"""
......@@ -1175,15 +1224,26 @@ class MarkClosureVisitor(CythonTransform):
node.needs_closure = self.needs_closure
self.needs_closure = True
return node
def visit_ClassDefNode(self, node):
def visit_CFuncDefNode(self, node):
self.visit_FuncDefNode(node)
if node.needs_closure:
error(node.pos, "closures inside cdef functions not yet supported")
return node
def visit_LambdaNode(self, node):
self.needs_closure = False
self.visitchildren(node)
node.needs_closure = self.needs_closure
self.needs_closure = True
return node
def visit_YieldNode(self, node):
def visit_ClassDefNode(self, node):
self.visitchildren(node)
self.needs_closure = True
return node
class CreateClosureClasses(CythonTransform):
# Output closure classes in module scope for all functions
# that need it.
......@@ -1194,21 +1254,39 @@ class CreateClosureClasses(CythonTransform):
return node
def create_class_from_scope(self, node, target_module_scope):
as_name = temp_name_handle("closure")
as_name = "%s%s" % (Naming.closure_class_prefix, node.entry.cname)
func_scope = node.local_scope
entry = target_module_scope.declare_c_class(name = as_name,
pos = node.pos, defining = True, implementing = True)
func_scope.scope_class = entry
class_scope = entry.type.scope
for entry in func_scope.entries.values():
class_scope.is_internal = True
if node.entry.scope.is_closure_scope:
class_scope.declare_var(pos=node.pos,
name=Naming.outer_scope_cname, # this could conflict?
cname=Naming.outer_scope_cname,
type=node.entry.scope.scope_class.type,
is_cdef=True)
entries = func_scope.entries.items()
entries.sort()
for name, entry in entries:
# This is wasteful--we should do this later when we know
# which vars are actually being used inside...
#
# Also, this happens before type inference and type
# analysis, so the entries created here may end up having
# incorrect or at least unspecified types.
class_scope.declare_var(pos=entry.pos,
name=entry.name,
cname=entry.cname,
type=entry.type,
is_cdef=True)
def visit_FuncDefNode(self, node):
self.create_class_from_scope(node, self.module_scope)
if node.needs_closure:
self.create_class_from_scope(node, self.module_scope)
self.visitchildren(node)
return node
......
......@@ -6,17 +6,21 @@ from Cython.Compiler.Scanning cimport PyrexScanner
cpdef p_ident(PyrexScanner s, message =*)
cpdef p_ident_list(PyrexScanner s)
cpdef p_binop_operator(PyrexScanner s)
cpdef p_binop_expr(PyrexScanner s, ops, p_sub_expr)
cpdef p_simple_expr(PyrexScanner s)
cpdef p_lambdef(PyrexScanner s, bint allow_conditional=*)
cpdef p_lambdef_nocond(PyrexScanner s)
cpdef p_test(PyrexScanner s)
cpdef p_test_nocond(PyrexScanner s)
cpdef p_or_test(PyrexScanner s)
cpdef p_rassoc_binop_expr(PyrexScanner s, ops, p_subexpr)
cpdef p_and_test(PyrexScanner s)
cpdef p_not_test(PyrexScanner s)
cpdef p_comparison(PyrexScanner s)
cpdef p_test_or_starred_expr(PyrexScanner s)
cpdef p_starred_expr(PyrexScanner s)
cpdef p_cascaded_cmp(PyrexScanner s)
cpdef p_cmp_op(PyrexScanner s)
cpdef p_starred_expr(PyrexScanner s)
cpdef p_bit_expr(PyrexScanner s)
cpdef p_xor_expr(PyrexScanner s)
cpdef p_and_expr(PyrexScanner s)
......@@ -27,6 +31,7 @@ cpdef p_factor(PyrexScanner s)
cpdef p_typecast(PyrexScanner s)
cpdef p_sizeof(PyrexScanner s)
cpdef p_yield_expression(PyrexScanner s)
cpdef p_yield_statement(PyrexScanner s)
cpdef p_power(PyrexScanner s)
cpdef p_new_expr(PyrexScanner s)
cpdef p_trailer(PyrexScanner s, node1)
......@@ -44,14 +49,17 @@ cpdef p_cat_string_literal(PyrexScanner s)
cpdef p_opt_string_literal(PyrexScanner s)
cpdef p_string_literal(PyrexScanner s, kind_override=*)
cpdef p_list_maker(PyrexScanner s)
cpdef p_list_iter(PyrexScanner s, body)
cpdef p_list_for(PyrexScanner s, body)
cpdef p_list_if(PyrexScanner s, body)
cpdef p_comp_iter(PyrexScanner s, body)
cpdef p_comp_for(PyrexScanner s, body)
cpdef p_comp_if(PyrexScanner s, body)
cpdef p_dict_or_set_maker(PyrexScanner s)
cpdef p_backquote_expr(PyrexScanner s)
cpdef p_simple_expr_list(PyrexScanner s)
cpdef p_expr(PyrexScanner s)
cpdef p_simple_expr_list(PyrexScanner s, expr=*)
cpdef p_test_or_starred_expr_list(s, expr=*)
cpdef p_testlist(PyrexScanner s)
cpdef p_testlist_star_expr(PyrexScanner s)
cpdef p_testlist_comp(PyrexScanner s)
cpdef p_genexp(PyrexScanner s, expr)
#-------------------------------------------------------
#
......@@ -80,12 +88,12 @@ cpdef p_if_clause(PyrexScanner s)
cpdef p_else_clause(PyrexScanner s)
cpdef p_while_statement(PyrexScanner s)
cpdef p_for_statement(PyrexScanner s)
cpdef p_for_bounds(PyrexScanner s)
cpdef p_for_bounds(PyrexScanner s, bint allow_testlist = *)
cpdef p_for_from_relation(PyrexScanner s)
cpdef p_for_from_step(PyrexScanner s)
cpdef p_target(PyrexScanner s, terminator)
cpdef p_for_target(PyrexScanner s)
cpdef p_for_iterator(PyrexScanner s)
cpdef p_for_iterator(PyrexScanner s, bint allow_testlist = *)
cpdef p_try_statement(PyrexScanner s)
cpdef p_except_clause(PyrexScanner s)
cpdef p_include_statement(PyrexScanner s, ctx)
......@@ -122,23 +130,24 @@ cpdef p_nogil(PyrexScanner s)
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_cdef_extern_block(PyrexScanner s, pos, ctx)
cpdef p_c_enum_definition(PyrexScanner s, pos, ctx)
cpdef p_c_enum_line(PyrexScanner s, ctx, items)
cpdef p_c_enum_item(PyrexScanner s, ctx, items)
cpdef p_c_enum_line(PyrexScanner s, ctx, list items)
cpdef p_c_enum_item(PyrexScanner s, ctx, list items)
cpdef p_c_struct_or_union_definition(PyrexScanner s, pos, ctx)
cpdef p_visibility(PyrexScanner s, prev_visibility)
cpdef p_c_modifiers(PyrexScanner s)
cpdef p_c_func_or_var_declaration(PyrexScanner s, pos, ctx)
cpdef p_ctypedef_statement(PyrexScanner s, ctx)
cpdef p_decorators(PyrexScanner s)
cpdef p_def_statement(PyrexScanner s, decorators = *)
cpdef p_def_statement(PyrexScanner s, list decorators = *)
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)
......
......@@ -87,9 +87,38 @@ def p_binop_expr(s, ops, p_sub_expr):
n1.truedivision = None # unknown
return n1
#expression: or_test [if or_test else test] | lambda_form
#lambdef: 'lambda' [varargslist] ':' test
def p_lambdef(s, allow_conditional=True):
# s.sy == 'lambda'
pos = s.position()
s.next()
if s.sy == ':':
args = []
star_arg = starstar_arg = None
else:
args, star_arg, starstar_arg = p_varargslist(
s, terminator=':', annotated=False)
s.expect(':')
if allow_conditional:
expr = p_test(s)
else:
expr = p_test_nocond(s)
return ExprNodes.LambdaNode(
pos, args = args,
star_arg = star_arg, starstar_arg = starstar_arg,
result_expr = expr)
#lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
def p_lambdef_nocond(s):
return p_lambdef(s, allow_conditional=False)
#test: or_test ['if' or_test 'else' test] | lambdef
def p_simple_expr(s):
def p_test(s):
if s.sy == 'lambda':
return p_lambdef(s)
pos = s.position()
expr = p_or_test(s)
if s.sy == 'if':
......@@ -100,11 +129,14 @@ def p_simple_expr(s):
return ExprNodes.CondExprNode(pos, test=test, true_val=expr, false_val=other)
else:
return expr
#test: or_test | lambda_form
def p_test(s):
return p_or_test(s)
#test_nocond: or_test | lambdef_nocond
def p_test_nocond(s):
if s.sy == 'lambda':
return p_lambdef_nocond(s)
else:
return p_or_test(s)
#or_test: and_test ('or' and_test)*
......@@ -152,6 +184,12 @@ def p_comparison(s):
n1.cascade = p_cascaded_cmp(s)
return n1
def p_test_or_starred_expr(s):
if s.sy == '*':
return p_starred_expr(s)
else:
return p_test(s)
def p_starred_expr(s):
pos = s.position()
if s.sy == '*':
......@@ -279,7 +317,7 @@ def p_sizeof(s):
# If it is actually a type, but parsable as an expression,
# we treat it as an expression here.
if looking_at_expr(s):
operand = p_simple_expr(s)
operand = p_test(s)
node = ExprNodes.SizeofVarNode(pos, operand = operand)
else:
base_type = p_c_base_type(s)
......@@ -293,10 +331,16 @@ def p_yield_expression(s):
# s.sy == "yield"
pos = s.position()
s.next()
if s.sy not in ('EOF', 'NEWLINE', ')'):
expr = p_expr(s)
s.error("generators ('yield') are not currently supported")
return Nodes.PassStatNode(pos)
if s.sy != ')' and s.sy not in statement_terminators:
arg = p_testlist(s)
else:
arg = None
return ExprNodes.YieldExprNode(pos, arg=arg)
def p_yield_statement(s):
# s.sy == "yield"
yield_expr = p_yield_expression(s)
return Nodes.ExprStatNode(yield_expr.pos, expr=yield_expr)
#power: atom trailer* ('**' factor)*
......@@ -351,9 +395,9 @@ def p_call(s, function):
s.error("only one star-arg parameter allowed",
pos = s.position())
s.next()
star_arg = p_simple_expr(s)
star_arg = p_test(s)
else:
arg = p_simple_expr(s)
arg = p_test(s)
if s.sy == '=':
s.next()
if not arg.is_name:
......@@ -361,7 +405,7 @@ def p_call(s, function):
pos = arg.pos)
encoded_name = EncodedString(arg.name)
keyword = ExprNodes.IdentifierStringNode(arg.pos, value = encoded_name)
arg = p_simple_expr(s)
arg = p_test(s)
keyword_args.append((keyword, arg))
else:
if keyword_args:
......@@ -375,9 +419,12 @@ def p_call(s, function):
break
s.next()
if s.sy == '**':
if s.sy == 'for':
if len(positional_args) == 1 and not star_arg:
positional_args = [ p_genexp(s, positional_args[0]) ]
elif s.sy == '**':
s.next()
starstar_arg = p_simple_expr(s)
starstar_arg = p_test(s)
if s.sy == ',':
s.next()
s.expect(')')
......@@ -469,7 +516,7 @@ def p_slice_element(s, follow_set):
# Simple expression which may be missing iff
# it is followed by something in follow_set.
if s.sy not in follow_set:
return p_simple_expr(s)
return p_test(s)
else:
return None
......@@ -501,7 +548,7 @@ def make_slice_node(pos, start, stop = None, step = None):
return ExprNodes.SliceNode(pos,
start = start, stop = stop, step = step)
#atom: '(' [testlist] ')' | '[' [listmaker] ']' | '{' [dict_or_set_maker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
#atom: '(' [yield_expr|testlist_comp] ')' | '[' [listmaker] ']' | '{' [dict_or_set_maker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
def p_atom(s):
pos = s.position()
......@@ -513,7 +560,7 @@ def p_atom(s):
elif s.sy == 'yield':
result = p_yield_expression(s)
else:
result = p_expr(s)
result = p_testlist_comp(s)
s.expect(')')
return result
elif sy == '[':
......@@ -713,10 +760,10 @@ def p_string_literal(s, kind_override=None):
return kind, value
# list_display ::= "[" [listmaker] "]"
# listmaker ::= expression ( list_for | ( "," expression )* [","] )
# list_iter ::= list_for | list_if
# list_for ::= "for" expression_list "in" testlist [list_iter]
# list_if ::= "if" test [list_iter]
# listmaker ::= expression ( comp_for | ( "," expression )* [","] )
# comp_iter ::= comp_for | comp_if
# comp_for ::= "for" expression_list "in" testlist [comp_iter]
# comp_if ::= "if" test [comp_iter]
def p_list_maker(s):
# s.sy == '['
......@@ -725,49 +772,52 @@ def p_list_maker(s):
if s.sy == ']':
s.expect(']')
return ExprNodes.ListNode(pos, args = [])
expr = p_simple_expr(s)
expr = p_test(s)
if s.sy == 'for':
target = ExprNodes.ListNode(pos, args = [])
append = ExprNodes.ComprehensionAppendNode(
pos, expr=expr, target=ExprNodes.CloneNode(target))
loop = p_list_for(s, Nodes.ExprStatNode(append.pos, expr=append))
loop = p_comp_for(s, append)
s.expect(']')
return ExprNodes.ComprehensionNode(
pos, loop=loop, append=append, target=target)
pos, loop=loop, append=append, target=target,
# list comprehensions leak their loop variable in Py2
has_local_scope = s.context.language_level >= 3)
else:
exprs = [expr]
if s.sy == ',':
s.next()
exprs += p_simple_expr_list(s)
exprs = p_simple_expr_list(s, expr)
else:
exprs = [expr]
s.expect(']')
return ExprNodes.ListNode(pos, args = exprs)
def p_list_iter(s, body):
def p_comp_iter(s, body):
if s.sy == 'for':
return p_list_for(s, body)
return p_comp_for(s, body)
elif s.sy == 'if':
return p_list_if(s, body)
return p_comp_if(s, body)
else:
# insert the 'append' operation into the loop
return body
def p_list_for(s, body):
def p_comp_for(s, body):
# s.sy == 'for'
pos = s.position()
s.next()
kw = p_for_bounds(s)
kw = p_for_bounds(s, allow_testlist=False)
kw['else_clause'] = None
kw['body'] = p_list_iter(s, body)
kw['body'] = p_comp_iter(s, body)
return Nodes.ForStatNode(pos, **kw)
def p_list_if(s, body):
def p_comp_if(s, body):
# s.sy == 'if'
pos = s.position()
s.next()
test = p_test(s)
test = p_test_nocond(s)
return Nodes.IfStatNode(pos,
if_clauses = [Nodes.IfClauseNode(pos, condition = test,
body = p_list_iter(s, body))],
body = p_comp_iter(s, body))],
else_clause = None )
#dictmaker: test ':' test (',' test ':' test)* [',']
......@@ -779,7 +829,7 @@ def p_dict_or_set_maker(s):
if s.sy == '}':
s.next()
return ExprNodes.DictNode(pos, key_value_pairs = [])
item = p_simple_expr(s)
item = p_test(s)
if s.sy == ',' or s.sy == '}':
# set literal
values = [item]
......@@ -787,7 +837,7 @@ def p_dict_or_set_maker(s):
s.next()
if s.sy == '}':
break
values.append( p_simple_expr(s) )
values.append( p_test(s) )
s.expect('}')
return ExprNodes.SetNode(pos, args=values)
elif s.sy == 'for':
......@@ -795,7 +845,7 @@ def p_dict_or_set_maker(s):
target = ExprNodes.SetNode(pos, args=[])
append = ExprNodes.ComprehensionAppendNode(
item.pos, expr=item, target=ExprNodes.CloneNode(target))
loop = p_list_for(s, Nodes.ExprStatNode(append.pos, expr=append))
loop = p_comp_for(s, append)
s.expect('}')
return ExprNodes.ComprehensionNode(
pos, loop=loop, append=append, target=target)
......@@ -803,14 +853,14 @@ def p_dict_or_set_maker(s):
# dict literal or comprehension
key = item
s.next()
value = p_simple_expr(s)
value = p_test(s)
if s.sy == 'for':
# dict comprehension
target = ExprNodes.DictNode(pos, key_value_pairs = [])
append = ExprNodes.DictComprehensionAppendNode(
item.pos, key_expr=key, value_expr=value,
target=ExprNodes.CloneNode(target))
loop = p_list_for(s, Nodes.ExprStatNode(append.pos, expr=append))
loop = p_comp_for(s, append)
s.expect('}')
return ExprNodes.ComprehensionNode(
pos, loop=loop, append=append, target=target)
......@@ -821,9 +871,9 @@ def p_dict_or_set_maker(s):
s.next()
if s.sy == '}':
break
key = p_simple_expr(s)
key = p_test(s)
s.expect(':')
value = p_simple_expr(s)
value = p_test(s)
items.append(
ExprNodes.DictItemNode(key.pos, key=key, value=value))
s.expect('}')
......@@ -833,50 +883,85 @@ def p_dict_or_set_maker(s):
s.expect('}')
return ExprNodes.DictNode(pos, key_value_pairs = [])
# NOTE: no longer in Py3 :)
def p_backquote_expr(s):
# s.sy == '`'
pos = s.position()
s.next()
arg = p_expr(s)
args = [p_test(s)]
while s.sy == ',':
s.next()
args.append(p_test(s))
s.expect('`')
if len(args) == 1:
arg = args[0]
else:
arg = ExprNodes.TupleNode(pos, args = args)
return ExprNodes.BackquoteNode(pos, arg = arg)
def p_simple_expr_list(s):
exprs = []
def p_simple_expr_list(s, expr=None):
exprs = expr is not None and [expr] or []
while s.sy not in expr_terminators:
expr = p_simple_expr(s)
exprs.append(expr)
exprs.append( p_test(s) )
if s.sy != ',':
break
s.next()
return exprs
def p_expr(s):
def p_test_or_starred_expr_list(s, expr=None):
exprs = expr is not None and [expr] or []
while s.sy not in expr_terminators:
exprs.append( p_test_or_starred_expr(s) )
if s.sy != ',':
break
s.next()
return exprs
#testlist: test (',' test)* [',']
def p_testlist(s):
pos = s.position()
expr = p_simple_expr(s)
expr = p_test(s)
if s.sy == ',':
s.next()
exprs = [expr] + p_simple_expr_list(s)
exprs = p_simple_expr_list(s, expr)
return ExprNodes.TupleNode(pos, args = exprs)
else:
return expr
# testlist_star_expr: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
#testlist: test (',' test)* [',']
# differs from p_expr only in the fact that it cannot contain conditional expressions
def p_testlist_star_expr(s):
pos = s.position()
expr = p_test_or_starred_expr(s)
if s.sy == ',':
s.next()
exprs = p_test_or_starred_expr_list(s, expr)
return ExprNodes.TupleNode(pos, args = exprs)
else:
return expr
def p_testlist(s):
# testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
def p_testlist_comp(s):
pos = s.position()
expr = p_test(s)
expr = p_test_or_starred_expr(s)
if s.sy == ',':
exprs = [expr]
while s.sy == ',':
s.next()
exprs.append(p_test(s))
s.next()
exprs = p_test_or_starred_expr_list(s, expr)
return ExprNodes.TupleNode(pos, args = exprs)
elif s.sy == 'for':
return p_genexp(s, expr)
else:
return expr
def p_genexp(s, expr):
# s.sy == 'for'
loop = p_comp_for(s, Nodes.ExprStatNode(
expr.pos, expr = ExprNodes.YieldExprNode(expr.pos, arg=expr)))
return ExprNodes.GeneratorExpressionNode(expr.pos, loop=loop)
expr_terminators = (')', ']', '}', ':', '=', 'NEWLINE')
#-------------------------------------------------------
......@@ -893,10 +978,14 @@ def p_global_statement(s):
return Nodes.GlobalNode(pos, names = names)
def p_expression_or_assignment(s):
expr_list = [p_expr(s)]
expr_list = [p_testlist_star_expr(s)]
while s.sy == '=':
s.next()
expr_list.append(p_expr(s))
if s.sy == 'yield':
expr = p_yield_expression(s)
else:
expr = p_testlist_star_expr(s)
expr_list.append(expr)
if len(expr_list) == 1:
if re.match(r"([+*/\%^\&|-]|<<|>>|\*\*|//)=", s.sy):
lhs = expr_list[0]
......@@ -904,7 +993,10 @@ def p_expression_or_assignment(s):
error(lhs.pos, "Illegal operand for inplace operation.")
operator = s.sy[:-1]
s.next()
rhs = p_expr(s)
if s.sy == 'yield':
rhs = p_yield_expression(s)
else:
rhs = p_testlist(s)
return Nodes.InPlaceAssignmentNode(lhs.pos, operator = operator, lhs = lhs, rhs = rhs)
expr = expr_list[0]
if isinstance(expr, (ExprNodes.UnicodeNode, ExprNodes.StringNode, ExprNodes.BytesNode)):
......@@ -927,7 +1019,7 @@ def p_print_statement(s):
s.next()
if s.sy == '>>':
s.next()
stream = p_simple_expr(s)
stream = p_test(s)
if s.sy == ',':
s.next()
ends_with_comma = s.sy in ('NEWLINE', 'EOF')
......@@ -935,13 +1027,13 @@ def p_print_statement(s):
stream = None
args = []
if s.sy not in ('NEWLINE', 'EOF'):
args.append(p_simple_expr(s))
args.append(p_test(s))
while s.sy == ',':
s.next()
if s.sy in ('NEWLINE', 'EOF'):
ends_with_comma = 1
break
args.append(p_simple_expr(s))
args.append(p_test(s))
arg_tuple = ExprNodes.TupleNode(pos, args = args)
return Nodes.PrintStatNode(pos,
arg_tuple = arg_tuple, stream = stream,
......@@ -954,10 +1046,10 @@ def p_exec_statement(s):
args = [ p_bit_expr(s) ]
if s.sy == 'in':
s.next()
args.append(p_simple_expr(s))
args.append(p_test(s))
if s.sy == ',':
s.next()
args.append(p_simple_expr(s))
args.append(p_test(s))
else:
error(pos, "'exec' currently requires a target mapping (globals/locals)")
return Nodes.ExecStatNode(pos, args = args)
......@@ -966,6 +1058,7 @@ def p_del_statement(s):
# s.sy == 'del'
pos = s.position()
s.next()
# FIXME: 'exprlist' in Python
args = p_simple_expr_list(s)
return Nodes.DelStatNode(pos, args = args)
......@@ -993,7 +1086,7 @@ def p_return_statement(s):
pos = s.position()
s.next()
if s.sy not in statement_terminators:
value = p_expr(s)
value = p_testlist(s)
else:
value = None
return Nodes.ReturnStatNode(pos, value = value)
......@@ -1006,13 +1099,13 @@ def p_raise_statement(s):
exc_value = None
exc_tb = None
if s.sy not in statement_terminators:
exc_type = p_simple_expr(s)
exc_type = p_test(s)
if s.sy == ',':
s.next()
exc_value = p_simple_expr(s)
exc_value = p_test(s)
if s.sy == ',':
s.next()
exc_tb = p_simple_expr(s)
exc_tb = p_test(s)
if exc_type or exc_value or exc_tb:
return Nodes.RaiseStatNode(pos,
exc_type = exc_type,
......@@ -1076,6 +1169,8 @@ def p_from_import_statement(s, first_statement = 0):
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(')')
......@@ -1154,10 +1249,10 @@ def p_assert_statement(s):
# s.sy == 'assert'
pos = s.position()
s.next()
cond = p_simple_expr(s)
cond = p_test(s)
if s.sy == ',':
s.next()
value = p_simple_expr(s)
value = p_test(s)
else:
value = None
return Nodes.AssertStatNode(pos, cond = cond, value = value)
......@@ -1178,7 +1273,7 @@ def p_if_statement(s):
def p_if_clause(s):
pos = s.position()
test = p_simple_expr(s)
test = p_test(s)
body = p_suite(s)
return Nodes.IfClauseNode(pos,
condition = test, body = body)
......@@ -1194,7 +1289,7 @@ def p_while_statement(s):
# s.sy == 'while'
pos = s.position()
s.next()
test = p_simple_expr(s)
test = p_test(s)
body = p_suite(s)
else_clause = p_else_clause(s)
return Nodes.WhileStatNode(pos,
......@@ -1205,16 +1300,16 @@ def p_for_statement(s):
# s.sy == 'for'
pos = s.position()
s.next()
kw = p_for_bounds(s)
kw = p_for_bounds(s, allow_testlist=True)
kw['body'] = p_suite(s)
kw['else_clause'] = p_else_clause(s)
return Nodes.ForStatNode(pos, **kw)
def p_for_bounds(s):
def p_for_bounds(s, allow_testlist=True):
target = p_for_target(s)
if s.sy == 'in':
s.next()
iterator = p_for_iterator(s)
iterator = p_for_iterator(s, allow_testlist)
return { 'target': target, 'iterator': iterator }
elif not s.in_python_file:
if s.sy == 'from':
......@@ -1288,9 +1383,12 @@ def p_target(s, terminator):
def p_for_target(s):
return p_target(s, 'in')
def p_for_iterator(s):
def p_for_iterator(s, allow_testlist=True):
pos = s.position()
expr = p_testlist(s)
if allow_testlist:
expr = p_testlist(s)
else:
expr = p_or_test(s)
return ExprNodes.IteratorNode(pos, sequence = expr)
def p_try_statement(s):
......@@ -1327,10 +1425,10 @@ def p_except_clause(s):
exc_type = None
exc_value = None
if s.sy != ':':
exc_type = p_simple_expr(s)
if s.sy == ',':
exc_type = p_test(s)
if s.sy == ',' or (s.sy == 'IDENT' and s.systring == 'as'):
s.next()
exc_value = p_simple_expr(s)
exc_value = p_test(s)
elif s.sy == 'IDENT' and s.systring == 'as':
# Py3 syntax requires a name here
s.next()
......@@ -1397,7 +1495,7 @@ def p_with_statement(s):
else:
error(pos, "Syntax error in template function declaration")
else:
manager = p_expr(s)
manager = p_test(s)
target = None
if s.sy == 'IDENT' and s.systring == 'as':
s.next()
......@@ -1432,7 +1530,7 @@ def p_simple_statement(s, first_statement = 0):
elif s.sy == 'from':
node = p_from_import_statement(s, first_statement = first_statement)
elif s.sy == 'yield':
node = p_yield_expression(s)
node = p_yield_statement(s)
elif s.sy == 'assert':
node = p_assert_statement(s)
elif s.sy == 'pass':
......@@ -1460,7 +1558,7 @@ def p_simple_statement_list(s, ctx, first_statement = 0):
def p_compile_time_expr(s):
old = s.compile_time_expr
s.compile_time_expr = 1
expr = p_expr(s)
expr = p_testlist(s)
s.compile_time_expr = old
return expr
......@@ -1518,7 +1616,7 @@ def p_statement(s, ctx, first_statement = 0):
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
......@@ -1551,7 +1649,9 @@ def p_statement(s, ctx, first_statement = 0):
if ctx.api:
s.error("'api' not allowed with this statement")
elif s.sy == 'def':
if ctx.level not in ('module', 'class', 'c_class', 'c_class_pxd', 'property'):
# def statements aren't allowed in pxd files, except
# as part of a cdef class
if ('pxd' in ctx.level) and (ctx.level != 'c_class_pxd'):
s.error('def statement not allowed here')
s.level = ctx.level
return p_def_statement(s, decorators)
......@@ -1643,7 +1743,7 @@ def p_positional_and_keyword_args(s, end_sy_set, templates = None):
s.next() # s.sy is '='
s.next()
if looking_at_expr(s):
arg = p_simple_expr(s)
arg = p_test(s)
else:
base_type = p_c_base_type(s, templates = templates)
declarator = p_c_declarator(s, empty = 1)
......@@ -1657,7 +1757,7 @@ def p_positional_and_keyword_args(s, end_sy_set, templates = None):
else:
if looking_at_expr(s):
arg = p_simple_expr(s)
arg = p_test(s)
else:
base_type = p_c_base_type(s, templates = templates)
declarator = p_c_declarator(s, empty = 1)
......@@ -1929,7 +2029,7 @@ def p_c_array_declarator(s, base):
pos = s.position()
s.next() # '['
if s.sy != ']':
dim = p_expr(s)
dim = p_testlist(s)
else:
dim = None
s.expect(']')
......@@ -1991,7 +2091,7 @@ def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag,
cname = p_opt_cname(s)
if name != "operator" and s.sy == '=' and assignable:
s.next()
rhs = p_simple_expr(s)
rhs = p_test(s)
else:
if nonempty:
error(s.position(), "Empty declarator")
......@@ -2057,20 +2157,21 @@ def p_exception_value_clause(s):
if s.sy == '?':
exc_check = 1
s.next()
exc_val = p_simple_expr(s)
exc_val = p_test(s)
return exc_val, exc_check
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()
......@@ -2084,10 +2185,12 @@ def p_optional_ellipsis(s):
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 = or_none = 0
default = None
annotation = None
if s.in_python_file:
# empty type declaration
base_type = Nodes.CSimpleBaseTypeNode(pos,
......@@ -2109,6 +2212,9 @@ def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0)
error(pos, "'%s None' only allowed in Python functions" % kind)
or_none = kind == 'or'
not_none = kind == 'not'
if annotated and s.sy == ':':
s.next()
annotation = p_test(s)
if s.sy == '=':
s.next()
if 'pxd' in s.level:
......@@ -2117,13 +2223,14 @@ def p_c_arg_decl(s, ctx, in_pyfunc, cmethod_flag = 0, nonempty = 0, kw_only = 0)
default = ExprNodes.BoolNode(1)
s.next()
else:
default = p_simple_expr(s)
default = p_test(s)
return Nodes.CArgDeclNode(pos,
base_type = base_type,
declarator = declarator,
not_none = not_none,
or_none = or_none,
default = default,
annotation = annotation,
kw_only = kw_only)
def p_api(s):
......@@ -2249,7 +2356,7 @@ def p_c_enum_item(s, ctx, items):
value = None
if s.sy == '=':
s.next()
value = p_simple_expr(s)
value = p_test(s)
items.append(Nodes.CEnumDefItemNode(pos,
name = name, cname = cname, value = value))
......@@ -2398,9 +2505,24 @@ def p_def_statement(s, decorators=None):
pos = s.position()
s.next()
name = EncodedString( p_ident(s) )
#args = []
s.expect('(');
args = p_c_arg_list(s, in_pyfunc = 1, nonempty_declarators = 1)
args, star_arg, starstar_arg = p_varargslist(s, terminator=')')
s.expect(')')
if p_nogil(s):
error(pos, "Python function cannot be declared nogil")
return_type_annotation = None
if s.sy == '->':
s.next()
return_type_annotation = p_test(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,
return_type_annotation = return_type_annotation)
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 == '*':
......@@ -2411,23 +2533,21 @@ def p_def_statement(s, decorators=None):
s.next()
args.extend(p_c_arg_list(s, in_pyfunc = 1,
nonempty_declarators = 1, kw_only = 1))
elif s.sy != ')':
elif s.sy != terminator:
s.error("Syntax error in Python function argument list")
if s.sy == '**':
s.next()
starstar_arg = p_py_arg_decl(s)
s.expect(')')
if p_nogil(s):
error(pos, "Python function cannot be declared nogil")
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)
return (args, star_arg, starstar_arg)
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_test(s)
return Nodes.PyArgDeclNode(pos, name = name, annotation = annotation)
def p_class_statement(s, decorators):
# s.sy == 'class'
......@@ -2677,6 +2797,7 @@ def p_cpp_class_definition(s, pos, ctx):
#----------------------------------------------
def print_parse_tree(f, node, level, key = None):
from types import ListType, TupleType
from Nodes import Node
ind = " " * level
if node:
......
......@@ -416,20 +416,27 @@ class BuiltinObjectType(PyObjectType):
def subtype_of(self, type):
return type.is_pyobject and self.assignable_from(type)
def type_test_code(self, arg, notnone=False):
def type_check_function(self, exact=True):
type_name = self.name
if type_name == 'bool':
return 'PyBool_Check'
if type_name == 'str':
type_check = 'PyString_CheckExact'
elif type_name == 'set':
type_check = 'PyAnySet_CheckExact'
type_check = 'PyString_Check'
elif type_name == 'frozenset':
type_check = 'PyFrozenSet_CheckExact'
elif type_name == 'bool':
type_check = 'PyBool_Check'
type_check = 'PyFrozenSet_Check'
else:
type_check = 'Py%s_CheckExact' % type_name.capitalize()
type_check = 'Py%s_Check' % type_name.capitalize()
if exact:
type_check += 'Exact'
return type_check
def isinstance_code(self, arg):
return '%s(%s)' % (self.type_check_function(exact=False), arg)
def type_test_code(self, arg, notnone=False):
type_check = self.type_check_function(exact=True)
check = 'likely(%s(%s))' % (type_check, arg)
if not notnone:
check = check + ('||((%s) == Py_None)' % arg)
......
......@@ -20,6 +20,7 @@ try:
set
except NameError:
from sets import Set as set
import copy
possible_identifier = re.compile(ur"(?![0-9])\w+$", re.U).match
nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
......@@ -146,6 +147,7 @@ class Entry(object):
is_arg = 0
is_local = 0
in_closure = 0
from_closure = 0
is_declared_generic = 0
is_readonly = 0
func_cname = None
......@@ -207,6 +209,7 @@ class Scope(object):
# return_type PyrexType or None Return type of function owning scope
# is_py_class_scope boolean Is a Python class scope
# is_c_class_scope boolean Is an extension type scope
# is_closure_scope boolean
# is_cpp_class_scope boolean Is a C++ class scope
# is_property_scope boolean Is a extension type property scope
# scope_prefix string Disambiguator for C names
......@@ -218,12 +221,15 @@ class Scope(object):
# nogil boolean In a nogil section
# directives dict Helper variable for the recursive
# analysis, contains directive values.
# is_internal boolean Is only used internally (simpler setup)
is_py_class_scope = 0
is_c_class_scope = 0
is_closure_scope = 0
is_cpp_class_scope = 0
is_property_scope = 0
is_module_scope = 0
is_internal = 0
scope_prefix = ""
in_cinclude = 0
nogil = 0
......@@ -260,9 +266,11 @@ class Scope(object):
self.obj_to_entry = {}
self.pystring_entries = []
self.buffer_entries = []
self.lambda_defs = []
self.control_flow = ControlFlow.LinearControlFlow()
self.return_type = None
self.id_counters = {}
def start_branching(self, pos):
self.control_flow = self.control_flow.start_branch(pos)
......@@ -290,7 +298,19 @@ class Scope(object):
prefix = "%s%s_" % (Naming.pyrex_prefix, name)
return self.mangle(prefix)
#return self.parent_scope.mangle(prefix, self.name)
def next_id(self, name=None):
# Return a cname fragment that is unique for this scope.
try:
count = self.id_counters[name] + 1
except KeyError:
count = 0
self.id_counters[name] = count
if name:
return '%s%d' % (name, count)
else:
return '%d' % count
def global_scope(self):
# Return the module-level scope containing this scope.
return self.outer_scope.global_scope()
......@@ -482,7 +502,7 @@ class Scope(object):
error(pos, "C++ class must have a default constructor to be stack allocated")
entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1
self.control_flow.set_state((), (name, 'initalized'), False)
self.control_flow.set_state((), (name, 'initialized'), False)
return entry
def declare_builtin(self, name, pos):
......@@ -498,7 +518,20 @@ class Scope(object):
entry.signature = pyfunction_signature
self.pyfunc_entries.append(entry)
return entry
def declare_lambda_function(self, func_cname, pos):
# Add an entry for an anonymous Python function.
entry = self.declare_var(None, py_object_type, pos,
cname=func_cname, visibility='private')
entry.name = EncodedString(func_cname)
entry.func_cname = func_cname
entry.signature = pyfunction_signature
self.pyfunc_entries.append(entry)
return entry
def add_lambda_def(self, def_node):
self.lambda_defs.append(def_node)
def register_pyfunction(self, entry):
self.pyfunc_entries.append(entry)
......@@ -577,14 +610,7 @@ class Scope(object):
# Look up name in this scope or an enclosing one.
# Return None if not found.
return (self.lookup_here(name)
or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
or None)
def lookup_from_inner(self, name):
# Look up name in this scope or an enclosing one.
# This is only called from enclosing scopes.
return (self.lookup_here(name)
or (self.outer_scope and self.outer_scope.lookup_from_inner(name))
or (self.outer_scope and self.outer_scope.lookup(name))
or None)
def lookup_here(self, name):
......@@ -1157,7 +1183,7 @@ class ModuleScope(Scope):
from TypeInference import PyObjectTypeInferer
PyObjectTypeInferer().infer_types(self)
class LocalScope(Scope):
class LocalScope(Scope):
def __init__(self, name, outer_scope, parent_scope = None):
if parent_scope is None:
......@@ -1202,31 +1228,94 @@ class LocalScope(Scope):
entry = self.global_scope().lookup_target(name)
self.entries[name] = entry
def lookup_from_inner(self, name):
entry = self.lookup_here(name)
if entry:
entry.in_closure = 1
return entry
else:
return (self.outer_scope and self.outer_scope.lookup_from_inner(name)) or None
def lookup(self, name):
# Look up name in this scope or an enclosing one.
# Return None if not found.
entry = Scope.lookup(self, name)
if entry is not None:
if entry.scope is not self and entry.scope.is_closure_scope:
# The actual c fragment for the different scopes differs
# on the outside and inside, so we make a new entry
entry.in_closure = True
# Would it be better to declare_var here?
inner_entry = Entry(entry.name, entry.cname, entry.type, entry.pos)
inner_entry.scope = self
inner_entry.is_variable = True
inner_entry.outer_entry = entry
inner_entry.from_closure = True
self.entries[name] = inner_entry
return inner_entry
return entry
def mangle_closure_cnames(self, scope_var):
def mangle_closure_cnames(self, outer_scope_cname):
for entry in self.entries.values():
if entry.in_closure:
if not hasattr(entry, 'orig_cname'):
entry.orig_cname = entry.cname
entry.cname = scope_var + "->" + entry.cname
if entry.from_closure:
cname = entry.outer_entry.cname
if cname.startswith(Naming.cur_scope_cname):
cname = cname[len(Naming.cur_scope_cname)+2:]
entry.cname = "%s->%s" % (outer_scope_cname, cname)
elif entry.in_closure:
entry.original_cname = entry.cname
entry.cname = "%s->%s" % (Naming.cur_scope_cname, entry.cname)
class GeneratorExpressionScope(LocalScope):
"""Scope for generator expressions and comprehensions. As opposed
to generators, these can be easily inlined in some cases, so all
we really need is a scope that holds the loop variable(s).
"""
def __init__(self, outer_scope):
name = outer_scope.global_scope().next_id(Naming.genexpr_id_ref)
LocalScope.__init__(self, name, outer_scope)
self.directives = outer_scope.directives
self.genexp_prefix = "%s%d%s" % (Naming.pyrex_prefix, len(name), name)
def mangle(self, prefix, name):
return '%s%s' % (self.genexp_prefix, self.outer_scope.mangle(self, prefix, name))
def declare_var(self, name, type, pos,
cname = None, visibility = 'private', is_cdef = True):
if type is unspecified_type:
# if the outer scope defines a type for this variable, inherit it
outer_entry = self.outer_scope.lookup(name)
if outer_entry and outer_entry.is_variable:
type = outer_entry.type # may still be 'unspecified_type' !
# the outer scope needs to generate code for the variable, but
# this scope must hold its name exclusively
cname = '%s%s' % (self.genexp_prefix, self.outer_scope.mangle(Naming.var_prefix, name))
entry = self.outer_scope.declare_var(None, type, pos, cname, visibility, is_cdef = True)
self.entries[name] = entry
return entry
class GeneratorLocalScope(LocalScope):
class ClosureScope(LocalScope):
def mangle_closure_cnames(self, scope_var):
is_closure_scope = True
def __init__(self, name, scope_name, outer_scope):
LocalScope.__init__(self, name, outer_scope)
self.closure_cname = "%s%s" % (Naming.closure_scope_prefix, scope_name)
# def mangle_closure_cnames(self, scope_var):
# for entry in self.entries.values() + self.temp_entries:
# entry.in_closure = 1
LocalScope.mangle_closure_cnames(self, scope_var)
# LocalScope.mangle_closure_cnames(self, scope_var)
# def mangle(self, prefix, name):
# return "%s->%s" % (Naming.scope_obj_cname, name)
# return "%s->%s" % (self.cur_scope_cname, name)
# return "%s->%s" % (self.closure_cname, name)
def declare_pyfunction(self, name, pos):
# Add an entry for a Python function.
entry = self.lookup_here(name)
if entry and not entry.type.is_cfunction:
# This is legal Python, but for now may produce invalid C.
error(pos, "'%s' already declared" % name)
entry = self.declare_var(name, py_object_type, pos)
entry.signature = pyfunction_signature
self.pyfunc_entries.append(entry)
return entry
class StructOrUnionScope(Scope):
# Namespace of a C struct or union.
......
......@@ -196,7 +196,7 @@ class MarkOverflowingArithmetic(CythonTransform):
self.visitchildren(node)
return node
class PyObjectTypeInferer:
class PyObjectTypeInferer(object):
"""
If it's not declared, it's a PyObject.
"""
......@@ -208,14 +208,14 @@ class PyObjectTypeInferer:
if entry.type is unspecified_type:
entry.type = py_object_type
class SimpleAssignmentTypeInferer:
class SimpleAssignmentTypeInferer(object):
"""
Very basic type inference.
"""
# TODO: Implement a real type inference algorithm.
# (Something more powerful than just extending this one...)
def infer_types(self, scope):
enabled = scope.directives['infer_types']
enabled = not scope.is_closure_scope and scope.directives['infer_types']
verbose = scope.directives['infer_types.verbose']
if enabled == True:
spanning_type = aggressive_spanning_type
......@@ -225,6 +225,8 @@ class SimpleAssignmentTypeInferer:
for entry in scope.entries.values():
if entry.type is unspecified_type:
entry.type = py_object_type
if scope.is_closure_scope:
fix_closure_entries(scope)
return
dependancies_by_entry = {} # entry -> dependancies
......@@ -286,6 +288,19 @@ class SimpleAssignmentTypeInferer:
entry.type = py_object_type
if verbose:
message(entry.pos, "inferred '%s' to be of type '%s' (default)" % (entry.name, entry.type))
#if scope.is_closure_scope:
# fix_closure_entries(scope)
def fix_closure_entries(scope):
"""Temporary work-around to fix field types in the closure class
that were unknown at the time of creation and only determined
during type inference.
"""
closure_entries = scope.scope_class.type.scope.entries
for name, entry in scope.entries.iteritems():
if name in closure_entries:
closure_entry = closure_entries[name]
closure_entry.type = entry.type
def find_spanning_type(type1, type2):
if type1 is type2:
......
......@@ -119,22 +119,36 @@ class ResultRefNode(AtomicExprNode):
subexprs = []
lhs_of_first_assignment = False
def __init__(self, expression):
self.pos = expression.pos
def __init__(self, expression=None, pos=None, type=None):
self.expression = expression
if hasattr(expression, "type"):
self.type = expression.type
self.pos = None
if expression is not None:
self.pos = expression.pos
if hasattr(expression, "type"):
self.type = expression.type
if pos is not None:
self.pos = pos
if type is not None:
self.type = type
assert self.pos is not None
def analyse_types(self, env):
self.type = self.expression.type
if self.expression is not None:
self.type = self.expression.type
def infer_type(self, env):
return self.expression.infer_type(env)
if self.expression is not None:
return self.expression.infer_type(env)
def is_simple(self):
return True
def result(self):
try:
return self.result_code
except AttributeError:
if self.expression is not None:
self.result_code = self.expression.result()
return self.result_code
def generate_evaluation_code(self, code):
......@@ -258,9 +272,6 @@ class TempResultFromStatNode(ExprNodes.ExprNode):
# body. Requires a ResultRefNode that it sets up to refer to its
# own temp result. The StatNode must assign a value to the result
# node, which then becomes the result of this node.
#
# This can only be used in/after type analysis.
#
subexprs = []
child_attrs = ['body']
......@@ -272,6 +283,12 @@ class TempResultFromStatNode(ExprNodes.ExprNode):
self.type = result_ref.type
self.is_temp = 1
def analyse_declarations(self, env):
self.body.analyse_declarations(env)
def analyse_types(self, env):
self.body.analyse_expressions(env)
def generate_result_code(self, code):
self.result_ref.result_code = self.result()
self.body.generate_execution_code(code)
......@@ -46,7 +46,7 @@ class BasicVisitor(object):
if self.access_path:
print self.access_path[-1][0].pos
print self.access_path[-1][0].__dict__
raise RuntimeError("Visitor does not accept object: %s" % obj)
raise RuntimeError("Visitor %r does not accept object: %s" % (self, obj))
#print "Caching " + cls.__name__
return handler_method
......@@ -260,7 +260,7 @@ class VisitorTransform(TreeVisitor):
class CythonTransform(VisitorTransform):
"""
Certain common conventions and utilitues for Cython transforms.
Certain common conventions and utilities for Cython transforms.
- Sets up the context of the pipeline in self.context
- Tracks directives in effect in self.current_directives
......@@ -352,7 +352,9 @@ class RecursiveNodeReplacer(VisitorTransform):
else:
return node
def recursively_replace_node(tree, old_node, new_node):
replace_in = RecursiveNodeReplacer(old_node, new_node)
replace_in(tree)
# Utils
......
......@@ -23,19 +23,19 @@ cdef extern from "Python.h":
bint PyBytes_CheckExact(object o)
# Return true if the object o is a string object, but not an instance of a subtype of the string type.
object PyBytes_FromString(char *v)
bytes PyBytes_FromString(char *v)
# Return value: New reference.
# Return a new string object with the value v on success, and NULL
# on failure. The parameter v must not be NULL; it will not be
# checked.
object PyBytes_FromStringAndSize(char *v, Py_ssize_t len)
bytes PyBytes_FromStringAndSize(char *v, Py_ssize_t len)
# Return value: New reference.
# Return a new string object with the value v and length len on
# success, and NULL on failure. If v is NULL, the contents of the
# string are uninitialized.
object PyBytes_FromFormat(char *format, ...)
bytes PyBytes_FromFormat(char *format, ...)
# Return value: New reference.
# Take a C printf()-style format string and a variable number of
# arguments, calculate the size of the resulting Python string and
......@@ -64,7 +64,7 @@ cdef extern from "Python.h":
# format string to be copied as-is to the result string, and any
# extra arguments discarded.
object PyBytes_FromFormatV(char *format, va_list vargs)
bytes PyBytes_FromFormatV(char *format, va_list vargs)
# Return value: New reference.
# Identical to PyBytes_FromFormat() except that it takes exactly two arguments.
......@@ -134,7 +134,7 @@ cdef extern from "Python.h":
# *string is set to NULL, a memory exception is set, and -1 is
# returned.
object PyBytes_Format(object format, object args)
bytes PyBytes_Format(object format, object args)
# Return value: New reference. Return a new string object from
# format and args. Analogous to format % args. The args argument
# must be a tuple.
......@@ -152,7 +152,7 @@ cdef extern from "Python.h":
# reference-count-neutral; you own the object after the call if
# and only if you owned it before the call.)
object PyBytes_InternFromString(char *v)
bytes PyBytes_InternFromString(char *v)
# Return value: New reference.
# A combination of PyBytes_FromString() and
# PyBytes_InternInPlace(), returning either a new string object
......
......@@ -188,16 +188,31 @@ def open_source_from_loader(loader,
stream = NormalisedNewlineStream(stream)
return stream
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):
......
......@@ -51,6 +51,9 @@ EXT_DEP_INCLUDES = [
VER_DEP_MODULES = {
# tests are excluded if 'CurrentPythonVersion OP VersionTuple', i.e.
# (2,4) : (operator.le, ...) excludes ... when PyVer <= 2.4.x
(2,5) : (operator.lt, lambda x: x in ['run.any',
'run.all',
]),
(2,4) : (operator.le, lambda x: x in ['run.extern_builtins_T258'
]),
(2,6) : (operator.lt, lambda x: x in ['run.print_function',
......@@ -786,7 +789,6 @@ if __name__ == '__main__':
if sys.version_info[0] >= 3:
options.doctests = False
options.pyregr = False
if options.with_cython:
try:
# try if Cython is installed in a Py3 version
......
......@@ -11,8 +11,10 @@ cascaded_list_unpacking_T467
compile.cpp_operators
cpp_templated_ctypedef
cpp_structs
genexpr_T491
with_statement_module_level_T536
function_as_method_T494
closure_inside_cdef_T554
# CPython regression tests that don't current work:
pyregr.test_threadsignals
......
if x:
def h():
pass
_ERRORS = u"""
2:1: def statement not allowed here
"""
def f():
def g():
pass
_ERRORS = u"""
2:1: def statement not allowed here
"""
cdef class VerboseGetItem(object):
cdef object sequence
def __init__(self, seq):
self.sequence = seq
def __getitem__(self, i):
print i
return self.sequence[i] # may raise IndexError
cimport cython
@cython.test_assert_path_exists("//SimpleCallNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def all_item(x):
"""
>>> all_item([1,1,1,1,1])
True
>>> all_item([1,1,1,1,0])
False
>>> all_item([0,1,1,1,0])
False
>>> all(VerboseGetItem([1,1,1,0,0]))
0
1
2
3
False
>>> all_item(VerboseGetItem([1,1,1,0,0]))
0
1
2
3
False
>>> all(VerboseGetItem([1,1,1,1,1]))
0
1
2
3
4
5
True
>>> all_item(VerboseGetItem([1,1,1,1,1]))
0
1
2
3
4
5
True
"""
return all(x)
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode")
def all_in_simple_gen(seq):
"""
>>> all_in_simple_gen([1,1,1])
True
>>> all_in_simple_gen([1,1,0])
False
>>> all_in_simple_gen([1,0,1])
False
>>> all_in_simple_gen(VerboseGetItem([1,1,1,1,1]))
0
1
2
3
4
5
True
>>> all_in_simple_gen(VerboseGetItem([1,1,0,1,1]))
0
1
2
False
"""
return all(x for x in seq)
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode")
def all_in_simple_gen_scope(seq):
"""
>>> all_in_simple_gen_scope([1,1,1])
True
>>> all_in_simple_gen_scope([1,1,0])
False
>>> all_in_simple_gen_scope([1,0,1])
False
>>> all_in_simple_gen_scope(VerboseGetItem([1,1,1,1,1]))
0
1
2
3
4
5
True
>>> all_in_simple_gen_scope(VerboseGetItem([1,1,0,1,1]))
0
1
2
False
"""
x = 'abc'
result = all(x for x in seq)
assert x == 'abc'
return result
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode")
def all_in_conditional_gen(seq):
"""
>>> all_in_conditional_gen([3,6,9])
False
>>> all_in_conditional_gen([0,3,7])
False
>>> all_in_conditional_gen([1,0,1])
True
>>> all_in_conditional_gen(VerboseGetItem([1,1,1,1,1]))
0
1
2
3
4
5
True
>>> all_in_conditional_gen(VerboseGetItem([1,1,0,1,1]))
0
1
2
3
4
5
True
"""
return all(x%3 for x in seq if x%2 == 1)
mixed_ustring = u'AbcDefGhIjKlmnoP'
lower_ustring = mixed_ustring.lower()
upper_ustring = mixed_ustring.upper()
@cython.test_assert_path_exists('//PythonCapiCallNode',
'//ForFromStatNode')
@cython.test_fail_if_path_exists('//SimpleCallNode',
'//ForInStatNode')
def all_lower_case_characters(unicode ustring):
"""
>>> all_lower_case_characters(mixed_ustring)
False
>>> all_lower_case_characters(upper_ustring)
False
>>> all_lower_case_characters(lower_ustring)
True
"""
return all(uchar.islower() for uchar in ustring)
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode",
"//InlinedGeneratorExpressionNode//IfStatNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode",
"//IfStatNode//CoerceToBooleanNode")
def all_in_typed_gen(seq):
"""
>>> all_in_typed_gen([1,1,1])
True
>>> all_in_typed_gen([1,0,0])
False
>>> all_in_typed_gen(VerboseGetItem([1,1,1,1,1]))
0
1
2
3
4
5
True
>>> all_in_typed_gen(VerboseGetItem([1,1,1,1,0]))
0
1
2
3
4
False
"""
cdef int x
return all(x for x in seq)
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode",
"//InlinedGeneratorExpressionNode//IfStatNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode",
"//IfStatNode//CoerceToBooleanNode")
def all_in_double_gen(seq):
"""
>>> all(x for L in [[1,1,1],[1,1,1],[1,1,1]] for x in L)
True
>>> all_in_double_gen([[1,1,1],[1,1,1],[1,1,1]])
True
>>> all(x for L in [[1,1,1],[1,1,1],[1,1,0]] for x in L)
False
>>> all_in_double_gen([[1,1,1],[1,1,1],[1,1,0]])
False
>>> all(x for L in [[1,1,1],[0,1,1],[1,1,1]] for x in L)
False
>>> all_in_double_gen([[1,1,1],[0,1,1],[1,1,1]])
False
>>> all_in_double_gen([VerboseGetItem([1,1,1]), VerboseGetItem([1,1,1,1,1])])
0
1
2
3
0
1
2
3
4
5
True
>>> all_in_double_gen([VerboseGetItem([1,1,1]),VerboseGetItem([1,1]),VerboseGetItem([1,1,0])])
0
1
2
3
0
1
2
0
1
2
False
"""
cdef int x
return all(x for L in seq for x in L)
cdef class VerboseGetItem(object):
cdef object sequence
def __init__(self, seq):
self.sequence = seq
def __getitem__(self, i):
print i
return self.sequence[i] # may raise IndexError
cimport cython
@cython.test_assert_path_exists("//SimpleCallNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def any_item(x):
"""
>>> any_item([0,0,1,0,0])
True
>>> any_item([0,0,0,0,1])
True
>>> any_item([0,0,0,0,0])
False
>>> any(VerboseGetItem([0,0,1,0,0]))
0
1
2
True
>>> any_item(VerboseGetItem([0,0,1,0,0]))
0
1
2
True
>>> any(VerboseGetItem([0,0,0,0,0]))
0
1
2
3
4
5
False
>>> any_item(VerboseGetItem([0,0,0,0,0]))
0
1
2
3
4
5
False
"""
return any(x)
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode")
def any_in_simple_gen(seq):
"""
>>> any_in_simple_gen([0,1,0])
True
>>> any_in_simple_gen([0,0,0])
False
>>> any_in_simple_gen(VerboseGetItem([0,0,1,0,0]))
0
1
2
True
>>> any_in_simple_gen(VerboseGetItem([0,0,0,0,0]))
0
1
2
3
4
5
False
"""
return any(x for x in seq)
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode")
def any_in_simple_gen_scope(seq):
"""
>>> any_in_simple_gen_scope([0,1,0])
True
>>> any_in_simple_gen_scope([0,0,0])
False
>>> any_in_simple_gen_scope(VerboseGetItem([0,0,1,0,0]))
0
1
2
True
>>> any_in_simple_gen_scope(VerboseGetItem([0,0,0,0,0]))
0
1
2
3
4
5
False
"""
x = 'abc'
result = any(x for x in seq)
assert x == 'abc'
return result
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode")
def any_in_conditional_gen(seq):
"""
>>> any_in_conditional_gen([3,6,9])
False
>>> any_in_conditional_gen([0,3,7])
True
>>> any_in_conditional_gen([1,0,1])
True
>>> any_in_conditional_gen(VerboseGetItem([0,0,3,0,0]))
0
1
2
3
4
5
False
>>> any_in_conditional_gen(VerboseGetItem([0,3,0,1,1]))
0
1
2
3
True
"""
return any(x%3 for x in seq if x%2 == 1)
mixed_ustring = u'AbcDefGhIjKlmnoP'
lower_ustring = mixed_ustring.lower()
upper_ustring = mixed_ustring.upper()
@cython.test_assert_path_exists('//PythonCapiCallNode',
'//ForFromStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
'//ForInStatNode')
def any_lower_case_characters(unicode ustring):
"""
>>> any_lower_case_characters(upper_ustring)
False
>>> any_lower_case_characters(mixed_ustring)
True
>>> any_lower_case_characters(lower_ustring)
True
"""
return any(uchar.islower() for uchar in ustring)
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode",
"//InlinedGeneratorExpressionNode//IfStatNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode",
"//IfStatNode//CoerceToBooleanNode")
def any_in_typed_gen(seq):
"""
>>> any_in_typed_gen([0,1,0])
True
>>> any_in_typed_gen([0,0,0])
False
>>> any_in_typed_gen(VerboseGetItem([0,0,1,0,0]))
0
1
2
True
>>> any_in_typed_gen(VerboseGetItem([0,0,0,0,0]))
0
1
2
3
4
5
False
"""
cdef int x
return any(x for x in seq)
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode",
"//InlinedGeneratorExpressionNode//IfStatNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode")
def any_in_gen_builtin_name(seq):
"""
>>> any_in_gen_builtin_name([0,1,0])
True
>>> any_in_gen_builtin_name([0,0,0])
False
>>> any_in_gen_builtin_name(VerboseGetItem([0,0,1,0,0]))
0
1
2
True
>>> any_in_gen_builtin_name(VerboseGetItem([0,0,0,0,0]))
0
1
2
3
4
5
False
"""
return any(type for type in seq)
@cython.test_assert_path_exists("//ForInStatNode",
"//InlinedGeneratorExpressionNode",
"//InlinedGeneratorExpressionNode//IfStatNode")
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//YieldExprNode",
"//IfStatNode//CoerceToBooleanNode")
def any_in_double_gen(seq):
"""
>>> any(x for L in [[0,0,0],[0,0,1],[0,0,0]] for x in L)
True
>>> any_in_double_gen([[0,0,0],[0,0,1],[0,0,0]])
True
>>> any(x for L in [[0,0,0],[0,0,0],[0,0,0]] for x in L)
False
>>> any_in_double_gen([[0,0,0],[0,0,0],[0,0,0]])
False
>>> any_in_double_gen([VerboseGetItem([0,0,0]), VerboseGetItem([0,0,1,0,0])])
0
1
2
3
0
1
2
True
>>> any_in_double_gen([VerboseGetItem([0,0,0]),VerboseGetItem([0,0]),VerboseGetItem([0,0,0])])
0
1
2
3
0
1
2
0
1
2
3
False
"""
cdef int x
return any(x for L in seq for x in L)
def f(dict d, x=4):
"""
>>> f({1:1, 2:2})
[1, 2]
"""
cdef dict d_new = {}
l = []
for k in d:
d = d_new
l.append(k)
l.sort()
return l
cimport cython
# min()
@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def min3(a,b,c):
"""
>>> min3(1,2,3)
1
>>> min3(2,3,1)
1
>>> min3(2,1,3)
1
>>> min3(3,1,2)
1
>>> min3(3,2,1)
1
"""
return min(a,b,c)
@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def min3_typed(int a, int b, int c):
"""
>>> min3_typed(1,2,3)
1
>>> min3_typed(2,3,1)
1
>>> min3_typed(2,1,3)
1
>>> min3_typed(3,1,2)
1
>>> min3_typed(3,2,1)
1
"""
return min(a,b,c)
@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def literal_min3():
"""
>>> literal_min3()
(1, 1, 1, 1, 1)
"""
return min(1,2,3), min(2,1,3), min(2,3,1), min(3,1,2), min(3,2,1)
# max()
@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def max3(a,b,c):
"""
>>> max3(1,2,3)
3
>>> max3(2,3,1)
3
>>> max3(2,1,3)
3
>>> max3(3,1,2)
3
>>> max3(3,2,1)
3
"""
return max(a,b,c)
@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def max3_typed(int a, int b, int c):
"""
>>> max3_typed(1,2,3)
3
>>> max3_typed(2,3,1)
3
>>> max3_typed(2,1,3)
3
>>> max3_typed(3,1,2)
3
>>> max3_typed(3,2,1)
3
"""
return max(a,b,c)
@cython.test_assert_path_exists("//CondExprNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
def literal_max3():
"""
>>> literal_max3()
(3, 3, 3, 3, 3)
"""
return max(1,2,3), max(2,1,3), max(2,3,1), max(3,1,2), max(3,2,1)
# The arguments in f() are put into the closure one after the other,
# so the reference of 'o' is filled in before the type errors are
# found. This leaves a reference in the closure instance on error
# return, which must be properly ref-counted to facilitate generic
# closure deallocation. In the case of an argument type error, it's
# actually best to just Py_CLEAR() the already handled references, as
# this frees them as early as possible.
# This test doesn't really check the ref-counting itself, it just
# reproduces the problem.
def func_with_typed_args(object o, int i, tuple t, double d):
"""
>>> g = func_with_typed_args(1, 2, (), 3.0)
>>> g()
(1, 2, (), 3.0)
>>> g = func_with_typed_args(1, 'x', (), 3.0)
Traceback (most recent call last):
TypeError: an integer is required
>>> g = func_with_typed_args(1, 2, 3, 3.0)
Traceback (most recent call last):
TypeError: Argument 't' has incorrect type (expected tuple, got int)
"""
def g():
return o, i, t, d
return g
__doc__ = """
>>> Num(13).is_prime()
args (Num(13),) kwds {}
True
>>> Num(13).is_prime(True)
args (Num(13), True) kwds {}
True
>>> Num(15).is_prime(print_factors=True)
args (Num(15),) kwds {'print_factors': True}
3 5
False
"""
def print_args(func):
def f(*args, **kwds):
print "args", args, "kwds", kwds
return func(*args, **kwds)
return f
cdef class Num:
cdef int n
def __init__(self, n):
self.n = n
def __repr__(self):
return "Num(%s)" % self.n
@print_args
def is_prime(self, bint print_factors=False):
if self.n == 2:
return True
elif self.n < 2:
return False
elif self.n % 2 == 0:
if print_factors:
print 2, self.n // 2
cdef int i = 3
while i*i <= self.n:
if self.n % i == 0:
if print_factors:
print i, self.n // i
return False
i += 2
return True
def call_f(x):
"""
>>> call_f(2)
4
"""
return f(x)
cdef f(x): # def here => works fine
def g(y): return y*x # cdef here => compile error
return g(x) # faults@ INCREF(.*cur_scope->.*v_x
#
# closure_tests_1.pyx
#
# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#
def g1425():
"""
>>> g1425()
142
"""
if (True):
def g1424():
if (True):
return 122
return (20)+(g1424())
else:
return 10000
def g1432():
"""
>>> g1432()
[0, []]
"""
def g1431():
return [0,[]]
x_1056 = g1431()
if (x_1056):
def g1430():
def g1429():
return (x_1056[0])
def g1428():
return (x_1056[0])
return (g1429())+(g1428())
x_1056[0] = g1430()
return x_1056
def g1435():
"""
>>> g1435()
4000
"""
def g1434():
def g1433(y_1057):
return y_1057
return g1433
return g1434()(4000)
def g1438():
"""
>>> g1438()
1
"""
def g1437():
def g1436(x_1058):
return x_1058
return g1436
f_1059 = g1437()
return (f_1059(0)+1)
def g1441():
"""
>>> g1441()
4
"""
def g1440():
def g1439(y_1060):
return y_1060
return g1439
f_1061 = g1440()
return f_1061(f_1061(4))
def g1446():
"""
>>> g1446()
4
"""
def g1445():
def g1444(f_1063):
return f_1063(f_1063(4))
return g1444
def g1443():
def g1442(y_1062):
return y_1062
return g1442
return g1445()(g1443())
def g1449():
"""
>>> g1449()
9000
"""
def g1448():
a_1064 = 4000
def g1447(b_1065):
return (a_1064)+(b_1065)
return g1447
return g1448()(5000)
def g1454():
"""
>>> g1454()
9000
"""
def g1453():
def g1452():
def g1450(a_1066):
def g1451(b_1067):
return (a_1066)+(b_1067)
return g1451
return g1450
return g1452()(4000)
return g1453()(5000)
def g1459():
"""
>>> g1459()
2
"""
def g1458():
def g1457(f_1069):
return f_1069(f_1069(0))
return g1457
def g1456():
def g1455(x_1068):
return (x_1068+1)
return g1455
return g1458()(g1456())
def g1462():
"""
>>> g1462()
0
"""
x_1072 = 0
def g1461():
def g1460(x_1070):
return x_1070
return g1460
f_1071 = g1461()
a_1075 = f_1071(x_1072)
b_1074 = f_1071(x_1072)
c_1073 = f_1071(x_1072)
return ((a_1075)+(b_1074))+(c_1073)
def g1465():
"""
>>> g1465()
3
"""
x_1080 = 0
y_1079 = 1
z_1078 = 2
def g1464():
def g1463(x_1076):
return x_1076
return g1463
f_1077 = g1464()
a_1083 = f_1077(x_1080)
b_1082 = f_1077(y_1079)
c_1081 = f_1077(z_1078)
return ((a_1083)+(b_1082))+(c_1081)
def g1468():
"""
>>> g1468()
0
"""
def g1467():
def g1466(x_1085, y_1084):
return x_1085
return g1466
f_1086 = g1467()
a_1087 = f_1086(0, 1)
return f_1086(a_1087, a_1087)
def g1471():
"""
>>> g1471()
0
"""
x_1094 = 0
y_1093 = 1
z_1092 = 2
def g1470():
def g1469(x_1090, y_1089, z_1088):
return x_1090
return g1469
f_1091 = g1470()
a_1097 = f_1091(x_1094, y_1093, z_1092)
b_1096 = y_1093
c_1095 = z_1092
return f_1091(a_1097, b_1096, c_1095)
def g1474():
"""
>>> g1474()
3
"""
def g1473():
def g1472(a_1101, b_1100, c_1099, d_1098):
return (a_1101)+(d_1098)
return g1472
f_1102 = g1473()
return f_1102(0, 1, 2, 3)
def g1478():
"""
>>> g1478()
3
"""
def g1477():
def g1476(x_1103):
return x_1103
return g1476
f_1104 = g1477()
def g1475():
a_1107 = 0
b_1106 = 1
c_1105 = 2
return (f_1104(a_1107))+((f_1104(b_1106))+(f_1104(c_1105)))
return (f_1104(0))+(g1475())
def g1483():
"""
>>> g1483()
"""
a_1108 = 0
def g1482():
def g1481():
return 0
return g1481
a_1110 = g1482()
def g1480():
def g1479():
return 11
return g1479
b_1109 = g1480()
a_1110 = 11
def g1486():
"""
>>> g1486()
"""
a_1111 = 0
def g1485():
def g1484():
a_1113 = 0
return g1484
a_1113 = g1485()
b_1112 = 11
return a_1113()
def g1491():
"""
>>> g1491()
0
"""
def g1490():
def g1489():
return 0
return g1489
a_1115 = g1490()
def g1488():
def g1487():
return 11
return g1487
b_1114 = g1488()
return a_1115()
def g1494():
"""
>>> g1494()
2
"""
def g1493():
x_1116 = 1
def g1492(y_1117):
return (x_1116)+(y_1117)
return g1492
f_1118 = g1493()
x_1119 = 0
return f_1118(f_1118(x_1119))
def g1501():
"""
>>> g1501()
3050
"""
def g1500():
def g1499():
def g1498(x_1121):
return (x_1121)+(50)
return g1498
t_1122 = g1499()
def g1497(f_1123):
return t_1122(f_1123(1000))
return g1497
def g1496():
def g1495(y_1120):
return (y_1120)+(2000)
return g1495
return g1500()(g1496())
def g1508():
"""
>>> g1508()
60
"""
def g1507():
def g1506():
def g1505():
def g1502(a_1124):
def g1503(b_1125):
def g1504(c_1126):
return (a_1124)+((b_1125)+(c_1126))
return g1504
return g1503
return g1502
return g1505()(10)
return g1506()(20)
return g1507()(30)
def g1513():
"""
>>> g1513()
5
"""
def g1512():
def g1509(b_1127):
def g1511():
def g1510(a_1128):
return (b_1127)+(a_1128)
return g1510
return g1511()(2)
return g1509
return g1512()(3)
def g1518():
"""
>>> g1518()
5
"""
def g1517():
def g1516(f_1130):
return f_1130(f_1130(5))
return g1516
def g1515():
def g1514(x_1129):
return x_1129
return g1514
return g1517()(g1515())
def g1523():
"""
>>> g1523()
8000
"""
def g1522():
def g1521():
def g1520(x_1131):
return (x_1131)+(3000)
return g1520
f_1132 = g1521()
def g1519(y_1133):
return f_1132(f_1132(y_1133))
return g1519
return g1522()(2000)
#
# closure_tests_2.pyx
#
# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#
def g1526():
"""
>>> g1526()
2
"""
x_1134 = 0
def g1525():
x_1136 = 1
z_1135 = x_1134
def g1524(y_1137):
return (x_1136)+((z_1135)+(y_1137))
return g1524
f_1138 = g1525()
return f_1138(f_1138(x_1134))
def g1535():
"""
>>> g1535()
3050
"""
def g1534():
def g1533():
def g1531(t_1141):
def g1532(f_1142):
return t_1141(f_1142(1000))
return g1532
return g1531
def g1530():
def g1529(x_1140):
return (x_1140)+(50)
return g1529
return g1533()(g1530())
def g1528():
def g1527(y_1139):
return (y_1139)+(2000)
return g1527
return g1534()(g1528())
def g1540():
"""
>>> g1540()
2050
"""
def g1539():
t_1143 = 50
def g1538(f_1144):
return (t_1143)+(f_1144())
return g1538
def g1537():
def g1536():
return 2000
return g1536
return g1539()(g1537())
def g1547():
"""
>>> g1547()
2050
"""
def g1546():
def g1545():
def g1543(t_1145):
def g1544(f_1146):
return (t_1145)+(f_1146())
return g1544
return g1543
return g1545()(50)
def g1542():
def g1541():
return 2000
return g1541
return g1546()(g1542())
def g1550():
"""
>>> g1550()
700
"""
def g1549():
x_1147 = 300
def g1548(y_1148):
return (x_1147)+(y_1148)
return g1548
return g1549()(400)
def g1553():
"""
>>> g1553()
0
"""
x_1152 = 3
def g1552():
def g1551(x_1150, y_1149):
return x_1150
return g1551
f_1151 = g1552()
if (f_1151(0, 0)):
return f_1151(f_1151(0, 0), x_1152)
else:
return 0
def g1562():
"""
>>> g1562()
False
"""
def g1561():
def g1556(x_1153):
def g1560():
def g1559():
return isinstance(x_1153, list)
if (g1559()):
def g1558():
def g1557():
return (x_1153[0])
return (g1557() == 0)
return (not g1558())
else:
return False
if (g1560()):
return x_1153
else:
return False
return g1556
f_1154 = g1561()
def g1555():
def g1554():
return [0,[]]
return [0,g1554()]
return f_1154(g1555())
def g1570():
"""
>>> g1570()
False
"""
def g1569():
def g1563(x_1155):
def g1568():
if (x_1155):
def g1567():
def g1566():
return isinstance(x_1155, list)
if (g1566()):
def g1565():
def g1564():
return (x_1155[0])
return (g1564() == 0)
return (not g1565())
else:
return False
return (not g1567())
else:
return False
if (g1568()):
return x_1155
else:
return False
return g1563
f_1156 = g1569()
return f_1156(0)
def g1575():
"""
>>> g1575()
[]
"""
def g1574():
def g1571(x_1157):
def g1573():
def g1572():
return isinstance(x_1157, list)
if (g1572()):
return True
else:
return (x_1157 == [])
if (g1573()):
return x_1157
else:
return []
return g1571
f_1158 = g1574()
return f_1158(0)
def g1578():
"""
>>> g1578()
4
"""
y_1159 = 4
def g1577():
def g1576(y_1160):
return y_1160
return g1576
f_1161 = g1577()
return f_1161(f_1161(y_1159))
def g1581():
"""
>>> g1581()
0
"""
y_1162 = 4
def g1580():
def g1579(x_1164, y_1163):
return 0
return g1579
f_1165 = g1580()
return f_1165(f_1165(y_1162, y_1162), f_1165(y_1162, y_1162))
def g1584():
"""
>>> g1584()
0
"""
y_1166 = 4
def g1583():
def g1582(x_1168, y_1167):
return 0
return g1582
f_1169 = g1583()
return f_1169(f_1169(y_1166, y_1166), f_1169(y_1166, f_1169(y_1166, y_1166)))
def g1587():
"""
>>> g1587()
0
"""
y_1170 = 4
def g1586():
def g1585(x_1172, y_1171):
return 0
return g1585
f_1173 = g1586()
return f_1173(f_1173(y_1170, f_1173(y_1170, y_1170)), f_1173(y_1170, f_1173(y_1170, y_1170)))
def g1594():
"""
>>> g1594()
4
"""
def g1593():
def g1588(y_1174):
def g1592():
def g1591(f_1176):
return f_1176(f_1176(y_1174))
return g1591
def g1590():
def g1589(y_1175):
return y_1175
return g1589
return g1592()(g1590())
return g1588
return g1593()(4)
def g1598():
"""
>>> g1598()
23
"""
def g1597():
def g1596(x_1177):
return x_1177
return g1596
f_1178 = g1597()
def g1595():
if (False):
return 1
else:
return f_1178(22)
return (g1595()+1)
def g1603():
"""
>>> g1603()
22
"""
def g1602():
def g1601(x_1179):
return x_1179
return g1601
f_1180 = g1602()
def g1600():
def g1599():
return 23 == 0
return f_1180(g1599())
if (g1600()):
return 1
else:
return 22
def g1611():
"""
>>> g1611()
5061
"""
def g1610():
def g1609(x_1182):
if (x_1182):
return (not x_1182)
else:
return x_1182
return g1609
f_1185 = g1610()
def g1608():
def g1607(x_1181):
return (10)*(x_1181)
return g1607
f2_1184 = g1608()
x_1183 = 23
def g1606():
def g1605():
def g1604():
return x_1183 == 0
return f_1185(g1604())
if (g1605()):
return 1
else:
return (x_1183)*(f2_1184((x_1183-1)))
return (g1606()+1)
def g1614():
"""
>>> g1614()
1
"""
def g1613():
def g1612():
return 0
return g1612
f_1186 = g1613()
x_1187 = f_1186()
return 1
def g1617():
"""
>>> g1617()
1
"""
def g1616():
def g1615():
return 0
return g1615
f_1188 = g1616()
f_1188()
return 1
def g1620():
"""
>>> g1620()
4
"""
def g1619():
def g1618(x_1189):
return x_1189
return g1618
f_1190 = g1619()
if (True):
f_1190(3)
return 4
else:
return 5
def g1623():
"""
>>> g1623()
6
"""
def g1622():
def g1621(x_1191):
return x_1191
return g1621
f_1192 = g1622()
(f_1192(4)) if (True) else (5)
return 6
def g1627():
"""
>>> g1627()
120
"""
def g1626():
def g1624(fact_1195, n_1194, acc_1193):
def g1625():
return n_1194 == 0
if (g1625()):
return acc_1193
else:
return fact_1195(fact_1195, (n_1194-1), (n_1194)*(acc_1193))
return g1624
fact_1196 = g1626()
return fact_1196(fact_1196, 5, 1)
def g1632():
"""
>>> g1632()
144
"""
def g1631():
def g1628(b_1199, c_1198, a_1197):
b_1203 = (b_1199)+(a_1197)
def g1630():
def g1629():
a_1201 = (b_1199)+(b_1199)
c_1200 = (c_1198)+(c_1198)
return (a_1201)+(a_1201)
return (a_1197)+(g1629())
a_1202 = g1630()
return (a_1202)*(a_1202)
return g1628
return g1631()(2, 3, 4)
def g1639():
"""
>>> g1639()
3
"""
def g1638():
def g1636(x_1204):
def g1637():
return x_1204()
return g1637
return g1636
f_1205 = g1638()
def g1635():
def g1634():
def g1633():
return 3
return g1633
return f_1205(g1634())
return g1635()()
def g1646():
"""
>>> g1646()
3628800
"""
def g1645():
def g1643(x_1207):
def g1644():
return x_1207 == 0
if (g1644()):
return 1
else:
return (x_1207)*(f_1206((x_1207)-(1)))
return g1643
f_1206 = g1645()
q_1208 = 17
def g1642():
def g1640(a_1209):
q_1208 = 10
def g1641():
return a_1209(q_1208)
return g1641
return g1640
g_1210 = g1642()
return g_1210(f_1206)()
#
# closure_tests_3.pyx
#
# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#
def g1649():
"""
>>> g1649()
6
"""
def g1648():
def g1647(x_1211):
return x_1211
return g1647
f_1212 = g1648()
if (f_1212(True)):
f_1212(3)
f_1212(4)
else:
f_1212(5)
return f_1212(6)
def g1653():
"""
>>> g1653()
5
"""
def g1652():
def g1651(x_1213):
return (x_1213+1)
return g1651
f_1214 = g1652()
def g1650():
f_1215 = 3
return (f_1215)+(1)
return f_1214(g1650())
def g1662():
"""
>>> g1662()
51
"""
x_1223 = 15
def g1661():
def g1660(h_1219, v_1218):
return (h_1219)*(v_1218)
return g1660
f_1222 = g1661()
def g1659():
def g1658(x_1217):
return (x_1217)+(5)
return g1658
k_1221 = g1659()
def g1657():
def g1656(x_1216):
return (x_1216+1)
return g1656
g_1220 = g1657()
def g1655():
def g1654():
g_1224 = 3
return f_1222(g_1224, x_1223)
return g_1220(g1654())
return k_1221(g1655())
def g1665():
"""
>>> g1665()
5
"""
x_1225 = 4
def g1664():
def g1663():
return x_1225
return g1663
f_1226 = g1664()
x_1225 = 5
return f_1226()
def g1670():
"""
>>> g1670()
5
"""
def g1669():
def g1668():
def g1667():
def g1666():
return 4
return g1666
y_1227 = g1667()
return y_1227()
return (g1668()+1)
x_1228 = g1669()
return x_1228
def g1674():
"""
>>> g1674()
1
"""
def g1673():
def g1671(n_1230):
def g1672():
return n_1230 == 0
if (g1672()):
return 1
else:
return one_1229((n_1230-1))
return g1671
one_1229 = g1673()
return one_1229(13)
def g1681():
"""
>>> g1681()
True
"""
def g1680():
def g1678(x_1234):
def g1679():
return x_1234 == 0
if (g1679()):
return True
else:
return odd_1231((x_1234-1))
return g1678
even_1232 = g1680()
def g1677():
def g1675(x_1233):
def g1676():
return x_1233 == 0
if (g1676()):
return False
else:
return even_1232((x_1233-1))
return g1675
odd_1231 = g1677()
return odd_1231(13)
def g1688():
"""
>>> g1688()
True
"""
t_1236 = True
f_1235 = False
def g1687():
def g1685(x_1240):
def g1686():
return x_1240 == 0
if (g1686()):
return t_1236
else:
return odd_1237((x_1240-1))
return g1685
even_1238 = g1687()
def g1684():
def g1682(x_1239):
def g1683():
return x_1239 == 0
if (g1683()):
return f_1235
else:
return even_1238((x_1239-1))
return g1682
odd_1237 = g1684()
return odd_1237(13)
def g1698():
"""
>>> g1698()
True
"""
def g1697():
def g1696(x_1241):
return x_1241
return g1696
even_1242 = g1697()
def g1695():
def g1694():
def g1692(x_1246):
def g1693():
return x_1246 == 0
if (g1693()):
return True
else:
return odd_1243((x_1246-1))
return g1692
even_1244 = g1694()
def g1691():
def g1689(x_1245):
def g1690():
return x_1245 == 0
if (g1690()):
return False
else:
return even_1244((x_1245-1))
return g1689
odd_1243 = g1691()
return odd_1243(13)
return even_1242(g1695())
def g1702():
"""
>>> g1702()
120
"""
def g1701():
def g1699(n_1248):
def g1700():
return n_1248 == 0
if (g1700()):
return 1
else:
return (n_1248)*(fact_1247((n_1248-1)))
return g1699
fact_1247 = g1701()
return fact_1247(5)
def g1716():
"""
>>> g1716()
10
"""
x_1249 = 5
def g1715():
def g1713(u_1263, v_1262, w_1261):
def g1714():
return u_1263 == 0
if (g1714()):
return b_1251(v_1262, w_1261)
else:
return a_1252((u_1263)-(1), v_1262, w_1261)
return g1713
a_1252 = g1715()
def g1712():
def g1705(q_1255, r_1254):
p_1256 = (q_1255)*(r_1254)
def g1711():
def g1709(n_1260):
def g1710():
return n_1260 == 0
if (g1710()):
return c_1250(p_1256)
else:
return o_1257((n_1260)-(1))
return g1709
e_1258 = g1711()
def g1708():
def g1706(n_1259):
def g1707():
return n_1259 == 0
if (g1707()):
return c_1250(x_1249)
else:
return e_1258((n_1259)-(1))
return g1706
o_1257 = g1708()
return e_1258((q_1255)*(r_1254))
return g1705
b_1251 = g1712()
def g1704():
def g1703(x_1253):
return (5)*(x_1253)
return g1703
c_1250 = g1704()
return a_1252(3, 2, 1)
def g1729():
"""
>>> g1729()
537516
"""
def g1728():
def g1727(x_1269):
return (x_1269+1)
return g1727
f_1276 = g1728()
def g1726():
def g1725(x_1268):
return (x_1268-1)
return g1725
g_1275 = g1726()
def g1724():
def g1723(x_1267):
return (x_1267+1)
return g1723
t_1274 = g1724()
def g1722():
def g1721(x_1266):
return (x_1266+1)
return g1721
j_1273 = g1722()
def g1720():
def g1719(x_1265):
return (x_1265+1)
return g1719
i_1272 = g1720()
def g1718():
def g1717(x_1264):
return (x_1264+1)
return g1717
h_1271 = g1718()
x_1270 = 80
a_1279 = f_1276(x_1270)
b_1278 = g_1275(x_1270)
c_1277 = h_1271(i_1272(j_1273(t_1274(x_1270))))
return (a_1279)*((b_1278)*((c_1277)+(0)))
def g1733():
"""
>>> g1733()
120
"""
def g1732():
def g1730(fact_1281, n_1280):
def g1731():
return n_1280 == 0
if (g1731()):
return 1
else:
return (fact_1281(fact_1281, (n_1280-1)))*(n_1280)
return g1730
fact_1282 = g1732()
return fact_1282(fact_1282, 5)
def g1737():
"""
>>> g1737()
10000
"""
def g1736():
def g1735(x_1283):
return (x_1283)+(1000)
return g1735
f_1284 = g1736()
def g1734():
return f_1284(-2) == 0
if (g1734()):
return f_1284(6000)
else:
return f_1284(f_1284(8000))
def g1741():
"""
>>> g1741()
10000
"""
def g1740():
def g1739(x_1285):
return (x_1285)+(1000)
return g1739
f_1286 = g1740()
def g1738():
return f_1286(-1) == 0
if (g1738()):
return f_1286(6000)
else:
return f_1286(f_1286(8000))
def g1747():
"""
>>> g1747()
8000
"""
def g1746():
def g1745(x_1288, y_1287):
return (x_1288)+(1000)
return g1745
f_1289 = g1746()
def g1744():
def g1743():
def g1742():
return 0
return f_1289(3000, g1742())
if (g1743()):
return f_1289(f_1289(4000, 0), 0)
else:
return 8000
return (g1744())+(2000)
def g1754():
"""
>>> g1754()
24
"""
def g1753():
def g1752():
def g1751():
def g1748(x_1290):
def g1749(y_1291):
def g1750(z_1292):
return (x_1290)+((y_1291)+((z_1292)+(y_1291)))
return g1750
return g1749
return g1748
return g1751()(5)
return g1752()(6)
return g1753()(7)
def g1765():
"""
>>> g1765()
35
"""
def g1764():
def g1763():
def g1762():
def g1761():
def g1760():
def g1755(x_1293):
def g1756(y_1294):
def g1757(z_1295):
def g1758(w_1296):
def g1759(u_1297):
return (x_1293)+((y_1294)+((z_1295)+((w_1296)+(u_1297))))
return g1759
return g1758
return g1757
return g1756
return g1755
return g1760()(5)
return g1761()(6)
return g1762()(7)
return g1763()(8)
return g1764()(9)
def g1769():
"""
>>> g1769()
True
"""
def g1768():
def g1767(x_1298):
return x_1298
return g1767
f_1299 = g1768()
def g1766():
return hasattr(f_1299, '__call__')
if (g1766()):
return True
else:
return False
def g1779():
"""
>>> g1779()
6
"""
def g1778():
def g1773(sum_1301, ls_1300):
def g1777():
return (ls_1300 == [])
if (g1777()):
return 0
else:
def g1776():
return (ls_1300[0])
def g1775():
def g1774():
return (ls_1300[1])
return sum_1301(sum_1301, g1774())
return (g1776())+(g1775())
return g1773
sum_1302 = g1778()
def g1772():
def g1771():
def g1770():
return [3,[]]
return [2,g1770()]
return [1,g1771()]
return sum_1302(sum_1302, g1772())
def g1785():
"""
>>> g1785()
1500
"""
def g1784():
def g1783():
def g1780(a_1303):
def g1781():
def g1782():
if (True):
return 200
(a_1303)+(g1782())
return 1500
return g1781
return g1780
return g1783()(1000)
return g1784()()
def g1791():
"""
>>> g1791()
102
"""
def g1790():
def g1789():
def g1786(b_1304):
def g1787(a_1305):
def g1788():
if (1):
return 2
a_1305 = g1788()
return (a_1305)+(b_1304)
return g1787
return g1786
return g1789()(100)
return g1790()(200)
def g1800():
"""
>>> g1800()
2600
"""
def g1799():
def g1798():
def g1797():
def g1792(a_1306):
def g1793(b_1307):
def g1794():
if (b_1307):
return 200
a_1306 = g1794()
def g1795(c_1308):
def g1796():
if (300):
return 400
c_1308 = g1796()
return (a_1306)+((b_1307)+(c_1308))
return g1795
return g1793
return g1792
return g1797()(1000)
return g1798()(2000)
return g1799()(3000)
def g1807():
"""
>>> g1807()
3628800
"""
def g1806():
def g1804(x_1310):
def g1805():
return x_1310 == 0
if (g1805()):
return 1
else:
return (x_1310)*(f_1309((x_1310)-(1)))
return g1804
f_1309 = g1806()
def g1803():
def g1801(a_1311):
def g1802(b_1312):
return a_1311(b_1312)
return g1802
return g1801
g_1313 = g1803()
return g_1313(f_1309)(10)
def g1828():
"""
>>> g1828()
[52, [44, [17, [44, [52, 17]]]]]
"""
def g1827():
def g1826():
return (a_1316)+(b_1315)
return g1826
f_1318 = g1827()
def g1825():
def g1822(y_1320):
def g1824():
def g1823(y_1321):
return y_1321
return g1823
g_1317 = g1824()
return (y_1320)+(y_1320)
return g1822
g_1317 = g1825()
a_1316 = 17
b_1315 = 35
def g1821():
def g1820():
def g1819():
return a_1316
return g1819
def g1818():
def g1817(v_1319):
a_1316 = v_1319
return g1817
return [g1820(),g1818()]
h_1314 = g1821()
x1_1324 = f_1318()
x2_1323 = g_1317(22)
def g1816():
def g1815():
return (h_1314[0])
return g1815()()
x3_1322 = g1816()
x4_1325 = g_1317(22)
def g1814():
return (h_1314[1])
g1814()(3)
x5_1327 = f_1318()
def g1813():
def g1812():
return (h_1314[0])
return g1812()()
x6_1326 = g1813()
def g1811():
def g1810():
def g1809():
def g1808():
return [x5_1327,x6_1326]
return [x4_1325,g1808()]
return [x3_1322,g1809()]
return [x2_1323,g1810()]
return [x1_1324,g1811()]
def g1843():
"""
>>> g1843()
[52, [17, [35, [17, 35]]]]
"""
def g1842():
def g1841():
return (a_1330)+(b_1329)
return g1841
f_1331 = g1842()
a_1330 = 17
b_1329 = 35
def g1840():
def g1839():
def g1838():
return a_1330
return g1838
def g1837():
def g1836():
return b_1329
return g1836
return [g1839(),g1837()]
h_1328 = g1840()
def g1835():
def g1834():
def g1833():
def g1832():
def g1831():
return (h_1328[0])
return g1831()()
def g1830():
def g1829():
return (h_1328[1])
return g1829()()
return [g1832(),g1830()]
return [b_1329,g1833()]
return [a_1330,g1834()]
return [f_1331(),g1835()]
#
# closure_tests_4.pyx
#
# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#
def g1852():
"""
>>> g1852()
[3, 42]
"""
def g1851():
def g1850(x_1333):
x_1334 = 3
return 3
return g1850
f_1332 = g1851()
def g1848():
def g1847(x_1336):
y_1337 = 14
y_1337 = 7
return y_1337
return g1847
g_1335 = g1848()
def g1849():
return [g_1335,3]
g_1335 = g1849()
def g1846():
def g1845(x_1340):
return x_1340
return g1845
h_1339 = g1846()
z_1338 = 42
def g1844():
return (g_1335[1])
return [g1844(),h_1339(z_1338)]
def g1864():
"""
>>> g1864()
True
"""
t_1342 = True
f_1341 = False
def g1863():
return [t_1342,f_1341]
bools_1345 = g1863()
def g1862():
def g1861(x_1343):
if ((not x_1343)):
return f_1341
else:
return t_1342
return g1861
id_1344 = g1862()
def g1860():
def g1857(x_1349):
def g1859():
return x_1349 == 0
if (g1859()):
def g1858():
return (bools_1345[0])
return id_1344(g1858())
else:
return odd_1346((x_1349)-(1))
return g1857
even_1347 = g1860()
def g1856():
def g1853(y_1348):
def g1855():
return y_1348 == 0
if (g1855()):
def g1854():
return (bools_1345[1])
return id_1344(g1854())
else:
return even_1347((y_1348)-(1))
return g1853
odd_1346 = g1856()
return odd_1346(5)
def g1872():
"""
>>> g1872()
35
"""
a_1350 = 5
def g1871():
return [a_1350,6]
b_1351 = g1871()
def g1870():
def g1869(x_1352):
return (x_1352)*(a_1350)
return g1869
f_1353 = g1870()
def g1867():
def g1866():
return (b_1351[0])
return (f_1353(a_1350))-(g1866())
if (g1867()):
def g1868():
if ((not a_1350)):
return (2)*(a_1350)
else:
return (2)+(a_1350)
b_1351[0] = g1868()
f_1353(a_1350)
else:
if ((not (not (f_1353(a_1350) < b_1351)))): (f_1353(a_1350))
def g1865():
return (b_1351[0])
return f_1353(g1865())
def g1885():
"""
>>> g1885()
9
"""
def g1884():
def g1883(x_1368, y_1367):
if ((not x_1368)):
return g_1355((x_1368+1), (y_1367+1))
else:
return h_1354((x_1368)+(y_1367))
return g1883
f_1356 = g1884()
def g1882():
def g1875(u_1359, v_1358):
a_1361 = (u_1359)+(v_1358)
b_1360 = (u_1359)*(v_1358)
def g1881():
def g1876(d_1363):
def g1880():
return [a_1361,b_1360]
p_1365 = g1880()
def g1879():
def g1877(m_1366):
if ((m_1366 < u_1359)):
return f_1356(m_1366, d_1363)
else:
def g1878():
return (p_1365[0])
return h_1354(g1878())
return g1877
q_1364 = g1879()
return q_1364(f_1356(a_1361, b_1360))
return g1876
e_1362 = g1881()
return e_1362(u_1359)
return g1875
g_1355 = g1882()
def g1874():
def g1873(w_1357):
return w_1357
return g1873
h_1354 = g1874()
return f_1356(4, 5)
def g1897():
"""
>>> g1897()
22
"""
def g1896():
def g1890(x_1373):
def g1895():
def g1894():
def g1893():
def g1891(y_1374):
def g1892(z_1375):
return (y_1374)+(z_1375)
return g1892
return g1891
return g1893()(6)
return g1894()(7)
return (x_1373)+(g1895())
return g1890
f_1370 = g1896()
def g1889():
def g1888():
def g1887():
def g1886(w_1372, u_1371):
return (w_1372)+(u_1371)
return g1886
return g1887()(8, 9)
return (5)+(g1888())
g_1369 = g1889()
return g_1369
def g1923():
"""
>>> g1923()
True
"""
y_1377 = []
z_1376 = 10
def g1911():
return [5,y_1377]
test_ls_1378 = g1911()
def g1922():
def g1913(f_1379):
def g1921():
def g1918(g_1382):
def g1920():
def g1919(x_1383):
return g_1382(g_1382)(x_1383)
return g1919
return f_1379(g1920())
return g1918
def g1917():
def g1914(g_1380):
def g1916():
def g1915(x_1381):
return g_1380(g_1380)(x_1381)
return g1915
return f_1379(g1916())
return g1914
return g1921()(g1917())
return g1913
y_1377 = g1922()
def g1912():
return [z_1376,test_ls_1378]
test_ls_1378 = g1912()
def g1910():
def g1906(ls_1385):
def g1909():
return (ls_1385 == [])
if (g1909()):
return 0
else:
def g1908():
def g1907():
return (ls_1385[1])
return length_1384(g1907())
return (1)+(g1908())
return g1906
length_1384 = g1910()
len_1386 = length_1384(test_ls_1378)
def g1905():
def g1904():
def g1903():
def g1898(len_1387):
def g1899(ls_1388):
def g1902():
return (ls_1388 == [])
if (g1902()):
return 0
else:
def g1901():
def g1900():
return (ls_1388[1])
return len_1387(g1900())
return (1)+(g1901())
return g1899
return g1898
return y_1377(g1903())
length_1384 = g1904()
return length_1384(test_ls_1378)
return (g1905() == len_1386)
def g1927():
"""
>>> g1927()
0
"""
def g1926():
def g1924():
def g1925():
return loop_1389()
return g1925
return g1924
loop_1389 = g1926()
loop_1389()
return 0
def g1935():
"""
>>> g1935()
668
"""
def g1934():
def g1928():
def g1933():
def g1931(link_1392):
def g1932():
return link_1392()
return g1932
return g1931
loop_1391 = g1933()
def g1930():
def g1929():
return 668
return g1929
return loop_1391(g1930())
return g1928
f_1390 = g1934()
return f_1390()()
def g1946():
"""
>>> g1946()
14629
"""
def g1945():
def g1944():
return 1
return g1944
if (g1945()):
a_1393 = 2
def g1943():
def g1942():
def g1941():
def g1938(x_1394):
def g1940():
def g1939():
a_1393 = 1
a_1393 = g1939()
x_1395 = g1940()
return x_1395
return g1938
return g1941()(1)
if (g1942()):
def g1937():
def g1936():
return None
return (a_1393 == g1936())
if (g1937()):
return True
else:
return False
else:
return False
if (g1943()):
return 778477
else:
return 14629
def g1949():
"""
>>> g1949()
2
"""
def g1948():
def g1947(x_1396):
return x_1396
return g1947
f_1397 = g1948()
a_1398 = 1
return ((f_1397(a_1398))+(a_1398))*(a_1398)
def g1952():
"""
>>> g1952()
17
"""
def g1951():
def g1950(x_1400, y_1399):
return x_1400
return g1950
k_1401 = g1951()
b_1402 = 17
return k_1401(k_1401(k_1401, 37), 37)(b_1402, (b_1402)*(b_1402))
def g1956():
"""
>>> g1956()
False
"""
def g1955():
def g1953():
n_1403 = 256
def g1954():
return ([0]*n_1403)
v_1404 = g1954()
v_1404[32] = n_1403
return v_1404[32]
return g1953
f_1405 = g1955()
return isinstance(f_1405(), list)
def g1959():
"""
>>> g1959()
60
"""
w_1409 = 4
x_1408 = 8
y_1407 = 16
z_1406 = 32
def g1958():
def g1957():
return (w_1409)+((x_1408)+((y_1407)+(z_1406)))
return g1957
f_1410 = g1958()
return f_1410()
def g1965():
"""
>>> g1965()
37
"""
def g1964():
def g1962(g_1412, u_1411):
def g1963():
if (u_1411):
return g_1412(37)
else:
return u_1411
return g_1412(g1963())
return g1962
f_1413 = g1964()
def g1961():
def g1960(x_1414):
return x_1414
return g1960
return f_1413(g1961(), 75)
def g1971():
"""
>>> g1971()
4687
"""
def g1970():
def g1968(h_1416, u_1415):
def g1969():
if (u_1415):
return h_1416((u_1415)+(37))
else:
return u_1415
return h_1416(g1969())
return g1968
f_1418 = g1970()
w_1417 = 62
def g1967():
def g1966(x_1419):
return (w_1417)-(x_1419)
return g1966
return f_1418(g1967(), (75)*(w_1417))
def g1983():
"""
>>> g1983()
True
"""
t_1421 = True
f_1420 = False
def g1982():
return [t_1421,f_1420]
bools_1424 = g1982()
def g1981():
def g1980(x_1422):
if ((not x_1422)):
return f_1420
else:
return t_1421
return g1980
id_1423 = g1981()
def g1979():
def g1976(x_1428):
def g1978():
def g1977():
return x_1428 == 0
return id_1423(g1977())
if (g1978()):
return (bools_1424[0])
else:
return odd_1425((x_1428)-(1))
return g1976
even_1426 = g1979()
def g1975():
def g1972(y_1427):
def g1974():
return y_1427 == 0
if (g1974()):
def g1973():
return (bools_1424[1])
return id_1423(g1973())
else:
return even_1426((y_1427)-(1))
return g1972
odd_1425 = g1975()
return odd_1425(5)
def g1990():
"""
>>> g1990()
48
"""
def g1989():
def g1984(x_1431, y_1430, z_1429):
def g1988():
def g1987(u_1435, v_1434):
x_1431 = u_1435
return (x_1431)+(v_1434)
return g1987
f_1437 = g1988()
def g1986():
def g1985(r_1433, s_1432):
y_1430 = (z_1429)+(s_1432)
return y_1430
return g1985
g_1436 = g1986()
return (f_1437(1, 2))*(g_1436(3, 4))
return g1984
return g1989()(10, 11, 12)
def g1997():
"""
>>> g1997()
176
"""
def g1996():
def g1991(x_1440, y_1439, z_1438):
f_1444 = False
def g1995():
def g1994(r_1442, s_1441):
y_1439 = (z_1438)+(s_1441)
return y_1439
return g1994
g_1443 = g1995()
def g1993():
def g1992(u_1446, v_1445):
v_1445 = u_1446
return (x_1440)+(v_1445)
return g1992
f_1444 = g1993()
return (f_1444(1, 2))*(g_1443(3, 4))
return g1991
return g1996()(10, 11, 12)
def g2002():
"""
>>> g2002()
5
"""
def g2001():
def g2000(x_1450):
return (x_1450)+(1)
return g2000
f_1448 = g2001()
def g1999():
def g1998(y_1449):
return f_1448(f_1448(y_1449))
return g1998
g_1447 = g1999()
return (f_1448(1))+(g_1447(1))
def g2010():
"""
>>> g2010()
1521
"""
y_1451 = 3
def g2009():
def g2007(x_1457):
def g2008():
return x_1457 == 0
if (g2008()):
return g_1453((x_1457)+(1))
else:
return f_1454((x_1457)-(y_1451))
return g2007
f_1454 = g2009()
def g2006():
def g2005(x_1456):
return h_1452((x_1456)*(x_1456))
return g2005
g_1453 = g2006()
def g2004():
def g2003(x_1455):
return x_1455
return g2003
h_1452 = g2004()
return g_1453(39)
def g2017():
"""
>>> g2017()
-1
"""
def g2014():
def g2013(x_1461):
return (x_1461)+(1)
return g2013
f_1459 = g2014()
def g2012():
def g2011(y_1460):
return f_1459(f_1459(y_1460))
return g2011
g_1458 = g2012()
def g2016():
def g2015(x_1462):
return (x_1462)-(1)
return g2015
f_1459 = g2016()
return (f_1459(1))+(g_1458(1))
def g2032():
"""
>>> g2032()
[52, [17, [35, [17, 35]]]]
"""
def g2031():
def g2030():
return (a_1465)+(b_1464)
return g2030
f_1466 = g2031()
a_1465 = 17
b_1464 = 35
def g2029():
def g2028():
def g2027():
return a_1465
return g2027
def g2026():
def g2025():
return b_1464
return g2025
return [g2028(),g2026()]
h_1463 = g2029()
def g2024():
def g2023():
def g2022():
def g2021():
def g2020():
return (h_1463[0])
return g2020()()
def g2019():
def g2018():
return (h_1463[1])
return g2018()()
return [g2021(),g2019()]
return [b_1464,g2022()]
return [a_1465,g2023()]
return [f_1466(),g2024()]
def g2038():
"""
>>> g2038()
120
"""
x_1469 = 5
def g2037():
a_1467 = 1
def g2036():
return a_1467
return g2036
th_1468 = g2037()
def g2035():
def g2033(n_1472, th_1471):
def g2034():
return n_1472 == 0
if (g2034()):
return th_1471()
else:
return (n_1472)*(fact_1470((n_1472)-(1), th_1471))
return g2033
fact_1470 = g2035()
return fact_1470(x_1469, th_1468)
def g2046():
"""
>>> g2046()
[120, -120]
"""
def g2045():
def g2044(n_1473):
return (n_1473 < 0)
return g2044
negative_1474 = g2045()
def g2043():
def g2041(n_1478):
def g2042():
return n_1478 == 0
if (g2042()):
return 1
else:
return (n_1478)*(fact_1476((n_1478)-(1)))
return g2041
fact_1476 = g2043()
def g2040():
def g2039(n_1477):
if ((not negative_1474(n_1477))):
return fact_1476(n_1477)
else:
return (0)-(fact_1476((0)-(n_1477)))
return g2039
call_fact_1475 = g2040()
return [call_fact_1475(5),call_fact_1475(-5)]
def g2050():
"""
>>> g2050()
[0, 1, 2, 3]
"""
def g2049():
def g2048(v_1482, i_1481, n_1480):
if ((not (i_1481 == n_1480))):
v_1482[i_1481] = i_1481
return iota_fill_1479(v_1482, (i_1481)+(1), n_1480)
return g2048
iota_fill_1479 = g2049()
n_1483 = 4
def g2047():
return ([0]*n_1483)
v_1484 = g2047()
iota_fill_1479(v_1484, 0, n_1483)
return v_1484
def g2061():
"""
>>> g2061()
[[33, 55], [77, 99]]
"""
def g2060():
def g2059():
def g2058():
def g2057():
def g2051(a_1485):
def g2052(b_1486):
def g2053(c_1487):
def g2054(d_1488):
def g2056():
return [a_1485,b_1486]
def g2055():
return [c_1487,d_1488]
return [g2056(),g2055()]
return g2054
return g2053
return g2052
return g2051
return g2057()(33)
return g2058()(55)
return g2059()(77)
return g2060()(99)
def g2075():
"""
>>> g2075()
[[[3, [21, [18, []]]], [4, [28, [24, []]]]], [[[0, [0, [0, []]]], [1, [7, [6, []]]]], [[408, 408], []]]]
"""
a_1489 = 17
def g2074():
def g2064(x_1490):
x1_1492 = (x_1490)+(1)
x2_1491 = (x_1490)+(2)
y1_1494 = (x1_1492)*(7)
y2_1493 = (x2_1491)*(7)
z1_1496 = (y1_1494)-(x1_1492)
z2_1495 = (y2_1493)-(x2_1491)
w1_1498 = (z1_1496)*(a_1489)
w2_1497 = (z2_1495)*(a_1489)
def g2073():
def g2068(b_1500):
if ((b_1500 == a_1489)):
def g2072():
def g2071():
return [z1_1496,[]]
return [y1_1494,g2071()]
return [x1_1492,g2072()]
else:
def g2070():
def g2069():
return [z2_1495,[]]
return [y2_1493,g2069()]
return [x2_1491,g2070()]
return g2068
g_1502 = g2073()
def g2067():
def g2066(c_1499):
if ((c_1499 == x_1490)):
return w1_1498
else:
return w2_1497
return g2066
h_1501 = g2067()
def g2065():
if (((x_1490)*(x_1490) == (x_1490)+(x_1490))):
return True
else:
return (x_1490 < 0)
if (g2065()):
return [g_1502(17),g_1502(16)]
else:
return [h_1501(x_1490),h_1501((x_1490)-(0))]
return g2064
f_1503 = g2074()
def g2063():
def g2062():
return [f_1503(3),[]]
return [f_1503(-1),g2062()]
return [f_1503(2),g2063()]
__doc__ = u"""
>>> f = add_n(3)
>>> f(2)
5
>>> f = add_n(1000000)
>>> f(1000000), f(-1000000)
(2000000, 0)
>>> a(5)()
8
>>> local_x(1)(2)(4)
4 2 1
15
# this currently crashes Cython due to redefinition
#>>> x(1)(2)(4)
#15
>>> x2(1)(2)(4)
4 2 1
15
>>> inner_override(2,4)()
5
>>> reassign(4)(2)
3
>>> reassign_int(4)(2)
3
>>> reassign_int_int(4)(2)
3
>>> def py_twofuncs(x):
... def f(a):
... return g(x) + a
... def g(b):
... return x + b
... return f
>>> py_twofuncs(1)(2) == cy_twofuncs(1)(2)
True
>>> py_twofuncs(3)(5) == cy_twofuncs(3)(5)
True
>>> inner_funcs = more_inner_funcs(1)(2,4,8)
>>> inner_funcs[0](16), inner_funcs[1](32), inner_funcs[2](64)
(19, 37, 73)
>>> switch_funcs([1,2,3], [4,5,6], 0)([10])
[1, 2, 3, 10]
>>> switch_funcs([1,2,3], [4,5,6], 1)([10])
[4, 5, 6, 10]
>>> switch_funcs([1,2,3], [4,5,6], 2) is None
True
>>> call_ignore_func()
"""
def add_n(int n):
def f(int x):
return x+n
return f
def a(int x):
def b():
def c():
return 3+x
return c()
return b
def local_x(int arg_x):
cdef int local_x = arg_x
def y(arg_y):
y = arg_y
def z(long arg_z):
cdef long z = arg_z
print z, y, local_x
return 8+z+y+local_x
return z
return y
# currently crashes Cython due to name redefinitions (see local_x())
## def x(int x):
## def y(y):
## def z(long z):
## return 8+z+y+x
## return z
## return y
def x2(int x2):
def y2(y2):
def z2(long z2):
print z2, y2, x2
return 8+z2+y2+x2
return z2
return y2
def inner_override(a,b):
def f():
a = 1
return a+b
return f
def reassign(x):
def f(a):
return a+x
x = 1
return f
def reassign_int(x):
def f(int a):
return a+x
x = 1
return f
def reassign_int_int(int x):
def f(int a):
return a+x
x = 1
return f
def cy_twofuncs(x):
def f(a):
return g(x) + a
def g(b):
return x + b
return f
def switch_funcs(a, b, int ix):
def f(x):
return a + x
def g(x):
return b + x
if ix == 0:
return f
elif ix == 1:
return g
else:
return None
def ignore_func(x):
def f():
return x
return None
def call_ignore_func():
ignore_func((1,2,3))
def more_inner_funcs(x):
# called with x==1
def f(a):
def g(b):
# called with 16
return a+b+x
return g
def g(b):
def f(a):
# called with 32
return a+b+x
return f
def h(b):
def f(a):
# called with 64
return a+b+x
return f
def resolve(a_f, b_g, b_h):
# called with (2,4,8)
return f(a_f), g(b_g), h(b_h)
return resolve
# cython: language_level=3
try:
sorted
except NameError:
def sorted(seq):
seq = list(seq)
seq.sort()
return seq
def print_function(*args):
"""
>>> print_function(1,2,3)
......@@ -17,3 +25,33 @@ def unicode_literals():
"""
print(isinstance(ustring, unicode) or type(ustring))
return ustring
def list_comp():
"""
>>> list_comp()
[0, 4, 8]
"""
x = 'abc'
result = [x*2 for x in range(5) if x % 2 == 0]
assert x == 'abc' # don't leak in Py3 code
return result
def set_comp():
"""
>>> sorted(set_comp())
[0, 4, 8]
"""
x = 'abc'
result = {x*2 for x in range(5) if x % 2 == 0}
assert x == 'abc' # don't leak
return result
def dict_comp():
"""
>>> sorted(dict_comp().items())
[(0, 0), (2, 4), (4, 8)]
"""
x = 'abc'
result = {x:x*2 for x in range(5) if x % 2 == 0}
assert x == 'abc' # don't leak
return result
__doc__ = u"""
>>> type(smoketest_dict()) is dict
True
>>> type(smoketest_list()) is dict
True
>>> sorted(smoketest_dict().items())
[(2, 0), (4, 4), (6, 8)]
>>> sorted(smoketest_list().items())
[(2, 0), (4, 4), (6, 8)]
>>> list(typed().items())
[(A, 1), (A, 1), (A, 1)]
>>> sorted(iterdict().items())
[(1, 'a'), (2, 'b'), (3, 'c')]
"""
cimport cython
def smoketest_dict():
return { x+2:x*2
for x in range(5)
if x % 2 == 0 }
def dictcomp():
"""
>>> sorted(dictcomp().items())
[(2, 0), (4, 4), (6, 8)]
>>> sorted(dictcomp().items())
[(2, 0), (4, 4), (6, 8)]
"""
x = 'abc'
result = { x+2:x*2
for x in range(5)
if x % 2 == 0 }
assert x == 'abc' # do not leak!
return result
@cython.test_fail_if_path_exists(
"//ComprehensionNode//ComprehensionAppendNode",
"//SimpleCallNode//ComprehensionNode")
"//GeneratorExpressionNode",
"//SimpleCallNode")
@cython.test_assert_path_exists(
"//ComprehensionNode",
"//ComprehensionNode//DictComprehensionAppendNode")
def smoketest_list():
return dict([ (x+2,x*2)
for x in range(5)
if x % 2 == 0 ])
def genexpr():
"""
>>> type(genexpr()) is dict
True
>>> type(genexpr()) is dict
True
"""
x = 'abc'
result = dict( (x+2,x*2)
for x in range(5)
if x % 2 == 0 )
assert x == 'abc'
return result
cdef class A:
def __repr__(self): return u"A"
def __richcmp__(one, other, op): return one is other
def __hash__(self): return id(self) % 65536
def typed():
def typed_dictcomp():
"""
>>> list(typed_dictcomp().items())
[(A, 1), (A, 1), (A, 1)]
"""
cdef A obj
return {obj:1 for obj in [A(), A(), A()]}
def iterdict():
def iterdict_dictcomp():
"""
>>> sorted(iterdict_dictcomp().items())
[(1, 'a'), (2, 'b'), (3, 'c')]
"""
cdef dict d = dict(a=1,b=2,c=3)
return {d[key]:key for key in d}
......
cimport cython
class SomeNumber(object):
def __init__(self, n):
self._n = n
def __repr__(self):
return "SomeNumber(%s)" % self._n
@cython.binding(True)
def add_to_func(self, x):
"""
>>> add_to_func(SomeNumber(2), 5)
7
>>> SomeNumber(3).add_to(10)
13
>>> SomeNumber.add_to(SomeNumber(22), 7)
29
"""
return self._n + x
@cython.binding(False)
def new_num(n):
"""
>>> new_num(11)
SomeNumber(11)
>>> SomeNumber.new(11)
SomeNumber(11)
>>> SomeNumber(3).new(11)
SomeNumber(11)
"""
return SomeNumber(n)
SomeNumber.add_to = add_to_func
SomeNumber.new = new_num
def test_genexpr():
"""
>>> gen = test_genexpr()
>>> list(gen)
[0, 1, 2, 3, 4]
"""
return (i for i in range(5))
def test_genexpr_typed():
"""
>>> gen = test_genexpr_typed()
>>> list(gen)
[0, 1, 2, 3, 4]
"""
cdef int i
return (i for i in range(5))
def test_genexpr_funccall():
"""
>>> test_genexpr_funccall()
[0, 1, 2, 3, 4]
"""
return list(i for i in range(5))
def test_genexpr_scope():
"""
>>> test_genexpr_scope()
([0, 1, 2, 3, 4], 'abc')
"""
i = 'abc'
gen = (i for i in range(5))
lst = list(gen)
return lst, i
def test_genexpr_closure():
"""
>>> gen = test_genexpr_closure()
>>> list(gen)
['a', 'b', 'c']
"""
abc = 'a' + 'b' + 'c'
return (c for c in abc)
cimport cython
## def range_tuple_genexp(int N):
## """
## >>> range_tuple_genexp(5)
## (0, 1, 2, 3, 4)
## """
## return tuple(i for i in range(N))
@cython.test_assert_path_exists('//ForFromStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
'//ForInStatNode')
def range_sum(int N):
"""
>>> sum(range(10))
45
>>> range_sum(10)
45
"""
result = sum(i for i in range(N))
return result
@cython.test_assert_path_exists('//ForFromStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
'//CoerceFromPyTypeNode//InlinedGeneratorExpressionNode',
'//ForInStatNode')
def range_sum_typed(int N):
"""
>>> sum(range(10))
45
>>> range_sum_typed(10)
45
"""
cdef int result = sum(i for i in range(N))
return result
@cython.test_assert_path_exists('//ForFromStatNode',
"//InlinedGeneratorExpressionNode",
"//ReturnStatNode//InlinedGeneratorExpressionNode",
"//ReturnStatNode//CoerceToPyTypeNode//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
'//CoerceFromPyTypeNode//InlinedGeneratorExpressionNode',
'//TypecastNode//InlinedGeneratorExpressionNode',
'//ForInStatNode')
def return_range_sum_cast(int N):
"""
>>> sum(range(10))
45
>>> return_range_sum_cast(10)
45
"""
return <int>sum(i for i in range(N))
@cython.test_assert_path_exists('//ForFromStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
'//ForInStatNode')
def return_range_sum(int N):
"""
>>> sum(range(10))
45
>>> return_range_sum(10)
45
"""
return sum(i for i in range(N))
@cython.test_assert_path_exists('//ForFromStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode',
'//ForInStatNode')
def return_range_sum_squares(int N):
"""
>>> sum([i*i for i in range(10)])
285
>>> return_range_sum_squares(10)
285
>>> sum([i*i for i in range(10000)])
333283335000
>>> return_range_sum_squares(10000)
333283335000
"""
return sum(i*i for i in range(N))
@cython.test_assert_path_exists('//ForInStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode')
def return_sum_squares(seq):
"""
>>> sum([i*i for i in range(10)])
285
>>> return_sum_squares(range(10))
285
>>> sum([i*i for i in range(10000)])
333283335000
>>> return_sum_squares(range(10000))
333283335000
"""
return sum(i*i for i in seq)
@cython.test_assert_path_exists('//ForInStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists('//SimpleCallNode')
def return_sum_squares_start(seq, int start):
"""
>>> sum([i*i for i in range(10)], -1)
284
>>> return_sum_squares_start(range(10), -1)
284
>>> sum([i*i for i in range(10000)], 9)
333283335009
>>> return_sum_squares_start(range(10000), 9)
333283335009
"""
return sum((i*i for i in seq), start)
@cython.test_assert_path_exists(
'//ForInStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists(
'//SimpleCallNode',
"//InlinedGeneratorExpressionNode//CoerceToPyTypeNode")
def return_typed_sum_squares_start(seq, int start):
"""
>>> sum([i*i for i in range(10)], -1)
284
>>> return_typed_sum_squares_start(range(10), -1)
284
>>> sum([i*i for i in range(1000)], 9)
332833509
>>> return_typed_sum_squares_start(range(1000), 9)
332833509
"""
cdef int i
return <int>sum((i*i for i in seq), start)
@cython.test_assert_path_exists(
'//ForInStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists(
'//SimpleCallNode',
"//InlinedGeneratorExpressionNode//CoerceToPyTypeNode")
def return_typed_sum_cond_exp(seq):
"""
>>> return_typed_sum_cond_exp([1,2,3,4])
2
"""
cdef int i
return <int>sum( 0 if i%2 else 1
for i in seq )
@cython.test_assert_path_exists(
'//ForInStatNode',
"//InlinedGeneratorExpressionNode")
@cython.test_fail_if_path_exists(
'//SimpleCallNode',
"//InlinedGeneratorExpressionNode//CoerceToPyTypeNode")
def return_typed_sum_cond_exp_in(seq):
"""
>>> return_typed_sum_cond_exp_in([1,2,3,4,5,6,7,8,9])
3
"""
cdef int i
return <int>sum( 0 if i%3 in (0,1) else 1
for i in seq )
cimport cython
cdef class A:
pass
def test_all():
@cython.test_assert_path_exists('//SimpleCallNode//SimpleCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode//PythonCapiCallNode',
'//PythonCapiCallNode//SimpleCallNode')
def test_non_optimised():
"""
>>> test_all()
>>> test_non_optimised()
True
"""
# Non-optimized
cdef object foo = A
assert isinstance(A(), foo)
assert isinstance(0, (int, long))
assert not isinstance(u"xyz", (int, long))
assert isinstance(complex(), complex) # FIXME: this should be optimised, too!
return True
@cython.test_assert_path_exists('//PythonCapiCallNode',
'//PythonCapiCallNode//SimpleCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode//SimpleCallNode',
'//SimpleCallNode//PythonCapiCallNode')
def test_optimised():
"""
>>> test_optimised()
True
"""
new_type = type('a',(),{})
......@@ -14,23 +37,39 @@ def test_all():
assert isinstance(int(), int)
assert isinstance(long(), long)
assert isinstance(float(), float)
assert isinstance(complex(), complex)
assert isinstance(bytes(), bytes)
assert isinstance(str(), str)
assert isinstance(unicode(), unicode)
assert isinstance(tuple(), tuple)
assert isinstance(list(), list)
assert isinstance(dict(), dict)
# if py_ver > (2, 3):
# assert isinstance(set(), set)
assert isinstance(set(), set)
assert isinstance(slice(0), slice)
assert not isinstance(u"foo", int)
assert isinstance(A, type)
return True
@cython.test_assert_path_exists('//PythonCapiCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode//SimpleCallNode',
'//SimpleCallNode//PythonCapiCallNode',
'//TupleNode//NameNode')
def test_optimised_tuple():
"""
>>> test_optimised_tuple()
True
"""
assert isinstance(bool(), (bool, int, long, float, bytes, str, unicode, tuple, list, dict, set, slice))
assert isinstance(int(), (bool, int, long, float, bytes, str, unicode, tuple, list, dict, set, slice))
assert isinstance(list(), (bool, int, long, float, bytes, str, unicode, tuple, list, dict, set, slice))
return True
@cython.test_assert_path_exists('//SimpleCallNode//SimpleCallNode')
@cython.test_fail_if_path_exists('//SimpleCallNode//PythonCapiCallNode',
'//PythonCapiCallNode//SimpleCallNode')
def test_custom():
"""
>>> test_custom()
True
"""
assert isinstance(A(), A)
assert not isinstance(u"foo", int)
# Non-optimized
cdef object foo = A
assert isinstance(A(), foo)
assert isinstance(0, (int, long))
assert not isinstance(u"xyz", (int, long))
return True
#
# Cython version of Knuth's "man or boy" test -- "It separates the man
# Algol 60 compilers from the boy Algol 60 compilers." Here's the
# original (from wikipedia):
#
# begin
# real procedure A (k, x1, x2, x3, x4, x5);
# value k; integer k;
# begin
# real procedure B;
# begin k:= k - 1;
# B:= A := A (k, B, x1, x2, x3, x4);
# end;
# if k <= 0 then A:= x4 + x5 else B;
# end;
# outreal (A (10, 1, -1, -1, 1, 0));
# end;
#
# and a table of values:
#
# k A
# 0 1
# 1 0
# 2 -2
# 3 0
# 4 1
# 5 0
# 6 1
# 7 -1
# 8 -10
# 9 -30
# 10 -67
#
# Past 10 or so, we blow the C stack -- can't just set a higher recursion limit
# to get around that one.
#
def compute(val):
if isinstance(val, int):
return val
else:
return val()
def a(in_k, x1, x2, x3, x4, x5):
"""
>>> import sys
>>> sys.setrecursionlimit(1350)
>>> a(10, 1, -1, -1, 1, 0)
-67
"""
k = [in_k]
def b():
k[0] -= 1
return a(k[0], b, x1, x2, x3, x4)
return compute(x4) + compute(x5) if k[0] <= 0 else b()
__doc__ = u"""
#>>> py_identity = lambda x:x
#>>> py_identity(1) == cy_identity(1)
#True
>>> idcall = make_identity()
>>> idcall(1)
1
>>> idcall(2)
2
>>> make_const0(1)()
1
>>> make_const1(1)(2)
1
>>> make_const1(1)(2)
1
>>> make_const_calc0()()
11
>>> make_const_calc1()(2)
11
>>> make_const_calc1_xy(8)(2)
27
>>> make_lambda_lambda(1)(2)(4)
7
>>> make_typed_lambda_lambda(1)(2)(4)
7
>>> partial_lambda = make_typed_lambda_lambda(1)(2)
>>> partial_lambda(4)
7
>>> partial_lambda(5)
8
"""
#cy_identity = lambda x:x
def make_identity():
return lambda x:x
def make_const0(x):
return lambda :x
def make_const1(x):
return lambda _:x
def make_const_calc0():
return lambda : 1*2*3+5
def make_const_calc1():
return lambda _: 1*2*3+5
def make_const_calc1_xy(x):
return lambda y: x*y+(1*2*3+5)
def make_lambda_lambda(x):
return lambda y : \
lambda z:x+y+z
def make_typed_lambda_lambda(int x):
return lambda int y : \
lambda int z:x+y+z
#
# lambda_tests.pyx
#
# Battery of tests for closures in Cython. Based on the collection of
# compiler tests from P423/B629 at Indiana University, Spring 1999 and
# Fall 2000. Special thanks to R. Kent Dybvig, Dan Friedman, Kevin
# Millikin, and everyone else who helped to generate the original
# tests. Converted into a collection of Python/Cython tests by Craig
# Citro.
#
# Note: This set of tests is split (somewhat randomly) into several
# files, simply because putting all the tests in a single file causes
# gcc and g++ to buckle under the load.
#
def g0():
"""
>>> g0()
4000
"""
return (lambda y_1: y_1)(4000)
def g1():
"""
>>> g1()
1
"""
f_3 = (lambda x_2: x_2)
return (f_3(0)+1)
def g2():
"""
>>> g2()
4
"""
f_5 = (lambda y_4: y_4)
return f_5(f_5(4))
def g3():
"""
>>> g3()
4
"""
return (lambda f_7: f_7(f_7(4)))((lambda y_6: y_6))
def g5():
"""
>>> g5()
9000
"""
def g4():
a_8 = 4000
return lambda b_9: ((a_8)+(b_9))
return g4()(5000)
def g6():
"""
>>> g6()
9000
"""
return (lambda a_10: (lambda b_11: (a_10)+(b_11)))(4000)(5000)
def g7():
"""
>>> g7()
2
"""
return (lambda f_13: f_13(f_13(0)))((lambda x_12: (x_12+1)))
def g8():
"""
>>> g8()
0
"""
f_16 = (lambda x_15, y_14: x_15)
a_17 = f_16(0, 1)
return f_16(a_17, a_17)
def g10():
"""
>>> g10()
3
"""
f_19 = (lambda x_18: x_18)
def g9():
a_22 = 0
b_21 = 1
c_20 = 2
return (f_19(a_22))+((f_19(b_21))+(f_19(c_20)))
return (f_19(0))+(g9())
def g12():
"""
>>> g12()
2
"""
def g11():
x_23 = 1
return lambda y_24: ((x_23)+(y_24))
f_25 = g11()
x_26 = 0
return f_25(f_25(x_26))
def g14():
"""
>>> g14()
3050
"""
def g13():
t_29 = (lambda x_28: (x_28)+(50))
return lambda f_30: (t_29(f_30(1000)))
return g13()((lambda y_27: (y_27)+(2000)))
def g15():
"""
>>> g15()
3050
"""
return (lambda t_33: (lambda f_34: t_33(f_34(1000))))((lambda x_32: (x_32)+(50)))((lambda y_31: (y_31)+(2000)))
def g17():
"""
>>> g17()
2050
"""
def g16():
t_35 = 50
return lambda f_36: ((t_35)+(f_36()))
return g16()((lambda : 2000))
def g18():
"""
>>> g18()
2050
"""
return (lambda t_37: (lambda f_38: (t_37)+(f_38())))(50)((lambda : 2000))
def g20():
"""
>>> g20()
700
"""
def g19():
x_39 = 300
return lambda y_40: ((x_39)+(y_40))
return g19()(400)
def g21():
"""
>>> g21()
0
"""
x_44 = 3
f_43 = (lambda x_42, y_41: x_42)
if (f_43(0, 0)):
return f_43(f_43(0, 0), x_44)
else:
return 0
def g22():
"""
>>> g22()
False
"""
f_46 = (lambda x_45: (x_45) if (((not ((x_45[0]) == 0))) if (isinstance(x_45, list)) else (False)) else (False))
return f_46([0,[0,[]]])
def g23():
"""
>>> g23()
False
"""
f_48 = (lambda x_47: (x_47) if (((not ((not ((x_47[0]) == 0))) if (isinstance(x_47, list)) else (False))) if (x_47) else (False)) else (False))
return f_48(0)
def g24():
"""
>>> g24()
[]
"""
f_50 = (lambda x_49: (x_49) if ((True) if (isinstance(x_49, list)) else ((x_49 == []))) else ([]))
return f_50(0)
def g25():
"""
>>> g25()
0
"""
y_51 = 4
f_54 = (lambda x_53, y_52: 0)
return f_54(f_54(y_51, y_51), f_54(y_51, y_51))
def g26():
"""
>>> g26()
0
"""
y_55 = 4
f_58 = (lambda x_57, y_56: 0)
return f_58(f_58(y_55, f_58(y_55, y_55)), f_58(y_55, f_58(y_55, y_55)))
def g27():
"""
>>> g27()
4
"""
return (lambda y_59: (lambda f_61: f_61(f_61(y_59)))((lambda y_60: y_60)))(4)
def g28():
"""
>>> g28()
23
"""
f_63 = (lambda x_62: x_62)
return ((1) if (False) else (f_63(22))+1)
def g29():
"""
>>> g29()
5061
"""
f_68 = (lambda x_65: ((not x_65)) if (x_65) else (x_65))
f2_67 = (lambda x_64: (10)*(x_64))
x_66 = 23
return ((1) if (f_68(x_66 == 0)) else ((x_66)*(f2_67((x_66-1))))+1)
def g30():
"""
>>> g30()
1
"""
one_69 = (lambda n_70: (1) if (n_70 == 0) else (one_69((n_70-1))))
return one_69(13)
def g31():
"""
>>> g31()
True
"""
even_72 = (lambda x_74: (True) if (x_74 == 0) else (odd_71((x_74-1))))
odd_71 = (lambda x_73: (False) if (x_73 == 0) else (even_72((x_73-1))))
return odd_71(13)
def g32():
"""
>>> g32()
False
"""
even_76 = (lambda x_78: (True) if (x_78 == 0) else (odd_75((x_78-1))))
odd_75 = (lambda x_77: (False) if (x_77 == 0) else (even_76((x_77-1))))
return even_76(13)
def g34():
"""
>>> g34()
True
"""
even_80 = (lambda x_79: x_79)
def g33():
even_82 = (lambda x_84: (True) if (x_84 == 0) else (odd_81((x_84-1))))
odd_81 = (lambda x_83: (False) if (x_83 == 0) else (even_82((x_83-1))))
return odd_81(13)
return even_80(g33())
def g35():
"""
>>> g35()
120
"""
fact_85 = (lambda n_86: (1) if (n_86 == 0) else ((n_86)*(fact_85((n_86-1)))))
return fact_85(5)
def g38():
"""
>>> g38()
10
"""
x_87 = 5
a_90 = (lambda u_101, v_100, w_99: (b_89(v_100, w_99)) if (u_101 == 0) else (a_90((u_101)-(1), v_100, w_99)))
def g37():
def g36(q_93, r_92):
p_94 = (q_93)*(r_92)
e_96 = (lambda n_98: (c_88(p_94)) if (n_98 == 0) else (o_95((n_98)-(1))))
o_95 = (lambda n_97: (c_88(x_87)) if (n_97 == 0) else (e_96((n_97)-(1))))
return e_96((q_93)*(r_92))
return g36
b_89 = g37()
c_88 = (lambda x_91: (5)*(x_91))
return a_90(3, 2, 1)
def g39():
"""
>>> g39()
120
"""
fact_104 = (lambda fact_103, n_102: (1) if (n_102 == 0) else ((fact_103(fact_103, (n_102-1)))*(n_102)))
return fact_104(fact_104, 5)
def g40():
"""
>>> g40()
35
"""
return (lambda x_105: (lambda y_106: (lambda z_107: (lambda w_108: (lambda u_109: (x_105)+((y_106)+((z_107)+((w_108)+(u_109)))))))))(5)(6)(7)(8)(9)
def g41():
"""
>>> g41()
6
"""
sum_112 = (lambda sum_111, ls_110: (0) if ((ls_110 == [])) else (((ls_110[0]))+(sum_111(sum_111, (ls_110[1])))))
return sum_112(sum_112, [1,[2,[3,[]]]])
def g46():
"""
>>> g46()
1500
"""
def g45():
def g44():
def g42(a_113):
def g43():
(a_113)+(200 if True else None)
return 1500
return g43
return g42
return g44()(1000)
return g45()()
def g53():
"""
>>> g53()
2600
"""
def g52():
def g51():
def g50():
def g47(a_114):
def g48(b_115):
a_114 = 200 if b_115 else None
def g49(c_116):
c_116 = 400 if 300 else None
return (a_114)+((b_115)+(c_116))
return g49
return g48
return g47
return g50()(1000)
return g51()(2000)
return g52()(3000)
def g54():
"""
>>> g54()
5
"""
return (lambda f_118: f_118(f_118(5)))((lambda x_117: x_117))
def g56():
"""
>>> g56()
8000
"""
def g55():
f_120 = (lambda x_119: (x_119)+(3000))
return lambda y_121: (f_120(f_120(y_121)))
return g55()(2000)
def g57():
"""
>>> g57()
120
"""
fact_125 = (lambda fact_124, n_123, acc_122: (acc_122) if (n_123 == 0) else (fact_124(fact_124, (n_123-1), (n_123)*(acc_122))))
return fact_125(fact_125, 5, 1)
def g58():
"""
>>> g58()
3
"""
f_127 = (lambda x_126: (lambda : x_126()))
return f_127((lambda : 3))()
def g59():
"""
>>> g59()
22
"""
f_129 = (lambda x_132: (x_132)+((lambda y_133: (lambda z_134: (y_133)+(z_134)))(6)(7)))
g_128 = (5)+((lambda w_131, u_130: (w_131)+(u_130))(8, 9))
return g_128
def g60():
"""
>>> g60()
0
"""
loop_135 = (lambda : (lambda : loop_135()))
loop_135()
return 0
def g63():
"""
>>> g63()
668
"""
def g62():
def g61():
loop_137 = (lambda link_138: (lambda : link_138()))
return loop_137((lambda : 668))
return g61
f_136 = g62()
return f_136()()
def g64():
"""
>>> g64()
17
"""
k_141 = (lambda x_140, y_139: x_140)
b_142 = 17
return k_141(k_141(k_141, 37), 37)(b_142, (b_142)*(b_142))
def g65():
"""
>>> g65()
37
"""
f_145 = (lambda g_144, u_143: g_144((g_144(37)) if (u_143) else (u_143)))
return f_145((lambda x_146: x_146), 75)
def g66():
"""
>>> g66()
4687
"""
f_150 = (lambda h_148, u_147: h_148((h_148((u_147)+(37))) if (u_147) else (u_147)))
w_149 = 62
return f_150((lambda x_151: (w_149)-(x_151)), (75)*(w_149))
def g67():
"""
>>> g67()
True
"""
t_153 = True
f_152 = False
bools_156 = [t_153,f_152]
id_155 = (lambda x_154: (f_152) if ((not x_154)) else (t_153))
even_158 = (lambda x_160: ((bools_156[0])) if (id_155(x_160 == 0)) else (odd_157((x_160)-(1))))
odd_157 = (lambda y_159: (id_155((bools_156[1]))) if (y_159 == 0) else (even_158((y_159)-(1))))
return odd_157(5)
def g68():
"""
>>> g68()
5
"""
f_162 = (lambda x_164: (x_164)+(1))
g_161 = (lambda y_163: f_162(f_162(y_163)))
return (f_162(1))+(g_161(1))
def g69():
"""
>>> g69()
1521
"""
y_165 = 3
f_168 = (lambda x_171: (g_167((x_171)+(1))) if (x_171 == 0) else (f_168((x_171)-(y_165))))
g_167 = (lambda x_170: h_166((x_170)*(x_170)))
h_166 = (lambda x_169: x_169)
return g_167(39)
def g70():
"""
>>> g70()
-1
"""
f_173 = (lambda x_175: (x_175)+(1))
g_172 = (lambda y_174: f_173(f_173(y_174)))
f_173 = (lambda x_176: (x_176)-(1))
return (f_173(1))+(g_172(1))
def g71():
"""
>>> g71()
[52, [17, [35, [17, 35]]]]
"""
f_180 = (lambda : (a_179)+(b_178))
a_179 = 17
b_178 = 35
h_177 = [(lambda : a_179),(lambda : b_178)]
return [f_180(),[a_179,[b_178,[(h_177[0])(),(h_177[1])()]]]]
def g73():
"""
>>> g73()
120
"""
x_183 = 5
def g72():
a_181 = 1
return lambda : (a_181)
th_182 = g72()
fact_184 = (lambda n_186, th_185: (th_185()) if (n_186 == 0) else ((n_186)*(fact_184((n_186)-(1), th_185))))
return fact_184(x_183, th_182)
def g74():
"""
>>> g74()
[120, -120]
"""
negative_188 = (lambda n_187: (n_187 < 0))
fact_190 = (lambda n_192: (1) if (n_192 == 0) else ((n_192)*(fact_190((n_192)-(1)))))
call_fact_189 = (lambda n_191: (fact_190(n_191)) if ((not negative_188(n_191))) else ((0)-(fact_190((0)-(n_191)))))
return [call_fact_189(5),call_fact_189(-5)]
def g75():
"""
>>> g75()
[[33, 55], [77, 99]]
"""
return (lambda a_193: (lambda b_194: (lambda c_195: (lambda d_196: [[a_193,b_194],[c_195,d_196]]))))(33)(55)(77)(99)
......@@ -3,7 +3,20 @@ def smoketest():
>>> smoketest()
[0, 4, 8]
"""
print [x*2 for x in range(5) if x % 2 == 0]
x = 'abc'
result = [x*2 for x in range(5) if x % 2 == 0]
assert x != 'abc'
return result
def list_genexp():
"""
>>> list_genexp()
[0, 4, 8]
"""
x = 'abc'
result = list(x*2 for x in range(5) if x % 2 == 0)
assert x == 'abc'
return result
def int_runvar():
"""
......@@ -33,3 +46,20 @@ def iterdict():
l = [d[key] for key in d]
l.sort()
print l
listcomp_result = [ i*i for i in range(5) ]
def global_listcomp():
"""
>>> [ i*i for i in range(5) ]
[0, 1, 4, 9, 16]
>>> listcomp_result
[0, 1, 4, 9, 16]
"""
def nested_result():
"""
>>> nested_result()
[[], [-1], [-1, 0], [-1, 0, 1]]
"""
result = [[a-1 for a in range(b)] for b in range(4)]
return result
......@@ -20,7 +20,8 @@ def get_locals_items(x, *args, **kwds):
return locals().items()
def get_locals_items_listcomp(x, *args, **kwds):
# FIXME: 'item' should *not* appear in locals() !
# FIXME: 'item' should *not* appear in locals() yet, as locals()
# is evaluated before assigning to item !
cdef int z = 5
y = "hi"
return [ item for item in locals().items() ]
......
cimport cython
class loud_list(list):
def __len__(self):
print "calling __len__"
return super(loud_list, self).__len__()
# max()
@cython.test_assert_path_exists(
'//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
'//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
'//PrintStatNode//SimpleCallNode//ConstNode')
def test_max2():
"""
>>> test_max2()
2
2
2
2
2
calling __len__
3
calling __len__
3
"""
cdef int my_int = 1
cdef object my_pyint = 2
cdef object my_list = loud_list([1,2,3])
print max(1, 2)
print max(2, my_int)
print max(my_int, 2)
print max(my_int, my_pyint)
print max(my_pyint, my_int)
print max(my_int, len(my_list))
print max(len(my_list), my_int)
@cython.test_assert_path_exists(
'//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
'//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
'//PrintStatNode//SimpleCallNode//ConstNode')
def test_max3():
"""
>>> test_max3()
calling __len__
3
calling __len__
calling __len__
3
"""
cdef int my_int = 1
cdef object my_pyint = 2
cdef object my_list = loud_list([1,2,3])
print max(my_int, my_pyint, len(my_list))
print max(my_pyint, my_list.__len__(), len(my_list))
@cython.test_assert_path_exists(
'//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
'//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
'//PrintStatNode//SimpleCallNode//ConstNode')
def test_maxN():
"""
>>> test_maxN()
calling __len__
3
calling __len__
3
calling __len__
3
"""
cdef int my_int = 1
cdef object my_pyint = 2
cdef object my_list = loud_list([1,2,3])
print max(my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))
print max(my_int, my_int, 0, my_pyint, my_int, len(my_list))
print max(my_int, my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))
# min()
@cython.test_assert_path_exists(
'//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
'//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
'//PrintStatNode//SimpleCallNode//ConstNode')
def test_min2():
"""
>>> test_min2()
1
1
1
1
1
calling __len__
1
calling __len__
1
"""
cdef int my_int = 1
cdef object my_pyint = 2
cdef object my_list = loud_list([1,2,3])
print min(1, 2)
print min(2, my_int)
print min(my_int, 2)
print min(my_int, my_pyint)
print min(my_pyint, my_int)
print min(my_int, len(my_list))
print min(len(my_list), my_int)
@cython.test_assert_path_exists(
'//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
'//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
'//PrintStatNode//SimpleCallNode//ConstNode')
def test_min3():
"""
>>> test_min3()
calling __len__
1
calling __len__
calling __len__
2
"""
cdef int my_int = 1
cdef object my_pyint = 2
cdef object my_list = loud_list([1,2,3])
print min(my_int, my_pyint, len(my_list))
print min(my_pyint, my_list.__len__(), len(my_list))
@cython.test_assert_path_exists(
'//PrintStatNode//CondExprNode')
@cython.test_fail_if_path_exists(
'//PrintStatNode//SimpleCallNode//CoerceToPyTypeNode',
'//PrintStatNode//SimpleCallNode//ConstNode')
def test_minN():
"""
>>> test_minN()
calling __len__
0
calling __len__
0
calling __len__
0
"""
cdef int my_int = 1
cdef object my_pyint = 2
cdef object my_list = loud_list([1,2,3])
print min(my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))
print min(my_int, my_int, 0, my_pyint, my_int, len(my_list))
print min(my_int, my_int, 2, my_int, 0, my_pyint, my_int, len(my_list))
def if_list_nogil(list obj):
"""
>>> if_list_nogil( [] )
False
>>> if_list_nogil( [1] )
True
>>> if_list_nogil(None)
False
"""
return _if_list_nogil(obj)
cdef bint _if_list_nogil(list obj) nogil:
if obj:
return True
else:
return False
#!/usr/bin/env python
__doc__=u"""
>>> t = RefCountInMeth()
>>> t.chk_meth()
True
>>> t.chk_nogil()
True
>>> t.chk_meth_if()
True
>>> t.chk_nogil_if()
True
"""
import sys
cdef class RefCountInMeth(object):
cdef double value
def __cinit__(self):
self.value = 1.5
cdef double c_get_value(self) nogil:
return self.value
cdef double c_get_value_if(self) nogil:
cdef double v
if 9>4:
v = 2.3
return self.value
cdef int c_meth(self):
cdef int v
v = sys.getrefcount(self)
return v
cdef int c_meth_if(self):
cdef int v
if 5>6:
v = 7
v = sys.getrefcount(self)
return v
def chk_meth(self):
cdef int a,b
a = sys.getrefcount(self)
b = self.c_meth()
return a==b
def chk_meth_if(self):
cdef int a,b
a = sys.getrefcount(self)
b = self.c_meth_if()
return a==b
def chk_nogil(self):
cdef double v
v = self.c_get_value()
return v==self.value
def chk_nogil_if(self):
cdef double v
v = self.c_get_value_if()
return v==self.value
__doc__ = u"""
>>> type(smoketest_set()) is not list
True
>>> type(smoketest_set()) is _set
True
>>> type(smoketest_list()) is _set
True
>>> sorted(smoketest_set())
[0, 4, 8]
>>> sorted(smoketest_list())
[0, 4, 8]
>>> list(typed())
[A, A, A]
>>> sorted(iterdict())
[1, 2, 3]
"""
cimport cython
# Py2.3 doesn't have the set type, but Cython does :)
_set = set
def smoketest_set():
return { x*2
def setcomp():
"""
>>> type(setcomp()) is not list
True
>>> type(setcomp()) is _set
True
>>> sorted(setcomp())
[0, 4, 8]
"""
x = 'abc'
result = { x*2
for x in range(5)
if x % 2 == 0 }
assert x == 'abc' # do not leak
return result
@cython.test_fail_if_path_exists("//SimpleCallNode//ComprehensionNode")
@cython.test_assert_path_exists("//ComprehensionNode",
"//ComprehensionNode//ComprehensionAppendNode")
def smoketest_list():
return set([ x*2
for x in range(5)
if x % 2 == 0 ])
@cython.test_fail_if_path_exists(
"//GeneratorExpressionNode",
"//SimpleCallNode")
@cython.test_assert_path_exists(
"//ComprehensionNode",
"//ComprehensionNode//ComprehensionAppendNode")
def genexp_set():
"""
>>> type(genexp_set()) is _set
True
>>> sorted(genexp_set())
[0, 4, 8]
"""
x = 'abc'
result = set( x*2
for x in range(5)
if x % 2 == 0 )
assert x == 'abc' # do not leak
return result
cdef class A:
def __repr__(self): return u"A"
......@@ -41,10 +46,18 @@ cdef class A:
def __hash__(self): return id(self) % 65536
def typed():
"""
>>> list(typed())
[A, A, A]
"""
cdef A obj
return {obj for obj in {A(), A(), A()}}
def iterdict():
"""
>>> sorted(iterdict())
[1, 2, 3]
"""
cdef dict d = dict(a=1,b=2,c=3)
return {d[key] for key in d}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment