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
72f8a46e
Commit
72f8a46e
authored
Mar 31, 2011
by
Vitja Makarov
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote branch 'upstream/master'
parents
62567a26
0a56c99d
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1066 additions
and
290 deletions
+1066
-290
Cython/CodeWriter.py
Cython/CodeWriter.py
+267
-79
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+7
-4
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+215
-81
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+23
-24
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+0
-1
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+11
-7
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+2
-2
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+50
-40
Cython/Debugger/Tests/test_libcython_in_gdb.py
Cython/Debugger/Tests/test_libcython_in_gdb.py
+26
-0
Cython/Debugger/Tests/test_libpython_in_gdb.py
Cython/Debugger/Tests/test_libpython_in_gdb.py
+1
-3
Cython/Debugger/libcython.py
Cython/Debugger/libcython.py
+84
-17
Cython/Debugger/libpython.py
Cython/Debugger/libpython.py
+58
-31
tests/bugs.txt
tests/bugs.txt
+1
-0
tests/compile/a_capi.pyx
tests/compile/a_capi.pyx
+9
-0
tests/compile/publicapi_api.pyx
tests/compile/publicapi_api.pyx
+65
-0
tests/compile/publicapi_mix.pyx
tests/compile/publicapi_mix.pyx
+77
-0
tests/compile/publicapi_pub.pyx
tests/compile/publicapi_pub.pyx
+65
-0
tests/compile/publicapi_pxd_mix.pxd
tests/compile/publicapi_pxd_mix.pxd
+68
-0
tests/compile/publicapi_pxd_mix.pyx
tests/compile/publicapi_pxd_mix.pyx
+15
-0
tests/run/capiimpl.pyx
tests/run/capiimpl.pyx
+22
-1
No files found.
Cython/CodeWriter.py
View file @
72f8a46e
...
...
@@ -26,12 +26,12 @@ class LinesResult(object):
self
.
put
(
s
)
self
.
newline
()
class
Code
Writer
(
TreeVisitor
):
class
Declaration
Writer
(
TreeVisitor
):
indent_string
=
u" "
def
__init__
(
self
,
result
=
None
):
super
(
Code
Writer
,
self
).
__init__
()
super
(
Declaration
Writer
,
self
).
__init__
()
if
result
is
None
:
result
=
LinesResult
()
self
.
result
=
result
...
...
@@ -41,6 +41,7 @@ class CodeWriter(TreeVisitor):
def
write
(
self
,
tree
):
self
.
visit
(
tree
)
return
self
.
result
def
indent
(
self
):
self
.
numindents
+=
1
...
...
@@ -54,6 +55,9 @@ class CodeWriter(TreeVisitor):
def
put
(
self
,
s
):
self
.
result
.
put
(
s
)
def
putline
(
self
,
s
):
self
.
result
.
putline
(
self
.
indent_string
*
self
.
numindents
+
s
)
def
endline
(
self
,
s
=
u""
):
self
.
result
.
putline
(
s
)
...
...
@@ -79,23 +83,45 @@ class CodeWriter(TreeVisitor):
def
visit_StatListNode
(
self
,
node
):
self
.
visitchildren
(
node
)
def
visit_FuncDefNode
(
self
,
node
):
self
.
startline
(
u"def %s("
%
node
.
name
)
self
.
comma_separated_list
(
node
.
args
)
self
.
endline
(
u"):"
)
def
visit_CDefExternNode
(
self
,
node
):
if
node
.
include_file
is
None
:
file
=
u'*'
else
:
file
=
u'"%s"'
%
node
.
include_file
self
.
putline
(
u"cdef extern from %s:"
%
file
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
def
visit_CArgDeclNode
(
self
,
node
):
if
node
.
base_type
.
name
is
not
None
:
self
.
visit
(
node
.
base_type
)
self
.
put
(
u" "
)
self
.
visit
(
node
.
declarator
)
if
node
.
default
is
not
None
:
self
.
put
(
u" = "
)
self
.
visit
(
node
.
default
)
def
visit_CPtrDeclaratorNode
(
self
,
node
):
self
.
put
(
'*'
)
self
.
visit
(
node
.
base
)
def
visit_CReferenceDeclaratorNode
(
self
,
node
):
self
.
put
(
'&'
)
self
.
visit
(
node
.
base
)
def
visit_CArrayDeclaratorNode
(
self
,
node
):
self
.
visit
(
node
.
base
)
self
.
put
(
u'['
)
if
node
.
dimension
is
not
None
:
self
.
visit
(
node
.
dimension
)
self
.
put
(
u']'
)
def
visit_CArrayDeclaratorNode
(
self
,
node
):
self
.
visit
(
node
.
base
)
self
.
put
(
u'['
)
if
node
.
dimension
is
not
None
:
self
.
visit
(
node
.
dimension
)
self
.
put
(
u']'
)
def
visit_CFuncDeclaratorNode
(
self
,
node
):
# TODO: except, gil, etc.
self
.
visit
(
node
.
base
)
self
.
put
(
u'('
)
self
.
comma_separated_list
(
node
.
args
)
self
.
endline
(
u')'
)
def
visit_CNameDeclaratorNode
(
self
,
node
):
self
.
put
(
node
.
name
)
...
...
@@ -108,22 +134,149 @@ class CodeWriter(TreeVisitor):
self
.
put
(
"short "
*
-
node
.
longness
)
elif
node
.
longness
>
0
:
self
.
put
(
"long "
*
node
.
longness
)
self
.
put
(
node
.
name
)
def
visit_CComplexBaseTypeNode
(
self
,
node
):
self
.
put
(
u'('
)
self
.
visit
(
node
.
base_type
)
self
.
visit
(
node
.
declarator
)
self
.
put
(
u')'
)
def
visit_CNestedBaseTypeNode
(
self
,
node
):
self
.
visit
(
node
.
base_type
)
self
.
put
(
u'.'
)
self
.
put
(
node
.
name
)
def
visit_SingleAssignmentNode
(
self
,
node
):
self
.
startline
()
self
.
visit
(
node
.
lhs
)
self
.
put
(
u" = "
)
self
.
visit
(
node
.
rhs
)
def
visit_TemplatedTypeNode
(
self
,
node
):
self
.
visit
(
node
.
base_type_node
)
self
.
put
(
u'['
)
self
.
comma_separated_list
(
node
.
positional_args
+
node
.
keyword_args
.
key_value_pairs
)
self
.
put
(
u']'
)
def
visit_CVarDefNode
(
self
,
node
):
self
.
startline
(
u"cdef "
)
self
.
visit
(
node
.
base_type
)
self
.
put
(
u" "
)
self
.
comma_separated_list
(
node
.
declarators
,
output_rhs
=
True
)
self
.
endline
()
def
visit_CascadedAssignmentNode
(
self
,
node
):
self
.
startline
()
for
lhs
in
node
.
lhs_list
:
self
.
visit
(
lhs
)
def
visit_container_node
(
self
,
node
,
decl
,
extras
,
attributes
):
# TODO: visibility
self
.
startline
(
decl
)
if
node
.
name
:
self
.
put
(
u' '
)
self
.
put
(
node
.
name
)
if
node
.
cname
is
not
None
:
self
.
put
(
u' "%s"'
%
node
.
cname
)
if
extras
:
self
.
put
(
extras
)
self
.
endline
(
':'
)
self
.
indent
()
if
not
attributes
:
self
.
putline
(
'pass'
)
else
:
for
attribute
in
attributes
:
self
.
visit
(
attribute
)
self
.
dedent
()
def
visit_CStructOrUnionDefNode
(
self
,
node
):
if
node
.
typedef_flag
:
decl
=
u'ctypedef '
else
:
decl
=
u'cdef '
if
node
.
visibility
==
'public'
:
decl
+=
u'public '
if
node
.
packed
:
decl
+=
u'packed '
decl
+=
node
.
kind
self
.
visit_container_node
(
node
,
decl
,
None
,
node
.
attributes
)
def
visit_CppClassNode
(
self
,
node
):
extras
=
""
if
node
.
templates
:
extras
=
u"[%s]"
%
", "
.
join
(
node
.
templates
)
if
node
.
base_classes
:
extras
+=
"(%s)"
%
", "
.
join
(
node
.
base_classes
)
self
.
visit_container_node
(
node
,
u"cdef cppclass"
,
extras
,
node
.
attributes
)
def
visit_CEnumDefNode
(
self
,
node
):
self
.
visit_container_node
(
node
,
u"cdef enum"
,
None
,
node
.
items
)
def
visit_CEnumDefItemNode
(
self
,
node
):
self
.
startline
(
node
.
name
)
if
node
.
cname
:
self
.
put
(
u' "%s"'
%
node
.
cname
)
if
node
.
value
:
self
.
put
(
u" = "
)
self
.
visit
(
node
.
rhs
)
self
.
visit
(
node
.
value
)
self
.
endline
()
def
visit_CClassDefNode
(
self
,
node
):
assert
not
node
.
module_name
if
node
.
decorators
:
for
decorator
in
node
.
decorators
:
self
.
visit
(
decorator
)
self
.
startline
(
u"cdef class "
)
self
.
put
(
node
.
class_name
)
if
node
.
base_class_name
:
self
.
put
(
u"("
)
if
node
.
base_class_module
:
self
.
put
(
node
.
base_class_module
)
self
.
put
(
u"."
)
self
.
put
(
node
.
base_class_name
)
self
.
put
(
u")"
)
self
.
endline
(
u":"
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
def
visit_CTypeDefNode
(
self
,
node
):
self
.
startline
(
u"ctypedef "
)
self
.
visit
(
node
.
base_type
)
self
.
put
(
u" "
)
self
.
visit
(
node
.
declarator
)
self
.
endline
()
def
visit_FuncDefNode
(
self
,
node
):
self
.
startline
(
u"def %s("
%
node
.
name
)
self
.
comma_separated_list
(
node
.
args
)
self
.
endline
(
u"):"
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
def
visit_CArgDeclNode
(
self
,
node
):
if
node
.
base_type
.
name
is
not
None
:
self
.
visit
(
node
.
base_type
)
self
.
put
(
u" "
)
self
.
visit
(
node
.
declarator
)
if
node
.
default
is
not
None
:
self
.
put
(
u" = "
)
self
.
visit
(
node
.
default
)
def
visit_CImportStatNode
(
self
,
node
):
self
.
startline
(
u"cimport "
)
self
.
put
(
node
.
module_name
)
if
node
.
as_name
:
self
.
put
(
u" as "
)
self
.
put
(
node
.
as_name
)
self
.
endline
()
def
visit_FromCImportStatNode
(
self
,
node
):
self
.
startline
(
u"from "
)
self
.
put
(
node
.
module_name
)
self
.
put
(
u" cimport "
)
first
=
True
for
pos
,
name
,
as_name
,
kind
in
node
.
imported_names
:
assert
kind
is
None
if
first
:
first
=
False
else
:
self
.
put
(
u", "
)
self
.
put
(
name
)
if
as_name
:
self
.
put
(
u" as "
)
self
.
put
(
as_name
)
self
.
endline
()
def
visit_NameNode
(
self
,
node
):
...
...
@@ -132,6 +285,31 @@ class CodeWriter(TreeVisitor):
def
visit_IntNode
(
self
,
node
):
self
.
put
(
node
.
value
)
def
visit_NoneNode
(
self
,
node
):
self
.
put
(
u"None"
)
def
visit_NotNode
(
self
,
node
):
self
.
put
(
u"(not "
)
self
.
visit
(
node
.
operand
)
self
.
put
(
u")"
)
def
visit_DecoratorNode
(
self
,
node
):
self
.
startline
(
"@"
)
self
.
visit
(
node
.
decorator
)
self
.
endline
()
def
visit_BinopNode
(
self
,
node
):
self
.
visit
(
node
.
operand1
)
self
.
put
(
u" %s "
%
node
.
operator
)
self
.
visit
(
node
.
operand2
)
def
visit_AttributeNode
(
self
,
node
):
self
.
visit
(
node
.
obj
)
self
.
put
(
u".%s"
%
node
.
attribute
)
def
visit_BoolNode
(
self
,
node
):
self
.
put
(
str
(
node
.
value
))
# FIXME: represent string nodes correctly
def
visit_StringNode
(
self
,
node
):
value
=
node
.
value
...
...
@@ -139,32 +317,27 @@ class CodeWriter(TreeVisitor):
value
=
value
.
encode
(
value
.
encoding
)
self
.
put
(
repr
(
value
))
def
visit_IfStatNode
(
self
,
node
):
# The IfClauseNode is handled directly without a seperate match
# for clariy.
self
.
startline
(
u"if "
)
self
.
visit
(
node
.
if_clauses
[
0
].
condition
)
self
.
endline
(
":"
)
self
.
indent
()
self
.
visit
(
node
.
if_clauses
[
0
].
body
)
self
.
dedent
()
for
clause
in
node
.
if_clauses
[
1
:]:
self
.
startline
(
"elif "
)
self
.
visit
(
clause
.
condition
)
self
.
endline
(
":"
)
self
.
indent
()
self
.
visit
(
clause
.
body
)
self
.
dedent
()
if
node
.
else_clause
is
not
None
:
self
.
line
(
"else:"
)
self
.
indent
()
self
.
visit
(
node
.
else_clause
)
self
.
dedent
()
def
visit_PassStatNode
(
self
,
node
):
self
.
startline
(
u"pass"
)
self
.
endline
()
class
CodeWriter
(
DeclarationWriter
):
def
visit_SingleAssignmentNode
(
self
,
node
):
self
.
startline
()
self
.
visit
(
node
.
lhs
)
self
.
put
(
u" = "
)
self
.
visit
(
node
.
rhs
)
self
.
endline
()
def
visit_CascadedAssignmentNode
(
self
,
node
):
self
.
startline
()
for
lhs
in
node
.
lhs_list
:
self
.
visit
(
lhs
)
self
.
put
(
u" = "
)
self
.
visit
(
node
.
rhs
)
self
.
endline
()
def
visit_PrintStatNode
(
self
,
node
):
self
.
startline
(
u"print "
)
self
.
comma_separated_list
(
node
.
arg_tuple
.
args
)
...
...
@@ -172,18 +345,6 @@ class CodeWriter(TreeVisitor):
self
.
put
(
u","
)
self
.
endline
()
def
visit_BinopNode
(
self
,
node
):
self
.
visit
(
node
.
operand1
)
self
.
put
(
u" %s "
%
node
.
operator
)
self
.
visit
(
node
.
operand2
)
def
visit_CVarDefNode
(
self
,
node
):
self
.
startline
(
u"cdef "
)
self
.
visit
(
node
.
base_type
)
self
.
put
(
u" "
)
self
.
comma_separated_list
(
node
.
declarators
,
output_rhs
=
True
)
self
.
endline
()
def
visit_ForInStatNode
(
self
,
node
):
self
.
startline
(
u"for "
)
self
.
visit
(
node
.
target
)
...
...
@@ -199,6 +360,28 @@ class CodeWriter(TreeVisitor):
self
.
visit
(
node
.
else_clause
)
self
.
dedent
()
def
visit_IfStatNode
(
self
,
node
):
# The IfClauseNode is handled directly without a seperate match
# for clariy.
self
.
startline
(
u"if "
)
self
.
visit
(
node
.
if_clauses
[
0
].
condition
)
self
.
endline
(
":"
)
self
.
indent
()
self
.
visit
(
node
.
if_clauses
[
0
].
body
)
self
.
dedent
()
for
clause
in
node
.
if_clauses
[
1
:]:
self
.
startline
(
"elif "
)
self
.
visit
(
clause
.
condition
)
self
.
endline
(
":"
)
self
.
indent
()
self
.
visit
(
clause
.
body
)
self
.
dedent
()
if
node
.
else_clause
is
not
None
:
self
.
line
(
"else:"
)
self
.
indent
()
self
.
visit
(
node
.
else_clause
)
self
.
dedent
()
def
visit_SequenceNode
(
self
,
node
):
self
.
comma_separated_list
(
node
.
args
)
# Might need to discover whether we need () around tuples...hmm...
...
...
@@ -244,13 +427,6 @@ class CodeWriter(TreeVisitor):
self
.
visit
(
node
.
body
)
self
.
dedent
()
def
visit_AttributeNode
(
self
,
node
):
self
.
visit
(
node
.
obj
)
self
.
put
(
u".%s"
%
node
.
attribute
)
def
visit_BoolNode
(
self
,
node
):
self
.
put
(
str
(
node
.
value
))
def
visit_TryFinallyStatNode
(
self
,
node
):
self
.
line
(
u"try:"
)
self
.
indent
()
...
...
@@ -289,25 +465,12 @@ class CodeWriter(TreeVisitor):
self
.
visit
(
node
.
value
)
self
.
endline
()
def
visit_DecoratorNode
(
self
,
node
):
self
.
startline
(
"@"
)
self
.
visit
(
node
.
decorator
)
self
.
endline
()
def
visit_ReraiseStatNode
(
self
,
node
):
self
.
line
(
"raise"
)
def
visit_NoneNode
(
self
,
node
):
self
.
put
(
u"None"
)
def
visit_ImportNode
(
self
,
node
):
self
.
put
(
u"(import %s)"
%
node
.
module_name
.
value
)
def
visit_NotNode
(
self
,
node
):
self
.
put
(
u"(not "
)
self
.
visit
(
node
.
operand
)
self
.
put
(
u")"
)
def
visit_TempsBlockNode
(
self
,
node
):
"""
Temporaries are output like $1_1', where the first number is
...
...
@@ -323,3 +486,28 @@ class CodeWriter(TreeVisitor):
def
visit_TempRefNode
(
self
,
node
):
self
.
put
(
self
.
tempnames
[
node
.
handle
])
class
PxdWriter
(
DeclarationWriter
):
def
__call__
(
self
,
node
):
print
u'
\
n
'
.
join
(
self
.
write
(
node
).
lines
)
return
node
def
visit_CFuncDefNode
(
self
,
node
):
if
'inline'
in
node
.
modifiers
:
return
if
node
.
overridable
:
self
.
startline
(
u'cpdef '
)
else
:
self
.
startline
(
u'cdef '
)
if
node
.
visibility
!=
'private'
:
self
.
put
(
node
.
visibility
)
self
.
put
(
u' '
)
if
node
.
api
:
self
.
put
(
u'api '
)
self
.
visit
(
node
.
declarator
)
def
visit_StatNode
(
self
,
node
):
pass
\ No newline at end of file
Cython/Compiler/ExprNodes.py
View file @
72f8a46e
...
...
@@ -867,9 +867,8 @@ class IntNode(ConstNode):
return
self
elif
dst_type
.
is_float
:
if
self
.
constant_result
is
not
not_a_constant
:
float_value
=
float
(
self
.
constant_result
)
return
FloatNode
(
self
.
pos
,
value
=
repr
(
float_value
),
type
=
dst_type
,
constant_result
=
float_value
)
return
FloatNode
(
self
.
pos
,
value
=
'%d.0'
%
int
(
self
.
constant_result
),
type
=
dst_type
,
constant_result
=
float
(
self
.
constant_result
))
else
:
return
FloatNode
(
self
.
pos
,
value
=
self
.
value
,
type
=
dst_type
,
constant_result
=
not_a_constant
)
...
...
@@ -3061,7 +3060,11 @@ class SimpleCallNode(CallNode):
# nogil anyway)
pass
else
:
self
.
args
[
i
]
=
arg
.
coerce_to_temp
(
env
)
#self.args[i] = arg.coerce_to_temp(env)
# instead: issue a warning
if
i
>
0
or
i
==
1
and
self
.
self
is
not
None
:
# skip first arg
warning
(
arg
.
pos
,
"Argument evaluation order in C function call is undefined and may not be as expected"
,
0
)
break
# Calc result type and code fragment
if
isinstance
(
self
.
function
,
NewExprNode
):
self
.
type
=
PyrexTypes
.
CPtrType
(
self
.
function
.
class_type
)
...
...
Cython/Compiler/ModuleNode.py
View file @
72f8a46e
...
...
@@ -73,7 +73,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self
.
generate_c_code
(
env
,
options
,
result
)
self
.
generate_h_code
(
env
,
options
,
result
)
self
.
generate_api_code
(
env
,
result
)
def
has_imported_c_functions
(
self
):
for
module
in
self
.
referenced_modules
:
for
entry
in
module
.
cfunc_entries
:
...
...
@@ -96,14 +96,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
f
.
close
()
def
generate_h_code
(
self
,
env
,
options
,
result
):
def
h_entries
(
entries
,
pxd
=
0
):
def
h_entries
(
entries
,
api
=
0
,
pxd
=
0
):
return
[
entry
for
entry
in
entries
if
entry
.
visibility
==
'public'
or
pxd
and
entry
.
defined_in_pxd
]
h_types
=
h_entries
(
env
.
type_entries
)
if
((
entry
.
visibility
==
'public'
)
or
(
api
and
entry
.
api
)
or
(
pxd
and
entry
.
defined_in_pxd
))]
h_types
=
h_entries
(
env
.
type_entries
,
api
=
1
)
h_vars
=
h_entries
(
env
.
var_entries
)
h_funcs
=
h_entries
(
env
.
cfunc_entries
)
h_extension_types
=
h_entries
(
env
.
c_class_entries
)
if
h_types
or
h_vars
or
h_funcs
or
h_extension_types
:
if
(
h_types
or
h_vars
or
h_funcs
or
h_extension_types
)
:
result
.
h_file
=
replace_suffix
(
result
.
c_file
,
".h"
)
h_code
=
Code
.
CCodeWriter
()
Code
.
GlobalState
(
h_code
)
...
...
@@ -112,32 +114,40 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
i_code
=
Code
.
PyrexCodeWriter
(
result
.
i_file
)
else
:
i_code
=
None
guard
=
Naming
.
h_guard_prefix
+
env
.
qualified_name
.
replace
(
"."
,
"__"
)
h_code
.
put_h_guard
(
guard
)
self
.
generate_extern_c_macro_definition
(
h_code
)
h_guard
=
Naming
.
h_guard_prefix
+
self
.
api_name
(
env
)
h_code
.
put_h_guard
(
h_guard
)
h_code
.
putln
(
""
)
self
.
generate_type_header_code
(
h_types
,
h_code
)
h_code
.
putln
(
""
)
h_code
.
putln
(
"#ifndef %s"
%
Naming
.
api_guard_prefix
+
self
.
api_name
(
env
))
if
h_vars
:
h_code
.
putln
(
""
)
for
entry
in
h_vars
:
self
.
generate_public_declaration
(
entry
,
h_code
,
i_code
)
if
h_funcs
:
h_code
.
putln
(
""
)
for
entry
in
h_funcs
:
self
.
generate_public_declaration
(
entry
,
h_code
,
i_code
)
api_guard
=
Naming
.
api_guard_prefix
+
self
.
api_name
(
env
)
h_code
.
putln
(
"#ifndef %s"
%
api_guard
)
h_code
.
putln
(
""
)
self
.
generate_extern_c_macro_definition
(
h_code
)
if
h_extension_types
:
h_code
.
putln
(
""
)
for
entry
in
h_extension_types
:
self
.
generate_cclass_header_code
(
entry
.
type
,
h_code
)
if
i_code
:
self
.
generate_cclass_include_code
(
entry
.
type
,
i_code
)
if
h_funcs
:
h_code
.
putln
(
""
)
for
entry
in
h_funcs
:
self
.
generate_public_declaration
(
entry
,
h_code
,
i_code
)
if
h_vars
:
h_code
.
putln
(
""
)
for
entry
in
h_vars
:
self
.
generate_public_declaration
(
entry
,
h_code
,
i_code
)
h_code
.
putln
(
""
)
h_code
.
putln
(
"#endif
"
)
h_code
.
putln
(
"#endif
/* !%s */"
%
api_guard
)
h_code
.
putln
(
""
)
h_code
.
putln
(
"#if PY_MAJOR_VERSION < 3"
)
h_code
.
putln
(
"PyMODINIT_FUNC init%s(void);"
%
env
.
module_name
)
h_code
.
putln
(
""
)
h_code
.
putln
(
"#else"
)
h_code
.
putln
(
"PyMODINIT_FUNC PyInit_%s(void);"
%
env
.
module_name
)
h_code
.
putln
(
"#endif"
)
h_code
.
putln
(
""
)
h_code
.
putln
(
"#endif /* !%s */"
%
h_guard
)
f
=
open_new_file
(
result
.
h_file
)
try
:
...
...
@@ -156,65 +166,70 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def
api_name
(
self
,
env
):
return
env
.
qualified_name
.
replace
(
"."
,
"__"
)
def
generate_api_code
(
self
,
env
,
result
):
api_funcs
=
[]
public_extension_types
=
[]
has_api_extension_types
=
0
for
entry
in
env
.
cfunc_entries
:
if
entry
.
api
:
api_funcs
.
append
(
entry
)
for
entry
in
env
.
c_class_entries
:
if
entry
.
visibility
==
'public'
:
public_extension_types
.
append
(
entry
)
if
entry
.
api
:
has_api_extension_types
=
1
if
api_funcs
or
has_api_extension_types
:
def
api_entries
(
entries
,
pxd
=
1
):
return
[
entry
for
entry
in
entries
if
entry
.
api
or
(
pxd
and
entry
.
defined_in_pxd
)]
api_vars
=
api_entries
(
env
.
var_entries
)
api_funcs
=
api_entries
(
env
.
cfunc_entries
)
api_extension_types
=
api_entries
(
env
.
c_class_entries
)
if
api_vars
or
api_funcs
or
api_extension_types
:
result
.
api_file
=
replace_suffix
(
result
.
c_file
,
"_api.h"
)
h_code
=
Code
.
CCodeWriter
()
Code
.
GlobalState
(
h_code
)
name
=
self
.
api_name
(
env
)
guard
=
Naming
.
api_guard_prefix
+
name
h_code
.
put_h_guard
(
guard
)
api_guard
=
Naming
.
api_guard_prefix
+
self
.
api_name
(
env
)
h_code
.
put_h_guard
(
api_guard
)
h_code
.
putln
(
'#include "Python.h"'
)
if
result
.
h_file
:
h_code
.
putln
(
'#include "%s"'
%
os
.
path
.
basename
(
result
.
h_file
))
for
entry
in
public_extension_types
:
type
=
entry
.
type
if
api_extension_types
:
h_code
.
putln
(
""
)
h_code
.
putln
(
"static PyTypeObject *%s;"
%
type
.
typeptr_cname
)
h_code
.
putln
(
"#define %s (*%s)"
%
(
type
.
typeobj_cname
,
type
.
typeptr_cname
))
for
entry
in
api_extension_types
:
type
=
entry
.
type
h_code
.
putln
(
"static PyTypeObject *%s = 0;"
%
type
.
typeptr_cname
)
h_code
.
putln
(
"#define %s (*%s)"
%
(
type
.
typeobj_cname
,
type
.
typeptr_cname
))
if
api_funcs
:
h_code
.
putln
(
""
)
for
entry
in
api_funcs
:
type
=
CPtrType
(
entry
.
type
)
h_code
.
putln
(
"static %s;"
%
type
.
declaration_code
(
entry
.
cname
))
h_code
.
putln
(
""
)
h_code
.
put_h_guard
(
Naming
.
api_func_guard
+
"import_module"
)
cname
=
env
.
mangle
(
Naming
.
func_prefix
,
entry
.
name
)
h_code
.
putln
(
"static %s = 0;"
%
type
.
declaration_code
(
cname
))
h_code
.
putln
(
"#define %s %s"
%
(
entry
.
name
,
cname
))
if
api_vars
:
h_code
.
putln
(
""
)
for
entry
in
api_vars
:
type
=
CPtrType
(
entry
.
type
)
cname
=
env
.
mangle
(
Naming
.
var_prefix
,
entry
.
name
)
h_code
.
putln
(
"static %s = 0;"
%
type
.
declaration_code
(
cname
))
h_code
.
putln
(
"#define %s (*%s)"
%
(
entry
.
name
,
cname
))
h_code
.
put
(
import_module_utility_code
.
impl
)
h_code
.
putln
(
""
)
h_code
.
putln
(
"#endif"
)
if
api_vars
:
h_code
.
put
(
voidptr_import_utility_code
.
impl
)
if
api_funcs
:
h_code
.
putln
(
""
)
h_code
.
put
(
function_import_utility_code
.
impl
)
if
public_extension_types
:
h_code
.
putln
(
""
)
if
api_extension_types
:
h_code
.
put
(
type_import_utility_code
.
impl
)
h_code
.
putln
(
""
)
h_code
.
putln
(
"static int import_%s(void) {"
%
name
)
h_code
.
putln
(
"static int import_%s(void) {"
%
self
.
api_name
(
env
)
)
h_code
.
putln
(
"PyObject *module = 0;"
)
h_code
.
putln
(
'module = __Pyx_ImportModule("%s");'
%
env
.
qualified_name
)
h_code
.
putln
(
"if (!module) goto bad;"
)
for
entry
in
api_funcs
:
cname
=
env
.
mangle
(
Naming
.
func_prefix
,
entry
.
name
)
sig
=
entry
.
type
.
signature_string
()
h_code
.
putln
(
'if (__Pyx_ImportFunction(module, "%s", (void (**)(void))&%s, "%s") < 0) goto bad;'
%
(
entry
.
name
,
entry
.
cname
,
sig
))
'if (__Pyx_ImportFunction(module, "%s", (void (**)(void))&%s, "%s") < 0) goto bad;'
%
(
entry
.
name
,
cname
,
sig
))
for
entry
in
api_vars
:
cname
=
env
.
mangle
(
Naming
.
var_prefix
,
entry
.
name
)
sig
=
entry
.
type
.
declaration_code
(
""
)
h_code
.
putln
(
'if (__Pyx_ImportVoidPtr(module, "%s", (void **)&%s, "%s") < 0) goto bad;'
%
(
entry
.
name
,
cname
,
sig
))
h_code
.
putln
(
"Py_DECREF(module); module = 0;"
)
for
entry
in
public
_extension_types
:
for
entry
in
api
_extension_types
:
self
.
generate_type_import_call
(
entry
.
type
,
h_code
,
"if (!%s) goto bad;"
%
entry
.
type
.
typeptr_cname
)
...
...
@@ -224,7 +239,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
h_code
.
putln
(
"return -1;"
)
h_code
.
putln
(
"}"
)
h_code
.
putln
(
""
)
h_code
.
putln
(
"#endif
"
)
h_code
.
putln
(
"#endif
/* !%s */"
%
api_guard
)
f
=
open_new_file
(
result
.
api_file
)
try
:
...
...
@@ -233,8 +248,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
f
.
close
()
def
generate_cclass_header_code
(
self
,
type
,
h_code
):
h_code
.
putln
(
"%s DL_IMPORT(PyTypeObject) %s;"
%
(
Naming
.
extern_c_macro
,
h_code
.
putln
(
"%s %s %s;"
%
(
Naming
.
extern_c_macro
,
PyrexTypes
.
public_decl
(
"PyTypeObject"
,
"DL_IMPORT"
),
type
.
typeobj_cname
))
def
generate_cclass_include_code
(
self
,
type
,
i_code
):
...
...
@@ -424,8 +440,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self
.
generate_objstruct_definition
(
type
,
code
)
for
entry
in
vtabslot_list
:
self
.
generate_objstruct_definition
(
entry
.
type
,
code
)
self
.
generate_typeobj_predeclaration
(
entry
,
code
)
for
entry
in
vtab_list
:
self
.
generate_typeobj
ect
_predeclaration
(
entry
,
code
)
self
.
generate_typeobj_predeclaration
(
entry
,
code
)
self
.
generate_exttype_vtable_struct
(
entry
,
code
)
self
.
generate_exttype_vtabptr_declaration
(
entry
,
code
)
...
...
@@ -685,6 +702,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
"#define _USE_MATH_DEFINES"
)
code
.
putln
(
"#endif"
)
code
.
putln
(
"#include <math.h>"
)
code
.
putln
(
"#define %s"
%
Naming
.
h_guard_prefix
+
self
.
api_name
(
env
))
code
.
putln
(
"#define %s"
%
Naming
.
api_guard_prefix
+
self
.
api_name
(
env
))
self
.
generate_includes
(
env
,
cimported_modules
,
code
)
code
.
putln
(
""
)
...
...
@@ -721,10 +739,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def
generate_extern_c_macro_definition
(
self
,
code
):
name
=
Naming
.
extern_c_macro
code
.
putln
(
"#ifdef __cplusplus"
)
code
.
putln
(
'#define %s extern "C"'
%
name
)
code
.
putln
(
"#else"
)
code
.
putln
(
"#define %s extern"
%
name
)
code
.
putln
(
"#ifndef %s"
%
name
)
code
.
putln
(
" #ifdef __cplusplus"
)
code
.
putln
(
' #define %s extern "C"'
%
name
)
code
.
putln
(
" #else"
)
code
.
putln
(
" #define %s extern"
%
name
)
code
.
putln
(
" #endif"
)
code
.
putln
(
"#endif"
)
def
generate_includes
(
self
,
env
,
cimported_modules
,
code
):
...
...
@@ -786,10 +806,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def
generate_typedef
(
self
,
entry
,
code
):
base_type
=
entry
.
type
.
typedef_base_type
if
base_type
.
is_numeric
:
writer
=
code
.
globalstate
[
'numeric_typedefs'
]
try
:
writer
=
code
.
globalstate
[
'numeric_typedefs'
]
except
KeyError
:
writer
=
code
else
:
writer
=
code
writer
.
putln
(
""
)
writer
.
mark_pos
(
entry
.
pos
)
writer
.
putln
(
"typedef %s;"
%
base_type
.
declaration_code
(
entry
.
cname
))
def
sue_header_footer
(
self
,
type
,
kind
,
name
):
...
...
@@ -813,7 +836,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
globalstate
.
use_utility_code
(
packed_struct_utility_code
)
header
,
footer
=
\
self
.
sue_header_footer
(
type
,
kind
,
type
.
cname
)
code
.
putln
(
""
)
if
packed
:
code
.
putln
(
"#if defined(__SUNPRO_C)"
)
code
.
putln
(
" #pragma pack(1)"
)
...
...
@@ -844,7 +866,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
name
=
entry
.
cname
or
entry
.
name
or
""
header
,
footer
=
\
self
.
sue_header_footer
(
type
,
"enum"
,
name
)
code
.
putln
(
""
)
code
.
putln
(
header
)
enum_values
=
entry
.
enum_values
if
not
enum_values
:
...
...
@@ -870,21 +891,23 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
value_code
)
code
.
putln
(
footer
)
def
generate_typeobj
ect
_predeclaration
(
self
,
entry
,
code
):
def
generate_typeobj_predeclaration
(
self
,
entry
,
code
):
code
.
putln
(
""
)
name
=
entry
.
type
.
typeobj_cname
if
name
:
if
entry
.
visibility
==
'extern'
and
not
entry
.
in_cinclude
:
code
.
putln
(
"%s
DL_IMPORT(PyTypeObject)
%s;"
%
(
code
.
putln
(
"%s
%s
%s;"
%
(
Naming
.
extern_c_macro
,
PyrexTypes
.
public_decl
(
"PyTypeObject"
,
"DL_IMPORT"
),
name
))
elif
entry
.
visibility
==
'public'
:
code
.
putln
(
"%s
DL_EXPORT(PyTypeObject)
%s;"
%
(
code
.
putln
(
"%s
%s
%s;"
%
(
Naming
.
extern_c_macro
,
PyrexTypes
.
public_decl
(
"PyTypeObject"
,
"DL_EXPORT"
),
name
))
# ??? Do we really need the rest of this? ???
#else:
# code.putln("static
forward
PyTypeObject %s;" % name)
# code.putln("static PyTypeObject %s;" % name)
def
generate_exttype_vtable_struct
(
self
,
entry
,
code
):
code
.
mark_pos
(
entry
.
pos
)
...
...
@@ -924,7 +947,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
return
# Forward declared but never defined
header
,
footer
=
\
self
.
sue_header_footer
(
type
,
"struct"
,
type
.
objstruct_cname
)
code
.
putln
(
""
)
code
.
putln
(
header
)
base_type
=
type
.
base_type
if
base_type
:
...
...
@@ -967,24 +989,26 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for
entry
in
env
.
cfunc_entries
:
if
entry
.
inline_func_in_pxd
or
(
not
entry
.
in_cinclude
and
(
definition
or
entry
.
defined_in_pxd
or
entry
.
visibility
==
'extern'
)):
if
entry
.
visibility
in
(
'public'
,
'extern'
):
if
entry
.
visibility
==
'public'
:
storage_class
=
"%s "
%
Naming
.
extern_c_macro
dll_linkage
=
"DL_EXPORT"
elif
entry
.
visibility
==
'extern'
:
storage_class
=
"%s "
%
Naming
.
extern_c_macro
dll_linkage
=
"DL_IMPORT"
elif
entry
.
visibility
==
'private'
:
storage_class
=
"static "
dll_linkage
=
None
else
:
storage_class
=
"static "
dll_linkage
=
None
type
=
entry
.
type
if
not
definition
and
entry
.
defined_in_pxd
:
type
=
CPtrType
(
type
)
header
=
type
.
declaration_code
(
entry
.
cname
,
dll_linkage
=
dll_linkage
)
if
entry
.
visibility
==
'private'
:
storage_class
=
"static "
elif
entry
.
visibility
==
'public'
:
storage_class
=
""
else
:
storage_class
=
"%s "
%
Naming
.
extern_c_macro
dll_linkage
=
dll_linkage
)
if
entry
.
func_modifiers
:
modifiers
=
'%s '
%
' '
.
join
([
modifier
.
upper
()
for
modifier
in
entry
.
func_modifiers
])
modifiers
=
"%s "
%
' '
.
join
(
entry
.
func_modifiers
).
upper
()
else
:
modifiers
=
''
code
.
putln
(
"%s%s%s; /*proto*/"
%
(
...
...
@@ -1810,6 +1834,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
"/*--- Global init code ---*/"
)
self
.
generate_global_init_code
(
env
,
code
)
code
.
putln
(
"/*--- Variable export code ---*/"
)
self
.
generate_c_variable_export_code
(
env
,
code
)
code
.
putln
(
"/*--- Function export code ---*/"
)
self
.
generate_c_function_export_code
(
env
,
code
)
...
...
@@ -1997,6 +2024,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if
entry
.
type
.
is_pyobject
and
entry
.
used
:
code
.
put_init_var_to_py_none
(
entry
,
nanny
=
False
)
def
generate_c_variable_export_code
(
self
,
env
,
code
):
# Generate code to create PyCFunction wrappers for exported C functions.
for
entry
in
env
.
var_entries
:
if
entry
.
api
or
entry
.
defined_in_pxd
:
env
.
use_utility_code
(
voidptr_export_utility_code
)
signature
=
entry
.
type
.
declaration_code
(
""
)
code
.
putln
(
'if (__Pyx_ExportVoidPtr("%s", (void *)&%s, "%s") < 0) %s'
%
(
entry
.
name
,
entry
.
cname
,
signature
,
code
.
error_goto
(
self
.
pos
)))
def
generate_c_function_export_code
(
self
,
env
,
code
):
# Generate code to create PyCFunction wrappers for exported C functions.
for
entry
in
env
.
cfunc_entries
:
...
...
@@ -2340,6 +2379,45 @@ bad:
#------------------------------------------------------------------------------------
voidptr_export_utility_code
=
UtilityCode
(
proto
=
"""
static int __Pyx_ExportVoidPtr(const char *name, void *p, const char *sig); /*proto*/
"""
,
impl
=
r"""
static int __Pyx_ExportVoidPtr(const char *name, void *p, const char *sig) {
PyObject *d = 0;
PyObject *cobj = 0;
d = PyObject_GetAttrString(%(MODULE)s, (char *)"%(API)s");
if (!d) {
PyErr_Clear();
d = PyDict_New();
if (!d)
goto bad;
Py_INCREF(d);
if (PyModule_AddObject(%(MODULE)s, (char *)"%(API)s", d) < 0)
goto bad;
}
#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
cobj = PyCapsule_New(p, sig, 0);
#else
cobj = PyCObject_FromVoidPtrAndDesc(p, (void *)sig, 0);
#endif
if (!cobj)
goto bad;
if (PyDict_SetItemString(d, name, cobj) < 0)
goto bad;
Py_DECREF(cobj);
Py_DECREF(d);
return 0;
bad:
Py_XDECREF(cobj);
Py_XDECREF(d);
return -1;
}
"""
%
{
'MODULE'
:
Naming
.
module_cname
,
'API'
:
Naming
.
api_name
}
)
function_export_utility_code
=
UtilityCode
(
proto
=
"""
static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig); /*proto*/
...
...
@@ -2384,6 +2462,62 @@ bad:
"""
%
{
'MODULE'
:
Naming
.
module_cname
,
'API'
:
Naming
.
api_name
}
)
voidptr_import_utility_code
=
UtilityCode
(
proto
=
"""
static int __Pyx_ImportVoidPtr(PyObject *module, const char *name, void **p, const char *sig); /*proto*/
"""
,
impl
=
"""
#ifndef __PYX_HAVE_RT_ImportVoidPtr
#define __PYX_HAVE_RT_ImportVoidPtr
static int __Pyx_ImportVoidPtr(PyObject *module, const char *name, void **p, const char *sig) {
PyObject *d = 0;
PyObject *cobj = 0;
d = PyObject_GetAttrString(module, (char *)"%(API)s");
if (!d)
goto bad;
cobj = PyDict_GetItemString(d, name);
if (!cobj) {
PyErr_Format(PyExc_ImportError,
"%%s does not export expected C variable %%s",
PyModule_GetName(module), name);
goto bad;
}
#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
if (!PyCapsule_IsValid(cobj, sig)) {
PyErr_Format(PyExc_TypeError,
"C variable %%s.%%s has wrong signature (expected %%s, got %%s)",
PyModule_GetName(module), name, sig, PyCapsule_GetName(cobj));
goto bad;
}
*p = PyCapsule_GetPointer(cobj, sig);
#else
{const char *desc, *s1, *s2;
desc = (const char *)PyCObject_GetDesc(cobj);
if (!desc)
goto bad;
s1 = desc; s2 = sig;
while (*s1 != '
\
\
0' && *s1 == *s2) { s1++; s2++; }
if (*s1 != *s2) {
PyErr_Format(PyExc_TypeError,
"C variable %%s.%%s has wrong signature (expected %%s, got %%s)",
PyModule_GetName(module), name, sig, desc);
goto bad;
}
*p = PyCObject_AsVoidPtr(cobj);}
#endif
if (!(*p))
goto bad;
Py_DECREF(d);
return 0;
bad:
Py_XDECREF(d);
return -1;
}
#endif
"""
%
dict
(
API
=
Naming
.
api_name
)
)
function_import_utility_code
=
UtilityCode
(
proto
=
"""
static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig); /*proto*/
...
...
Cython/Compiler/Nodes.py
View file @
72f8a46e
...
...
@@ -970,7 +970,7 @@ class CVarDefNode(StatNode):
error
(
self
.
pos
,
"Only 'extern' C variable declaration allowed in .pxd file"
)
entry
=
dest_scope
.
declare_var
(
name
,
type
,
declarator
.
pos
,
cname
=
cname
,
visibility
=
visibility
,
is_cdef
=
1
)
cname
=
cname
,
visibility
=
visibility
,
api
=
self
.
api
,
is_cdef
=
1
)
entry
.
needs_property
=
need_property
...
...
@@ -980,6 +980,7 @@ class CStructOrUnionDefNode(StatNode):
# kind "struct" or "union"
# typedef_flag boolean
# visibility "public" or "private"
# api boolean
# in_pxd boolean
# attributes [CVarDefNode] or None
# entry Entry
...
...
@@ -995,7 +996,8 @@ class CStructOrUnionDefNode(StatNode):
scope
=
StructOrUnionScope
(
self
.
name
)
self
.
entry
=
env
.
declare_struct_or_union
(
self
.
name
,
self
.
kind
,
scope
,
self
.
typedef_flag
,
self
.
pos
,
self
.
cname
,
visibility
=
self
.
visibility
,
packed
=
self
.
packed
)
self
.
cname
,
visibility
=
self
.
visibility
,
api
=
self
.
api
,
packed
=
self
.
packed
)
if
self
.
attributes
is
not
None
:
if
self
.
in_pxd
and
not
env
.
in_cinclude
:
self
.
entry
.
defined_in_pxd
=
1
...
...
@@ -1078,15 +1080,16 @@ class CEnumDefNode(StatNode):
# items [CEnumDefItemNode]
# typedef_flag boolean
# visibility "public" or "private"
# api boolean
# in_pxd boolean
# entry Entry
child_attrs
=
[
"items"
]
def
analyse_declarations
(
self
,
env
):
self
.
entry
=
env
.
declare_enum
(
self
.
name
,
self
.
pos
,
cname
=
self
.
cname
,
typedef_flag
=
self
.
typedef_flag
,
visibility
=
self
.
visibility
)
visibility
=
self
.
visibility
,
api
=
self
.
api
)
if
self
.
items
is
not
None
:
if
self
.
in_pxd
and
not
env
.
in_cinclude
:
self
.
entry
.
defined_in_pxd
=
1
...
...
@@ -1097,7 +1100,7 @@ class CEnumDefNode(StatNode):
pass
def
generate_execution_code
(
self
,
code
):
if
self
.
visibility
==
'public'
:
if
self
.
visibility
==
'public'
or
self
.
api
:
temp
=
code
.
funcstate
.
allocate_temp
(
PyrexTypes
.
py_object_type
,
manage_ref
=
True
)
for
item
in
self
.
entry
.
enum_values
:
code
.
putln
(
"%s = PyInt_FromLong(%s); %s"
%
(
...
...
@@ -1127,9 +1130,9 @@ class CEnumDefItemNode(StatNode):
if
not
self
.
value
.
type
.
is_int
:
self
.
value
=
self
.
value
.
coerce_to
(
PyrexTypes
.
c_int_type
,
env
)
self
.
value
.
analyse_const_expression
(
env
)
entry
=
env
.
declare_const
(
self
.
name
,
enum_entry
.
type
,
entry
=
env
.
declare_const
(
self
.
name
,
enum_entry
.
type
,
self
.
value
,
self
.
pos
,
cname
=
self
.
cname
,
visibility
=
enum_entry
.
visibility
)
visibility
=
enum_entry
.
visibility
,
api
=
enum_entry
.
api
)
enum_entry
.
enum_values
.
append
(
entry
)
...
...
@@ -1137,6 +1140,7 @@ class CTypeDefNode(StatNode):
# base_type CBaseTypeNode
# declarator CDeclaratorNode
# visibility "public" or "private"
# api boolean
# in_pxd boolean
child_attrs
=
[
"base_type"
,
"declarator"
]
...
...
@@ -1147,10 +1151,10 @@ class CTypeDefNode(StatNode):
name
=
name_declarator
.
name
cname
=
name_declarator
.
cname
entry
=
env
.
declare_typedef
(
name
,
type
,
self
.
pos
,
cname
=
cname
,
visibility
=
self
.
visibility
)
cname
=
cname
,
visibility
=
self
.
visibility
,
api
=
self
.
api
)
if
self
.
in_pxd
and
not
env
.
in_cinclude
:
entry
.
defined_in_pxd
=
1
def
analyse_expressions
(
self
,
env
):
pass
def
generate_execution_code
(
self
,
code
):
...
...
@@ -1742,7 +1746,6 @@ class CFuncDefNode(FuncDefNode):
def
generate_function_header
(
self
,
code
,
with_pymethdef
,
with_opt_args
=
1
,
with_dispatch
=
1
,
cname
=
None
):
arg_decls
=
[]
type
=
self
.
type
visibility
=
self
.
entry
.
visibility
for
arg
in
type
.
args
[:
len
(
type
.
args
)
-
type
.
optional_arg_count
]:
arg_decls
.
append
(
arg
.
declaration_code
())
if
with_dispatch
and
self
.
overridable
:
...
...
@@ -1756,24 +1759,20 @@ class CFuncDefNode(FuncDefNode):
if
cname
is
None
:
cname
=
self
.
entry
.
func_cname
entity
=
type
.
function_header_code
(
cname
,
', '
.
join
(
arg_decls
))
if
visibility
==
'public
'
:
dll_linkage
=
"DL_EXPORT
"
if
self
.
entry
.
visibility
==
'private
'
:
storage_class
=
"static
"
else
:
dll_linkage
=
None
header
=
self
.
return_type
.
declaration_code
(
entity
,
dll_linkage
=
dll_linkage
)
if
visibility
==
'extern'
:
storage_class
=
"%s "
%
Naming
.
extern_c_macro
elif
visibility
==
'public'
:
storage_class
=
""
else
:
storage_class
=
"static
"
dll_linkage
=
None
modifiers
=
"
"
if
'inline'
in
self
.
modifiers
:
self
.
modifiers
[
self
.
modifiers
.
index
(
'inline'
)]
=
'cython_inline'
code
.
putln
(
"%s%s %s {"
%
(
storage_class
,
' '
.
join
(
self
.
modifiers
).
upper
(),
# macro forms
header
))
if
self
.
modifiers
:
modifiers
=
"%s "
%
' '
.
join
(
self
.
modifiers
).
upper
()
header
=
self
.
return_type
.
declaration_code
(
entity
,
dll_linkage
=
dll_linkage
)
#print (storage_class, modifiers, header)
code
.
putln
(
"%s%s%s {"
%
(
storage_class
,
modifiers
,
header
))
def
generate_argument_declarations
(
self
,
env
,
code
):
for
arg
in
self
.
args
:
...
...
Cython/Compiler/ParseTreeTransforms.py
View file @
72f8a46e
...
...
@@ -64,7 +64,6 @@ class SkipDeclarations(object):
def
visit_CStructOrUnionDefNode
(
self
,
node
):
return
node
class
NormalizeTree
(
CythonTransform
):
"""
This transform fixes up a few things after parsing
...
...
Cython/Compiler/Parsing.py
View file @
72f8a46e
...
...
@@ -2428,7 +2428,7 @@ def p_c_enum_definition(s, pos, ctx):
return
Nodes
.
CEnumDefNode
(
pos
,
name
=
name
,
cname
=
cname
,
items
=
items
,
typedef_flag
=
ctx
.
typedef_flag
,
visibility
=
ctx
.
visibility
,
in_pxd
=
ctx
.
level
==
'module_pxd'
)
api
=
ctx
.
api
,
in_pxd
=
ctx
.
level
==
'module_pxd'
)
def
p_c_enum_line
(
s
,
ctx
,
items
):
if
s
.
sy
!=
'pass'
:
...
...
@@ -2486,10 +2486,10 @@ def p_c_struct_or_union_definition(s, pos, ctx):
s
.
expect_dedent
()
else
:
s
.
expect_newline
(
"Syntax error in struct or union definition"
)
return
Nodes
.
CStructOrUnionDefNode
(
pos
,
return
Nodes
.
CStructOrUnionDefNode
(
pos
,
name
=
name
,
cname
=
cname
,
kind
=
kind
,
attributes
=
attributes
,
typedef_flag
=
ctx
.
typedef_flag
,
visibility
=
ctx
.
visibility
,
in_pxd
=
ctx
.
level
==
'module_pxd'
,
packed
=
packed
)
api
=
ctx
.
api
,
in_pxd
=
ctx
.
level
==
'module_pxd'
,
packed
=
packed
)
def
p_visibility
(
s
,
prev_visibility
):
pos
=
s
.
position
()
...
...
@@ -2574,7 +2574,8 @@ def p_ctypedef_statement(s, ctx):
s
.
expect_newline
(
"Syntax error in ctypedef statement"
)
return
Nodes
.
CTypeDefNode
(
pos
,
base_type
=
base_type
,
declarator
=
declarator
,
visibility
=
visibility
,
declarator
=
declarator
,
visibility
=
visibility
,
api
=
api
,
in_pxd
=
ctx
.
level
==
'module_pxd'
)
def
p_decorators
(
s
):
...
...
@@ -2701,8 +2702,8 @@ def p_c_class_definition(s, pos, ctx):
base_class_module
=
"."
.
join
(
base_class_path
[:
-
1
])
base_class_name
=
base_class_path
[
-
1
]
if
s
.
sy
==
'['
:
if
ctx
.
visibility
not
in
(
'public'
,
'extern'
):
error
(
s
.
position
(),
"Name options only allowed for 'public' or 'extern' C class"
)
if
ctx
.
visibility
not
in
(
'public'
,
'extern'
)
and
not
ctx
.
api
:
error
(
s
.
position
(),
"Name options only allowed for 'public'
, 'api',
or 'extern' C class"
)
objstruct_name
,
typeobj_name
=
p_c_class_options
(
s
)
if
s
.
sy
==
':'
:
if
ctx
.
level
==
'module_pxd'
:
...
...
@@ -2726,7 +2727,10 @@ def p_c_class_definition(s, pos, ctx):
error
(
pos
,
"Type object name specification required for 'public' C class"
)
elif
ctx
.
visibility
==
'private'
:
if
ctx
.
api
:
error
(
pos
,
"Only 'public' C class can be declared 'api'"
)
if
not
objstruct_name
:
error
(
pos
,
"Object struct name specification required for 'api' C class"
)
if
not
typeobj_name
:
error
(
pos
,
"Type object name specification required for 'api' C class"
)
else
:
error
(
pos
,
"Invalid class visibility '%s'"
%
ctx
.
visibility
)
return
Nodes
.
CClassDefNode
(
pos
,
...
...
Cython/Compiler/PyrexTypes.py
View file @
72f8a46e
...
...
@@ -1190,8 +1190,8 @@ class CComplexType(CNumericType):
visibility
=
"extern"
)
scope
.
parent_type
=
self
scope
.
directives
=
{}
scope
.
declare_var
(
"real"
,
self
.
real_type
,
None
,
"real"
,
is_cdef
=
True
)
scope
.
declare_var
(
"imag"
,
self
.
real_type
,
None
,
"imag"
,
is_cdef
=
True
)
scope
.
declare_var
(
"real"
,
self
.
real_type
,
None
,
cname
=
"real"
,
is_cdef
=
True
)
scope
.
declare_var
(
"imag"
,
self
.
real_type
,
None
,
cname
=
"imag"
,
is_cdef
=
True
)
entry
=
scope
.
declare_cfunction
(
"conjugate"
,
CFuncType
(
self
,
[
CFuncTypeArg
(
"self"
,
self
,
None
)],
nogil
=
True
),
...
...
Cython/Compiler/Symtab.py
View file @
72f8a46e
...
...
@@ -361,10 +361,10 @@ class Scope(object):
def qualify_name(self, name):
return EncodedString("
%
s
.
%
s
" % (self.qualified_name, name))
def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'):
def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'
, api = 0
):
# Add an entry for a named constant.
if not cname:
if self.in_cinclude or
visibility == 'public'
:
if self.in_cinclude or
(visibility == 'public' or api)
:
cname = name
else:
cname = self.mangle(Naming.enum_prefix, name)
...
...
@@ -374,21 +374,22 @@ class Scope(object):
return entry
def declare_type(self, name, type, pos,
cname = None, visibility = 'private', defining = 1, shadow = 0):
cname = None, visibility = 'private',
api = 0,
defining = 1, shadow = 0):
# Add an entry for a type definition.
if not cname:
cname = name
entry = self.declare(name, cname, type, pos, visibility, shadow)
entry.is_type = 1
entry.api = api
if defining:
self.type_entries.append(entry)
# here we would set as_variable to an object representing this type
return entry
def declare_typedef(self, name, base_type, pos, cname = None,
visibility = 'private'
):
visibility = 'private', api = 0
):
if not cname:
if self.in_cinclude or
visibility == 'public'
:
if self.in_cinclude or
(visibility == 'public' or api)
:
cname = name
else:
cname = self.mangle(Naming.type_prefix, name)
...
...
@@ -398,16 +399,18 @@ class Scope(object):
except ValueError, e:
error(pos, e.args[0])
type = PyrexTypes.error_type
entry = self.declare_type(name, type, pos, cname, visibility)
entry = self.declare_type(name, type, pos, cname,
visibility = visibility, api = api)
type.qualified_name = entry.qualified_name
return entry
def declare_struct_or_union(self, name, kind, scope,
typedef_flag, pos, cname = None, visibility = 'private',
packed = False):
def declare_struct_or_union(self, name, kind, scope,
typedef_flag, pos, cname = None,
visibility = 'private', api = 0,
packed = False):
# Add an entry for a struct or union definition.
if not cname:
if self.in_cinclude or
visibility == 'public'
:
if self.in_cinclude or
(visibility == 'public' or api)
:
cname = name
else:
cname = self.mangle(Naming.type_prefix, name)
...
...
@@ -416,7 +419,8 @@ class Scope(object):
type = PyrexTypes.CStructOrUnionType(
name, kind, scope, typedef_flag, cname, packed)
entry = self.declare_type(name, type, pos, cname,
visibility = visibility, defining = scope is not None)
visibility = visibility, api = api,
defining = scope is not None)
self.sue_entries.append(entry)
type.entry = entry
else:
...
...
@@ -482,12 +486,12 @@ class Scope(object):
if entry.visibility != visibility:
error(pos, "'%s'
previously
declared
as
'%s'" % (
entry.name, entry.visibility))
def declare_enum(self, name, pos, cname, typedef_flag,
visibility = 'private'):
visibility = 'private'
, api = 0
):
if name:
if not cname:
if self.in_cinclude or
visibility == 'public'
:
if self.in_cinclude or
(visibility == 'public' or api)
:
cname = name
else:
cname = self.mangle(Naming.type_prefix, name)
...
...
@@ -495,13 +499,13 @@ class Scope(object):
else:
type = PyrexTypes.c_anon_enum_type
entry = self.declare_type(name, type, pos, cname = cname,
visibility = visibility)
visibility = visibility
, api = api
)
entry.enum_values = []
self.sue_entries.append(entry)
return entry
return entry
def declare_var(self, name, type, pos,
cname = None, visibility = 'private'
, is_cdef = 0):
cname = None, visibility = 'private', api = 0
, is_cdef = 0):
# Add an entry for a variable.
if not cname:
if visibility != 'private':
...
...
@@ -514,6 +518,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
entry.api = api
self.control_flow.set_state((), (name, 'initialized'), False)
return entry
...
...
@@ -995,13 +1000,13 @@ class ModuleScope(Scope):
return entry
def declare_var(self, name, type, pos,
cname = None, visibility = 'private'
, is_cdef = 0):
cname = None, visibility = 'private', api = 0
, is_cdef = 0):
# Add an entry for a global variable. If it is a Python
# object type, and not declared with cdef, it will live
# in the module dictionary, otherwise it will be a C
# global variable.
entry = Scope.declare_var(self, name, type, pos,
cname, visibility,
is_cdef)
cname=cname, visibility=visibility, api=api, is_cdef=
is_cdef)
if not visibility in ('private', 'public', 'extern'):
error(pos, "
Module
-
level
variable
cannot
be
declared
%
s
" % visibility)
if not is_cdef:
...
...
@@ -1033,10 +1038,10 @@ class ModuleScope(Scope):
buffer_defaults = None, shadow = 0):
# If this is a non-extern typedef class, expose the typedef, but use
# the non-typedef struct internally to avoid needing forward
# declarations for anonymous structs.
# declarations for anonymous structs.
if typedef_flag and visibility != 'extern':
if
visibility != 'public'
:
warning(pos, "
ctypedef
only
valid
for
public
and
extern
classes
", 2)
if
not (visibility == 'public' or api)
:
warning(pos, "
ctypedef
only
valid
for
'extern'
,
'public'
,
and
'api'
", 2)
objtypedef_cname = objstruct_cname
typedef_flag = 0
else:
...
...
@@ -1283,12 +1288,12 @@ class LocalScope(Scope):
return
entry
def
declare_var
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'private'
,
is_cdef
=
0
):
cname
=
None
,
visibility
=
'private'
,
api
=
0
,
is_cdef
=
0
):
# Add an entry for a local variable.
if
visibility
in
(
'public'
,
'readonly'
):
error
(
pos
,
"Local variable cannot be declared %s"
%
visibility
)
entry
=
Scope
.
declare_var
(
self
,
name
,
type
,
pos
,
cname
,
visibility
,
is_cdef
)
cname
=
cname
,
visibility
=
visibility
,
api
=
api
,
is_cdef
=
is_cdef
)
if
type
.
is_pyobject
and
not
Options
.
init_local_none
:
entry
.
init
=
"0"
entry
.
init_to_none
=
(
type
.
is_pyobject
or
type
.
is_unspecified
)
and
Options
.
init_local_none
...
...
@@ -1365,7 +1370,7 @@ class GeneratorExpressionScope(Scope):
return
'%s%s'
%
(
self
.
genexp_prefix
,
self
.
parent_scope
.
mangle
(
prefix
,
name
))
def
declare_var
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'private'
,
is_cdef
=
True
):
cname
=
None
,
visibility
=
'private'
,
api
=
0
,
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
)
...
...
@@ -1408,7 +1413,7 @@ class StructOrUnionScope(Scope):
Scope
.
__init__
(
self
,
name
,
None
,
None
)
def
declare_var
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'private'
,
is_cdef
=
0
,
allow_pyobject
=
0
):
cname
=
None
,
visibility
=
'private'
,
api
=
0
,
is_cdef
=
0
,
allow_pyobject
=
0
):
# Add an entry for an attribute.
if
not
cname
:
cname
=
name
...
...
@@ -1430,7 +1435,8 @@ class StructOrUnionScope(Scope):
def
declare_cfunction
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'private'
,
defining
=
0
,
api
=
0
,
in_pxd
=
0
,
modifiers
=
()):
# currently no utility code ...
return
self
.
declare_var
(
name
,
type
,
pos
,
cname
,
visibility
)
return
self
.
declare_var
(
name
,
type
,
pos
,
cname
=
cname
,
visibility
=
visibility
)
class
ClassScope
(
Scope
):
# Abstract base class for namespace of
...
...
@@ -1474,12 +1480,12 @@ class PyClassScope(ClassScope):
is_py_class_scope
=
1
def
declare_var
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'private'
,
is_cdef
=
0
):
cname
=
None
,
visibility
=
'private'
,
api
=
0
,
is_cdef
=
0
):
if
type
is
unspecified_type
:
type
=
py_object_type
# Add an entry for a class attribute.
entry
=
Scope
.
declare_var
(
self
,
name
,
type
,
pos
,
cname
,
visibility
,
is_cdef
)
cname
=
cname
,
visibility
=
visibility
,
api
=
api
,
is_cdef
=
is_cdef
)
entry
.
is_pyglobal
=
1
entry
.
is_pyclass_attr
=
1
return
entry
...
...
@@ -1536,7 +1542,7 @@ class CClassScope(ClassScope):
self
.
parent_type
.
base_type
.
scope
.
needs_gc
())
def
declare_var
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'private'
,
is_cdef
=
0
):
cname
=
None
,
visibility
=
'private'
,
api
=
0
,
is_cdef
=
0
):
if
is_cdef
:
# Add an entry for an attribute.
if
self
.
defined
:
...
...
@@ -1576,7 +1582,7 @@ class CClassScope(ClassScope):
type
=
py_object_type
# Add an entry for a class attribute.
entry
=
Scope
.
declare_var
(
self
,
name
,
type
,
pos
,
cname
,
visibility
,
is_cdef
)
cname
=
cname
,
visibility
=
visibility
,
api
=
api
,
is_cdef
=
is_cdef
)
entry
.
is_member
=
1
entry
.
is_pyglobal
=
1
# xxx: is_pyglobal changes behaviour in so many places that
# I keep it in for now. is_member should be enough
...
...
@@ -1592,7 +1598,8 @@ class CClassScope(ClassScope):
if
name
==
"__new__"
:
error
(
pos
,
"__new__ method of extension type will change semantics "
"in a future version of Pyrex and Cython. Use __cinit__ instead."
)
entry
=
self
.
declare_var
(
name
,
py_object_type
,
pos
,
visibility
=
'extern'
)
entry
=
self
.
declare_var
(
name
,
py_object_type
,
pos
,
visibility
=
'extern'
)
special_sig
=
get_special_method_signature
(
name
)
if
special_sig
:
# Special methods get put in the method table with a particular
...
...
@@ -1717,7 +1724,8 @@ class CppClassScope(Scope):
self
.
inherited_var_entries
=
[]
def
declare_var
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'extern'
,
is_cdef
=
0
,
allow_pyobject
=
0
):
cname
=
None
,
visibility
=
'extern'
,
api
=
0
,
is_cdef
=
0
,
allow_pyobject
=
0
):
# Add an entry for an attribute.
if
not
cname
:
cname
=
name
...
...
@@ -1758,15 +1766,16 @@ class CppClassScope(Scope):
error
(
pos
,
"no matching function for call to %s::%s()"
%
(
self
.
default_constructor
,
self
.
default_constructor
))
def
declare_cfunction
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'extern'
,
defining
=
0
,
api
=
0
,
in_pxd
=
0
,
modifiers
=
(),
utility_code
=
None
):
def
declare_cfunction
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'extern'
,
api
=
0
,
defining
=
0
,
in_pxd
=
0
,
modifiers
=
(),
utility_code
=
None
):
if
name
==
self
.
name
.
split
(
'::'
)[
-
1
]
and
cname
is
None
:
self
.
check_base_default_constructor
(
pos
)
name
=
'<init>'
type
.
return_type
=
self
.
lookup
(
self
.
name
).
type
prev_entry
=
self
.
lookup_here
(
name
)
entry
=
self
.
declare_var
(
name
,
type
,
pos
,
cname
,
visibility
)
entry
=
self
.
declare_var
(
name
,
type
,
pos
,
cname
=
cname
,
visibility
=
visibility
)
if
prev_entry
:
entry
.
overloaded_alternatives
=
prev_entry
.
all_alternatives
()
entry
.
utility_code
=
utility_code
...
...
@@ -1790,8 +1799,9 @@ class CppClassScope(Scope):
self
.
inherited_var_entries
.
append
(
entry
)
for
base_entry
in
base_scope
.
cfunc_entries
:
entry
=
self
.
declare_cfunction
(
base_entry
.
name
,
base_entry
.
type
,
base_entry
.
pos
,
base_entry
.
cname
,
base_entry
.
visibility
,
base_entry
.
func_modifiers
,
base_entry
.
pos
,
base_entry
.
cname
,
base_entry
.
visibility
,
0
,
modifiers
=
base_entry
.
func_modifiers
,
utility_code
=
base_entry
.
utility_code
)
entry
.
is_inherited
=
1
...
...
Cython/Debugger/Tests/test_libcython_in_gdb.py
View file @
72f8a46e
...
...
@@ -378,6 +378,32 @@ class TestExec(DebugTestCase):
gdb
.
execute
(
'cy exec some_random_var = 14'
)
self
.
assertEqual
(
'14'
,
self
.
eval_command
(
'some_random_var'
))
class
CySet
(
DebugTestCase
):
def
test_cyset
(
self
):
self
.
break_and_run
(
'os.path.join("foo", "bar")'
)
gdb
.
execute
(
'cy set a = $cy_eval("{None: []}")'
)
stringvalue
=
self
.
read_var
(
"a"
,
cast_to
=
str
)
self
.
assertEqual
(
stringvalue
,
"{None: []}"
)
class
TestCyEval
(
DebugTestCase
):
"Test the $cy_eval() gdb function."
def
test_cy_eval
(
self
):
# This function leaks a few objects in the GDB python process. This
# is no biggie
self
.
break_and_run
(
'os.path.join("foo", "bar")'
)
result
=
gdb
.
execute
(
'print $cy_eval("None")'
,
to_string
=
True
)
assert
re
.
match
(
r'\
$
\d+ = None\n'
,
result
),
result
result
=
gdb
.
execute
(
'print $cy_eval("[a]")'
,
to_string
=
True
)
assert
re
.
match
(
r'\
$
\d+ = \
[
0\
]
', result), result
class TestClosure(DebugTestCase):
def break_and_run_func(self, funcname):
...
...
Cython/Debugger/Tests/test_libpython_in_gdb.py
View file @
72f8a46e
...
...
@@ -112,6 +112,4 @@ class TestPrettyPrinters(test_libcython_in_gdb.DebugTestCase):
def
test_frame_type
(
self
):
frame
=
self
.
pyobject_fromcode
(
'PyEval_GetFrame()'
)
self
.
assertEqual
(
type
(
frame
),
libpython
.
PyFrameObjectPtr
)
self
.
assertEqual
(
type
(
frame
),
libpython
.
PyFrameObjectPtr
)
\ No newline at end of file
Cython/Debugger/libcython.py
View file @
72f8a46e
...
...
@@ -592,6 +592,7 @@ class CyCy(CythonCommand):
cy bt / cy backtrace
cy list
cy print
cy set
cy locals
cy globals
cy exec
...
...
@@ -607,6 +608,7 @@ class CyCy(CythonCommand):
completer_class
,
prefix
=
True
)
commands
=
dict
(
# GDB commands
import_
=
CyImport
.
register
(),
break_
=
CyBreak
.
register
(),
step
=
CyStep
.
register
(),
...
...
@@ -624,9 +626,13 @@ class CyCy(CythonCommand):
globals
=
CyGlobals
.
register
(),
exec_
=
libpython
.
FixGdbCommand
(
'cy exec'
,
'-cy-exec'
),
_exec
=
CyExec
.
register
(),
set
=
CySet
.
register
(),
# GDB functions
cy_cname
=
CyCName
(
'cy_cname'
),
cy_cvalue
=
CyCValue
(
'cy_cvalue'
),
cy_lineno
=
CyLine
(
'cy_lineno'
),
cy_eval
=
CyEval
(
'cy_eval'
),
)
for
command_name
,
command
in
commands
.
iteritems
():
...
...
@@ -1169,15 +1175,14 @@ class CyGlobals(CyLocals):
max_name_length
,
' '
)
class
CyExec
(
CythonCommand
,
libpython
.
PyExec
):
class
EvaluateOrExecuteCodeMixin
(
object
):
"""
Execute Python code in the nearest Python or Cython frame.
Evaluate or execute Python code in a Cython or Python frame. The 'evalcode'
method evaluations Python code, prints a traceback if an exception went
uncaught, and returns any return value as a gdb.Value (NULL on exception).
"""
name
=
'-cy-exec'
command_class
=
gdb
.
COMMAND_STACK
completer_class
=
gdb
.
COMPLETE_NONE
def
_fill_locals_dict
(
self
,
executor
,
local_dict_pointer
):
"Fill a remotely allocated dict with values from the Cython C stack"
cython_func
=
self
.
get_cython_function
()
...
...
@@ -1208,28 +1213,22 @@ class CyExec(CythonCommand, libpython.PyExec):
raise
gdb
.
GdbError
(
"Unable to execute Python code."
)
finally
:
# PyDict_SetItem doesn't steal our reference
executor
.
decref
(
pystringp
)
executor
.
x
decref
(
pystringp
)
def
_find_first_cython_or_python_frame
(
self
):
frame
=
gdb
.
selected_frame
()
while
frame
:
if
(
self
.
is_cython_function
(
frame
)
or
self
.
is_python_function
(
frame
)):
frame
.
select
()
return
frame
frame
=
frame
.
older
()
raise
gdb
.
GdbError
(
"There is no Cython or Python frame on the stack."
)
def
invoke
(
self
,
expr
,
from_tty
):
frame
=
self
.
_find_first_cython_or_python_frame
()
if
self
.
is_python_function
(
frame
):
libpython
.
py_exec
.
invoke
(
expr
,
from_tty
)
return
expr
,
input_type
=
self
.
readcode
(
expr
)
executor
=
libpython
.
PythonCodeExecutor
()
def
_evalcode_cython
(
self
,
executor
,
code
,
input_type
):
with
libpython
.
FetchAndRestoreError
():
# get the dict of Cython globals and construct a dict in the
# inferior with Cython locals
...
...
@@ -1240,9 +1239,65 @@ class CyExec(CythonCommand, libpython.PyExec):
try
:
self
.
_fill_locals_dict
(
executor
,
libpython
.
pointervalue
(
local_dict
))
executor
.
evalcode
(
expr
,
input_type
,
global_dict
,
local_dict
)
result
=
executor
.
evalcode
(
code
,
input_type
,
global_dict
,
local_dict
)
finally
:
executor
.
decref
(
libpython
.
pointervalue
(
local_dict
))
executor
.
xdecref
(
libpython
.
pointervalue
(
local_dict
))
return
result
def
evalcode
(
self
,
code
,
input_type
):
"""
Evaluate `code` in a Python or Cython stack frame using the given
`input_type`.
"""
frame
=
self
.
_find_first_cython_or_python_frame
()
executor
=
libpython
.
PythonCodeExecutor
()
if
self
.
is_python_function
(
frame
):
return
libpython
.
_evalcode_python
(
executor
,
code
,
input_type
)
return
self
.
_evalcode_cython
(
executor
,
code
,
input_type
)
class
CyExec
(
CythonCommand
,
libpython
.
PyExec
,
EvaluateOrExecuteCodeMixin
):
"""
Execute Python code in the nearest Python or Cython frame.
"""
name
=
'-cy-exec'
command_class
=
gdb
.
COMMAND_STACK
completer_class
=
gdb
.
COMPLETE_NONE
def
invoke
(
self
,
expr
,
from_tty
):
expr
,
input_type
=
self
.
readcode
(
expr
)
executor
=
libpython
.
PythonCodeExecutor
()
executor
.
xdecref
(
self
.
evalcode
(
expr
,
executor
.
Py_single_input
))
class
CySet
(
CythonCommand
):
"""
Set a Cython variable to a certain value
cy set my_cython_c_variable = 10
cy set my_cython_py_variable = $cy_eval("{'doner': 'kebab'}")
This is equivalent to
set $cy_value("my_cython_variable") = 10
"""
name
=
'cy set'
command_class
=
gdb
.
COMMAND_DATA
completer_class
=
gdb
.
COMPLETE_NONE
@
require_cython_frame
def
invoke
(
self
,
expr
,
from_tty
):
name_and_expr
=
expr
.
split
(
'='
,
1
)
if
len
(
name_and_expr
)
!=
2
:
raise
gdb
.
GdbError
(
"Invalid expression. Use 'cy set var = expr'."
)
varname
,
expr
=
name_and_expr
cname
=
self
.
cy
.
cy_cname
.
invoke
(
varname
.
strip
())
gdb
.
execute
(
"set %s = %s"
%
(
cname
,
expr
))
# Functions
...
...
@@ -1312,6 +1367,18 @@ class CyLine(gdb.Function, CythonBase):
def
invoke
(
self
):
return
self
.
get_cython_lineno
()
class
CyEval
(
gdb
.
Function
,
CythonBase
,
EvaluateOrExecuteCodeMixin
):
"""
Evaluate Python code in the nearest Python or Cython frame and return
"""
@
gdb_function_value_to_unicode
def
invoke
(
self
,
python_expression
):
input_type
=
libpython
.
PythonCodeExecutor
.
Py_eval_input
return
self
.
evalcode
(
python_expression
,
input_type
)
cython_info
=
CythonInfo
()
cy
=
CyCy
.
register
()
cython_info
.
cy
=
cy
...
...
Cython/Debugger/libpython.py
View file @
72f8a46e
...
...
@@ -1949,26 +1949,40 @@ class ExecutionControlCommandBase(gdb.Command):
gdb.execute("
delete
%
s
" % bp)
def filter_output(self, result):
output = []
match_finish = re.search(r'^Value returned is
\
$
\
d+ = (.*)', result,
re.MULTILINE)
if match_finish:
output.append('Value returned: %s' % match_finish.group(1))
reflags = re.MULTILINE
regexes = [
output_on_halt = [
(r'^Program received signal .*', reflags|re.DOTALL),
(r'.*[Ww]arning.*', 0),
(r'^Program exited .*', reflags),
]
for regex, flags in regexes:
match = re.search(regex, result, flags)
if match:
output.append(match.group(0))
output_always = [
# output when halting on a watchpoint
(r'^(Old|New) value = .*', reflags),
# output from the 'display' command
(r'^
\
d+:
\
w+ = .*', reflags),
]
def filter_output(regexes):
output = []
for regex, flags in regexes:
for match in re.finditer(regex, result, flags):
output.append(match.group(0))
return '
\
n
'.join(output)
# Filter the return value output of the 'finish' command
match_finish = re.search(r'^Value returned is
\
$
\
d+ = (.*)', result,
re.MULTILINE)
if match_finish:
finish_output = 'Value returned: %s
\
n
' % match_finish.group(1)
else:
finish_output = ''
return (filter_output(output_on_halt),
finish_output + filter_output(output_always))
return '
\
n
'.join(output)
def stopped(self):
return get_selected_inferior().pid == 0
...
...
@@ -1979,17 +1993,23 @@ class ExecutionControlCommandBase(gdb.Command):
of source code or the result of the last executed gdb command (passed
in as the `result` argument).
"""
result
= self.filter_output(result)
output_on_halt, output_always
= self.filter_output(result)
if self.stopped():
print result.strip()
print output_always
print output_on_halt
else:
frame = gdb.selected_frame()
source_line = self.lang_info.get_source_line(frame)
if self.lang_info.is_relevant_function(frame):
raised_exception = self.lang_info.exc_info(frame)
if raised_exception:
print raised_exception
print self.lang_info.get_source_line(frame) or result
if source_line:
if output_always.rstrip():
print output_always.rstrip()
print source_line
else:
print result
...
...
@@ -2190,12 +2210,12 @@ class PythonInfo(LanguageInfo):
try:
tstate = frame.read_var('
tstate
').dereference()
if gdb.parse_and_eval('
tstate
->
frame
==
f'):
# tstate local variable initialized
# tstate local variable initialized
, check for an exception
inf_type = tstate['
curexc_type
']
inf_value = tstate['
curexc_value
']
if inf_type:
return '
An
exception
was
raised
:
%
s
(
%
s
)
' % (inf_type,
inf_value)
return '
An
exception
was
raised
:
%
s
' % (inf_value,)
except (ValueError, RuntimeError), e:
# Could not read the variable tstate or it'
s
memory
,
it
's ok
pass
...
...
@@ -2342,7 +2362,7 @@ class PythonCodeExecutor(object):
"Increment the reference count of a Python object in the inferior."
gdb
.
parse_and_eval
(
'Py_IncRef((PyObject *) %d)'
%
pointer
)
def
decref
(
self
,
pointer
):
def
x
decref
(
self
,
pointer
):
"Decrement the reference count of a Python object in the inferior."
# Py_DecRef is like Py_XDECREF, but a function. So we don't have
# to check for NULL. This should also decref all our allocated
...
...
@@ -2382,10 +2402,11 @@ class PythonCodeExecutor(object):
with
FetchAndRestoreError
():
try
:
self
.
decref
(
gdb
.
parse_and_eval
(
code
)
)
pyobject_return_value
=
gdb
.
parse_and_eval
(
code
)
finally
:
self
.
free
(
pointer
)
return
pyobject_return_value
class
FetchAndRestoreError
(
PythonCodeExecutor
):
"""
...
...
@@ -2462,6 +2483,20 @@ class FixGdbCommand(gdb.Command):
self
.
fix_gdb
()
def
_evalcode_python
(
executor
,
code
,
input_type
):
"""
Execute Python code in the most recent stack frame.
"""
global_dict
=
gdb
.
parse_and_eval
(
'PyEval_GetGlobals()'
)
local_dict
=
gdb
.
parse_and_eval
(
'PyEval_GetLocals()'
)
if
(
pointervalue
(
global_dict
)
==
0
or
pointervalue
(
local_dict
)
==
0
):
raise
gdb
.
GdbError
(
"Unable to find the locals or globals of the "
"most recent Python function (relative to the "
"selected frame)."
)
return
executor
.
evalcode
(
code
,
input_type
,
global_dict
,
local_dict
)
class
PyExec
(
gdb
.
Command
):
def
readcode
(
self
,
expr
):
...
...
@@ -2484,17 +2519,9 @@ class PyExec(gdb.Command):
def
invoke
(
self
,
expr
,
from_tty
):
expr
,
input_type
=
self
.
readcode
(
expr
)
executor
=
PythonCodeExecutor
()
global_dict
=
gdb
.
parse_and_eval
(
'PyEval_GetGlobals()'
)
local_dict
=
gdb
.
parse_and_eval
(
'PyEval_GetLocals()'
)
if
pointervalue
(
global_dict
)
==
0
or
pointervalue
(
local_dict
)
==
0
:
raise
gdb
.
GdbError
(
"Unable to find the locals or globals of the "
"most recent Python function (relative to the "
"selected frame)."
)
executor
.
evalcode
(
expr
,
input_type
,
global_dict
,
local_dict
)
executor
.
xdecref
(
_evalcode_python
(
executor
,
input_type
,
global_dict
,
local_dict
))
gdb
.
execute
(
'set breakpoint pending on'
)
...
...
tests/bugs.txt
View file @
72f8a46e
...
...
@@ -17,6 +17,7 @@ pure_mode_cmethod_inheritance_T583
genexpr_iterable_lookup_T600
for_from_pyvar_loop_T601
decorators_T593
temp_sideeffects_T654
# CPython regression tests that don't current work:
pyregr.test_threadsignals
...
...
tests/compile/a_capi.pyx
View file @
72f8a46e
...
...
@@ -11,6 +11,12 @@ cdef public class C[type C_Type, object C_Obj]:
cdef
public
Zax
*
blarg
cdef
public
C
c_pub
=
C
()
cdef
api
C
c_api
=
C
()
cdef
public
dict
o_pub
=
C
()
cdef
api
list
o_api
=
C
()
cdef
api
float
f
(
Foo
*
x
):
pass
...
...
@@ -19,3 +25,6 @@ cdef public void g(Blarg *x):
cdef
public
api
void
h
(
Zax
*
x
):
pass
cdef
extern
from
"a_capi.h"
:
pass
tests/compile/publicapi_api.pyx
0 → 100644
View file @
72f8a46e
# --
ctypedef
int
Int0
ctypedef
api
int
Int1
ctypedef
enum
EnumA0
:
EA0
ctypedef
api
enum
EnumA1
:
EA1
cdef
enum
EnumB0
:
EB0
=
0
cdef
api
enum
EnumB1
:
EB1
=
1
cdef
Int0
i0
=
0
cdef
EnumA0
ea0
=
EA0
cdef
EnumB0
eb0
=
EB0
cdef
api
Int1
i1
=
0
cdef
api
EnumA1
ea1
=
EA1
cdef
api
EnumB1
eb1
=
EB1
# --
ctypedef
struct
StructA0
:
int
SA0
ctypedef
api
struct
StructA1
:
int
SA1
cdef
struct
StructB0
:
int
SB0
cdef
api
struct
StructB1
:
int
SB1
cdef
StructA0
sa0
=
{
'SA0'
:
0
}
cdef
StructB0
sb0
=
{
'SB0'
:
2
}
cdef
api
StructA1
sa1
=
{
'SA1'
:
1
}
cdef
api
StructB1
sb1
=
{
'SB1'
:
3
}
# --
ctypedef
class
Foo0
:
pass
ctypedef
api
class
Foo1
[
type
PyFoo1_Type
,
object
PyFoo1_Object
]:
pass
cdef
class
Bar0
:
pass
cdef
api
class
Bar1
[
type
PyBar1_Type
,
object
PyBar1_Object
]:
pass
cdef
Foo0
f0
=
None
cdef
Bar0
b0
=
None
cdef
api
Foo1
f1
=
None
cdef
api
Bar1
b1
=
None
# --
cdef
void
bar0
():
pass
cdef
api
void
bar1
():
pass
cdef
void
*
spam0
(
object
o
)
except
NULL
:
return
NULL
cdef
api
void
*
spam1
(
object
o
)
except
NULL
:
return
NULL
bar0
()
bar1
()
spam0
(
None
)
spam1
(
None
)
# --
tests/compile/publicapi_mix.pyx
0 → 100644
View file @
72f8a46e
# --
ctypedef
int
Int0
ctypedef
public
int
Int1
ctypedef
api
int
Int2
ctypedef
public
api
int
Int3
ctypedef
enum
EnumA0
:
EA0
ctypedef
public
enum
EnumA1
:
EA1
ctypedef
api
enum
EnumA2
:
EA2
ctypedef
public
api
enum
EnumA3
:
EA3
cdef
enum
EnumB0
:
EB0
=
0
cdef
public
enum
EnumB1
:
EB1
=
1
cdef
api
enum
EnumB2
:
EB2
=
2
cdef
public
api
enum
EnumB3
:
EB3
=
3
# --
ctypedef
struct
StructA0
:
int
SA0
ctypedef
public
struct
StructA1
:
int
SA1
ctypedef
api
struct
StructA2
:
int
SA2
ctypedef
public
api
struct
StructA3
:
int
SA3
cdef
struct
StructB0
:
int
SB0
cdef
public
struct
StructB1
:
int
SB1
cdef
api
struct
StructB2
:
int
SB2
cdef
public
api
struct
StructB3
:
int
SB3
# --
ctypedef
class
Foo0
:
pass
ctypedef
public
class
Foo1
[
type
PyFoo1_Type
,
object
PyFoo1_Object
]:
pass
ctypedef
api
class
Foo2
[
type
PyFoo2_Type
,
object
PyFoo2_Object
]:
pass
ctypedef
public
api
class
Foo3
[
type
PyFoo3_Type
,
object
PyFoo3_Object
]:
pass
cdef
class
Bar0
:
pass
cdef
public
class
Bar1
[
type
PyBar1_Type
,
object
PyBar1_Object
]:
pass
cdef
api
class
Bar2
[
type
PyBar2_Type
,
object
PyBar2_Object
]:
pass
cdef
public
api
class
Bar3
[
type
PyBar3_Type
,
object
PyBar3_Object
]:
pass
# --
cdef
void
bar0
():
pass
cdef
public
void
bar1
():
pass
cdef
api
void
bar2
():
pass
cdef
public
api
void
bar3
():
pass
cdef
void
*
spam0
(
object
o
)
except
NULL
:
return
NULL
cdef
public
void
*
spam1
(
object
o
)
except
NULL
:
return
NULL
cdef
api
void
*
spam2
(
object
o
)
except
NULL
:
return
NULL
cdef
public
api
void
*
spam3
(
object
o
)
except
NULL
:
return
NULL
bar0
()
spam0
(
None
)
# --
cdef
double
d0
=
0
cdef
public
double
d1
=
1
cdef
api
double
d2
=
2
cdef
public
api
double
d3
=
3
cdef
object
o0
=
None
cdef
public
object
o1
=
None
cdef
api
object
o2
=
None
cdef
public
api
object
o3
=
None
# --
tests/compile/publicapi_pub.pyx
0 → 100644
View file @
72f8a46e
# --
ctypedef
int
Int0
ctypedef
public
int
Int1
ctypedef
enum
EnumA0
:
EA0
ctypedef
public
enum
EnumA1
:
EA1
cdef
enum
EnumB0
:
EB0
=
0
cdef
public
enum
EnumB1
:
EB1
=
1
cdef
Int0
i0
=
0
cdef
EnumA0
ea0
=
EA0
cdef
EnumB0
eb0
=
EB0
cdef
public
Int1
i1
=
0
cdef
public
EnumA1
ea1
=
EA1
cdef
public
EnumB1
eb1
=
EB1
# --
ctypedef
struct
StructA0
:
int
SA0
ctypedef
public
struct
StructA1
:
int
SA1
cdef
struct
StructB0
:
int
SB0
cdef
public
struct
StructB1
:
int
SB1
cdef
StructA0
sa0
=
{
'SA0'
:
0
}
cdef
StructB0
sb0
=
{
'SB0'
:
2
}
cdef
public
StructA1
sa1
=
{
'SA1'
:
1
}
cdef
public
StructB1
sb1
=
{
'SB1'
:
3
}
# --
ctypedef
class
Foo0
:
pass
ctypedef
public
class
Foo1
[
type
PyFoo1_Type
,
object
PyFoo1_Object
]:
pass
cdef
class
Bar0
:
pass
cdef
public
class
Bar1
[
type
PyBar1_Type
,
object
PyBar1_Object
]:
pass
cdef
Foo0
f0
=
None
cdef
Bar0
b0
=
None
cdef
public
Foo1
f1
=
None
cdef
public
Bar1
b1
=
None
# --
cdef
void
bar0
():
pass
cdef
public
void
bar1
():
pass
cdef
void
*
spam0
(
object
o
)
except
NULL
:
return
NULL
cdef
public
void
*
spam1
(
object
o
)
except
NULL
:
return
NULL
bar0
()
bar1
()
spam0
(
None
)
spam1
(
None
)
# --
tests/compile/publicapi_pxd_mix.pxd
0 → 100644
View file @
72f8a46e
# --
ctypedef
int
Int0
ctypedef
public
int
Int1
ctypedef
api
int
Int2
ctypedef
public
api
int
Int3
ctypedef
enum
EnumA0
:
EA0
ctypedef
public
enum
EnumA1
:
EA1
ctypedef
api
enum
EnumA2
:
EA2
ctypedef
public
api
enum
EnumA3
:
EA3
cdef
enum
EnumB0
:
EB0
=
0
cdef
public
enum
EnumB1
:
EB1
=
1
cdef
api
enum
EnumB2
:
EB2
=
2
cdef
public
api
enum
EnumB3
:
EB3
=
3
# --
ctypedef
struct
StructA0
:
int
SA0
ctypedef
public
struct
StructA1
:
int
SA1
ctypedef
api
struct
StructA2
:
int
SA2
ctypedef
public
api
struct
StructA3
:
int
SA3
cdef
struct
StructB0
:
int
SB0
cdef
public
struct
StructB1
:
int
SB1
cdef
api
struct
StructB2
:
int
SB2
cdef
public
api
struct
StructB3
:
int
SB3
# --
ctypedef
class
Foo0
:
pass
ctypedef
public
class
Foo1
[
type
PyFoo1_Type
,
object
PyFoo1_Object
]:
pass
ctypedef
api
class
Foo2
[
type
PyFoo2_Type
,
object
PyFoo2_Object
]:
pass
ctypedef
public
api
class
Foo3
[
type
PyFoo3_Type
,
object
PyFoo3_Object
]:
pass
cdef
class
Bar0
:
pass
cdef
public
class
Bar1
[
type
PyBar1_Type
,
object
PyBar1_Object
]:
pass
cdef
api
class
Bar2
[
type
PyBar2_Type
,
object
PyBar2_Object
]:
pass
cdef
public
api
class
Bar3
[
type
PyBar3_Type
,
object
PyBar3_Object
]:
pass
# --
cdef
inline
void
bar0
():
pass
cdef
public
void
bar1
()
cdef
api
void
bar2
()
cdef
public
api
void
bar3
()
cdef
inline
void
*
spam0
(
object
o
)
except
NULL
:
return
NULL
cdef
public
void
*
spam1
(
object
o
)
except
NULL
cdef
api
void
*
spam2
(
object
o
)
nogil
except
NULL
cdef
public
api
void
*
spam3
(
object
o
)
except
NULL
with
gil
# --
#cdef public int i1
#cdef api int i2
#cdef public api int i3
# --
tests/compile/publicapi_pxd_mix.pyx
0 → 100644
View file @
72f8a46e
cdef
class
Foo1
:
pass
cdef
class
Foo2
:
pass
cdef
class
Foo3
:
pass
cdef
class
Bar1
:
pass
cdef
class
Bar2
:
pass
cdef
class
Bar3
:
pass
cdef
public
void
bar1
():
pass
cdef
api
void
bar2
():
pass
cdef
public
api
void
bar3
():
pass
cdef
public
void
*
spam1
(
object
o
)
except
NULL
:
return
NULL
cdef
api
void
*
spam2
(
object
o
)
nogil
except
NULL
:
return
NULL
cdef
public
api
void
*
spam3
(
object
o
)
except
NULL
with
gil
:
return
NULL
tests/run/capiimpl.pyx
View file @
72f8a46e
...
...
@@ -2,8 +2,20 @@ __doc__ = u"""
>>> import sys
>>> sys.getrefcount(Foo.__pyx_vtable__)
2
>>> sys.getrefcount(__pyx_capi__['
spam
'])
>>> sys.getrefcount(__pyx_capi__['
ten
'])
2
>>> sys.getrefcount(__pyx_capi__['pi'])
2
>>> sys.getrefcount(__pyx_capi__['obj'])
2
>>> sys.getrefcount(__pyx_capi__['dct'])
2
>>> sys.getrefcount(__pyx_capi__['one'])
2
>>> sys.getrefcount(__pyx_capi__['two'])
Traceback (most recent call last):
...
KeyError: 'two'
"""
cdef
public
api
class
Foo
[
type
FooType
,
object
FooObject
]:
...
...
@@ -12,3 +24,12 @@ cdef public api class Foo [type FooType, object FooObject]:
cdef
api
void
spam
():
pass
cdef
api
int
ten
=
10
cdef
api
double
pi
=
3.14
cdef
api
object
obj
=
object
()
cdef
api
dict
dct
=
{}
cdef
public
api
int
one
=
1
cdef
public
int
two
=
2
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