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
8b04a094
Commit
8b04a094
authored
Apr 29, 2019
by
gsamain
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cypclass constructor wrapper
parent
eb702aa0
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
302 additions
and
12 deletions
+302
-12
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+29
-4
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+165
-3
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+108
-5
No files found.
Cython/Compiler/ExprNodes.py
View file @
8b04a094
...
@@ -5512,15 +5512,40 @@ class CallNode(ExprNode):
...
@@ -5512,15 +5512,40 @@ class CallNode(ExprNode):
elif
type
and
type
.
is_cpp_class
:
elif
type
and
type
.
is_cpp_class
:
self
.
args
=
[
arg
.
analyse_types
(
env
)
for
arg
in
self
.
args
]
self
.
args
=
[
arg
.
analyse_types
(
env
)
for
arg
in
self
.
args
]
constructor
=
type
.
scope
.
lookup
(
"<init>"
)
constructor
=
type
.
scope
.
lookup
(
"<init>"
)
if
not
constructor
:
constructor_type
=
None
constructor_cname
=
None
if
type
.
is_cyp_class
:
constructor
=
wrapper
=
type
.
scope
.
lookup_here
(
"<constructor>"
)
if
not
wrapper
:
error
(
self
.
function
.
pos
,
"no constructor wrapper found for Cypclass type '%s'"
%
self
.
function
.
name
)
namespace_list
=
wrapper
.
func_cname
.
split
(
'::'
)
templates
=
''
if
type
.
templates
:
templates
=
'<'
+
','
.
join
([
param
.
declaration_code
(
''
)
for
param
in
type
.
templates
if
not
PyrexTypes
.
is_optional_template_param
(
param
)
and
not
param
.
is_fused
])
+
'>'
if
len
(
namespace_list
)
>
2
:
# We do this because cypclass wrappers are outside of the class namespace
# in the C++ code, but they are declared within the class scope
constructor_cname
=
'::'
.
join
(
namespace_list
[:
-
2
]
+
[
namespace_list
[
-
1
]])
+
templates
else
:
constructor_cname
=
namespace_list
[
-
1
]
+
templates
constructor_type
=
wrapper
.
type
elif
not
constructor
:
error
(
self
.
function
.
pos
,
"no constructor found for C++ type '%s'"
%
self
.
function
.
name
)
error
(
self
.
function
.
pos
,
"no constructor found for C++ type '%s'"
%
self
.
function
.
name
)
self
.
type
=
error_type
self
.
type
=
error_type
return
self
return
self
self
.
function
=
RawCNameExprNode
(
self
.
function
.
pos
,
constructor
.
type
)
else
:
constructor_type
=
constructor
.
type
constructor_cname
=
type
.
empty_declaration_code
()
self
.
function
=
RawCNameExprNode
(
self
.
function
.
pos
,
constructor_type
)
self
.
function
.
entry
=
constructor
self
.
function
.
entry
=
constructor
self
.
function
.
set_cname
(
type
.
empty_declaration_code
()
)
self
.
function
.
set_cname
(
constructor_cname
)
self
.
analyse_c_function_call
(
env
)
self
.
analyse_c_function_call
(
env
)
self
.
type
=
type
if
type
.
is_cyp_class
:
self
.
type
=
constructor_type
.
return_type
else
:
self
.
type
=
type
return
True
return
True
def
is_lvalue
(
self
):
def
is_lvalue
(
self
):
...
...
Cython/Compiler/ModuleNode.py
View file @
8b04a094
...
@@ -586,6 +586,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -586,6 +586,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type_entries
.
append
(
entry
)
type_entries
.
append
(
entry
)
type_entries
=
[
t
for
t
in
type_entries
if
t
not
in
vtabslot_entries
]
type_entries
=
[
t
for
t
in
type_entries
if
t
not
in
vtabslot_entries
]
self
.
generate_type_header_code
(
type_entries
,
code
)
self
.
generate_type_header_code
(
type_entries
,
code
)
self
.
generate_cyp_class_wrapper_definitions
(
type_entries
,
code
)
for
entry
in
vtabslot_list
:
for
entry
in
vtabslot_list
:
self
.
generate_objstruct_definition
(
entry
.
type
,
code
)
self
.
generate_objstruct_definition
(
entry
.
type
,
code
)
self
.
generate_typeobj_predeclaration
(
entry
,
code
)
self
.
generate_typeobj_predeclaration
(
entry
,
code
)
...
@@ -816,6 +817,22 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -816,6 +817,22 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
elif
type
.
is_extension_type
:
elif
type
.
is_extension_type
:
self
.
generate_objstruct_definition
(
type
,
code
)
self
.
generate_objstruct_definition
(
type
,
code
)
def
generate_cyp_class_wrapper_definitions
(
self
,
type_entries
,
code
):
for
entry
in
type_entries
:
if
entry
.
type
.
is_cyp_class
:
# Generate wrapper constructor
scope
=
entry
.
type
.
scope
wrapper
=
scope
.
lookup_here
(
"<constructor>"
)
constructor
=
scope
.
lookup_here
(
"<init>"
)
new
=
scope
.
lookup_here
(
"__new__"
)
alloc
=
scope
.
lookup_here
(
"<alloc>"
)
if
not
wrapper
:
error
(
self
.
pos
,
"No constructor wrapper found for cypclass %s, did you write an __init__ method ?"
%
type
.
name
)
return
for
wrapper_entry
in
wrapper
.
all_alternatives
():
if
wrapper_entry
.
used
or
entry
.
type
.
templates
:
self
.
generate_cyp_class_wrapper_definition
(
entry
.
type
,
wrapper_entry
,
constructor
,
new
,
alloc
,
code
)
def
generate_gcc33_hack
(
self
,
env
,
code
):
def
generate_gcc33_hack
(
self
,
env
,
code
):
# Workaround for spurious warning generation in gcc 3.3
# Workaround for spurious warning generation in gcc 3.3
code
.
putln
(
""
)
code
.
putln
(
""
)
...
@@ -900,6 +917,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -900,6 +917,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
mark_pos
(
entry
.
pos
)
code
.
mark_pos
(
entry
.
pos
)
type
=
entry
.
type
type
=
entry
.
type
scope
=
type
.
scope
scope
=
type
.
scope
default_constructor
=
False
if
scope
:
if
scope
:
if
type
.
templates
:
if
type
.
templates
:
code
.
putln
(
"template <class %s>"
%
", class "
.
join
(
code
.
putln
(
"template <class %s>"
%
", class "
.
join
(
...
@@ -923,8 +941,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -923,8 +941,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
has_virtual_methods
=
False
has_virtual_methods
=
False
constructor
=
None
constructor
=
None
destructor
=
None
destructor
=
None
if
type
.
is_cyp_class
:
has_virtual_methods
=
True
for
attr
in
scope
.
var_entries
:
for
attr
in
scope
.
var_entries
:
cname
=
attr
.
cname
cname
=
attr
.
cname
if
attr
.
type
.
is_cfunction
and
attr
.
type
.
is_static_method
:
if
attr
.
type
.
is_cfunction
and
attr
.
type
.
is_static_method
:
...
@@ -957,7 +973,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -957,7 +973,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else
:
else
:
code
.
putln
(
"%s(%s);"
%
(
type
.
cname
,
", "
.
join
(
arg_decls
)))
code
.
putln
(
"%s(%s);"
%
(
type
.
cname
,
", "
.
join
(
arg_decls
)))
if
constructor
or
py_attrs
:
if
not
type
.
is_cyp_class
and
(
constructor
or
py_attrs
)
:
if
constructor
:
if
constructor
:
for
constructor_alternative
in
constructor
.
all_alternatives
():
for
constructor_alternative
in
constructor
.
all_alternatives
():
arg_decls
=
[]
arg_decls
=
[]
...
@@ -1022,12 +1038,158 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
...
@@ -1022,12 +1038,158 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else
:
else
:
code
.
putln
(
"%s(const %s& __Pyx_other);"
%
(
type
.
cname
,
type
.
cname
))
code
.
putln
(
"%s(const %s& __Pyx_other);"
%
(
type
.
cname
,
type
.
cname
))
code
.
putln
(
"%s& operator=(const %s& __Pyx_other);"
%
(
type
.
cname
,
type
.
cname
))
code
.
putln
(
"%s& operator=(const %s& __Pyx_other);"
%
(
type
.
cname
,
type
.
cname
))
if
type
.
is_cyp_class
:
code
.
putln
(
"// Auto generating default constructor to have Python-like behaviour"
)
code
.
putln
(
"%s(){}"
%
type
.
cname
)
code
.
putln
(
"// Generating __alloc__ function (used for __new__ calls)"
)
alloc_entry
=
scope
.
lookup_here
(
"<alloc>"
)
code
.
putln
(
"static %s { return new %s(); }"
%
(
alloc_entry
.
type
.
declaration_code
(
alloc_entry
.
cname
),
type
.
declaration_code
(
""
,
deref
=
1
)))
code
.
putln
(
"};"
)
code
.
putln
(
"};"
)
if
type
.
is_cyp_class
:
if
type
.
is_cyp_class
:
code
.
globalstate
.
use_utility_code
(
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load
(
"CyObjects"
,
"CyObjects.cpp"
,
proto_block
=
"utility_code_proto_before_types"
))
UtilityCode
.
load
(
"CyObjects"
,
"CyObjects.cpp"
,
proto_block
=
"utility_code_proto_before_types"
))
def
generate_cyp_class_wrapper_definition
(
self
,
type
,
wrapper_entry
,
constructor_entry
,
new_entry
,
alloc_entry
,
code
):
if
type
.
templates
:
code
.
putln
(
"template <typename %s>"
%
", class "
.
join
(
[
T
.
empty_declaration_code
()
for
T
in
type
.
templates
]))
init_entry
=
constructor_entry
self_type
=
wrapper_entry
.
type
.
return_type
.
declaration_code
(
''
)
type_string
=
type
.
empty_declaration_code
()
class_name
=
type
.
name
wrapper_cname
=
"%s__constructor__%s"
%
(
Naming
.
func_prefix
,
class_name
)
wrapper_type
=
wrapper_entry
.
type
arg_decls
=
[]
arg_names
=
[]
for
arg
in
wrapper_type
.
args
[:
len
(
wrapper_type
.
args
)
-
wrapper_type
.
optional_arg_count
]:
arg_decl
=
arg
.
declaration_code
()
arg_decls
.
append
(
arg_decl
)
arg_names
.
append
(
arg
.
cname
)
if
wrapper_type
.
optional_arg_count
:
arg_decls
.
append
(
wrapper_type
.
op_arg_struct
.
declaration_code
(
Naming
.
optional_args_cname
))
arg_names
.
append
(
Naming
.
optional_args_cname
)
if
wrapper_type
.
has_varargs
:
# We can't safely handle varargs because we need
# to know where the size argument is to start a va_list
error
(
wrapper_entry
.
pos
,
"Cypclass cannot handle variable arguments constructors, but you can use optional arguments (arg=some_value)"
)
if
not
arg_decls
:
arg_decls
=
[
"void"
]
decl_arg_string
=
', '
.
join
(
arg_decls
)
code
.
putln
(
"static %s %s(%s)"
%
(
self_type
,
wrapper_cname
,
decl_arg_string
))
code
.
putln
(
"{"
)
wrapper_arg_types
=
[
arg
.
type
for
arg
in
wrapper_entry
.
type
.
args
]
pos
=
wrapper_entry
.
pos
or
type
.
entry
.
pos
if
new_entry
:
alloc_type
=
alloc_entry
.
type
new_arg_types
=
[
alloc_type
]
+
wrapper_arg_types
new_entry
=
PyrexTypes
.
best_match
(
new_arg_types
,
new_entry
.
all_alternatives
(),
pos
)
if
new_entry
:
alloc_call_string
=
"("
+
new_entry
.
type
.
original_alloc_type
.
type
.
declaration_code
(
""
)
+
") %s"
%
alloc_entry
.
func_cname
new_arg_names
=
[
alloc_call_string
]
+
arg_names
new_arg_string
=
', '
.
join
(
new_arg_names
)
code
.
putln
(
"%s self =(%s) %s(%s);"
%
(
self_type
,
self_type
,
new_entry
.
func_cname
,
new_arg_string
))
else
:
code
.
putln
(
"%s self = new %s();"
%
(
self_type
,
type_string
))
if
init_entry
:
init_entry
=
PyrexTypes
.
best_match
(
wrapper_arg_types
,
init_entry
.
all_alternatives
(),
None
)
if
init_entry
and
(
not
new_entry
or
new_entry
.
type
.
return_type
==
type
):
# Calling __init__
max_init_nargs
=
len
(
init_entry
.
type
.
args
)
min_init_nargs
=
max_init_nargs
-
init_entry
.
type
.
optional_arg_count
max_wrapper_nargs
=
len
(
wrapper_entry
.
type
.
args
)
min_wrapper_nargs
=
max_wrapper_nargs
-
wrapper_entry
.
type
.
optional_arg_count
if
min_init_nargs
==
min_wrapper_nargs
:
# The optional arguments begin at the same rank for both function
# => just pass the wrapper opt args structure, and everything will be fine.
if
max_wrapper_nargs
>
min_wrapper_nargs
:
# The wrapper has optional args
arg_names
[
-
1
]
=
"(%s) %s"
%
(
init_entry
.
type
.
op_arg_struct
.
declaration_code
(
''
),
arg_names
[
-
1
])
elif
max_init_nargs
>
min_init_nargs
:
# The wrapper has no optional args but the __init__ function does
arg_names
.
append
(
"(%s) NULL"
%
init_entry
.
type
.
op_arg_struct
.
declaration_code
(
''
))
# else, neither __init__ nor __new__ have optional arguments, nothing to do
elif
min_wrapper_nargs
<
min_init_nargs
:
# It means some args from the wrapper should be at
# their default values, which we cannot know from here,
# so shout and stop, sadly.
error
(
init_entry
.
pos
,
"Could not call this __init__ function because the corresponding __new__ wrapper isn't aware of default values"
)
error
(
wrapper_entry
.
pos
,
"Wrapped __new__ is here (some args passed to __init__ could be at their default values)"
)
elif
min_wrapper_nargs
>
min_init_nargs
:
# Here, the __init__ optional arguments start before
# the __new__ ones. We have to unpack the __new__ opt args struct
# in some variables and then repack in the __init__ opt args struct.
init_opt_args_name_list
=
[
arg
.
cname
for
arg
in
wrapper_entry
.
type
.
args
[
min_init_nargs
:]]
# The first __init__ optional arguments are mandatory
# in the __new__ signature, so they will always appear
# in the __init__ optional arguments structure
init_opt_args_number
=
"init_opt_n"
code
.
putln
(
"int %s = %s;"
%
(
init_opt_args_number
,
min_wrapper_nargs
-
min_init_nargs
))
if
wrapper_entry
.
type
.
optional_arg_count
:
for
i
,
arg
in
enumerate
(
wrapper_entry
.
type
.
args
[
min_wrapper_nargs
:]):
# It's an opt arg => it's not declared in the (c++) function scope => declare a variable for it
arg_name
=
arg
.
cname
code
.
putln
(
"%s;"
%
arg
.
type
.
declaration_code
(
arg_name
))
# Arguments unpacking
optional_struct_name
=
arg_names
.
pop
()
code
.
putln
(
"if (%s) {"
%
optional_struct_name
)
# This is necessary to keep __init__ informed of
# how many optional arguments were explicitely given
code
.
putln
(
"%s += %s->%sn;"
%
(
init_opt_args_number
,
optional_struct_name
,
Naming
.
pyrex_prefix
))
braces_number
=
1
+
max_wrapper_nargs
-
min_wrapper_nargs
for
i
,
arg
in
enumerate
(
wrapper_entry
.
type
.
args
[
min_wrapper_nargs
:]):
code
.
putln
(
"if(%s->%sn > %s) {"
%
(
optional_struct_name
,
Naming
.
pyrex_prefix
,
i
))
code
.
putln
(
"%s = %s->%s;"
%
(
arg
.
cname
,
optional_struct_name
,
wrapper_entry
.
type
.
op_arg_struct
.
base_type
.
scope
.
var_entries
[
i
+
1
].
cname
))
for
_
in
range
(
braces_number
):
code
.
putln
(
'}'
)
# Arguments packing
init_opt_args_struct_name
=
"init_opt_args"
code
.
putln
(
"%s;"
%
init_entry
.
type
.
op_arg_struct
.
base_type
.
declaration_code
(
init_opt_args_struct_name
))
code
.
putln
(
"%s.%sn = %s;"
%
(
init_opt_args_struct_name
,
Naming
.
pyrex_prefix
,
init_opt_args_number
))
for
i
,
arg_name
in
enumerate
(
init_opt_args_name_list
):
# The second tuple member is a bit tricky.
# Actually, the only way we have to precisely know the attribute cname
# which corresponds to the argument in the opt args struct
# is to rely on the declaration order in the struct scope.
# FuncDefNode doesn't do this because it has it's declarator node,
# which is not our case here.
code
.
putln
(
"%s.%s = %s;"
%
(
init_opt_args_struct_name
,
init_entry
.
type
.
opt_arg_cname
(
init_entry
.
type
.
args
[
min_init_nargs
+
i
].
name
),
arg_name
))
arg_names
=
arg_names
[:
min_init_nargs
]
+
[
"&"
+
init_opt_args_struct_name
]
init_arg_string
=
','
.
join
(
arg_names
)
code
.
putln
(
"self->%s(%s);"
%
(
init_entry
.
cname
,
init_arg_string
))
code
.
putln
(
"return self;"
)
code
.
putln
(
"}"
)
def
generate_enum_definition
(
self
,
entry
,
code
):
def
generate_enum_definition
(
self
,
entry
,
code
):
code
.
mark_pos
(
entry
.
pos
)
code
.
mark_pos
(
entry
.
pos
)
type
=
entry
.
type
type
=
entry
.
type
...
...
Cython/Compiler/Symtab.py
View file @
8b04a094
...
@@ -652,7 +652,28 @@ class Scope(object):
...
@@ -652,7 +652,28 @@ class Scope(object):
if
scope
:
if
scope
:
entry
.
type
.
set_scope
(
scope
)
entry
.
type
.
set_scope
(
scope
)
declare_inherited_attributes
(
entry
,
base_classes
)
declare_inherited_attributes
(
entry
,
base_classes
)
scope
.
declare_var
(
name
=
"this"
,
cname
=
"this"
,
type
=
PyrexTypes
.
CPtrType
(
entry
.
type
),
pos
=
entry
.
pos
)
this_type
=
PyrexTypes
.
CPtrType
(
entry
.
type
)
if
not
cypclass
else
entry
.
type
scope
.
declare_var
(
name
=
"this"
,
cname
=
"this"
,
type
=
this_type
,
pos
=
entry
.
pos
)
if
cypclass
:
# Declare a shadow default constructor
wrapper_type
=
PyrexTypes
.
CFuncType
(
entry
.
type
,
[],
nogil
=
1
)
wrapper_cname
=
"%s__constructor__%s"
%
(
Naming
.
func_prefix
,
name
)
wrapper_name
=
"<constructor>"
wrapper_entry
=
scope
.
declare
(
wrapper_name
,
wrapper_cname
,
wrapper_type
,
pos
,
visibility
)
wrapper_type
.
entry
=
wrapper_entry
wrapper_entry
.
is_inherited
=
1
wrapper_entry
.
is_cfunction
=
1
wrapper_entry
.
func_cname
=
"%s::%s"
%
(
entry
.
type
.
empty_declaration_code
(),
wrapper_cname
)
# Declare the default __alloc__ method
alloc_type
=
wrapper_type
alloc_cname
=
"%s__alloc__%s"
%
(
Naming
.
func_prefix
,
name
)
alloc_name
=
"<alloc>"
alloc_entry
=
scope
.
declare
(
alloc_name
,
alloc_cname
,
alloc_type
,
pos
,
visibility
)
alloc_type
.
entry
=
alloc_entry
alloc_entry
.
is_cfunction
=
1
alloc_entry
.
func_cname
=
"%s::%s"
%
(
entry
.
type
.
empty_declaration_code
(),
alloc_cname
)
if
self
.
is_cpp_class_scope
:
if
self
.
is_cpp_class_scope
:
entry
.
type
.
namespace
=
self
.
outer_scope
.
lookup
(
self
.
name
).
type
entry
.
type
.
namespace
=
self
.
outer_scope
.
lookup
(
self
.
name
).
type
return
entry
return
entry
...
@@ -2442,6 +2463,26 @@ class CppClassScope(Scope):
...
@@ -2442,6 +2463,26 @@ class CppClassScope(Scope):
self
.
var_entries
.
append
(
entry
)
self
.
var_entries
.
append
(
entry
)
return
entry
return
entry
def
declare_constructor_wrapper
(
self
,
args
,
pos
,
defining
=
0
,
has_varargs
=
0
,
optional_arg_count
=
0
,
op_arg_struct
=
None
,
return_type
=
None
):
if
not
return_type
:
return_type
=
self
.
type
class_type
=
self
.
parent_type
class_name
=
self
.
name
.
split
(
'::'
)[
-
1
]
wrapper_cname
=
"%s__constructor__%s"
%
(
Naming
.
func_prefix
,
class_name
)
wrapper_name
=
"<constructor>"
wrapper_type
=
PyrexTypes
.
CFuncType
(
return_type
,
args
,
nogil
=
1
,
has_varargs
=
has_varargs
,
optional_arg_count
=
optional_arg_count
)
if
op_arg_struct
:
wrapper_type
.
op_arg_struct
=
op_arg_struct
wrapper_entry
=
self
.
declare
(
wrapper_name
,
wrapper_cname
,
wrapper_type
,
pos
,
'extern'
)
wrapper_type
.
entry
=
wrapper_entry
wrapper_entry
.
is_cfunction
=
1
if
defining
:
wrapper_entry
.
func_cname
=
"%s::%s"
%
(
class_type
.
empty_declaration_code
(),
wrapper_cname
)
return
wrapper_entry
def
declare_cfunction
(
self
,
name
,
type
,
pos
,
def
declare_cfunction
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'extern'
,
api
=
0
,
in_pxd
=
0
,
cname
=
None
,
visibility
=
'extern'
,
api
=
0
,
in_pxd
=
0
,
defining
=
0
,
modifiers
=
(),
utility_code
=
None
,
overridable
=
False
):
defining
=
0
,
modifiers
=
(),
utility_code
=
None
,
overridable
=
False
):
...
@@ -2454,16 +2495,40 @@ class CppClassScope(Scope):
...
@@ -2454,16 +2495,40 @@ class CppClassScope(Scope):
# arguments that cannot by called by value.
# arguments that cannot by called by value.
type
.
original_args
=
type
.
args
type
.
original_args
=
type
.
args
def
maybe_ref
(
arg
):
def
maybe_ref
(
arg
):
if
arg
.
type
.
is_cpp_class
and
not
arg
.
type
.
is_reference
:
if
arg
.
type
.
is_cpp_class
and
not
arg
.
type
.
is_reference
and
not
arg
.
type
.
is_cyp_class
:
return
PyrexTypes
.
CFuncTypeArg
(
return
PyrexTypes
.
CFuncTypeArg
(
arg
.
name
,
PyrexTypes
.
c_ref_type
(
arg
.
type
),
arg
.
pos
)
arg
.
name
,
PyrexTypes
.
c_ref_type
(
arg
.
type
),
arg
.
pos
)
else
:
else
:
return
arg
return
arg
type
.
args
=
[
maybe_ref
(
arg
)
for
arg
in
type
.
args
]
type
.
args
=
[
maybe_ref
(
arg
)
for
arg
in
type
.
args
]
if
self
.
type
.
is_cyp_class
and
not
self
.
lookup_here
(
"__new__"
):
self
.
declare_constructor_wrapper
(
type
.
args
,
pos
,
defining
,
type
.
has_varargs
,
type
.
optional_arg_count
,
getattr
(
type
,
'op_arg_struct'
,
None
))
elif
name
==
'__dealloc__'
and
cname
is
None
:
elif
name
==
'__dealloc__'
and
cname
is
None
:
cname
=
"%s__dealloc__%s"
%
(
Naming
.
func_prefix
,
class_name
)
cname
=
"%s__dealloc__%s"
%
(
Naming
.
func_prefix
,
class_name
)
name
=
'<del>'
name
=
'<del>'
type
.
return_type
=
PyrexTypes
.
c_void_type
type
.
return_type
=
PyrexTypes
.
c_void_type
elif
name
==
'__alloc__'
and
self
.
type
.
is_cyp_class
:
cname
=
"%s__alloc__%s"
%
(
Naming
.
func_prefix
,
class_name
)
name
=
'<alloc>'
elif
name
==
'__new__'
and
self
.
type
.
is_cyp_class
:
if
name
in
self
.
entries
:
if
self
.
entries
[
name
].
is_inherited
:
del
self
.
entries
[
name
]
else
:
error
(
pos
,
"Couldn't have more than one __new__ function"
)
if
self
.
lookup_here
(
"<constructor>"
):
del
self
.
entries
[
"<constructor>"
]
self
.
declare_constructor_wrapper
(
type
.
args
[
1
:],
pos
,
defining
,
type
.
has_varargs
,
type
.
optional_arg_count
,
getattr
(
type
,
'op_arg_struct'
,
None
),
return_type
=
type
.
return_type
)
type
.
original_alloc_type
=
type
.
args
[
0
]
if
name
in
(
'<init>'
,
'<del>'
)
and
type
.
nogil
:
if
name
in
(
'<init>'
,
'<del>'
)
and
type
.
nogil
:
for
base
in
self
.
type
.
base_classes
:
for
base
in
self
.
type
.
base_classes
:
if
base
is
cy_object_type
:
if
base
is
cy_object_type
:
...
@@ -2497,14 +2562,50 @@ class CppClassScope(Scope):
...
@@ -2497,14 +2562,50 @@ class CppClassScope(Scope):
# to work with this type.
# to work with this type.
for
base_entry
in
\
for
base_entry
in
\
base_scope
.
inherited_var_entries
+
base_scope
.
var_entries
:
base_scope
.
inherited_var_entries
+
base_scope
.
var_entries
:
base_entry_type
=
base_entry
.
type
#constructor/destructor is not inherited
#constructor/destructor is not inherited
if
base_entry
.
name
in
(
"<init>"
,
"<del>"
):
if
base_entry
.
name
==
"<del>"
\
or
base_entry
.
name
==
"<init>"
and
not
self
.
parent_type
.
is_cyp_class
\
or
base_entry
.
name
in
(
"<constructor>"
,
"<alloc>"
)
and
self
.
parent_type
.
is_cyp_class
:
continue
continue
elif
base_entry
.
name
==
"<init>"
and
not
self
.
lookup_here
(
"__new__"
):
wrapper_entry
=
self
.
declare_constructor_wrapper
(
base_entry_type
.
args
,
base_entry
.
pos
,
defining
=
1
,
has_varargs
=
base_entry_type
.
has_varargs
,
optional_arg_count
=
base_entry_type
.
optional_arg_count
,
op_arg_struct
=
getattr
(
base_entry_type
,
'op_arg_struct'
,
None
),
return_type
=
self
.
parent_type
)
wrapper_entry
.
is_inherited
=
1
#print base_entry.name, self.entries
#print base_entry.name, self.entries
elif
base_entry
.
name
==
"__new__"
and
self
.
parent_type
.
is_cyp_class
:
# Rewrite first argument for __new__
alloc_type
=
PyrexTypes
.
CPtrType
(
PyrexTypes
.
CFuncType
(
self
.
parent_type
,
[],
nogil
=
1
))
alloc_arg
=
PyrexTypes
.
CFuncTypeArg
(
base_entry
.
type
.
args
[
0
].
name
,
alloc_type
,
base_entry
.
type
.
args
[
0
].
pos
,
cname
=
base_entry
.
type
.
args
[
0
].
cname
)
base_entry_type
=
PyrexTypes
.
CFuncType
(
base_entry_type
.
return_type
,
[
alloc_arg
]
+
base_entry_type
.
args
[
1
:],
nogil
=
1
,
has_varargs
=
base_entry_type
.
has_varargs
,
optional_arg_count
=
base_entry_type
.
optional_arg_count
)
if
hasattr
(
base_entry
.
type
,
'op_arg_struct'
):
base_entry_type
.
op_arg_struct
=
base_entry
.
type
.
op_arg_struct
base_entry_type
.
original_alloc_type
=
base_entry
.
type
.
original_alloc_type
if
base_entry
.
name
in
self
.
entries
:
del
self
.
entries
[
base_entry
.
name
]
del
self
.
entries
[
"<constructor>"
]
elif
"<init>"
in
self
.
entries
:
del
self
.
entries
[
"<constructor>"
]
wrapper_entry
=
self
.
declare_constructor_wrapper
(
base_entry_type
.
args
[
1
:],
base_entry
.
pos
,
defining
=
1
,
has_varargs
=
base_entry_type
.
has_varargs
,
optional_arg_count
=
base_entry_type
.
optional_arg_count
,
op_arg_struct
=
getattr
(
base_entry_type
,
'op_arg_struct'
,
None
),
return_type
=
base_entry_type
.
return_type
)
wrapper_entry
.
is_inherited
=
1
if
base_entry
.
name
in
self
.
entries
:
if
base_entry
.
name
in
self
.
entries
:
base_entry
.
name
# FIXME: is there anything to do in this case?
base_entry
.
name
# FIXME: is there anything to do in this case?
entry
=
self
.
declare
(
base_entry
.
name
,
base_entry
.
cname
,
entry
=
self
.
declare
(
base_entry
.
name
,
base_entry
.
cname
,
base_entry
.
type
,
None
,
'extern'
)
base_entry
_
type
,
None
,
'extern'
)
entry
.
is_variable
=
1
entry
.
is_variable
=
1
entry
.
is_inherited
=
1
entry
.
is_inherited
=
1
entry
.
is_cfunction
=
base_entry
.
is_cfunction
entry
.
is_cfunction
=
base_entry
.
is_cfunction
...
@@ -2558,7 +2659,9 @@ class CppClassScope(Scope):
...
@@ -2558,7 +2659,9 @@ class CppClassScope(Scope):
name
=
"<init>"
name
=
"<init>"
elif
name
==
"__dealloc__"
:
elif
name
==
"__dealloc__"
:
name
=
"<del>"
name
=
"<del>"
return
super
(
CppClassScope
,
self
).
lookup_here
(
name
)
elif
name
==
"__alloc__"
:
name
=
"<alloc>"
return
super
(
CppClassScope
,
self
).
lookup_here
(
name
)
class
PropertyScope
(
Scope
):
class
PropertyScope
(
Scope
):
...
...
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