Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
74006e33
Commit
74006e33
authored
Oct 05, 2009
by
Dag Sverre Seljebotn
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
b127d487
fbc20b57
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
378 additions
and
71 deletions
+378
-71
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+8
-6
Cython/Compiler/Main.py
Cython/Compiler/Main.py
+8
-1
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+10
-13
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+3
-5
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+43
-21
Cython/Compiler/Options.py
Cython/Compiler/Options.py
+8
-2
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+15
-4
Cython/Compiler/Tests/TestTreePath.py
Cython/Compiler/Tests/TestTreePath.py
+38
-0
Cython/Compiler/TreePath.py
Cython/Compiler/TreePath.py
+31
-8
Cython/Compiler/Visitor.py
Cython/Compiler/Visitor.py
+16
-0
Cython/TestUtils.py
Cython/TestUtils.py
+29
-1
runtests.py
runtests.py
+3
-1
tests/compile/first_assignment.pyx
tests/compile/first_assignment.pyx
+31
-0
tests/errors/tree_assert.pyx
tests/errors/tree_assert.pyx
+17
-0
tests/run/dictcomp.pyx
tests/run/dictcomp.pyx
+24
-4
tests/run/enumerate_T316.pyx
tests/run/enumerate_T316.pyx
+13
-0
tests/run/for_in_range_T372.pyx
tests/run/for_in_range_T372.pyx
+59
-0
tests/run/setcomp.pyx
tests/run/setcomp.pyx
+22
-5
No files found.
Cython/Compiler/ExprNodes.py
View file @
74006e33
...
...
@@ -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
])
...
...
Cython/Compiler/Main.py
View file @
74006e33
...
...
@@ -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"
:
...
...
Cython/Compiler/ModuleNode.py
View file @
74006e33
...
...
@@ -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"));'
%
(
...
...
Cython/Compiler/Nodes.py
View file @
74006e33
...
...
@@ -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
=
\
...
...
Cython/Compiler/Optimize.py
View file @
74006e33
...
...
@@ -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
,
...
...
Cython/Compiler/Options.py
View file @
74006e33
...
...
@@ -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
):
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
74006e33
...
...
@@ -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
])
...
...
Cython/Compiler/Tests/TestTreePath.py
View file @
74006e33
...
...
@@ -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
()
Cython/Compiler/TreePath.py
View file @
74006e33
...
...
@@ -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,
...
...
Cython/Compiler/Visitor.py
View file @
74006e33
...
...
@@ -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
...
...
Cython/TestUtils.py
View file @
74006e33
...
...
@@ -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
\
n
Expected:
\
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
runtests.py
View file @
74006e33
...
...
@@ -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
)
...
...
tests/compile/first_assignment.pyx
0 → 100644
View file @
74006e33
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
tests/errors/tree_assert.pyx
0 → 100644
View file @
74006e33
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
"""
tests/run/dictcomp.pyx
View file @
74006e33
__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"
...
...
tests/run/enumerate_T316.pyx
View file @
74006e33
...
...
@@ -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
)))):
...
...
tests/run/for_in_range_T372.pyx
0 → 100644
View file @
74006e33
__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!"
tests/run/setcomp.pyx
View file @
74006e33
__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"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment