Commit 74006e33 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents b127d487 fbc20b57
......@@ -2348,9 +2348,6 @@ class SimpleCallNode(CallNode):
arg_list_code.append(actual_arg.result())
result = "%s(%s)" % (self.function.result(),
', '.join(arg_list_code))
# if self.wrapper_call or \
# self.function.entry.is_unbound_cmethod and self.function.entry.type.is_overridable:
# result = "(%s = 1, %s)" % (Naming.skip_dispatch_cname, result)
return result
def generate_result_code(self, code):
......@@ -3271,6 +3268,8 @@ class ListNode(SequenceNode):
# obj_conversion_errors [PyrexError] used internally
# orignial_args [ExprNode] used internally
obj_conversion_errors = []
gil_message = "Constructing Python list"
def analyse_expressions(self, env):
......@@ -3403,12 +3402,13 @@ class ComprehensionAppendNode(ExprNode):
# Need to be careful to avoid infinite recursion:
# target must not be in child_attrs/subexprs
subexprs = ['expr']
type = PyrexTypes.c_int_type
def analyse_types(self, env):
self.expr.analyse_types(env)
if not self.expr.type.is_pyobject:
self.expr = self.expr.coerce_to_pyobject(env)
self.type = PyrexTypes.c_int_type
self.is_temp = 1
def generate_result_code(self, code):
......@@ -3429,7 +3429,7 @@ class ComprehensionAppendNode(ExprNode):
class DictComprehensionAppendNode(ComprehensionAppendNode):
subexprs = ['key_expr', 'value_expr']
def analyse_types(self, env):
self.key_expr.analyse_types(env)
if not self.key_expr.type.is_pyobject:
......@@ -3437,7 +3437,6 @@ class DictComprehensionAppendNode(ComprehensionAppendNode):
self.value_expr.analyse_types(env)
if not self.value_expr.type.is_pyobject:
self.value_expr = self.value_expr.coerce_to_pyobject(env)
self.type = PyrexTypes.c_int_type
self.is_temp = 1
def generate_result_code(self, code):
......@@ -3504,6 +3503,9 @@ class DictNode(ExprNode):
is_temp = 1
type = dict_type
type = dict_type
obj_conversion_errors = []
def calculate_constant_result(self):
self.constant_result = dict([
item.constant_result for item in self.key_value_pairs])
......
......@@ -163,9 +163,14 @@ class Context(object):
module_node.scope.utility_code_list.extend(scope.utility_code_list)
return module_node
test_support = []
if options.evaluate_tree_assertions:
from Cython.TestUtils import TreeAssertVisitor
test_support.append(TreeAssertVisitor())
return ([
create_parse(self),
] + self.create_pipeline(pxd=False, py=py) + [
] + self.create_pipeline(pxd=False, py=py) + test_support + [
inject_pxd_code,
abort_on_errors,
generate_pyx_code,
......@@ -592,6 +597,7 @@ class CompilationOptions(object):
verbose boolean Always print source names being compiled
quiet boolean Don't print source names in recursive mode
compiler_directives dict Overrides for pragma options (see Options.py)
evaluate_tree_assertions boolean Test support: evaluate parse tree assertions
Following options are experimental and only used on MacOSX:
......@@ -780,6 +786,7 @@ default_options = dict(
verbose = 0,
quiet = 0,
compiler_directives = {},
evaluate_tree_assertions = False,
emit_linenums = False,
)
if sys.platform == "mac":
......
......@@ -1668,13 +1668,21 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("/*--- Initialize various global constants etc. ---*/")
code.putln(code.error_goto_if_neg("__Pyx_InitGlobals()", self.pos))
__main__name = code.globalstate.get_py_string_const(
EncodedString("__main__"), identifier=True)
code.putln("if (%s%s) {" % (Naming.module_is_main, self.full_module_name.replace('.', '__')))
code.putln(
'if (__Pyx_SetAttrString(%s, "__name__", %s) < 0) %s;' % (
env.module_cname,
__main__name.cname,
code.error_goto(self.pos)))
code.putln("}")
if Options.cache_builtins:
code.putln("/*--- Builtin init code ---*/")
code.putln(code.error_goto_if_neg("__Pyx_InitCachedBuiltins()",
self.pos))
code.putln("%s = 0;" % Naming.skip_dispatch_cname);
code.putln("/*--- Global init code ---*/")
self.generate_global_init_code(env, code)
......@@ -1840,17 +1848,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
env.module_cname,
Naming.builtins_cname,
code.error_goto(self.pos)))
__main__name = code.globalstate.get_py_string_const(
EncodedString("__main__"), identifier=True)
code.putln("if (%s%s) {" % (Naming.module_is_main, self.full_module_name.replace('.', '__')))
code.putln(
'if (__Pyx_SetAttrString(%s, "__name__", %s) < 0) %s;' % (
env.module_cname,
__main__name.cname,
code.error_goto(self.pos)))
code.putln("}")
if Options.pre_import is not None:
code.putln(
'%s = PyImport_AddModule(__Pyx_NAMESTR("%s"));' % (
......
......@@ -3971,6 +3971,8 @@ class ForFromStatNode(LoopNode, StatNode):
# depend on whether or not the loop is a python type.
self.py_loopvar_node.generate_evaluation_code(code)
self.target.generate_assignment_code(self.py_loopvar_node, code)
if from_range:
code.funcstate.release_temp(loopvar_name)
break_label = code.break_label
code.set_loop_labels(old_loop_labels)
if self.else_clause:
......@@ -4746,11 +4748,7 @@ utility_function_predeclarations = \
typedef struct {PyObject **p; char *s; long n; char is_unicode; char intern; char is_identifier;} __Pyx_StringTabEntry; /*proto*/
""" + """
static int %(skip_dispatch_cname)s = 0;
""" % { 'skip_dispatch_cname': Naming.skip_dispatch_cname }
"""
if Options.gcc_branch_hints:
branch_prediction_macros = \
......
......@@ -34,11 +34,11 @@ def is_common_value(a, b):
return not a.is_py_attr and is_common_value(a.obj, b.obj) and a.attribute == b.attribute
return False
class IterationTransform(Visitor.VisitorTransform):
"""Transform some common for-in loop patterns into efficient C loops:
- for-in-dict loop becomes a while loop calling PyDict_Next()
- for-in-enumerate is replaced by an external counter variable
- for-in-range loop becomes a plain C for loop
"""
PyDict_Next_func_type = PyrexTypes.CFuncType(
......@@ -184,7 +184,7 @@ class IterationTransform(Visitor.VisitorTransform):
node.iterator.sequence = enumerate_function.arg_tuple.args[0]
# recurse into loop to check for further optimisations
return UtilNodes.LetNode(temp, self._optimise_for_loop(node))
return UtilNodes.LetNode(temp, self._optimise_for_loop(node))
def _transform_range_iteration(self, node, range_function):
args = range_function.arg_tuple.args
......@@ -224,6 +224,13 @@ class IterationTransform(Visitor.VisitorTransform):
bound2 = args[1].coerce_to_integer(self.current_scope)
step = step.coerce_to_integer(self.current_scope)
if not isinstance(bound2, ExprNodes.ConstNode):
# stop bound must be immutable => keep it in a temp var
bound2_is_temp = True
bound2 = UtilNodes.LetRefNode(bound2)
else:
bound2_is_temp = False
for_node = Nodes.ForFromStatNode(
node.pos,
target=node.target,
......@@ -232,6 +239,10 @@ class IterationTransform(Visitor.VisitorTransform):
step=step, body=node.body,
else_clause=node.else_clause,
from_range=True)
if bound2_is_temp:
for_node = UtilNodes.LetNode(bound2, for_node)
return for_node
def _transform_dict_iteration(self, node, dict_obj, keys, values):
......@@ -613,24 +624,41 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
])
def _handle_simple_function_dict(self, node, pos_args):
"""Replace dict(some_dict) by PyDict_Copy(some_dict).
"""Replace dict(some_dict) by PyDict_Copy(some_dict) and
dict([ (a,b) for ... ]) by a literal { a:b for ... }.
"""
if len(pos_args.args) != 1:
return node
dict_arg = pos_args.args[0]
if dict_arg.type is not Builtin.dict_type:
return node
dict_arg = ExprNodes.NoneCheckNode(
dict_arg, "PyExc_TypeError", "'NoneType' is not iterable")
return ExprNodes.PythonCapiCallNode(
node.pos, "PyDict_Copy", self.PyDict_Copy_func_type,
args = [dict_arg],
is_temp = node.is_temp
)
arg = pos_args.args[0]
if arg.type is Builtin.dict_type:
arg = ExprNodes.NoneCheckNode(
arg, "PyExc_TypeError", "'NoneType' is not iterable")
return ExprNodes.PythonCapiCallNode(
node.pos, "PyDict_Copy", self.PyDict_Copy_func_type,
args = [arg],
is_temp = node.is_temp
)
elif isinstance(arg, ExprNodes.ComprehensionNode) and \
arg.type is Builtin.list_type:
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=[], is_temp=1)
new_append_node = ExprNodes.DictComprehensionAppendNode(
append_node.pos, target=target_node,
key_expr=key_node, value_expr=value_node,
is_temp=1)
arg.target = target_node
arg.type = target_node.type
replace_in = Visitor.RecursiveNodeReplacer(append_node, new_append_node)
return replace_in(arg)
return node
def _handle_simple_function_set(self, node, pos_args):
"""Replace set([a,b,...]) by a literal set {a,b,...}.
"""Replace set([a,b,...]) by a literal set {a,b,...} and
set([ x for ... ]) by a literal { x for ... }.
"""
arg_count = len(pos_args.args)
if arg_count == 0:
......@@ -881,12 +909,6 @@ class OptimizeBuiltinCalls(Visitor.VisitorTransform):
self.PyUnicode_AsXyzString_func_type,
'encode', is_unbound_method, [string_node])
return self._substitute_method_call(
node, "PyUnicode_AsEncodedString",
self.PyUnicode_AsEncodedString_func_type,
'encode', is_unbound_method,
[string_node, encoding_node, null_node])
return self._substitute_method_call(
node, "PyUnicode_AsEncodedString",
self.PyUnicode_AsEncodedString_func_type,
......
......@@ -68,7 +68,11 @@ option_defaults = {
'c99_complex' : False, # Don't use macro wrappers for complex arith, not sure what to name this...
'callspec' : "",
'profile': False,
'autotestdict': True
'autotestdict': True,
# test support
'test_assert_path_exists' : [],
'test_fail_if_path_exists' : [],
}
# Override types possibilities above, if needed
......@@ -80,7 +84,9 @@ for key, val in option_defaults.items():
option_scopes = { # defaults to available everywhere
# 'module', 'function', 'class', 'with statement'
'autotestdict' : ('module',)
'autotestdict' : ('module',),
'test_assert_path_exists' : ('function',),
'test_fail_if_path_exists' : ('function',),
}
def parse_option_value(name, value):
......
......@@ -457,6 +457,11 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
raise PostParseError(dec.function.pos,
'The %s option takes no prepositional arguments' % optname)
return optname, dict([(key.value, value) for key, value in kwds.key_value_pairs])
elif optiontype is list:
if kwds and len(kwds) != 0:
raise PostParseError(dec.function.pos,
'The %s option takes no keyword arguments' % optname)
return optname, [ str(arg.value) for arg in args ]
else:
assert False
......@@ -499,10 +504,16 @@ class InterpretCompilerDirectives(CythonTransform, SkipDeclarations):
legal_scopes = Options.option_scopes.get(name, None)
if not self.check_directive_scope(node.pos, name, 'function'):
continue
if name in optdict and isinstance(optdict[name], dict):
# only keywords can be merged, everything else
# overrides completely
optdict[name].update(value)
if name in optdict:
old_value = optdict[name]
# keywords and arg lists can be merged, everything
# else overrides completely
if isinstance(old_value, dict):
old_value.update(value)
elif isinstance(old_value, list):
old_value.extend(value)
else:
optdict[name] = value
else:
optdict[name] = value
body = StatListNode(node.pos, stats=[node])
......
......@@ -2,6 +2,7 @@ import unittest
from Cython.Compiler.Visitor import PrintTree
from Cython.TestUtils import TransformTest
from Cython.Compiler.TreePath import find_first, find_all
from Cython.Compiler import Nodes, ExprNodes
class TestTreePath(TransformTest):
_tree = None
......@@ -24,6 +25,12 @@ class TestTreePath(TransformTest):
self.assertEquals(1, len(find_all(t, "//ReturnStatNode")))
self.assertEquals(1, len(find_all(t, "//DefNode//ReturnStatNode")))
def test_node_path_star(self):
t = self._build_tree()
self.assertEquals(10, len(find_all(t, "//*")))
self.assertEquals(8, len(find_all(t, "//DefNode//*")))
self.assertEquals(0, len(find_all(t, "//NameNode//*")))
def test_node_path_attribute(self):
t = self._build_tree()
self.assertEquals(2, len(find_all(t, "//NameNode/@name")))
......@@ -34,18 +41,49 @@ class TestTreePath(TransformTest):
self.assertEquals(1, len(find_all(t, "//DefNode/ReturnStatNode/NameNode")))
self.assertEquals(1, len(find_all(t, "//ReturnStatNode/NameNode")))
def test_node_path_node_predicate(self):
t = self._build_tree()
self.assertEquals(0, len(find_all(t, "//DefNode[.//ForInStatNode]")))
self.assertEquals(2, len(find_all(t, "//DefNode[.//NameNode]")))
self.assertEquals(1, len(find_all(t, "//ReturnStatNode[./NameNode]")))
self.assertEquals(Nodes.ReturnStatNode,
type(find_first(t, "//ReturnStatNode[./NameNode]")))
def test_node_path_node_predicate_step(self):
t = self._build_tree()
self.assertEquals(2, len(find_all(t, "//DefNode[.//NameNode]")))
self.assertEquals(8, len(find_all(t, "//DefNode[.//NameNode]//*")))
self.assertEquals(1, len(find_all(t, "//DefNode[.//NameNode]//ReturnStatNode")))
self.assertEquals(Nodes.ReturnStatNode,
type(find_first(t, "//DefNode[.//NameNode]//ReturnStatNode")))
def test_node_path_attribute_exists(self):
t = self._build_tree()
self.assertEquals(2, len(find_all(t, "//NameNode[@name]")))
self.assertEquals(ExprNodes.NameNode,
type(find_first(t, "//NameNode[@name]")))
def test_node_path_attribute_exists_not(self):
t = self._build_tree()
self.assertEquals(0, len(find_all(t, "//NameNode[not(@name)]")))
self.assertEquals(2, len(find_all(t, "//NameNode[not(@honking)]")))
def test_node_path_and(self):
t = self._build_tree()
self.assertEquals(1, len(find_all(t, "//DefNode[.//ReturnStatNode and .//NameNode]")))
self.assertEquals(0, len(find_all(t, "//NameNode[@honking and @name]")))
self.assertEquals(0, len(find_all(t, "//NameNode[@name and @honking]")))
self.assertEquals(2, len(find_all(t, "//DefNode[.//NameNode[@name] and @name]")))
def test_node_path_attribute_string_predicate(self):
t = self._build_tree()
self.assertEquals(1, len(find_all(t, "//NameNode[@name = 'decorator']")))
def test_node_path_recursive_predicate(self):
t = self._build_tree()
self.assertEquals(2, len(find_all(t, "//DefNode[.//NameNode[@name]]")))
self.assertEquals(1, len(find_all(t, "//DefNode[.//NameNode[@name = 'decorator']]")))
self.assertEquals(1, len(find_all(t, "//DefNode[.//ReturnStatNode[./NameNode[@name = 'fun']]/NameNode]")))
if __name__ == '__main__':
unittest.main()
......@@ -54,7 +54,7 @@ def parse_func(next, token):
def handle_func_not(next, token):
"""
func(...)
not(...)
"""
name, predicate = parse_func(next, token)
......@@ -167,14 +167,20 @@ def handle_attribute(next, token):
def parse_path_value(next):
token = next()
value = token[0]
if value[:1] == "'" or value[:1] == '"':
value = value[1:-1]
else:
if value:
if value[:1] == "'" or value[:1] == '"':
return value[1:-1]
try:
value = int(value)
return int(value)
except ValueError:
raise ValueError("Invalid attribute predicate: '%s'" % value)
return value
pass
else:
name = token[1].lower()
if name == 'true':
return True
elif name == 'false':
return False
raise ValueError("Invalid attribute predicate: '%s'" % value)
def handle_predicate(next, token):
token = next()
......@@ -189,6 +195,9 @@ def handle_predicate(next, token):
if token[0] == "/":
token = next()
if not token[0] and token[1] == 'and':
return logical_and(selector, handle_predicate(next, token))
def select(result):
for node in result:
subresult = iter((node,))
......@@ -196,8 +205,22 @@ def handle_predicate(next, token):
subresult = select(subresult)
predicate_result = _get_first_or_none(subresult)
if predicate_result is not None:
yield predicate_result
yield node
return select
def logical_and(lhs_selects, rhs_select):
def select(result):
for node in result:
subresult = iter((node,))
for select in lhs_selects:
subresult = select(subresult)
predicate_result = _get_first_or_none(subresult)
subresult = iter((node,))
if predicate_result is not None:
for result_node in rhs_select(subresult):
yield node
return select
operations = {
"@": handle_attribute,
......
......@@ -306,6 +306,22 @@ class ScopeTrackingTransform(CythonTransform):
def visit_CStructOrUnionDefNode(self, node):
return self.visit_scope(node, 'struct')
class RecursiveNodeReplacer(VisitorTransform):
"""
Recursively replace all occurrences of a node in a subtree by
another node.
"""
def __init__(self, orig_node, new_node):
super(RecursiveNodeReplacer, self).__init__()
self.orig_node, self.new_node = orig_node, new_node
def visit_Node(self, node):
self.visitchildren(node)
if node is self.orig_node:
return self.new_node
else:
return node
......
......@@ -4,7 +4,8 @@ import unittest
from Cython.Compiler.ModuleNode import ModuleNode
import Cython.Compiler.Main as Main
from Cython.Compiler.TreeFragment import TreeFragment, strip_common_indent
from Cython.Compiler.Visitor import TreeVisitor
from Cython.Compiler.Visitor import TreeVisitor, VisitorTransform
from Cython.Compiler import TreePath
class NodeTypeWriter(TreeVisitor):
def __init__(self):
......@@ -74,6 +75,10 @@ class CythonTest(unittest.TestCase):
self.assertEqual(len(result_lines), len(expected_lines),
"Unmatched lines. Got:\n%s\nExpected:\n%s" % ("\n".join(result_lines), expected))
def assertNodeExists(self, path, result_tree):
self.assertNotEqual(TreePath.find_first(result_tree, path), None,
"Path '%s' not found in result tree" % path)
def fragment(self, code, pxds={}, pipeline=[]):
"Simply create a tree fragment using the name of the test-case in parse errors."
name = self.id()
......@@ -136,3 +141,26 @@ class TransformTest(CythonTest):
tree = T(tree)
return tree
class TreeAssertVisitor(VisitorTransform):
# actually, a TreeVisitor would be enough, but this needs to run
# as part of the compiler pipeline
def visit_CompilerDirectivesNode(self, node):
directives = node.directives
if 'test_assert_path_exists' in directives:
for path in directives['test_assert_path_exists']:
if TreePath.find_first(node, path) is None:
Errors.error(
node.pos,
"Expected path '%s' not found in result tree" % path)
if 'test_fail_if_path_exists' in directives:
for path in directives['test_fail_if_path_exists']:
if TreePath.find_first(node, path) is not None:
Errors.error(
node.pos,
"Unexpected path '%s' found in result tree" % path)
self.visitchildren(node)
return node
visit_Node = VisitorTransform.recurse_to_children
......@@ -279,7 +279,9 @@ class CythonCompileTestCase(unittest.TestCase):
annotate = annotate,
use_listing_file = False,
cplus = self.language == 'cpp',
generate_pxi = False)
generate_pxi = False,
evaluate_tree_assertions = True,
)
cython_compile(source, options=options,
full_module_name=module)
......
cimport cython
@cython.test_assert_path_exists(
"//SingleAssignmentNode",
"//SingleAssignmentNode[./NameNode[@name = 'a']]",
"//SingleAssignmentNode[./NameNode[@name = 'a'] and @first = True]",
)
def test_cdef():
cdef int a = 1
@cython.test_assert_path_exists(
"//SingleAssignmentNode",
"//SingleAssignmentNode[./NameNode[@name = 'a']]",
# FIXME: currently not working
# "//SingleAssignmentNode[./NameNode[@name = 'a'] and @first = True]",
)
def test_py():
a = 1
@cython.test_assert_path_exists(
"//SingleAssignmentNode",
"//SingleAssignmentNode[./NameNode[@name = 'a']]",
# FIXME: currently not working
# "//SingleAssignmentNode[./NameNode[@name = 'a'] and @first = True]",
)
def test_cond():
if True:
a = 1
else:
a = 2
cimport cython
@cython.test_fail_if_path_exists("//SimpleCallNode",
"//NameNode")
@cython.test_assert_path_exists("//ComprehensionNode",
"//ComprehensionNode//FuncDefNode")
def test():
object()
_ERRORS = u"""
8:0: Expected path '//ComprehensionNode' not found in result tree
8:0: Expected path '//ComprehensionNode//FuncDefNode' not found in result tree
8:0: Unexpected path '//NameNode' found in result tree
8:0: Unexpected path '//SimpleCallNode' found in result tree
"""
__doc__ = u"""
>>> type(smoketest()) is dict
>>> type(smoketest_dict()) is dict
True
>>> type(smoketest_list()) is dict
True
>>> sorted(smoketest().items())
>>> 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')]
"""
def smoketest():
return {x+2:x*2 for x in range(5) if x % 2 == 0}
cimport cython
def smoketest_dict():
return { x+2:x*2
for x in range(5)
if x % 2 == 0 }
@cython.test_fail_if_path_exists(
"//ComprehensionNode//ComprehensionAppendNode",
"//SimpleCallNode//ComprehensionNode")
@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 ])
cdef class A:
def __repr__(self): return u"A"
......
......@@ -63,20 +63,26 @@ __doc__ = u"""
"""
cimport cython
@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def go_py_enumerate():
for i,k in enumerate(range(1,5)):
print i, k
@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def go_c_enumerate():
cdef int i,k
for i,k in enumerate(range(1,5)):
print i, k
@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def go_c_enumerate_step():
cdef int i,k
for i,k in enumerate(range(1,7,2)):
print i, k
@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def py_enumerate_dict(dict d):
cdef int i = 55
k = 99
......@@ -84,6 +90,7 @@ def py_enumerate_dict(dict d):
print i, k
print u"::", i, k
@cython.test_fail_if_path_exists("//SimpleCallNode")
def py_enumerate_break(*t):
i,k = 55,99
for i,k in enumerate(t):
......@@ -91,6 +98,7 @@ def py_enumerate_break(*t):
break
print u"::", i, k
@cython.test_fail_if_path_exists("//SimpleCallNode")
def py_enumerate_return(*t):
i,k = 55,99
for i,k in enumerate(t):
......@@ -98,6 +106,7 @@ def py_enumerate_return(*t):
return
print u"::", i, k
@cython.test_fail_if_path_exists("//SimpleCallNode")
def py_enumerate_continue(*t):
i,k = 55,99
for i,k in enumerate(t):
......@@ -105,20 +114,24 @@ def py_enumerate_continue(*t):
continue
print u"::", i, k
@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def empty_c_enumerate():
cdef int i = 55, k = 99
for i,k in enumerate(range(0)):
print i, k
return i, k
# not currently optimised
def single_target_enumerate():
for t in enumerate(range(1,5)):
print t[0], t[1]
@cython.test_fail_if_path_exists("//SimpleCallNode//NameNode[@name = 'enumerate']")
def multi_enumerate():
for a,(b,(c,d)) in enumerate(enumerate(enumerate(range(1,5)))):
print a,b,c,d
@cython.test_fail_if_path_exists("//SimpleCallNode")
def multi_c_enumerate():
cdef int a,b,c,d
for a,(b,(c,d)) in enumerate(enumerate(enumerate(range(1,5)))):
......
__doc__ = u"""
>>> test_modify()
0 1 2 3 4
(4, 0)
>>> test_fix()
0 1 2 3 4
4
>>> test_break()
0 1 2
(2, 0)
>>> test_return()
0 1 2
(2, 0)
"""
cimport cython
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_modify():
cdef int i, n = 5
for i in range(n):
print i,
n = 0
print
return i,n
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_fix():
cdef int i
for i in range(5):
print i,
print
return i
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_break():
cdef int i, n = 5
for i in range(n):
print i,
n = 0
if i == 2:
break
print
return i,n
@cython.test_assert_path_exists("//ForFromStatNode")
@cython.test_fail_if_path_exists("//ForInStatNode")
def test_return():
cdef int i, n = 5
for i in range(n):
print i,
n = 0
if i == 2:
return i,n
print
return "FAILED!"
__doc__ = u"""
>>> type(smoketest()) is not list
>>> type(smoketest_set()) is not list
True
>>> type(smoketest()) is _set
>>> type(smoketest_set()) is _set
True
>>> type(smoketest_list()) is _set
True
>>> sorted(smoketest())
>>> 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():
return {x*2 for x in range(5) if x % 2 == 0}
def smoketest_set():
return { x*2
for x in range(5)
if x % 2 == 0 }
@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 ])
cdef class A:
def __repr__(self): return u"A"
......
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