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
Boxiang Sun
cython
Commits
406674e1
Commit
406674e1
authored
Apr 21, 2010
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
generic way to wrap an ExprNode in a NoneCheckNode
parent
d1b5807f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
89 additions
and
25 deletions
+89
-25
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+76
-8
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+13
-17
No files found.
Cython/Compiler/ExprNodes.py
View file @
406674e1
...
...
@@ -636,10 +636,22 @@ class ExprNode(Node):
# a constant, local var, C global var, struct member
# reference, or temporary.
return
self
.
result_in_temp
()
def
may_be_none
(
self
):
return
self
.
type
.
is_pyobject
def
as_cython_attribute
(
self
):
return
None
def
as_none_safe_node
(
self
,
error
,
message
):
# Wraps the node in a NoneCheckNode if it is not known to be
# not-None (e.g. because it is a Python literal).
if
self
.
may_be_none
():
return
NoneCheckNode
(
self
,
error
,
message
)
else
:
return
self
class
AtomicExprNode
(
ExprNode
):
# Abstract base class for expression nodes which have
# no sub-expressions.
...
...
@@ -660,7 +672,10 @@ class PyConstNode(AtomicExprNode):
def
is_simple
(
self
):
return
1
def
may_be_none
(
self
):
return
False
def
analyse_types
(
self
,
env
):
pass
...
...
@@ -682,7 +697,11 @@ class NoneNode(PyConstNode):
def
compile_time_value
(
self
,
denv
):
return
None
def
may_be_none
(
self
):
return
True
class
EllipsisNode
(
PyConstNode
):
# '...' in a subscript list.
...
...
@@ -704,7 +723,10 @@ class ConstNode(AtomicExprNode):
def
is_simple
(
self
):
return
1
def
may_be_none
(
self
):
return
False
def
analyse_types
(
self
,
env
):
pass
# Types are held in class variables
...
...
@@ -1012,6 +1034,9 @@ class LongNode(AtomicExprNode):
def
analyse_types
(
self
,
env
):
self
.
is_temp
=
1
def
may_be_none
(
self
):
return
False
gil_message
=
"Constructing Python long int"
def
generate_result_code
(
self
,
code
):
...
...
@@ -1039,6 +1064,9 @@ class ImagNode(AtomicExprNode):
def
analyse_types
(
self
,
env
):
self
.
type
.
create_declaration_utility_code
(
env
)
def
may_be_none
(
self
):
return
False
def
coerce_to
(
self
,
dst_type
,
env
):
if
self
.
type
is
dst_type
:
return
self
...
...
@@ -1098,7 +1126,10 @@ class NewExprNode(AtomicExprNode):
def
analyse_types
(
self
,
env
):
if
self
.
type
is
None
:
self
.
infer_type
(
env
)
def
may_be_none
(
self
):
return
False
def
generate_result_code
(
self
,
code
):
pass
...
...
@@ -2958,6 +2989,9 @@ class AsTupleNode(ExprNode):
self
.
type
=
tuple_type
self
.
is_temp
=
1
def
may_be_none
(
self
):
return
False
nogil_check
=
Node
.
gil_error
gil_message
=
"Constructing Python tuple"
...
...
@@ -3434,6 +3468,9 @@ class SequenceNode(ExprNode):
self
.
type
=
py_object_type
self
.
is_temp
=
1
def
may_be_none
(
self
):
return
False
def
analyse_target_types
(
self
,
env
):
self
.
iterator
=
PyTempNode
(
self
.
pos
,
env
)
self
.
unpacked_items
=
[]
...
...
@@ -3817,6 +3854,9 @@ class ComprehensionNode(ExprNode):
self
.
type
=
self
.
target
.
type
self
.
loop
.
analyse_expressions
(
env
)
def
may_be_none
(
self
):
return
False
def
calculate_result_code
(
self
):
return
self
.
target
.
result
()
...
...
@@ -3897,6 +3937,9 @@ class SetNode(ExprNode):
self
.
type
=
set_type
self
.
is_temp
=
1
def
may_be_none
(
self
):
return
False
def
calculate_constant_result
(
self
):
self
.
constant_result
=
set
([
arg
.
constant_result
for
arg
in
self
.
args
])
...
...
@@ -3964,6 +4007,9 @@ class DictNode(ExprNode):
item
.
analyse_types
(
env
)
self
.
obj_conversion_errors
=
held_errors
()
release_errors
(
ignore
=
True
)
def
may_be_none
(
self
):
return
False
def
coerce_to
(
self
,
dst_type
,
env
):
if
dst_type
.
is_pyobject
:
...
...
@@ -4094,6 +4140,9 @@ class ClassNode(ExprNode):
self
.
is_temp
=
1
env
.
use_utility_code
(
create_class_utility_code
);
def
may_be_none
(
self
):
return
False
gil_message
=
"Constructing Python class"
def
generate_result_code
(
self
,
code
):
...
...
@@ -4129,6 +4178,9 @@ class UnboundMethodNode(ExprNode):
def
analyse_types
(
self
,
env
):
self
.
function
.
analyse_types
(
env
)
def
may_be_none
(
self
):
return
False
gil_message
=
"Constructing an unbound method"
def
generate_result_code
(
self
,
code
):
...
...
@@ -4154,6 +4206,9 @@ class PyCFunctionNode(AtomicExprNode):
def
analyse_types
(
self
,
env
):
pass
def
may_be_none
(
self
):
return
False
gil_message
=
"Constructing Python function"
...
...
@@ -4675,7 +4730,10 @@ class TypeofNode(ExprNode):
self
.
pos
,
value
=
StringEncoding
.
EncodedString
(
str
(
self
.
operand
.
type
)))
self
.
literal
.
analyse_types
(
env
)
self
.
literal
=
self
.
literal
.
coerce_to_pyobject
(
env
)
def
may_be_none
(
self
):
return
False
def
generate_evaluation_code
(
self
,
code
):
self
.
literal
.
generate_evaluation_code
(
code
)
...
...
@@ -5756,8 +5814,8 @@ class PrimaryCmpNode(ExprNode, CmpNode):
self
.
operand2
=
self
.
operand2
.
coerce_to
(
bytes_type
,
env
)
env
.
use_utility_code
(
char_in_bytes_utility_code
)
if
not
isinstance
(
self
.
operand2
,
(
UnicodeNode
,
BytesNode
)):
self
.
operand2
=
NoneCheckN
ode
(
self
.
operand2
,
"PyExc_TypeError"
,
self
.
operand2
=
self
.
operand2
.
as_none_safe_n
ode
(
"PyExc_TypeError"
,
"argument of type 'NoneType' is not iterable"
)
else
:
common_type
=
py_object_type
...
...
@@ -6087,6 +6145,9 @@ class NoneCheckNode(CoercionNode):
def
analyse_types
(
self
,
env
):
pass
def
may_be_none
(
self
):
return
False
def
result_in_temp
(
self
):
return
self
.
arg
.
result_in_temp
()
...
...
@@ -6129,6 +6190,10 @@ class CoerceToPyTypeNode(CoercionNode):
gil_message
=
"Converting to Python object"
def
may_be_none
(
self
):
# FIXME: is this always safe?
return
False
def
coerce_to_boolean
(
self
,
env
):
return
self
.
arg
.
coerce_to_boolean
(
env
).
coerce_to_temp
(
env
)
...
...
@@ -6351,6 +6416,9 @@ class ModuleRefNode(ExprNode):
def
analyse_types
(
self
,
env
):
pass
def
may_be_none
(
self
):
return
False
def
calculate_result_code
(
self
):
return
Naming
.
module_cname
...
...
Cython/Compiler/Optimize.py
View file @
406674e1
...
...
@@ -173,8 +173,7 @@ class IterationTransform(Visitor.VisitorTransform):
return
node
unpack_temp_node
=
UtilNodes
.
LetRefNode
(
ExprNodes
.
NoneCheckNode
(
slice_node
,
"PyExc_TypeError"
,
"'NoneType' is not iterable"
))
slice_node
.
as_none_safe_node
(
"PyExc_TypeError"
,
"'NoneType' is not iterable"
))
slice_base_node
=
ExprNodes
.
PythonCapiCallNode
(
slice_node
.
pos
,
unpack_func
,
unpack_func_type
,
...
...
@@ -1313,8 +1312,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
return
node
arg
=
pos_args
[
0
]
if
arg
.
type
is
Builtin
.
dict_type
:
arg
=
ExprNodes
.
NoneCheckNode
(
arg
,
"PyExc_TypeError"
,
"'NoneType' is not iterable"
)
arg
=
arg
.
as_none_safe_node
(
"PyExc_TypeError"
,
"'NoneType' is not iterable"
)
return
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"PyDict_Copy"
,
self
.
PyDict_Copy_func_type
,
args
=
[
arg
],
...
...
@@ -1337,9 +1335,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
return
node
if
not
isinstance
(
list_arg
,
(
ExprNodes
.
ComprehensionNode
,
ExprNodes
.
ListNode
)):
pos_args
[
0
]
=
ExprNodes
.
NoneCheckNode
(
list_arg
,
"PyExc_TypeError"
,
"'NoneType' object is not iterable"
)
pos_args
[
0
]
=
list_arg
.
as_none_safe_node
(
"PyExc_TypeError"
,
"'NoneType' object is not iterable"
)
return
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"PyList_AsTuple"
,
self
.
PyList_AsTuple_func_type
,
...
...
@@ -1499,9 +1496,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
if
cfunc_name
is
None
:
return
node
if
not
arg
.
is_literal
:
arg
=
ExprNodes
.
NoneCheckNode
(
arg
,
"PyExc_TypeError"
,
"object of type 'NoneType' has no len()"
)
arg
=
arg
.
as_none_safe_node
(
"PyExc_TypeError"
,
"object of type 'NoneType' has no len()"
)
new_node
=
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
cfunc_name
,
self
.
PyObject_Size_func_type
,
args
=
[
arg
],
...
...
@@ -1564,8 +1560,8 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
if
not
type_arg
.
type_entry
:
# arbitrary variable, needs a None check for safety
type_arg
=
ExprNodes
.
NoneCheckN
ode
(
type_arg
,
"PyExc_TypeError"
,
type_arg
=
type_arg
.
as_none_safe_n
ode
(
"PyExc_TypeError"
,
"object.__new__(X): X is not a type object (NoneType)"
)
return
ExprNodes
.
PythonCapiCallNode
(
...
...
@@ -2126,13 +2122,13 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
if
args
and
not
args
[
0
].
is_literal
:
self_arg
=
args
[
0
]
if
is_unbound_method
:
self_arg
=
ExprNodes
.
NoneCheckN
ode
(
self_arg
,
"PyExc_TypeError"
,
self_arg
=
self_arg
.
as_none_safe_n
ode
(
"PyExc_TypeError"
,
"descriptor '%s' requires a '%s' object but received a 'NoneType'"
%
(
attr_name
,
node
.
function
.
obj
.
name
))
attr_name
,
node
.
function
.
obj
.
name
))
else
:
self_arg
=
ExprNodes
.
NoneCheckN
ode
(
self_arg
,
"PyExc_AttributeError"
,
self_arg
=
self_arg
.
as_none_safe_n
ode
(
"PyExc_AttributeError"
,
"'NoneType' object has no attribute '%s'"
%
attr_name
)
args
[
0
]
=
self_arg
return
ExprNodes
.
PythonCapiCallNode
(
...
...
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