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
Kirill Smelkov
cython
Commits
2a6bfe21
Commit
2a6bfe21
authored
Nov 26, 2009
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
017241bf
4fa6d965
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
158 additions
and
34 deletions
+158
-34
Cython/Compiler/Optimize.py
Cython/Compiler/Optimize.py
+70
-31
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+5
-3
tests/run/builtinnames.pyx
tests/run/builtinnames.pyx
+18
-0
tests/run/charptr_len.pyx
tests/run/charptr_len.pyx
+65
-0
No files found.
Cython/Compiler/Optimize.py
View file @
2a6bfe21
...
@@ -740,19 +740,22 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -740,19 +740,22 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
arg_tuple
=
node
.
positional_args
arg_tuple
=
node
.
positional_args
if
not
isinstance
(
arg_tuple
,
ExprNodes
.
TupleNode
):
if
not
isinstance
(
arg_tuple
,
ExprNodes
.
TupleNode
):
return
node
return
node
args
=
arg_tuple
.
args
return
self
.
_dispatch_to_handler
(
return
self
.
_dispatch_to_handler
(
node
,
function
,
arg
_tuple
,
node
.
keyword_args
)
node
,
function
,
arg
s
,
node
.
keyword_args
)
def
visit_SimpleCallNode
(
self
,
node
):
def
visit_SimpleCallNode
(
self
,
node
):
self
.
visitchildren
(
node
)
self
.
visitchildren
(
node
)
function
=
node
.
function
function
=
node
.
function
if
not
function
.
type
.
is_pyobject
:
if
function
.
type
.
is_pyobject
:
return
node
arg_tuple
=
node
.
arg_tuple
arg_tuple
=
node
.
arg_tuple
if
not
isinstance
(
arg_tuple
,
ExprNodes
.
TupleNode
):
if
not
isinstance
(
arg_tuple
,
ExprNodes
.
TupleNode
):
return
node
return
node
args
=
arg_tuple
.
args
else
:
args
=
node
.
args
return
self
.
_dispatch_to_handler
(
return
self
.
_dispatch_to_handler
(
node
,
node
.
function
,
arg_tuple
)
node
,
function
,
args
)
### cleanup to avoid redundant coercions to/from Python types
### cleanup to avoid redundant coercions to/from Python types
...
@@ -823,20 +826,25 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -823,20 +826,25 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
handler
=
getattr
(
self
,
'_handle_any_%s'
%
match_name
,
None
)
handler
=
getattr
(
self
,
'_handle_any_%s'
%
match_name
,
None
)
return
handler
return
handler
def
_dispatch_to_handler
(
self
,
node
,
function
,
arg_
tuple
,
kwargs
=
None
):
def
_dispatch_to_handler
(
self
,
node
,
function
,
arg_
list
,
kwargs
=
None
):
if
function
.
is_name
:
if
function
.
is_name
:
match_name
=
"_function_%s"
%
function
.
name
# we only consider functions that are either builtin
# Python functions or builtins that were already replaced
# into a C function call (defined in the builtin scope)
is_builtin
=
function
.
entry
.
is_builtin
\
or
getattr
(
function
.
entry
,
'scope'
,
None
)
is
Builtin
.
builtin_scope
if
not
is_builtin
:
return
node
function_handler
=
self
.
_find_handler
(
function_handler
=
self
.
_find_handler
(
"function_%s"
%
function
.
name
,
kwargs
)
"function_%s"
%
function
.
name
,
kwargs
)
if
function_handler
is
None
:
if
function_handler
is
None
:
return
node
return
node
if
kwargs
:
if
kwargs
:
return
function_handler
(
node
,
arg_
tuple
,
kwargs
)
return
function_handler
(
node
,
arg_
list
,
kwargs
)
else
:
else
:
return
function_handler
(
node
,
arg_
tuple
)
return
function_handler
(
node
,
arg_
list
)
elif
function
.
is_attribute
:
elif
function
.
is_attribute
and
function
.
type
.
is_pyobject
:
attr_name
=
function
.
attribute
attr_name
=
function
.
attribute
arg_list
=
arg_tuple
.
args
self_arg
=
function
.
obj
self_arg
=
function
.
obj
obj_type
=
self_arg
.
type
obj_type
=
self_arg
.
type
is_unbound_method
=
False
is_unbound_method
=
False
...
@@ -892,7 +900,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -892,7 +900,7 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
"""Replace dict(a=b,c=d,...) by the underlying keyword dict
"""Replace dict(a=b,c=d,...) by the underlying keyword dict
construction which is done anyway.
construction which is done anyway.
"""
"""
if
len
(
pos_args
.
args
)
>
0
:
if
len
(
pos_args
)
>
0
:
return
node
return
node
if
not
isinstance
(
kwargs
,
ExprNodes
.
DictNode
):
if
not
isinstance
(
kwargs
,
ExprNodes
.
DictNode
):
return
node
return
node
...
@@ -910,9 +918,9 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -910,9 +918,9 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
"""Replace dict(some_dict) by PyDict_Copy(some_dict) and
"""Replace dict(some_dict) by PyDict_Copy(some_dict) and
dict([ (a,b) for ... ]) by a literal { a:b for ... }.
dict([ (a,b) for ... ]) by a literal { a:b for ... }.
"""
"""
if
len
(
pos_args
.
args
)
!=
1
:
if
len
(
pos_args
)
!=
1
:
return
node
return
node
arg
=
pos_args
.
args
[
0
]
arg
=
pos_args
[
0
]
if
arg
.
type
is
Builtin
.
dict_type
:
if
arg
.
type
is
Builtin
.
dict_type
:
arg
=
ExprNodes
.
NoneCheckNode
(
arg
=
ExprNodes
.
NoneCheckNode
(
arg
,
"PyExc_TypeError"
,
"'NoneType' is not iterable"
)
arg
,
"PyExc_TypeError"
,
"'NoneType' is not iterable"
)
...
@@ -943,13 +951,13 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -943,13 +951,13 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
"""Replace set([a,b,...]) by a literal set {a,b,...} and
"""Replace set([a,b,...]) by a literal set {a,b,...} and
set([ x for ... ]) by a literal { x for ... }.
set([ x for ... ]) by a literal { x for ... }.
"""
"""
arg_count
=
len
(
pos_args
.
args
)
arg_count
=
len
(
pos_args
)
if
arg_count
==
0
:
if
arg_count
==
0
:
return
ExprNodes
.
SetNode
(
node
.
pos
,
args
=
[],
return
ExprNodes
.
SetNode
(
node
.
pos
,
args
=
[],
type
=
Builtin
.
set_type
,
is_temp
=
1
)
type
=
Builtin
.
set_type
,
is_temp
=
1
)
if
arg_count
>
1
:
if
arg_count
>
1
:
return
node
return
node
iterable
=
pos_args
.
args
[
0
]
iterable
=
pos_args
[
0
]
if
isinstance
(
iterable
,
(
ExprNodes
.
ListNode
,
ExprNodes
.
TupleNode
)):
if
isinstance
(
iterable
,
(
ExprNodes
.
ListNode
,
ExprNodes
.
TupleNode
)):
return
ExprNodes
.
SetNode
(
node
.
pos
,
args
=
iterable
.
args
,
return
ExprNodes
.
SetNode
(
node
.
pos
,
args
=
iterable
.
args
,
type
=
Builtin
.
set_type
,
is_temp
=
1
)
type
=
Builtin
.
set_type
,
is_temp
=
1
)
...
@@ -971,20 +979,20 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -971,20 +979,20 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
def
_handle_simple_function_tuple
(
self
,
node
,
pos_args
):
def
_handle_simple_function_tuple
(
self
,
node
,
pos_args
):
"""Replace tuple([...]) by a call to PyList_AsTuple.
"""Replace tuple([...]) by a call to PyList_AsTuple.
"""
"""
if
len
(
pos_args
.
args
)
!=
1
:
if
len
(
pos_args
)
!=
1
:
return
node
return
node
list_arg
=
pos_args
.
args
[
0
]
list_arg
=
pos_args
[
0
]
if
list_arg
.
type
is
not
Builtin
.
list_type
:
if
list_arg
.
type
is
not
Builtin
.
list_type
:
return
node
return
node
if
not
isinstance
(
list_arg
,
(
ExprNodes
.
ComprehensionNode
,
if
not
isinstance
(
list_arg
,
(
ExprNodes
.
ComprehensionNode
,
ExprNodes
.
ListNode
)):
ExprNodes
.
ListNode
)):
pos_args
.
args
[
0
]
=
ExprNodes
.
NoneCheckNode
(
pos_args
[
0
]
=
ExprNodes
.
NoneCheckNode
(
list_arg
,
"PyExc_TypeError"
,
list_arg
,
"PyExc_TypeError"
,
"'NoneType' object is not iterable"
)
"'NoneType' object is not iterable"
)
return
ExprNodes
.
PythonCapiCallNode
(
return
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"PyList_AsTuple"
,
self
.
PyList_AsTuple_func_type
,
node
.
pos
,
"PyList_AsTuple"
,
self
.
PyList_AsTuple_func_type
,
args
=
pos_args
.
args
,
args
=
pos_args
,
is_temp
=
node
.
is_temp
is_temp
=
node
.
is_temp
)
)
...
@@ -1004,22 +1012,21 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -1004,22 +1012,21 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
])
])
def
_handle_simple_function_getattr
(
self
,
node
,
pos_args
):
def
_handle_simple_function_getattr
(
self
,
node
,
pos_args
):
args
=
pos_args
.
args
if
len
(
pos_args
)
==
2
:
if
len
(
args
)
==
2
:
node
=
ExprNodes
.
PythonCapiCallNode
(
node
=
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"PyObject_GetAttr"
,
self
.
PyObject_GetAttr2_func_type
,
node
.
pos
,
"PyObject_GetAttr"
,
self
.
PyObject_GetAttr2_func_type
,
args
=
args
,
args
=
pos_
args
,
is_temp
=
node
.
is_temp
is_temp
=
node
.
is_temp
)
)
elif
len
(
args
)
==
3
:
elif
len
(
pos_
args
)
==
3
:
node
=
ExprNodes
.
PythonCapiCallNode
(
node
=
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"__Pyx_GetAttr3"
,
self
.
PyObject_GetAttr3_func_type
,
node
.
pos
,
"__Pyx_GetAttr3"
,
self
.
PyObject_GetAttr3_func_type
,
utility_code
=
Builtin
.
getattr3_utility_code
,
utility_code
=
Builtin
.
getattr3_utility_code
,
args
=
args
,
args
=
pos_
args
,
is_temp
=
node
.
is_temp
is_temp
=
node
.
is_temp
)
)
else
:
else
:
self
.
_error_wrong_arg_count
(
'getattr'
,
node
,
args
,
'2 or 3'
)
self
.
_error_wrong_arg_count
(
'getattr'
,
node
,
pos_
args
,
'2 or 3'
)
return
node
return
node
Pyx_Type_func_type
=
PyrexTypes
.
CFuncType
(
Pyx_Type_func_type
=
PyrexTypes
.
CFuncType
(
...
@@ -1028,17 +1035,42 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
...
@@ -1028,17 +1035,42 @@ class OptimizeBuiltinCalls(Visitor.EnvTransform):
])
])
def
_handle_simple_function_type
(
self
,
node
,
pos_args
):
def
_handle_simple_function_type
(
self
,
node
,
pos_args
):
args
=
pos_args
.
args
if
len
(
pos_args
)
!=
1
:
if
len
(
args
)
!=
1
:
return
node
return
node
node
=
ExprNodes
.
PythonCapiCallNode
(
node
=
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"__Pyx_Type"
,
self
.
Pyx_Type_func_type
,
node
.
pos
,
"__Pyx_Type"
,
self
.
Pyx_Type_func_type
,
args
=
args
,
args
=
pos_
args
,
is_temp
=
node
.
is_temp
,
is_temp
=
node
.
is_temp
,
utility_code
=
pytype_utility_code
,
utility_code
=
pytype_utility_code
,
)
)
return
node
return
node
Pyx_strlen_func_type
=
PyrexTypes
.
CFuncType
(
PyrexTypes
.
c_size_t_type
,
[
PyrexTypes
.
CFuncTypeArg
(
"bytes"
,
PyrexTypes
.
c_char_ptr_type
,
None
)
])
def
_handle_simple_function_len
(
self
,
node
,
pos_args
):
# note: this only works because we already replaced len() by
# PyObject_Length() which returns a Py_ssize_t instead of a
# Python object, so we can return a plain size_t instead
# without caring about Python object conversion etc.
if
len
(
pos_args
)
!=
1
:
self
.
_error_wrong_arg_count
(
'len'
,
node
,
pos_args
,
1
)
return
node
arg
=
pos_args
[
0
]
if
isinstance
(
arg
,
ExprNodes
.
CoerceToPyTypeNode
):
arg
=
arg
.
arg
if
not
arg
.
type
.
is_string
:
return
node
node
=
ExprNodes
.
PythonCapiCallNode
(
node
.
pos
,
"strlen"
,
self
.
Pyx_strlen_func_type
,
args
=
[
arg
],
is_temp
=
node
.
is_temp
,
utility_code
=
include_string_h_utility_code
,
)
return
node
### special methods
### special methods
Pyx_tp_new_func_type
=
PyrexTypes
.
CFuncType
(
Pyx_tp_new_func_type
=
PyrexTypes
.
CFuncType
(
...
@@ -1477,6 +1509,13 @@ static INLINE PyObject* __Pyx_Type(PyObject* o) {
...
@@ -1477,6 +1509,13 @@ static INLINE PyObject* __Pyx_Type(PyObject* o) {
)
)
include_string_h_utility_code
=
UtilityCode
(
proto
=
"""
#include <string.h>
"""
)
tpnew_utility_code
=
UtilityCode
(
tpnew_utility_code
=
UtilityCode
(
proto
=
"""
proto
=
"""
static INLINE PyObject* __Pyx_tp_new(PyObject* type_obj) {
static INLINE PyObject* __Pyx_tp_new(PyObject* type_obj) {
...
...
Cython/Compiler/Symtab.py
View file @
2a6bfe21
...
@@ -624,6 +624,7 @@ class BuiltinScope(Scope):
...
@@ -624,6 +624,7 @@ class BuiltinScope(Scope):
var_entry.is_variable = 1
var_entry.is_variable = 1
var_entry.is_cglobal = 1
var_entry.is_cglobal = 1
var_entry.is_readonly = 1
var_entry.is_readonly = 1
var_entry.is_builtin = 1
var_entry.utility_code = utility_code
var_entry.utility_code = utility_code
entry.as_variable = var_entry
entry.as_variable = var_entry
...
@@ -1184,6 +1185,9 @@ class ClassScope(Scope):
...
@@ -1184,6 +1185,9 @@ class ClassScope(Scope):
return self.outer_scope.add_string_const(value, identifier)
return self.outer_scope.add_string_const(value, identifier)
def lookup(self, name):
def lookup(self, name):
entry = Scope.lookup(self, name)
if entry:
return entry
if name == "classmethod":
if name == "classmethod":
# We don'
t
want
to
use
the
builtin
classmethod
here
'cause it won'
t
do
the
# We don'
t
want
to
use
the
builtin
classmethod
here
'cause it won'
t
do
the
# right thing in this scope (as the class memebers aren't still functions).
# right thing in this scope (as the class memebers aren't still functions).
...
@@ -1197,9 +1201,7 @@ class ClassScope(Scope):
...
@@ -1197,9 +1201,7 @@ class ClassScope(Scope):
py_object_type
,
py_object_type
,
[
PyrexTypes
.
CFuncTypeArg
(
""
,
py_object_type
,
None
)],
0
,
0
))
[
PyrexTypes
.
CFuncTypeArg
(
""
,
py_object_type
,
None
)],
0
,
0
))
entry
.
is_cfunction
=
1
entry
.
is_cfunction
=
1
return
entry
return
entry
else
:
return
Scope
.
lookup
(
self
,
name
)
class
PyClassScope
(
ClassScope
):
class
PyClassScope
(
ClassScope
):
...
...
tests/run/builtinnames.pyx
View file @
2a6bfe21
cimport
cython
def
test_file_py
(
file
):
def
test_file_py
(
file
):
assert
isinstance
(
file
,
(
str
,
unicode
)),
\
assert
isinstance
(
file
,
(
str
,
unicode
)),
\
u"not a string, found '%s' instead"
%
file
.
__class__
.
__name__
u"not a string, found '%s' instead"
%
file
.
__class__
.
__name__
...
@@ -12,19 +14,35 @@ cdef test_file_c(file):
...
@@ -12,19 +14,35 @@ cdef test_file_c(file):
def
range
(
arg
):
def
range
(
arg
):
return
u'range'
+
arg
return
u'range'
+
arg
def
len
(
arg
):
return
u'len'
+
arg
cdef
type
(
arg
):
cdef
type
(
arg
):
return
u'type'
+
arg
return
u'type'
+
arg
@
cython
.
test_fail_if_path_exists
(
'//SimpleCallNode/NameNode[@name="type" and @entry.is_cfunction]'
,
'//SimpleCallNode/NameNode[@name="len" and @entry.is_cfunction]'
,
)
@
cython
.
test_assert_path_exists
(
'//SimpleCallNode/NameNode[@name="type"]'
,
'//SimpleCallNode/NameNode[@name="type" and not(@entry.is_cfunction)]'
,
'//SimpleCallNode/NameNode[@name="len"]'
,
)
def
test_c
(
arg
):
def
test_c
(
arg
):
"""
"""
>>> test_c('abc')
>>> test_c('abc')
fileabc
fileabc
lenabc
typeabc
typeabc
>>> print(test_file_py('abc'))
>>> print(test_file_py('abc'))
abc
abc
>>> print(range('abc'))
>>> print(range('abc'))
rangeabc
rangeabc
>>> print(len('abc'))
lenabc
"""
"""
print
test_file_c
(
arg
)
print
test_file_c
(
arg
)
print
len
(
arg
)
print
type
(
arg
)
print
type
(
arg
)
tests/run/charptr_len.pyx
0 → 100644
View file @
2a6bfe21
__doc__
=
"""
>>> lentest_char()
7
>>> lentest_char_c()
7
>>> lentest_uchar()
7
>>> lentest_uchar_c()
7
>>> lentest_py()
7
>>> lentest_py_c()
7
"""
cimport
cython
cdef
char
*
s
=
b"abcdefg"
cdef
unsigned
char
*
us
=
b"abcdefg"
cdef
bytes
pystr
=
b"abcdefg"
@
cython
.
test_assert_path_exists
(
"//PythonCapiCallNode"
,
)
def
lentest_char
():
return
len
(
s
)
@
cython
.
test_assert_path_exists
(
"//PythonCapiCallNode"
,
)
def
lentest_char_c
():
cdef
Py_ssize_t
l
=
len
(
s
)
return
l
@
cython
.
test_assert_path_exists
(
"//PythonCapiCallNode"
,
)
def
lentest_uchar
():
return
len
(
us
)
@
cython
.
test_assert_path_exists
(
"//PythonCapiCallNode"
,
)
def
lentest_uchar_c
():
cdef
Py_ssize_t
l
=
len
(
us
)
return
l
@
cython
.
test_assert_path_exists
(
"//SimpleCallNode"
,
)
def
lentest_py
():
return
len
(
pystr
)
@
cython
.
test_assert_path_exists
(
"//SimpleCallNode"
,
)
def
lentest_py_c
():
cdef
Py_ssize_t
l
=
len
(
pystr
)
return
l
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