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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
ccda96cb
Commit
ccda96cb
authored
Feb 20, 2010
by
Robert Bradshaw
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow nested C++ types.
parent
da38498e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
102 additions
and
51 deletions
+102
-51
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+4
-0
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+21
-0
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+12
-5
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+12
-4
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+53
-42
No files found.
Cython/Compiler/ExprNodes.py
View file @
ccda96cb
...
@@ -3062,6 +3062,10 @@ class AttributeNode(ExprNode):
...
@@ -3062,6 +3062,10 @@ class AttributeNode(ExprNode):
module_scope
=
self
.
obj
.
analyse_as_module
(
env
)
module_scope
=
self
.
obj
.
analyse_as_module
(
env
)
if
module_scope
:
if
module_scope
:
return
module_scope
.
lookup_type
(
self
.
attribute
)
return
module_scope
.
lookup_type
(
self
.
attribute
)
if
not
isinstance
(
self
.
obj
,
(
UnicodeNode
,
StringNode
,
BytesNode
)):
base_type
=
self
.
obj
.
analyse_as_type
(
env
)
if
base_type
and
hasattr
(
base_type
,
'scope'
):
return
base_type
.
scope
.
lookup_type
(
self
.
attribute
)
return
None
return
None
def
analyse_as_extension_type
(
self
,
env
):
def
analyse_as_extension_type
(
self
,
env
):
...
...
Cython/Compiler/Nodes.py
View file @
ccda96cb
...
@@ -779,6 +779,27 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
...
@@ -779,6 +779,27 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
else
:
else
:
return
PyrexTypes
.
error_type
return
PyrexTypes
.
error_type
class
CNestedBaseTypeNode
(
CBaseTypeNode
):
# For C++ classes that live inside other C++ classes.
# name string
# base_type CBaseTypeNode
child_attrs
=
[
'base_type'
]
def
analyse
(
self
,
env
,
could_be_name
=
None
):
base_type
=
self
.
base_type
.
analyse
(
env
)
if
base_type
is
PyrexTypes
.
error_type
:
return
PyrexTypes
.
error_type
if
not
base_type
.
is_cpp_class
:
error
(
self
.
pos
,
"'%s' is not a valid type scope"
%
base_type
)
return
PyrexTypes
.
error_type
type_entry
=
base_type
.
scope
.
lookup_here
(
self
.
name
)
if
not
type_entry
or
not
type_entry
.
is_type
:
error
(
self
.
pos
,
"'%s.%s' is not a type identifier"
%
(
base_type
,
self
.
name
))
return
PyrexTypes
.
error_type
return
type_entry
.
type
class
TemplatedTypeNode
(
CBaseTypeNode
):
class
TemplatedTypeNode
(
CBaseTypeNode
):
# After parsing:
# After parsing:
# positional_args [ExprNode] List of positional arguments
# positional_args [ExprNode] List of positional arguments
...
...
Cython/Compiler/Parsing.py
View file @
ccda96cb
...
@@ -1869,11 +1869,15 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
...
@@ -1869,11 +1869,15 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
complex
=
complex
,
longness
=
longness
,
complex
=
complex
,
longness
=
longness
,
is_self_arg
=
self_flag
,
templates
=
templates
)
is_self_arg
=
self_flag
,
templates
=
templates
)
if
s
.
sy
==
'['
:
if
s
.
sy
==
'['
:
return
p_buffer_or_template
(
s
,
type_node
,
templates
)
type_node
=
p_buffer_or_template
(
s
,
type_node
,
templates
)
else
:
return
type_node
if
s
.
sy
==
'.'
:
s
.
next
()
name
=
p_ident
(
s
)
type_node
=
Nodes
.
CNestedBaseTypeNode
(
pos
,
base_type
=
type_node
,
name
=
name
)
return
type_node
def
p_buffer_or_template
(
s
,
base_type_node
,
templates
):
def
p_buffer_or_template
(
s
,
base_type_node
,
templates
):
# s.sy == '['
# s.sy == '['
...
@@ -2729,7 +2733,10 @@ def p_cpp_class_definition(s, pos, ctx):
...
@@ -2729,7 +2733,10 @@ def p_cpp_class_definition(s, pos, ctx):
body_ctx = Ctx(visibility = ctx.visibility)
body_ctx = Ctx(visibility = ctx.visibility)
body_ctx.templates = templates
body_ctx.templates = templates
while s.sy != 'DEDENT':
while s.sy != 'DEDENT':
if s.sy != 'pass':
if s.systring == 'cppclass':
attributes.append(
p_cpp_class_definition(s, s.position(), body_ctx))
elif s.sy != 'pass':
attributes.append(
attributes.append(
p_c_func_or_var_declaration(s, s.position(), body_ctx))
p_c_func_or_var_declaration(s, s.position(), body_ctx))
else:
else:
...
...
Cython/Compiler/PyrexTypes.py
View file @
ccda96cb
...
@@ -1821,6 +1821,7 @@ class CppClassType(CType):
...
@@ -1821,6 +1821,7 @@ class CppClassType(CType):
is_cpp_class
=
1
is_cpp_class
=
1
has_attributes
=
1
has_attributes
=
1
exception_check
=
True
exception_check
=
True
namespace
=
None
def
__init__
(
self
,
name
,
scope
,
cname
,
base_classes
,
templates
=
None
,
template_type
=
None
):
def
__init__
(
self
,
name
,
scope
,
cname
,
base_classes
,
templates
=
None
,
template_type
=
None
):
self
.
name
=
name
self
.
name
=
name
...
@@ -1843,18 +1844,22 @@ class CppClassType(CType):
...
@@ -1843,18 +1844,22 @@ class CppClassType(CType):
return
self
.
specialize
(
dict
(
zip
(
self
.
templates
,
template_values
)))
return
self
.
specialize
(
dict
(
zip
(
self
.
templates
,
template_values
)))
def
specialize
(
self
,
values
):
def
specialize
(
self
,
values
):
if
not
self
.
templates
:
if
not
self
.
templates
and
not
self
.
namespace
:
return
self
return
self
if
self
.
templates
is
None
:
self
.
templates
=
[]
key
=
tuple
(
values
.
items
())
key
=
tuple
(
values
.
items
())
if
key
in
self
.
specializations
:
if
key
in
self
.
specializations
:
return
self
.
specializations
[
key
]
return
self
.
specializations
[
key
]
template_values
=
[
t
.
specialize
(
values
)
for
t
in
self
.
templates
]
template_values
=
[
t
.
specialize
(
values
)
for
t
in
self
.
templates
]
specialized
=
self
.
specializations
[
key
]
=
\
specialized
=
self
.
specializations
[
key
]
=
\
CppClassType
(
self
.
name
,
None
,
self
.
cname
,
[],
template_values
,
template_type
=
self
)
CppClassType
(
self
.
name
,
None
,
self
.
cname
,
[],
template_values
,
template_type
=
self
)
# Need to do these *after* self.specializations[key] is set
to
# Need to do these *after* self.specializations[key] is set
# avoid infinite recursion on circular references.
#
to
avoid infinite recursion on circular references.
specialized
.
base_classes
=
[
b
.
specialize
(
values
)
for
b
in
self
.
base_classes
]
specialized
.
base_classes
=
[
b
.
specialize
(
values
)
for
b
in
self
.
base_classes
]
specialized
.
scope
=
self
.
scope
.
specialize
(
values
)
specialized
.
scope
=
self
.
scope
.
specialize
(
values
)
if
self
.
namespace
is
not
None
:
specialized
.
namespace
=
self
.
namespace
.
specialize
(
values
)
return
specialized
return
specialized
def
declaration_code
(
self
,
entity_code
,
for_display
=
0
,
dll_linkage
=
None
,
pyrex
=
0
):
def
declaration_code
(
self
,
entity_code
,
for_display
=
0
,
dll_linkage
=
None
,
pyrex
=
0
):
...
@@ -1866,7 +1871,10 @@ class CppClassType(CType):
...
@@ -1866,7 +1871,10 @@ class CppClassType(CType):
if
for_display
or
pyrex
:
if
for_display
or
pyrex
:
name
=
self
.
name
name
=
self
.
name
else
:
else
:
name
=
self
.
cname
if
self
.
namespace
is
not
None
:
name
=
"%s::%s"
%
(
self
.
namespace
.
declaration_code
(
''
),
self
.
cname
)
else
:
name
=
self
.
cname
return
"%s%s %s"
%
(
name
,
templates
,
entity_code
)
return
"%s%s %s"
%
(
name
,
templates
,
entity_code
)
def
is_subclass
(
self
,
other_type
):
def
is_subclass
(
self
,
other_type
):
...
...
Cython/Compiler/Symtab.py
View file @
ccda96cb
...
@@ -219,6 +219,7 @@ class Scope(object):
...
@@ -219,6 +219,7 @@ class Scope(object):
is_py_class_scope = 0
is_py_class_scope = 0
is_c_class_scope = 0
is_c_class_scope = 0
is_cpp_class_scope = 0
is_module_scope = 0
is_module_scope = 0
scope_prefix = ""
scope_prefix = ""
in_cinclude = 0
in_cinclude = 0
...
@@ -399,6 +400,44 @@ class Scope(object):
...
@@ -399,6 +400,44 @@ class Scope(object):
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
return entry
return entry
def declare_cpp_class(self, name, scope,
pos, cname = None, base_classes = [],
visibility = 'extern', templates = None):
if visibility != 'extern':
error(pos, "
C
++
classes
may
only
be
extern
")
if cname is None:
cname = name
entry = self.lookup(name)
if not entry:
type = PyrexTypes.CppClassType(
name, scope, cname, base_classes, templates = templates)
entry = self.declare_type(name, type, pos, cname,
visibility = visibility, defining = scope is not None)
else:
if not (entry.is_type and entry.type.is_cpp_class):
warning(pos, "'%s'
redeclared
" % name, 0)
elif scope and entry.type.scope:
warning(pos, "'%s'
already
defined
(
ignoring
second
definition
)
" % name, 0)
else:
if scope:
entry.type.scope = scope
self.type_entries.append(entry)
if not scope and not entry.type.scope:
entry.type.scope = CppClassScope(name, self)
if templates is not None:
for T in templates:
template_entry = entry.type.scope.declare(T.name, T.name, T, None, 'extern')
template_entry.is_type = 1
def declare_inherited_attributes(entry, base_classes):
for base_class in base_classes:
declare_inherited_attributes(entry, base_class.base_classes)
entry.type.scope.declare_inherited_cpp_attributes(base_class.scope)
declare_inherited_attributes(entry, base_classes)
if self.is_cpp_class_scope:
entry.type.namespace = self.outer_scope.lookup(self.name).type
return entry
def check_previous_typedef_flag(self, entry, typedef_flag, pos):
def check_previous_typedef_flag(self, entry, typedef_flag, pos):
if typedef_flag != entry.type.typedef_flag:
if typedef_flag != entry.type.typedef_flag:
error(pos, "'%s'
previously
declared
using
'%s'" % (
error(pos, "'%s'
previously
declared
using
'%s'" % (
...
@@ -1004,42 +1043,6 @@ class ModuleScope(Scope):
...
@@ -1004,42 +1043,6 @@ class ModuleScope(Scope):
if typedef_flag and not self.in_cinclude:
if typedef_flag and not self.in_cinclude:
error(pos, "Forward-referenced type must use '
cdef
', not '
ctypedef
'")
error(pos, "Forward-referenced type must use '
cdef
', not '
ctypedef
'")
def declare_cpp_class(self, name, scope,
pos, cname = None, base_classes = [],
visibility = '
extern
', templates = None):
if visibility != '
extern
':
error(pos, "C++ classes may only be extern")
if cname is None:
cname = name
entry = self.lookup(name)
if not entry:
type = PyrexTypes.CppClassType(
name, scope, cname, base_classes, templates = templates)
entry = self.declare_type(name, type, pos, cname,
visibility = visibility, defining = scope is not None)
else:
if not (entry.is_type and entry.type.is_cpp_class):
warning(pos, "'
%
s
' redeclared " % name, 0)
elif scope and entry.type.scope:
warning(pos, "'
%
s
' already defined (ignoring second definition)" % name, 0)
else:
if scope:
entry.type.scope = scope
self.type_entries.append(entry)
if not scope and not entry.type.scope:
entry.type.scope = CppClassScope(name, self)
if templates is not None:
for T in templates:
template_entry = entry.type.scope.declare(T.name, T.name, T, None, '
extern
')
template_entry.is_type = 1
def declare_inherited_attributes(entry, base_classes):
for base_class in base_classes:
declare_inherited_attributes(entry, base_class.base_classes)
entry.type.scope.declare_inherited_cpp_attributes(base_class.scope)
declare_inherited_attributes(entry, base_classes)
return entry
def allocate_vtable_names(self, entry):
def allocate_vtable_names(self, entry):
# If extension type has a vtable, allocate vtable struct and
# If extension type has a vtable, allocate vtable struct and
# slot names for it.
# slot names for it.
...
@@ -1510,13 +1513,15 @@ class CClassScope(ClassScope):
...
@@ -1510,13 +1513,15 @@ class CClassScope(ClassScope):
class
CppClassScope
(
Scope
):
class
CppClassScope
(
Scope
):
# Namespace of a C++ class.
# Namespace of a C++ class.
inherited_var_entries
=
[]
is_cpp_class_scope
=
1
default_constructor
=
None
default_constructor
=
None
def
__init__
(
self
,
name
,
outer_scope
):
def
__init__
(
self
,
name
,
outer_scope
):
Scope
.
__init__
(
self
,
name
,
outer_scope
,
None
)
Scope
.
__init__
(
self
,
name
,
outer_scope
,
None
)
self
.
directives
=
outer_scope
.
directives
self
.
directives
=
outer_scope
.
directives
self
.
inherited_var_entries
=
[]
def
declare_var
(
self
,
name
,
type
,
pos
,
def
declare_var
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'extern'
,
is_cdef
=
0
,
allow_pyobject
=
0
):
cname
=
None
,
visibility
=
'extern'
,
is_cdef
=
0
,
allow_pyobject
=
0
):
...
@@ -1598,11 +1603,17 @@ class CppClassScope(Scope):
...
@@ -1598,11 +1603,17 @@ class CppClassScope(Scope):
def
specialize
(
self
,
values
):
def
specialize
(
self
,
values
):
scope
=
CppClassScope
(
self
.
name
,
self
.
outer_scope
)
scope
=
CppClassScope
(
self
.
name
,
self
.
outer_scope
)
for
entry
in
self
.
entries
.
values
():
for
entry
in
self
.
entries
.
values
():
scope
.
declare_var
(
entry
.
name
,
if
entry
.
is_type
:
entry
.
type
.
specialize
(
values
),
scope
.
declare_type
(
entry
.
name
,
entry
.
pos
,
entry
.
type
.
specialize
(
values
),
entry
.
cname
,
entry
.
pos
,
entry
.
visibility
)
entry
.
cname
)
else
:
scope
.
declare_var
(
entry
.
name
,
entry
.
type
.
specialize
(
values
),
entry
.
pos
,
entry
.
cname
,
entry
.
visibility
)
return
scope
return
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