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
Show 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):
module_scope
=
self
.
obj
.
analyse_as_module
(
env
)
if
module_scope
:
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
def
analyse_as_extension_type
(
self
,
env
):
...
...
Cython/Compiler/Nodes.py
View file @
ccda96cb
...
...
@@ -779,6 +779,27 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
else
:
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
):
# After parsing:
# positional_args [ExprNode] List of positional arguments
...
...
Cython/Compiler/Parsing.py
View file @
ccda96cb
...
...
@@ -1869,10 +1869,14 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
complex
=
complex
,
longness
=
longness
,
is_self_arg
=
self_flag
,
templates
=
templates
)
if
s
.
sy
==
'['
:
return
p_buffer_or_template
(
s
,
type_node
,
templates
)
else
:
type_node
=
p_buffer_or_template
(
s
,
type_node
,
templates
)
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
):
...
...
@@ -2729,7 +2733,10 @@ def p_cpp_class_definition(s, pos, ctx):
body_ctx = Ctx(visibility = ctx.visibility)
body_ctx.templates = templates
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(
p_c_func_or_var_declaration(s, s.position(), body_ctx))
else:
...
...
Cython/Compiler/PyrexTypes.py
View file @
ccda96cb
...
...
@@ -1821,6 +1821,7 @@ class CppClassType(CType):
is_cpp_class
=
1
has_attributes
=
1
exception_check
=
True
namespace
=
None
def
__init__
(
self
,
name
,
scope
,
cname
,
base_classes
,
templates
=
None
,
template_type
=
None
):
self
.
name
=
name
...
...
@@ -1843,18 +1844,22 @@ class CppClassType(CType):
return
self
.
specialize
(
dict
(
zip
(
self
.
templates
,
template_values
)))
def
specialize
(
self
,
values
):
if
not
self
.
templates
:
if
not
self
.
templates
and
not
self
.
namespace
:
return
self
if
self
.
templates
is
None
:
self
.
templates
=
[]
key
=
tuple
(
values
.
items
())
if
key
in
self
.
specializations
:
return
self
.
specializations
[
key
]
template_values
=
[
t
.
specialize
(
values
)
for
t
in
self
.
templates
]
specialized
=
self
.
specializations
[
key
]
=
\
CppClassType
(
self
.
name
,
None
,
self
.
cname
,
[],
template_values
,
template_type
=
self
)
# Need to do these *after* self.specializations[key] is set
to
# avoid infinite recursion on circular references.
# Need to do these *after* self.specializations[key] is set
#
to
avoid infinite recursion on circular references.
specialized
.
base_classes
=
[
b
.
specialize
(
values
)
for
b
in
self
.
base_classes
]
specialized
.
scope
=
self
.
scope
.
specialize
(
values
)
if
self
.
namespace
is
not
None
:
specialized
.
namespace
=
self
.
namespace
.
specialize
(
values
)
return
specialized
def
declaration_code
(
self
,
entity_code
,
for_display
=
0
,
dll_linkage
=
None
,
pyrex
=
0
):
...
...
@@ -1865,6 +1870,9 @@ class CppClassType(CType):
templates
=
""
if
for_display
or
pyrex
:
name
=
self
.
name
else
:
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
)
...
...
Cython/Compiler/Symtab.py
View file @
ccda96cb
...
...
@@ -219,6 +219,7 @@ class Scope(object):
is_py_class_scope = 0
is_c_class_scope = 0
is_cpp_class_scope = 0
is_module_scope = 0
scope_prefix = ""
in_cinclude = 0
...
...
@@ -399,6 +400,44 @@ class Scope(object):
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
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):
if typedef_flag != entry.type.typedef_flag:
error(pos, "'%s'
previously
declared
using
'%s'" % (
...
...
@@ -1004,42 +1043,6 @@ class ModuleScope(Scope):
if typedef_flag and not self.in_cinclude:
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):
# If extension type has a vtable, allocate vtable struct and
# slot names for it.
...
...
@@ -1510,13 +1513,15 @@ class CClassScope(ClassScope):
class
CppClassScope
(
Scope
):
# Namespace of a C++ class.
inherited_var_entries
=
[]
is_cpp_class_scope
=
1
default_constructor
=
None
def
__init__
(
self
,
name
,
outer_scope
):
Scope
.
__init__
(
self
,
name
,
outer_scope
,
None
)
self
.
directives
=
outer_scope
.
directives
self
.
inherited_var_entries
=
[]
def
declare_var
(
self
,
name
,
type
,
pos
,
cname
=
None
,
visibility
=
'extern'
,
is_cdef
=
0
,
allow_pyobject
=
0
):
...
...
@@ -1598,6 +1603,12 @@ class CppClassScope(Scope):
def
specialize
(
self
,
values
):
scope
=
CppClassScope
(
self
.
name
,
self
.
outer_scope
)
for
entry
in
self
.
entries
.
values
():
if
entry
.
is_type
:
scope
.
declare_type
(
entry
.
name
,
entry
.
type
.
specialize
(
values
),
entry
.
pos
,
entry
.
cname
)
else
:
scope
.
declare_var
(
entry
.
name
,
entry
.
type
.
specialize
(
values
),
entry
.
pos
,
...
...
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