mirror of
https://github.com/boostorg/python.git
synced 2026-02-01 20:52:13 +00:00
- Fixed "char**" bug
- Lots of internal changes: phase 1 of Meta-Programming complete. [SVN r18919]
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
2 July 2003
|
||||
Jim Wilson found a bug where types like "char**" were being interpreted as
|
||||
"char*". Thanks Jim!
|
||||
|
||||
16 June 2003
|
||||
Thanks to discussions with David Abrahams and Roman Sulzhyk, some behaviours
|
||||
have changed:
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
Suppose that you want to add a function to a class, turning it into a method:</p>
|
||||
Suppose that you want to add a function to a class, turning it into a member
|
||||
function:</p>
|
||||
<code><pre>
|
||||
<span class=keyword>struct </span><span class=identifier>World
|
||||
</span><span class=special>{
|
||||
@@ -38,7 +39,7 @@ Suppose that you want to add a function to a class, turning it into a method:</p
|
||||
}
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Here, we want to make <tt>greet</tt> work as a method of the class <tt>World</tt>. We do
|
||||
Here, we want to make <tt>greet</tt> work as a member function of the class <tt>World</tt>. We do
|
||||
that using the <tt>add_method</tt> construct:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>W </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=string>"World"</span><span class=special>, </span><span class=string>"hello.h"</span><span class=special>)
|
||||
@@ -46,7 +47,7 @@ that using the <tt>add_method</tt> construct:</p>
|
||||
</span></pre></code>
|
||||
<p>
|
||||
Notice also that then you can rename it, set its policy, just like a regular
|
||||
method:</p>
|
||||
member function:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>rename</span><span class=special>(</span><span class=identifier>W</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=literal>'Greet'</span><span class=special>)
|
||||
</span></pre></code>
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
</table>
|
||||
<p>
|
||||
Even thought Pyste can identify various elements in the C++ code, like virtual
|
||||
methods, attributes, and so on, one thing that it can't do is to guess the
|
||||
semantics of functions that return pointers or references. In this case, the
|
||||
user must manually specify the policy. Policies are explained in the
|
||||
member functions, attributes, and so on, one thing that it can't do is to
|
||||
guess the semantics of functions that return pointers or references. In this
|
||||
case, the user must manually specify the policy. Policies are explained in the
|
||||
<a href="../../doc/tutorial/doc/call_policies.html">
|
||||
tutorial</a>.</p>
|
||||
<p>
|
||||
@@ -44,8 +44,8 @@ becomes in Pyste: </p>
|
||||
<span class=identifier>return_internal_reference</span><span class=special>(</span><span class=number>1</span><span class=special>, </span><span class=identifier>with_custodian_and_ward</span><span class=special>(</span><span class=number>1</span><span class=special>, </span><span class=number>2</span><span class=special>))
|
||||
</span></pre></code>
|
||||
<p>
|
||||
The user can specify policies for functions and methods with the <tt>set_policy</tt>
|
||||
function:</p>
|
||||
The user can specify policies for functions and virtual member functions with
|
||||
the <tt>set_policy</tt> function:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>set_policy</span><span class=special>(</span><span class=identifier>f</span><span class=special>, </span><span class=identifier>return_internal_reference</span><span class=special>())
|
||||
</span><span class=identifier>set_policy</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>foo</span><span class=special>, </span><span class=identifier>return_value_policy</span><span class=special>(</span><span class=identifier>manage_new_object</span><span class=special>))
|
||||
@@ -54,10 +54,11 @@ function:</p>
|
||||
<tr>
|
||||
<td class="note_box">
|
||||
|
||||
<img src="theme/note.gif"></img> <b>What if a function or method needs a policy and the user
|
||||
doesn't set one?</b><br><br> If a function/method needs a policy and one was not
|
||||
set, Pyste will issue a error. The user should then go in the interface file
|
||||
and set the policy for it, otherwise the generated cpp won't compile.
|
||||
<img src="theme/note.gif"></img> <b>What if a function or member function needs a policy and
|
||||
the user doesn't set one?</b><br><br> If a function needs a policy and one
|
||||
was not set, Pyste will issue a error. The user should then go in the
|
||||
interface file and set the policy for it, otherwise the generated cpp won't
|
||||
compile.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -66,7 +67,7 @@ and set the policy for it, otherwise the generated cpp won't compile.
|
||||
<td class="note_box">
|
||||
|
||||
<img src="theme/note.gif"></img>
|
||||
Note that, for functions/methods that return <tt>const T&</tt>, the policy
|
||||
Note that, for functions that return <tt>const T&</tt>, the policy
|
||||
<tt>return_value_policy<copy_const_reference>()</tt> wil be used by default, because
|
||||
that's normally what you want. You can change it to something else if you need
|
||||
to, though.
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
You can easily rename functions, classes, methods, attributes, etc. Just use the
|
||||
You can easily rename functions, classes, member functions, attributes, etc. Just use the
|
||||
function <tt>rename</tt>, like this:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>World </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=string>"World"</span><span class=special>, </span><span class=string>"hello.h"</span><span class=special>)
|
||||
@@ -34,7 +34,7 @@ function <tt>rename</tt>, like this:</p>
|
||||
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>show</span><span class=special>, </span><span class=string>"Show"</span><span class=special>)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
You can rename methods and attributes using this syntax:</p>
|
||||
You can rename member functions and attributes using this syntax:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>rename</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>greet</span><span class=special>, </span><span class=string>"Greet"</span><span class=special>)
|
||||
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>set</span><span class=special>, </span><span class=string>"Set"</span><span class=special>)
|
||||
@@ -43,7 +43,7 @@ You can rename methods and attributes using this syntax:</p>
|
||||
</span><span class=identifier>rename</span><span class=special>(</span><span class=identifier>choice</span><span class=special>.</span><span class=identifier>blue</span><span class=special>, </span><span class=string>"Blue"</span><span class=special>)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
You can exclude functions, classes, methods, attributes, etc, in the same way,
|
||||
You can exclude functions, classes, member functions, attributes, etc, in the same way,
|
||||
with the function <tt>exclude</tt>:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>exclude</span><span class=special>(</span><span class=identifier>World</span><span class=special>.</span><span class=identifier>greet</span><span class=special>)
|
||||
@@ -59,6 +59,18 @@ To access the operators of a class, access the member <tt>operator</tt> like thi
|
||||
</span></pre></code>
|
||||
<p>
|
||||
The string inside the brackets is the same as the name of the operator in C++.<br></p>
|
||||
<a name="virtual_member_functions"></a><h2>Virtual Member Functions</h2><p>
|
||||
Pyste automatically generates wrappers for virtual member functions, but you
|
||||
may want to disable this behaviour (for performance reasons, or to let the
|
||||
code more clean) if you do not plan to override the functions in Python. To do
|
||||
this, use the function <tt>final</tt>:</p>
|
||||
<code><pre>
|
||||
<span class=identifier>C </span><span class=special>= </span><span class=identifier>Class</span><span class=special>(</span><span class=literal>'C'</span><span class=special>, </span><span class=literal>'C.h'</span><span class=special>)
|
||||
</span><span class=identifier>final</span><span class=special>(</span><span class=identifier>C</span><span class=special>.</span><span class=identifier>foo</span><span class=special>) </span>##<span class=identifier>C</span><span class=special>::</span><span class=identifier>foo </span><span class=identifier>is </span><span class=identifier>a </span><span class=keyword>virtual </span><span class=identifier>member </span><span class=identifier>function
|
||||
</span></pre></code>
|
||||
<p>
|
||||
No virtual wrapper code will be generated for the virtual member function
|
||||
C::foo that way.</p>
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td width="30"><a href="../index.html"><img src="theme/u_arr.gif" border="0"></a></td>
|
||||
|
||||
@@ -32,8 +32,8 @@ cpp file with <a href="../../index.html">
|
||||
Boost.Python</a> code, with all the classes and functions exported.</p>
|
||||
<p>
|
||||
Besides declaring the classes and functions, the user has a number of other
|
||||
options, like renaming classes and methods, excluding methods and attributes,
|
||||
and so on. </p>
|
||||
options, like renaming e excluding classes and member functionis. Those are
|
||||
explained later on.</p>
|
||||
<a name="basics"></a><h2>Basics</h2><p>
|
||||
Suppose we have a class and some functions that we want to expose to Python
|
||||
declared in the header <tt>hello.h</tt>:</p>
|
||||
|
||||
@@ -75,10 +75,9 @@ You can optionally declare the function in the interface file itself:</p>
|
||||
</span><span class=identifier>set_wrapper</span><span class=special>(</span><span class=identifier>names</span><span class=special>, </span><span class=identifier>names_wrapper</span><span class=special>)
|
||||
</span></pre></code>
|
||||
<p>
|
||||
The same mechanism can be used with methods too. Just remember that the first
|
||||
parameter of wrappers for methods is a pointer to the class, like in
|
||||
<a href="../../index.html">
|
||||
Boost.Python</a>:</p>
|
||||
The same mechanism can be used with member functions too. Just remember that
|
||||
the first parameter of wrappers for member functions is a pointer to the
|
||||
class, as in:</p>
|
||||
<code><pre>
|
||||
<span class=keyword>struct </span><span class=identifier>C
|
||||
</span><span class=special>{
|
||||
@@ -104,7 +103,7 @@ And then in the interface file:</p>
|
||||
Boost.Python</a> accepts either a pointer or a
|
||||
reference to the class in wrappers for member functions as the first parameter,
|
||||
Pyste expects them to be a <b>pointer</b>. Doing otherwise will prevent your
|
||||
code to compile when you set a wrapper for a virtual method.
|
||||
code to compile when you set a wrapper for a virtual member function.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -46,24 +46,24 @@ class ClassExporter(Exporter):
|
||||
|
||||
|
||||
def ScopeName(self):
|
||||
return makeid(self.class_.FullName()) + '_scope'
|
||||
return makeid(self.class_._FullName()) + '_scope'
|
||||
|
||||
|
||||
def Unit(self):
|
||||
return makeid(self.class_.name)
|
||||
return makeid(self.class_._name)
|
||||
|
||||
|
||||
def Name(self):
|
||||
return self.class_.FullName()
|
||||
return self.class_._FullName()
|
||||
|
||||
|
||||
def SetDeclarations(self, declarations):
|
||||
Exporter.SetDeclarations(self, declarations)
|
||||
decl = self.GetDeclaration(self.info.name)
|
||||
if isinstance(decl, Typedef):
|
||||
self.class_ = self.GetDeclaration(decl.type.name)
|
||||
self.class_ = self.GetDeclaration(decl._type._name)
|
||||
if not self.info.rename:
|
||||
self.info.rename = decl.name
|
||||
self.info.rename = decl._name
|
||||
else:
|
||||
self.class_ = decl
|
||||
self.class_ = copy.deepcopy(self.class_)
|
||||
@@ -72,10 +72,10 @@ class ClassExporter(Exporter):
|
||||
|
||||
def ClassBases(self):
|
||||
all_bases = []
|
||||
for level in self.class_.hierarchy:
|
||||
for level in self.class_._hierarchy:
|
||||
for base in level:
|
||||
all_bases.append(base)
|
||||
return [self.GetDeclaration(x.name) for x in all_bases]
|
||||
return [self.GetDeclaration(x._name) for x in all_bases]
|
||||
|
||||
|
||||
def Order(self):
|
||||
@@ -83,15 +83,13 @@ class ClassExporter(Exporter):
|
||||
bases' bases. Do this because base classes must be instantialized
|
||||
before the derived classes in the module definition.
|
||||
'''
|
||||
return '%s_%s' % (len(self.ClassBases()), self.class_.FullName())
|
||||
return '%s_%s' % (len(self.ClassBases()), self.class_._FullName())
|
||||
|
||||
|
||||
def Export(self, codeunit, exported_names):
|
||||
self.InheritMethods(exported_names)
|
||||
self.MakeNonVirtual()
|
||||
if not self.info.exclude:
|
||||
self.CheckIsForwardDeclared()
|
||||
self.CheckForwardDeclarations()
|
||||
self.ExportBasics()
|
||||
self.ExportBases(exported_names)
|
||||
self.ExportConstructors()
|
||||
@@ -110,43 +108,31 @@ class ClassExporter(Exporter):
|
||||
'''Go up in the class hierarchy looking for classes that were not
|
||||
exported yet, and then add their public members to this classes
|
||||
members, as if they were members of this class. This allows the user to
|
||||
just export one type and automatically get all the methods from the
|
||||
just export one type and automatically get all the members from the
|
||||
base classes.
|
||||
'''
|
||||
valid_members = (Method, ClassVariable, NestedClass, ClassOperator,
|
||||
ConverterOperator, ClassEnumeration)
|
||||
for level in self.class_.hierarchy:
|
||||
for level in self.class_._hierarchy:
|
||||
level_exported = False
|
||||
for base in level:
|
||||
base = self.GetDeclaration(base.name)
|
||||
if base.FullName() not in exported_names:
|
||||
for member in base.members:
|
||||
base = self.GetDeclaration(base._name)
|
||||
if base._FullName() not in exported_names:
|
||||
for member in base:
|
||||
if type(member) in valid_members:
|
||||
member = copy.deepcopy(member)
|
||||
#if type(member) not in (ClassVariable,:
|
||||
# member.class_ = self.class_.FullName()
|
||||
self.class_.members.append(member)
|
||||
# member.class_ = self.class_._FullName()
|
||||
self.class_._AddMember(member)
|
||||
else:
|
||||
level_exported = True
|
||||
if level_exported:
|
||||
break
|
||||
self.public_members = \
|
||||
[x for x in self.class_.members if x.visibility == Scope.public]
|
||||
def IsValid(member):
|
||||
return isinstance(member, valid_members) and member._visibility == Scope.public
|
||||
self.public_members = [x for x in self.class_ if IsValid(x)]
|
||||
|
||||
def CheckIsForwardDeclared(self):
|
||||
if self.class_.incomplete:
|
||||
print "--> Error: Class %s is forward declared! " \
|
||||
"Please use the header with its complete definition." \
|
||||
% self.class_.FullName()
|
||||
print
|
||||
|
||||
|
||||
def CheckForwardDeclarations(self):
|
||||
for m in self.public_members:
|
||||
if isinstance(m, Function):
|
||||
exporterutils.WarnForwardDeclarations(m)
|
||||
|
||||
|
||||
def Write(self, codeunit):
|
||||
indent = self.INDENT
|
||||
boost_ns = namespaces.python
|
||||
@@ -210,23 +196,22 @@ class ClassExporter(Exporter):
|
||||
|
||||
def ExportBasics(self):
|
||||
'Export the name of the class and its class_ statement'
|
||||
self.Add('template', self.class_.FullName())
|
||||
name = self.info.rename or self.class_.name
|
||||
self.Add('template', self.class_._FullName())
|
||||
name = self.info.rename or self.class_._name
|
||||
self.Add('constructor', '"%s"' % name)
|
||||
|
||||
|
||||
def ExportBases(self, exported_names):
|
||||
'Expose the bases of the class into the template section'
|
||||
hierarchy = self.class_.hierarchy
|
||||
hierarchy = self.class_._hierarchy
|
||||
for level in hierarchy:
|
||||
exported = []
|
||||
for base in level:
|
||||
if base.visibility == Scope.public and base.name in exported_names:
|
||||
exported.append(base.name)
|
||||
if base._visibility == Scope.public and base._name in exported_names:
|
||||
exported.append(base._name)
|
||||
if exported:
|
||||
code = namespaces.python + 'bases< %s > ' % (', '.join(exported))
|
||||
self.Add('template', code)
|
||||
return
|
||||
|
||||
|
||||
def ExportConstructors(self):
|
||||
@@ -238,9 +223,9 @@ class ClassExporter(Exporter):
|
||||
|
||||
def init_code(cons):
|
||||
'return the init<>() code for the given contructor'
|
||||
param_list = [p.FullName() for p in cons.parameters]
|
||||
min_params_list = param_list[:cons.minArgs]
|
||||
max_params_list = param_list[cons.minArgs:]
|
||||
param_list = [p._FullName() for p in cons._parameters]
|
||||
min_params_list = param_list[:cons._minArgs]
|
||||
max_params_list = param_list[cons._minArgs:]
|
||||
min_params = ', '.join(min_params_list)
|
||||
max_params = ', '.join(max_params_list)
|
||||
init = py_ns + 'init< '
|
||||
@@ -255,9 +240,9 @@ class ClassExporter(Exporter):
|
||||
constructors = [x for x in self.public_members if isinstance(x, Constructor)]
|
||||
self.constructors = constructors[:]
|
||||
# don't export the copy constructor if the class is abstract
|
||||
if self.class_.abstract:
|
||||
if self.class_._abstract:
|
||||
for cons in constructors:
|
||||
if cons.IsCopy():
|
||||
if cons._IsCopy():
|
||||
constructors.remove(cons)
|
||||
break
|
||||
if not constructors:
|
||||
@@ -267,7 +252,7 @@ class ClassExporter(Exporter):
|
||||
# write the constructor with less parameters to the constructor section
|
||||
smaller = None
|
||||
for cons in constructors:
|
||||
if smaller is None or len(cons.parameters) < len(smaller.parameters):
|
||||
if smaller is None or len(cons._parameters) < len(smaller._parameters):
|
||||
smaller = cons
|
||||
assert smaller is not None
|
||||
self.Add('constructor', init_code(smaller))
|
||||
@@ -277,7 +262,7 @@ class ClassExporter(Exporter):
|
||||
code = '.def(%s)' % init_code(cons)
|
||||
self.Add('inside', code)
|
||||
# check if the class is copyable
|
||||
if not self.class_.HasCopyConstructor() or self.class_.abstract:
|
||||
if not self.class_._HasCopyConstructor() or self.class_._abstract:
|
||||
self.Add('template', namespaces.boost + 'noncopyable')
|
||||
|
||||
|
||||
@@ -285,11 +270,11 @@ class ClassExporter(Exporter):
|
||||
'Export the variables of the class, both static and simple variables'
|
||||
vars = [x for x in self.public_members if isinstance(x, Variable)]
|
||||
for var in vars:
|
||||
if self.info[var.name].exclude:
|
||||
if self.info[var._name].exclude:
|
||||
continue
|
||||
name = self.info[var.name].rename or var.name
|
||||
fullname = var.FullName()
|
||||
if var.type.const:
|
||||
name = self.info[var._name].rename or var._name
|
||||
fullname = var._FullName()
|
||||
if var._type._const:
|
||||
def_ = '.def_readonly'
|
||||
else:
|
||||
def_ = '.def_readwrite'
|
||||
@@ -299,8 +284,8 @@ class ClassExporter(Exporter):
|
||||
|
||||
def OverloadName(self, method):
|
||||
'Returns the name of the overloads struct for the given method'
|
||||
name = makeid(method.FullName())
|
||||
overloads = '_overloads_%i_%i' % (method.minArgs, method.maxArgs)
|
||||
name = makeid(method._FullName())
|
||||
overloads = '_overloads_%i_%i' % (method._minArgs, method._maxArgs)
|
||||
return name + overloads
|
||||
|
||||
|
||||
@@ -322,13 +307,13 @@ class ClassExporter(Exporter):
|
||||
declared = {}
|
||||
def DeclareOverloads(m):
|
||||
'Declares the macro for the generation of the overloads'
|
||||
if (isinstance(m, Method) and m.static) or type(m) == Function:
|
||||
func = m.FullName()
|
||||
if (isinstance(m, Method) and m._static) or type(m) == Function:
|
||||
func = m._FullName()
|
||||
macro = 'BOOST_PYTHON_FUNCTION_OVERLOADS'
|
||||
else:
|
||||
func = m.name
|
||||
func = m._name
|
||||
macro = 'BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS'
|
||||
code = '%s(%s, %s, %i, %i)\n' % (macro, self.OverloadName(m), func, m.minArgs, m.maxArgs)
|
||||
code = '%s(%s, %s, %i, %i)\n' % (macro, self.OverloadName(m), func, m._minArgs, m._maxArgs)
|
||||
if code not in declared:
|
||||
declared[code] = True
|
||||
self.Add('declaration', code)
|
||||
@@ -337,37 +322,29 @@ class ClassExporter(Exporter):
|
||||
def Pointer(m):
|
||||
'returns the correct pointer declaration for the method m'
|
||||
# check if this method has a wrapper set for him
|
||||
wrapper = self.info[method.name].wrapper
|
||||
wrapper = self.info[m._name].wrapper
|
||||
if wrapper:
|
||||
return '&' + wrapper.FullName()
|
||||
# return normal pointers to the methods of the class
|
||||
if isinstance(m, Method):
|
||||
is_unique = self.class_.IsUnique(m.name)
|
||||
else:
|
||||
# function
|
||||
is_unique = len(self.GetDeclarations(m.FullName())) == 1
|
||||
if is_unique:
|
||||
return '&' + method.FullName()
|
||||
else:
|
||||
return method.PointerDeclaration()
|
||||
return m._PointerDeclaration()
|
||||
|
||||
def IsExportable(m):
|
||||
'Returns true if the given method is exportable by this routine'
|
||||
ignore = (Constructor, ClassOperator, Destructor)
|
||||
return isinstance(m, Function) and not isinstance(m, ignore) and not m.virtual
|
||||
return isinstance(m, Function) and not isinstance(m, ignore) and not m._virtual
|
||||
|
||||
methods = [x for x in self.public_members if IsExportable(x)]
|
||||
methods.extend(self.GetAddedMethods())
|
||||
|
||||
for method in methods:
|
||||
method_info = self.info[method.name]
|
||||
method_info = self.info[method._name]
|
||||
|
||||
# skip this method if it was excluded by the user
|
||||
if method_info.exclude:
|
||||
continue
|
||||
|
||||
# rename the method if the user requested
|
||||
name = method_info.rename or method.name
|
||||
name = method_info.rename or method._name
|
||||
|
||||
# warn the user if this method needs a policy and doesn't have one
|
||||
method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)
|
||||
@@ -378,7 +355,7 @@ class ClassExporter(Exporter):
|
||||
policy = ', %s%s()' % (namespaces.python, policy.Code())
|
||||
# check for overloads
|
||||
overload = ''
|
||||
if method.minArgs != method.maxArgs:
|
||||
if method._minArgs != method._maxArgs:
|
||||
# add the overloads for this method
|
||||
DeclareOverloads(method)
|
||||
overload_name = self.OverloadName(method)
|
||||
@@ -392,7 +369,7 @@ class ClassExporter(Exporter):
|
||||
code += ')'
|
||||
self.Add('inside', code)
|
||||
# static method
|
||||
if isinstance(method, Method) and method.static:
|
||||
if isinstance(method, Method) and method._static:
|
||||
code = '.staticmethod("%s")' % name
|
||||
self.Add('inside', code)
|
||||
# add wrapper code if this method has one
|
||||
@@ -404,16 +381,16 @@ class ClassExporter(Exporter):
|
||||
def MakeNonVirtual(self):
|
||||
'''Make all methods that the user indicated to no_override no more virtual, delegating their
|
||||
export to the ExportMethods routine'''
|
||||
for member in self.class_.members:
|
||||
if type(member) == Method and member.virtual:
|
||||
member.virtual = not self.info[member.name].no_override
|
||||
for member in self.class_:
|
||||
if type(member) == Method and member._virtual:
|
||||
member._virtual = not self.info[member._name].no_override
|
||||
|
||||
|
||||
def ExportVirtualMethods(self):
|
||||
# check if this class has any virtual methods
|
||||
has_virtual_methods = False
|
||||
for member in self.class_.members:
|
||||
if type(member) == Method and member.virtual:
|
||||
for member in self.class_:
|
||||
if type(member) == Method and member._virtual:
|
||||
has_virtual_methods = True
|
||||
break
|
||||
|
||||
@@ -432,7 +409,7 @@ class ClassExporter(Exporter):
|
||||
BOOST_SUPPORTED_OPERATORS = dict(zip(BOOST_SUPPORTED_OPERATORS, range(len(BOOST_SUPPORTED_OPERATORS))))
|
||||
|
||||
# a dict of operators that are not directly supported by boost, but can be exposed
|
||||
# simply as a function with a special signature
|
||||
# simply as a function with a special name
|
||||
BOOST_RENAME_OPERATORS = {
|
||||
'()' : '__call__',
|
||||
}
|
||||
@@ -459,26 +436,26 @@ class ClassExporter(Exporter):
|
||||
for decl in self.declarations:
|
||||
if isinstance(decl, Operator):
|
||||
# check if one of the params is this class
|
||||
for param in decl.parameters:
|
||||
if param.name == self.class_.FullName():
|
||||
for param in decl._parameters:
|
||||
if param._name == self.class_._FullName():
|
||||
operators.append(decl)
|
||||
break
|
||||
return operators
|
||||
|
||||
def GetOperand(param):
|
||||
'Returns the operand of this parameter (either "self", or "other<type>")'
|
||||
if param.name == self.class_.FullName():
|
||||
if param._name == self.class_._FullName():
|
||||
return namespaces.python + 'self'
|
||||
else:
|
||||
return namespaces.python + ('other< %s >()' % param.name)
|
||||
return namespaces.python + ('other< %s >()' % param._name)
|
||||
|
||||
|
||||
def HandleSpecialOperator(operator):
|
||||
# gatter information about the operator and its parameters
|
||||
result_name = operator.result.name
|
||||
result_name = operator._result._name
|
||||
param1_name = ''
|
||||
if operator.parameters:
|
||||
param1_name = operator.parameters[0].name
|
||||
if operator._parameters:
|
||||
param1_name = operator._parameters[0]._name
|
||||
|
||||
# check for str
|
||||
ostream = 'basic_ostream'
|
||||
@@ -496,23 +473,21 @@ class ClassExporter(Exporter):
|
||||
frees = GetFreeOperators()
|
||||
members = [x for x in self.public_members if type(x) == ClassOperator]
|
||||
all_operators = frees + members
|
||||
operators = [x for x in all_operators if not self.info['operator'][x.name].exclude]
|
||||
operators = [x for x in all_operators if not self.info['operator'][x._name].exclude]
|
||||
|
||||
for operator in operators:
|
||||
# gatter information about the operator, for use later
|
||||
wrapper = self.info['operator'][operator.name].wrapper
|
||||
wrapper = self.info['operator'][operator._name].wrapper
|
||||
if wrapper:
|
||||
pointer = '&' + wrapper.FullName()
|
||||
if wrapper.code:
|
||||
self.Add('declaration', wrapper.code)
|
||||
elif isinstance(operator, ClassOperator) and self.class_.IsUnique(operator.name):
|
||||
pointer = '&' + operator.FullName()
|
||||
else:
|
||||
pointer = operator.PointerDeclaration()
|
||||
rename = self.info['operator'][operator.name].rename
|
||||
pointer = operator._PointerDeclaration()
|
||||
rename = self.info['operator'][operator._name].rename
|
||||
|
||||
# check if this operator will be exported as a method
|
||||
export_as_method = wrapper or rename or operator.name in self.BOOST_RENAME_OPERATORS
|
||||
export_as_method = wrapper or rename or operator._name in self.BOOST_RENAME_OPERATORS
|
||||
|
||||
# check if this operator has a special representation in boost
|
||||
special_code = HandleSpecialOperator(operator)
|
||||
@@ -524,9 +499,9 @@ class ClassExporter(Exporter):
|
||||
if wrapper:
|
||||
rename = wrapper.name
|
||||
else:
|
||||
rename = self.BOOST_RENAME_OPERATORS[operator.name]
|
||||
rename = self.BOOST_RENAME_OPERATORS[operator._name]
|
||||
policy = ''
|
||||
policy_obj = self.info['operator'][operator.name].policy
|
||||
policy_obj = self.info['operator'][operator._name].policy
|
||||
if policy_obj:
|
||||
policy = ', %s()' % policy_obj.Code()
|
||||
self.Add('inside', '.def("%s", %s%s)' % (rename, pointer, policy))
|
||||
@@ -534,24 +509,24 @@ class ClassExporter(Exporter):
|
||||
elif has_special_representation:
|
||||
self.Add('inside', special_code)
|
||||
|
||||
elif operator.name in self.BOOST_SUPPORTED_OPERATORS:
|
||||
elif operator._name in self.BOOST_SUPPORTED_OPERATORS:
|
||||
# export this operator using boost's facilities
|
||||
op = operator
|
||||
is_unary = isinstance(op, Operator) and len(op.parameters) == 1 or\
|
||||
isinstance(op, ClassOperator) and len(op.parameters) == 0
|
||||
is_unary = isinstance(op, Operator) and len(op._parameters) == 1 or\
|
||||
isinstance(op, ClassOperator) and len(op._parameters) == 0
|
||||
if is_unary:
|
||||
self.Add('inside', '.def( %s%sself )' % \
|
||||
(operator.name, namespaces.python))
|
||||
(operator._name, namespaces.python))
|
||||
else:
|
||||
# binary operator
|
||||
if len(operator.parameters) == 2:
|
||||
left_operand = GetOperand(operator.parameters[0])
|
||||
right_operand = GetOperand(operator.parameters[1])
|
||||
if len(operator._parameters) == 2:
|
||||
left_operand = GetOperand(operator._parameters[0])
|
||||
right_operand = GetOperand(operator._parameters[1])
|
||||
else:
|
||||
left_operand = namespaces.python + 'self'
|
||||
right_operand = GetOperand(operator.parameters[0])
|
||||
right_operand = GetOperand(operator._parameters[0])
|
||||
self.Add('inside', '.def( %s %s %s )' % \
|
||||
(left_operand, operator.name, right_operand))
|
||||
(left_operand, operator._name, right_operand))
|
||||
|
||||
# export the converters.
|
||||
# export them as simple functions with a pre-determined name
|
||||
@@ -559,8 +534,8 @@ class ClassExporter(Exporter):
|
||||
converters = [x for x in self.public_members if type(x) == ConverterOperator]
|
||||
|
||||
def ConverterMethodName(converter):
|
||||
result_fullname = converter.result.FullName()
|
||||
result_name = converter.result.name
|
||||
result_fullname = converter._result._FullName()
|
||||
result_name = converter._result._name
|
||||
for regex, method_name in self.SPECIAL_CONVERTERS.items():
|
||||
if regex.match(result_fullname):
|
||||
return method_name
|
||||
@@ -570,7 +545,7 @@ class ClassExporter(Exporter):
|
||||
return 'to_' + result_name
|
||||
|
||||
for converter in converters:
|
||||
info = self.info['operator'][converter.result.FullName()]
|
||||
info = self.info['operator'][converter._result._FullName()]
|
||||
# check if this operator should be excluded
|
||||
if info.exclude:
|
||||
continue
|
||||
@@ -579,10 +554,7 @@ class ClassExporter(Exporter):
|
||||
if info.rename or not special_code:
|
||||
# export as method
|
||||
name = info.rename or ConverterMethodName(converter)
|
||||
if self.class_.IsUnique(converter.name):
|
||||
pointer = '&' + converter.FullName()
|
||||
else:
|
||||
pointer = converter.PointerDeclaration()
|
||||
pointer = converter._PointerDeclaration()
|
||||
policy_code = ''
|
||||
if info.policy:
|
||||
policy_code = ', %s()' % info.policy.Code()
|
||||
@@ -596,9 +568,9 @@ class ClassExporter(Exporter):
|
||||
def ExportNestedClasses(self, exported_names):
|
||||
nested_classes = [x for x in self.public_members if isinstance(x, NestedClass)]
|
||||
for nested_class in nested_classes:
|
||||
nested_info = self.info[nested_class.name]
|
||||
nested_info = self.info[nested_class._name]
|
||||
nested_info.include = self.info.include
|
||||
nested_info.name = nested_class.FullName()
|
||||
nested_info.name = nested_class._FullName()
|
||||
exporter = ClassExporter(nested_info)
|
||||
exporter.SetDeclarations(self.declarations)
|
||||
codeunit = SingleCodeUnit(None, None)
|
||||
@@ -609,9 +581,9 @@ class ClassExporter(Exporter):
|
||||
def ExportNestedEnums(self):
|
||||
nested_enums = [x for x in self.public_members if isinstance(x, ClassEnumeration)]
|
||||
for enum in nested_enums:
|
||||
enum_info = self.info[enum.name]
|
||||
enum_info = self.info[enum._name]
|
||||
enum_info.include = self.info.include
|
||||
enum_info.name = enum.FullName()
|
||||
enum_info.name = enum._FullName()
|
||||
exporter = EnumExporter(enum_info)
|
||||
exporter.SetDeclarations(self.declarations)
|
||||
codeunit = SingleCodeUnit(None, None)
|
||||
@@ -622,17 +594,9 @@ class ClassExporter(Exporter):
|
||||
def ExportSmartPointer(self):
|
||||
smart_ptr = self.info.smart_ptr
|
||||
if smart_ptr:
|
||||
class_name = self.class_.FullName()
|
||||
class_name = self.class_._FullName()
|
||||
smart_ptr = smart_ptr % class_name
|
||||
#self.Add('template', smart_ptr)
|
||||
|
||||
self.Add('scope', '// Temporary code for smart pointers')
|
||||
self.Add('scope', namespaces.python + 'objects::class_value_wrapper< ')
|
||||
self.Add('scope', ' %s, objects::make_ptr_instance< ' % smart_ptr)
|
||||
self.Add('scope', ' %s, objects::pointer_holder< ' % class_name)
|
||||
self.Add('scope', ' %s, %s >' % (smart_ptr, class_name))
|
||||
self.Add('scope', ' >')
|
||||
self.Add('scope', '>();')
|
||||
self.Add('scope', '%s::register_ptr_to_python< %s >();' % (namespaces.python, smart_ptr))
|
||||
|
||||
|
||||
def ExportOpaquePointerPolicies(self):
|
||||
@@ -640,8 +604,8 @@ class ClassExporter(Exporter):
|
||||
methods = [x for x in self.public_members if isinstance(x, Method)]
|
||||
for method in methods:
|
||||
return_opaque_policy = return_value_policy(return_opaque_pointer)
|
||||
if self.info[method.name].policy == return_opaque_policy:
|
||||
macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % method.result.name
|
||||
if self.info[method._name].policy == return_opaque_policy:
|
||||
macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % method._result._name
|
||||
if macro not in self._exported_opaque_pointers:
|
||||
self.Add('declaration-outside', macro)
|
||||
self._exported_opaque_pointers[macro] = 1
|
||||
@@ -653,9 +617,9 @@ class ClassExporter(Exporter):
|
||||
|
||||
def _ParamsInfo(m, count=None):
|
||||
if count is None:
|
||||
count = len(m.parameters)
|
||||
count = len(m._parameters)
|
||||
param_names = ['p%i' % i for i in range(count)]
|
||||
param_types = [x.FullName() for x in m.parameters[:count]]
|
||||
param_types = [x._FullName() for x in m._parameters[:count]]
|
||||
params = ['%s %s' % (t, n) for t, n in zip(param_types, param_names)]
|
||||
#for i, p in enumerate(m.parameters[:count]):
|
||||
# if p.default is not None:
|
||||
@@ -672,7 +636,7 @@ class _VirtualWrapperGenerator(object):
|
||||
self.class_ = class_
|
||||
self.bases = bases[:]
|
||||
self.info = info
|
||||
self.wrapper_name = makeid(class_.FullName()) + '_Wrapper'
|
||||
self.wrapper_name = makeid(class_._FullName()) + '_Wrapper'
|
||||
self.virtual_methods = None
|
||||
self._method_count = {}
|
||||
self.GenerateVirtualMethods()
|
||||
@@ -683,9 +647,9 @@ class _VirtualWrapperGenerator(object):
|
||||
number of default arguments. Always returns at least one name, and return from
|
||||
the one with most arguments to the one with the least.
|
||||
'''
|
||||
base_name = 'default_' + method.name
|
||||
minArgs = method.minArgs
|
||||
maxArgs = method.maxArgs
|
||||
base_name = 'default_' + method._name
|
||||
minArgs = method._minArgs
|
||||
maxArgs = method._maxArgs
|
||||
if minArgs == maxArgs:
|
||||
return [base_name]
|
||||
else:
|
||||
@@ -699,18 +663,18 @@ class _VirtualWrapperGenerator(object):
|
||||
'''
|
||||
pyste = namespaces.pyste
|
||||
python = namespaces.python
|
||||
rename = self.info[method.name].rename or method.name
|
||||
result = method.result.FullName()
|
||||
rename = self.info[method._name].rename or method._name
|
||||
result = method._result._FullName()
|
||||
return_str = 'return '
|
||||
if result == 'void':
|
||||
return_str = ''
|
||||
params, param_names, param_types = _ParamsInfo(method)
|
||||
constantness = ''
|
||||
if method.const:
|
||||
if method._const:
|
||||
constantness = ' const'
|
||||
|
||||
# call_method callback
|
||||
decl = indent + '%s %s(%s)%s {\n' % (result, method.name, params, constantness)
|
||||
decl = indent + '%s %s(%s)%s {\n' % (result, method._name, params, constantness)
|
||||
param_names_str = ', '.join(param_names)
|
||||
if param_names_str:
|
||||
param_names_str = ', ' + param_names_str
|
||||
@@ -721,19 +685,19 @@ class _VirtualWrapperGenerator(object):
|
||||
# default implementations (with overloading)
|
||||
def DefaultImpl(method, param_names):
|
||||
'Return the body of a default implementation wrapper'
|
||||
wrapper = self.info[method.name].wrapper
|
||||
wrapper = self.info[method._name].wrapper
|
||||
if not wrapper:
|
||||
# return the default implementation of the class
|
||||
return '%s%s::%s(%s);\n' % \
|
||||
(return_str, self.class_.FullName(), method.name, ', '.join(param_names))
|
||||
(return_str, self.class_._FullName(), method._name, ', '.join(param_names))
|
||||
else:
|
||||
# return a call for the wrapper
|
||||
params = ', '.join(['this'] + param_names)
|
||||
return '%s%s(%s);\n' % (return_str, wrapper.FullName(), params)
|
||||
|
||||
if not method.abstract and method.visibility != Scope.private:
|
||||
minArgs = method.minArgs
|
||||
maxArgs = method.maxArgs
|
||||
if not method._abstract and method._visibility != Scope.private:
|
||||
minArgs = method._minArgs
|
||||
maxArgs = method._maxArgs
|
||||
impl_names = self.DefaultImplementationNames(method)
|
||||
for impl_name, argNum in zip(impl_names, range(minArgs, maxArgs+1)):
|
||||
params, param_names, param_types = _ParamsInfo(method, argNum)
|
||||
@@ -749,38 +713,35 @@ class _VirtualWrapperGenerator(object):
|
||||
statement to export this method.'''
|
||||
# dont define abstract methods
|
||||
pyste = namespaces.pyste
|
||||
rename = self.info[method.name].rename or method.name
|
||||
rename = self.info[method._name].rename or method._name
|
||||
default_names = self.DefaultImplementationNames(method)
|
||||
class_name = self.class_.FullName()
|
||||
class_name = self.class_._FullName()
|
||||
wrapper_name = pyste + self.wrapper_name
|
||||
result = method.result.FullName()
|
||||
is_method_unique = self.IsMethodUnique(method.name)
|
||||
result = method._result._FullName()
|
||||
is_method_unique = method._is_unique
|
||||
constantness = ''
|
||||
if method.const:
|
||||
if method._const:
|
||||
constantness = ' const'
|
||||
|
||||
# create a list of default-impl pointers
|
||||
minArgs = method.minArgs
|
||||
maxArgs = method.maxArgs
|
||||
minArgs = method._minArgs
|
||||
maxArgs = method._maxArgs
|
||||
if is_method_unique:
|
||||
default_pointers = ['&%s::%s' % (wrapper_name, x) for x in default_names]
|
||||
else:
|
||||
default_pointers = []
|
||||
for impl_name, argNum in zip(default_names, range(minArgs, maxArgs+1)):
|
||||
param_list = [x.FullName() for x in method.parameters[:argNum]]
|
||||
param_list = [x._FullName() for x in method._parameters[:argNum]]
|
||||
params = ', '.join(param_list)
|
||||
signature = '%s (%s::*)(%s)%s' % (result, wrapper_name, params, constantness)
|
||||
default_pointer = '(%s)&%s::%s' % (signature, wrapper_name, impl_name)
|
||||
default_pointers.append(default_pointer)
|
||||
|
||||
# get the pointer of the method
|
||||
if is_method_unique:
|
||||
pointer = '&' + method.FullName()
|
||||
else:
|
||||
pointer = method.PointerDeclaration()
|
||||
pointer = method._PointerDeclaration()
|
||||
|
||||
# Add policy to overloaded methods also
|
||||
policy = self.info[method.name].policy or ''
|
||||
policy = self.info[method._name].policy or ''
|
||||
if policy:
|
||||
policy = ', %s%s()' % (namespaces.python, policy.Code())
|
||||
|
||||
@@ -805,14 +766,14 @@ class _VirtualWrapperGenerator(object):
|
||||
'''
|
||||
def IsVirtual(m):
|
||||
return type(m) is Method and \
|
||||
m.virtual and \
|
||||
m.visibility != Scope.private
|
||||
m._virtual and \
|
||||
m._visibility != Scope.private
|
||||
|
||||
all_methods = [x for x in self.class_.members if IsVirtual(x)]
|
||||
all_methods = [x for x in self.class_ if IsVirtual(x)]
|
||||
for base in self.bases:
|
||||
base_methods = [x.Copy() for x in base if IsVirtual(x)]
|
||||
base_methods = [copy.deepcopy(x) for x in base if IsVirtual(x)]
|
||||
for base_method in base_methods:
|
||||
base_method.class_ = self.class_.FullName()
|
||||
base_method.class_ = self.class_._FullName()
|
||||
all_methods.append(base_method)
|
||||
|
||||
# extract the virtual methods, avoiding duplications. The duplication
|
||||
@@ -820,16 +781,16 @@ class _VirtualWrapperGenerator(object):
|
||||
# that inherited members are correctly excluded if the subclass overrides
|
||||
# them.
|
||||
def MethodSig(method):
|
||||
if method.const:
|
||||
if method._const:
|
||||
const = 'const'
|
||||
else:
|
||||
const = ''
|
||||
if method.result:
|
||||
result = method.result.FullName()
|
||||
if method._result:
|
||||
result = method._result._FullName()
|
||||
else:
|
||||
result = ''
|
||||
params = ', '.join([x.FullName() for x in method.parameters])
|
||||
return '%s %s(%s) %s' % (result, method.name, params, const)
|
||||
params = ', '.join([x._FullName() for x in method._parameters])
|
||||
return '%s %s(%s) %s' % (result, method._name, params, const)
|
||||
|
||||
self.virtual_methods = []
|
||||
already_added = {}
|
||||
@@ -840,25 +801,16 @@ class _VirtualWrapperGenerator(object):
|
||||
already_added[sig] = 0
|
||||
|
||||
|
||||
def IsMethodUnique(self, method):
|
||||
if not self._method_count:
|
||||
for m in self.virtual_methods:
|
||||
self._method_count[m.name] = self._method_count.get(m.name, 0) + 1
|
||||
return self._method_count[method] == 1
|
||||
|
||||
|
||||
def Constructors(self):
|
||||
def IsValid(m):
|
||||
return isinstance(m, Constructor) and m.visibility == Scope.public
|
||||
return [m for m in self.class_.members if IsValid(m)]
|
||||
return self.class_._Constructors(publics_only=True)
|
||||
|
||||
|
||||
def GenerateDefinitions(self):
|
||||
defs = []
|
||||
for method in self.virtual_methods:
|
||||
exclude = self.info[method.name].exclude
|
||||
exclude = self.info[method._name].exclude
|
||||
# generate definitions only for public methods and non-abstract methods
|
||||
if method.visibility == Scope.public and not method.abstract and not exclude:
|
||||
if method._visibility == Scope.public and not method._abstract and not exclude:
|
||||
defs.extend(self.MethodDefinition(method))
|
||||
return defs
|
||||
|
||||
@@ -867,13 +819,13 @@ class _VirtualWrapperGenerator(object):
|
||||
'Return the wrapper for this class'
|
||||
|
||||
# generate the class code
|
||||
class_name = self.class_.FullName()
|
||||
class_name = self.class_._FullName()
|
||||
code = 'struct %s: %s\n' % (self.wrapper_name, class_name)
|
||||
code += '{\n'
|
||||
# generate constructors (with the overloads for each one)
|
||||
for cons in self.Constructors(): # only public constructors
|
||||
minArgs = cons.minArgs
|
||||
maxArgs = cons.maxArgs
|
||||
minArgs = cons._minArgs
|
||||
maxArgs = cons._maxArgs
|
||||
# from the min number of arguments to the max number, generate
|
||||
# all version of the given constructor
|
||||
cons_code = ''
|
||||
@@ -889,7 +841,7 @@ class _VirtualWrapperGenerator(object):
|
||||
# generate the body
|
||||
body = []
|
||||
for method in self.virtual_methods:
|
||||
if not self.info[method.name].exclude:
|
||||
if not self.info[method._name].exclude:
|
||||
body.append(self.Declaration(method, indent))
|
||||
body = '\n'.join(body)
|
||||
code += body + '\n'
|
||||
|
||||
@@ -21,16 +21,16 @@ class EnumExporter(Exporter):
|
||||
if not self.info.exclude:
|
||||
indent = self.INDENT
|
||||
in_indent = self.INDENT*2
|
||||
rename = self.info.rename or self.enum.name
|
||||
full_name = self.enum.FullName()
|
||||
rename = self.info.rename or self.enum._name
|
||||
full_name = self.enum._FullName()
|
||||
if rename == "$_0" or rename == '._0':
|
||||
full_name = "int"
|
||||
rename = "unnamed"
|
||||
code = indent + namespaces.python
|
||||
code += 'enum_< %s >("%s")\n' % (full_name, rename)
|
||||
for name in self.enum.values:
|
||||
for name in self.enum._values:
|
||||
rename = self.info[name].rename or name
|
||||
value_fullname = self.enum.ValueFullName(name)
|
||||
value_fullname = self.enum._ValueFullName(name)
|
||||
code += in_indent + '.value("%s", %s)\n' % (rename, value_fullname)
|
||||
code += indent + ';\n\n'
|
||||
codeunit.Write('module', code)
|
||||
|
||||
@@ -55,7 +55,7 @@ class Exporter:
|
||||
def GetDeclarations(self, fullname):
|
||||
decls = []
|
||||
for decl in self.declarations:
|
||||
if decl.FullName() == fullname:
|
||||
if decl._FullName() == fullname:
|
||||
decls.append(decl)
|
||||
if not decls:
|
||||
raise RuntimeError, 'no %s declaration found!' % fullname
|
||||
|
||||
@@ -22,22 +22,19 @@ class FunctionExporter(Exporter):
|
||||
decls = self.GetDeclarations(self.info.name)
|
||||
for decl in decls:
|
||||
self.info.policy = exporterutils.HandlePolicy(decl, self.info.policy)
|
||||
exporterutils.WarnForwardDeclarations(decl)
|
||||
self.ExportDeclaration(decl, len(decls) == 1, codeunit)
|
||||
self.ExportOpaquePointer(decl, codeunit)
|
||||
self.GenerateOverloads(decls, codeunit)
|
||||
|
||||
|
||||
def ExportDeclaration(self, decl, unique, codeunit):
|
||||
name = self.info.rename or decl.name
|
||||
name = self.info.rename or decl._name
|
||||
defs = namespaces.python + 'def("%s", ' % name
|
||||
wrapper = self.info.wrapper
|
||||
if wrapper:
|
||||
pointer = '&' + wrapper.FullName()
|
||||
elif not unique:
|
||||
pointer = decl.PointerDeclaration()
|
||||
else:
|
||||
pointer = '&' + decl.FullName()
|
||||
pointer = decl._PointerDeclaration()
|
||||
defs += pointer
|
||||
defs += self.PolicyCode()
|
||||
overload = self.OverloadName(decl)
|
||||
@@ -51,9 +48,9 @@ class FunctionExporter(Exporter):
|
||||
|
||||
|
||||
def OverloadName(self, decl):
|
||||
if decl.minArgs != decl.maxArgs:
|
||||
if decl._minArgs != decl._maxArgs:
|
||||
return '%s_overloads_%i_%i' % \
|
||||
(decl.name, decl.minArgs, decl.maxArgs)
|
||||
(decl._name, decl._minArgs, decl._maxArgs)
|
||||
else:
|
||||
return ''
|
||||
|
||||
@@ -64,7 +61,7 @@ class FunctionExporter(Exporter):
|
||||
overload = self.OverloadName(decl)
|
||||
if overload and overload not in codes:
|
||||
code = 'BOOST_PYTHON_FUNCTION_OVERLOADS(%s, %s, %i, %i)' %\
|
||||
(overload, decl.FullName(), decl.minArgs, decl.maxArgs)
|
||||
(overload, decl._FullName(), decl._minArgs, decl_.maxArgs)
|
||||
codeunit.Write('declaration', code + '\n')
|
||||
codes[overload] = None
|
||||
|
||||
@@ -80,7 +77,7 @@ class FunctionExporter(Exporter):
|
||||
|
||||
def ExportOpaquePointer(self, function, codeunit):
|
||||
if self.info.policy == return_value_policy(return_opaque_pointer):
|
||||
type = function.result.name
|
||||
type = function._result._name
|
||||
macro = 'BOOST_PYTHON_OPAQUE_SPECIALIZED_TYPE_ID(%s)' % type
|
||||
if macro not in self._exported_opaque_pointers:
|
||||
codeunit.Write('declaration-outside', macro)
|
||||
|
||||
@@ -5,6 +5,9 @@ from copy import deepcopy
|
||||
from utils import enumerate
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Exceptions
|
||||
#==============================================================================
|
||||
class InvalidXMLError(Exception): pass
|
||||
|
||||
class ParserError(Exception): pass
|
||||
@@ -12,6 +15,9 @@ class ParserError(Exception): pass
|
||||
class InvalidContextError(ParserError): pass
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# GCCXMLParser
|
||||
#==============================================================================
|
||||
class GCCXMLParser(object):
|
||||
'Parse a GCC_XML file and extract the top-level declarations.'
|
||||
|
||||
@@ -21,6 +27,7 @@ class GCCXMLParser(object):
|
||||
self.elements = self.GetElementsFromXML(filename)
|
||||
# high level declarations
|
||||
self.declarations = []
|
||||
self._names = {}
|
||||
# parse the elements
|
||||
for id in self.elements:
|
||||
element, decl = self.elements[id]
|
||||
@@ -37,6 +44,12 @@ class GCCXMLParser(object):
|
||||
|
||||
|
||||
def AddDecl(self, decl):
|
||||
if decl._FullName() in self._names:
|
||||
decl._is_unique= False
|
||||
for d in self.declarations:
|
||||
if d._FullName() == decl._FullName():
|
||||
d._is_unique = False
|
||||
self._names[decl._FullName()] = 0
|
||||
self.declarations.append(decl)
|
||||
|
||||
|
||||
@@ -102,18 +115,17 @@ class GCCXMLParser(object):
|
||||
restricted, id = Check(id, 'r')
|
||||
decl = self.GetDecl(id)
|
||||
if isinstance(decl, Type):
|
||||
res = decl.Copy()
|
||||
res = deepcopy(decl)
|
||||
if const:
|
||||
res.const = const
|
||||
res._const = const
|
||||
if volatile:
|
||||
res.volatile = volatile
|
||||
res._volatile = volatile
|
||||
if restricted:
|
||||
res.restricted = restricted
|
||||
res._restricted = restricted
|
||||
else:
|
||||
res = Type(decl.FullName(), const)
|
||||
res.volatile = volatile
|
||||
res.restricted = restricted
|
||||
res.incomplete = decl.incomplete
|
||||
res = Type(decl._FullName(), const)
|
||||
res._volatile = volatile
|
||||
res._restricted = restricted
|
||||
return res
|
||||
|
||||
|
||||
@@ -130,8 +142,7 @@ class GCCXMLParser(object):
|
||||
|
||||
def ParseUnknown(self, id, element):
|
||||
name = '__Unknown_Element_%s' % id
|
||||
namespace = '::'
|
||||
decl = Declaration(name, namespace)
|
||||
decl = Unknown(name)
|
||||
self.Update(id, decl)
|
||||
|
||||
|
||||
@@ -139,10 +150,10 @@ class GCCXMLParser(object):
|
||||
namespace = element.get('name')
|
||||
context = element.get('context')
|
||||
if context:
|
||||
outerns = self.GetDecl(context)
|
||||
if not outerns.endswith('::'):
|
||||
outerns += '::'
|
||||
namespace = outerns + namespace
|
||||
outer = self.GetDecl(context)
|
||||
if not outer.endswith('::'):
|
||||
outer += '::'
|
||||
namespace = outer + namespace
|
||||
if namespace.startswith('::'):
|
||||
namespace = namespace[2:]
|
||||
self.Update(id, namespace)
|
||||
@@ -155,19 +166,19 @@ class GCCXMLParser(object):
|
||||
|
||||
def ParseVariable(self, id, element):
|
||||
# in gcc_xml, a static Field is declared as a Variable, so we check
|
||||
# this and call the Field parser if apply.
|
||||
# this and call the Field parser.
|
||||
context = self.GetDecl(element.get('context'))
|
||||
if isinstance(context, Class):
|
||||
self.ParseField(id, element)
|
||||
elem, decl = self.elements[id]
|
||||
decl.static = True
|
||||
decl._static = True
|
||||
else:
|
||||
namespace = context
|
||||
name = element.get('name')
|
||||
type_ = self.GetType(element.get('type'))
|
||||
location = self.GetLocation(element.get('location'))
|
||||
variable = Variable(type_, name, namespace)
|
||||
variable.location = location
|
||||
variable._location = location
|
||||
self.AddDecl(variable)
|
||||
self.Update(id, variable)
|
||||
|
||||
@@ -176,9 +187,9 @@ class GCCXMLParser(object):
|
||||
args = []
|
||||
for child in element:
|
||||
if child.tag == 'Argument':
|
||||
type_ = self.GetType(child.get('type'))
|
||||
type_.default = child.get('default')
|
||||
args.append(type_)
|
||||
type = self.GetType(child.get('type'))
|
||||
type._default = child.get('default')
|
||||
args.append(type)
|
||||
return args
|
||||
|
||||
|
||||
@@ -190,8 +201,9 @@ class GCCXMLParser(object):
|
||||
namespace = self.GetDecl(element.get('context'))
|
||||
location = self.GetLocation(element.get('location'))
|
||||
params = self.GetArguments(element)
|
||||
incomplete = bool(int(element.get('incomplete', 0)))
|
||||
function = functionType(name, namespace, returns, params)
|
||||
function.location = location
|
||||
function._location = location
|
||||
self.AddDecl(function)
|
||||
self.Update(id, function)
|
||||
|
||||
@@ -225,10 +237,10 @@ class GCCXMLParser(object):
|
||||
# "Unimplemented" tag, but we are not interested in this classes
|
||||
# anyway
|
||||
continue
|
||||
base = Base(decl.FullName(), visib)
|
||||
base = Base(decl._FullName(), visib)
|
||||
this_level.append(base)
|
||||
# normalize with the other levels
|
||||
for index, level in enumerate(decl.hierarchy):
|
||||
for index, level in enumerate(decl._hierarchy):
|
||||
if index < len(next_levels):
|
||||
next_levels[index] = next_levels[index] + level
|
||||
else:
|
||||
@@ -256,25 +268,27 @@ class GCCXMLParser(object):
|
||||
abstract = bool(int(element.get('abstract', '0')))
|
||||
location = self.GetLocation(element.get('location'))
|
||||
context = self.GetDecl(element.get('context'))
|
||||
incomplete = bool(element.get('incomplete', False))
|
||||
incomplete = bool(int(element.get('incomplete', 0)))
|
||||
if isinstance(context, str):
|
||||
class_ = Class(name, context, [], abstract)
|
||||
else:
|
||||
# a nested class
|
||||
visib = element.get('access', Scope.public)
|
||||
class_ = NestedClass(
|
||||
name, context.FullName(), visib, [], abstract)
|
||||
self.AddDecl(class_)
|
||||
name, context._FullName(), visib, [], abstract)
|
||||
class_._incomplete = incomplete
|
||||
# we have to add the declaration of the class before trying
|
||||
# to parse its members and bases, to avoid recursion.
|
||||
class_.location = location
|
||||
class_.incomplete = incomplete
|
||||
self.AddDecl(class_)
|
||||
class_._location = location
|
||||
self.Update(id, class_)
|
||||
# now we can get the members and the bases
|
||||
class_.hierarchy = self.GetHierarchy(element.get('bases'))
|
||||
if class_.hierarchy:
|
||||
class_.bases = class_.hierarchy[0]
|
||||
class_.members = self.GetMembers(element.get('members'))
|
||||
class_._hierarchy = self.GetHierarchy(element.get('bases'))
|
||||
if class_._hierarchy:
|
||||
class_._bases = class_._hierarchy[0]
|
||||
members = self.GetMembers(element.get('members'))
|
||||
for member in members:
|
||||
class_._AddMember(member)
|
||||
|
||||
|
||||
def ParseStruct(self, id, element):
|
||||
@@ -288,26 +302,24 @@ class GCCXMLParser(object):
|
||||
|
||||
|
||||
def ParseArrayType(self, id, element):
|
||||
type_ = self.GetType(element.get('type'))
|
||||
type = self.GetType(element.get('type'))
|
||||
min = element.get('min')
|
||||
max = element.get('max')
|
||||
array = ArrayType(type_.name, type_.const)
|
||||
array.min = min
|
||||
array.max = max
|
||||
array = ArrayType(type._name, type._const, min, max)
|
||||
self.Update(id, array)
|
||||
|
||||
|
||||
def ParseReferenceType(self, id, element):
|
||||
type_ = self.GetType(element.get('type'))
|
||||
expand = not isinstance(type_, FunctionType)
|
||||
ref = ReferenceType(type_.name, type_.const, None, type_.incomplete, expand)
|
||||
type = self.GetType(element.get('type'))
|
||||
expand = not isinstance(type, FunctionType)
|
||||
ref = ReferenceType(type._name, type._const, None, expand, type._suffix)
|
||||
self.Update(id, ref)
|
||||
|
||||
|
||||
def ParsePointerType(self, id, element):
|
||||
type_ = self.GetType(element.get('type'))
|
||||
expand = not isinstance(type_, FunctionType)
|
||||
ref = PointerType(type_.name, type_.const, None, type_.incomplete, expand)
|
||||
type = self.GetType(element.get('type'))
|
||||
expand = not isinstance(type, FunctionType)
|
||||
ref = PointerType(type._name, type._const, None, expand, type._suffix)
|
||||
self.Update(id, ref)
|
||||
|
||||
|
||||
@@ -319,7 +331,7 @@ class GCCXMLParser(object):
|
||||
|
||||
|
||||
def ParseMethodType(self, id, element):
|
||||
class_ = self.GetDecl(element.get('basetype')).FullName()
|
||||
class_ = self.GetDecl(element.get('basetype'))._FullName()
|
||||
result = self.GetType(element.get('returns'))
|
||||
args = self.GetArguments(element)
|
||||
method = MethodType(result, args, class_)
|
||||
@@ -329,19 +341,19 @@ class GCCXMLParser(object):
|
||||
def ParseField(self, id, element):
|
||||
name = element.get('name')
|
||||
visib = element.get('access', Scope.public)
|
||||
classname = self.GetDecl(element.get('context')).FullName()
|
||||
classname = self.GetDecl(element.get('context'))._FullName()
|
||||
type_ = self.GetType(element.get('type'))
|
||||
static = bool(int(element.get('extern', '0')))
|
||||
location = self.GetLocation(element.get('location'))
|
||||
var = ClassVariable(type_, name, classname, visib, static)
|
||||
var.location = location
|
||||
var._location = location
|
||||
self.Update(id, var)
|
||||
|
||||
|
||||
def ParseMethod(self, id, element, methodType=Method):
|
||||
name = element.get('name')
|
||||
result = self.GetType(element.get('returns'))
|
||||
classname = self.GetDecl(element.get('context')).FullName()
|
||||
classname = self.GetDecl(element.get('context'))._FullName()
|
||||
visib = element.get('access', Scope.public)
|
||||
static = bool(int(element.get('static', '0')))
|
||||
virtual = bool(int(element.get('virtual', '0')))
|
||||
@@ -351,7 +363,7 @@ class GCCXMLParser(object):
|
||||
params = self.GetArguments(element)
|
||||
method = methodType(
|
||||
name, classname, result, params, visib, virtual, abstract, static, const)
|
||||
method.location = location
|
||||
method._location = location
|
||||
self.Update(id, method)
|
||||
|
||||
|
||||
@@ -362,22 +374,22 @@ class GCCXMLParser(object):
|
||||
def ParseConstructor(self, id, element):
|
||||
name = element.get('name')
|
||||
visib = element.get('access', Scope.public)
|
||||
classname = self.GetDecl(element.get('context')).FullName()
|
||||
classname = self.GetDecl(element.get('context'))._FullName()
|
||||
location = self.GetLocation(element.get('location'))
|
||||
params = self.GetArguments(element)
|
||||
ctor = Constructor(name, classname, params, visib)
|
||||
ctor.location = location
|
||||
ctor._location = location
|
||||
self.Update(id, ctor)
|
||||
|
||||
|
||||
def ParseDestructor(self, id, element):
|
||||
name = element.get('name')
|
||||
visib = element.get('access', Scope.public)
|
||||
classname = self.GetDecl(element.get('context')).FullName()
|
||||
classname = self.GetDecl(element.get('context'))._FullName()
|
||||
virtual = bool(int(element.get('virtual', '0')))
|
||||
location = self.GetLocation(element.get('location'))
|
||||
des = Destructor(name, classname, visib, virtual)
|
||||
des.location = location
|
||||
des._location = location
|
||||
self.Update(id, des)
|
||||
|
||||
|
||||
@@ -390,7 +402,7 @@ class GCCXMLParser(object):
|
||||
type = self.GetType(element.get('type'))
|
||||
context = self.GetDecl(element.get('context'))
|
||||
if isinstance(context, Class):
|
||||
context = context.FullName()
|
||||
context = context._FullName()
|
||||
typedef = Typedef(type, name, context)
|
||||
self.Update(id, typedef)
|
||||
self.AddDecl(typedef)
|
||||
@@ -400,41 +412,23 @@ class GCCXMLParser(object):
|
||||
name = element.get('name')
|
||||
location = self.GetLocation(element.get('location'))
|
||||
context = self.GetDecl(element.get('context'))
|
||||
incomplete = bool(int(element.get('incomplete', 0)))
|
||||
if isinstance(context, str):
|
||||
enum = Enumeration(name, context)
|
||||
else:
|
||||
visib = element.get('access', Scope.public)
|
||||
enum = ClassEnumeration(name, context.FullName(), visib)
|
||||
enum = ClassEnumeration(name, context._FullName(), visib)
|
||||
self.AddDecl(enum)
|
||||
enum.location = location
|
||||
enum._location = location
|
||||
for child in element:
|
||||
if child.tag == 'EnumValue':
|
||||
name = child.get('name')
|
||||
value = int(child.get('init'))
|
||||
enum.values[name] = value
|
||||
enum._values[name] = value
|
||||
enum._incomplete = incomplete
|
||||
self.Update(id, enum)
|
||||
|
||||
|
||||
def ParseUnimplemented(self, id, element):
|
||||
'No idea of what this is'
|
||||
self.Update(id, Declaration('', ''))
|
||||
|
||||
|
||||
def ParseUnion(self, id, element):
|
||||
name = element.get('name')
|
||||
context = self.GetDecl(element.get('context'))
|
||||
location = self.GetLocation(element.get('location'))
|
||||
if isinstance(context, str):
|
||||
# a free union
|
||||
union = Union(name, context)
|
||||
self.AddDecl(union)
|
||||
else:
|
||||
visib = element.get('access', Scope.public)
|
||||
union = ClassUnion(name, context.FullName(), visib)
|
||||
union.location = location
|
||||
self.Update(id, union)
|
||||
|
||||
|
||||
|
||||
def ParseDeclarations(filename):
|
||||
'Returns a list of the top declarations found in the gcc_xml file.'
|
||||
|
||||
@@ -32,8 +32,8 @@ class HeaderExporter(Exporter):
|
||||
header = os.path.normpath(self.parser_header)
|
||||
for decl in self.declarations:
|
||||
# check if this declaration is in the header
|
||||
location = os.path.normpath(decl.location[0])
|
||||
if location == header and not self.IsInternalName(decl.name):
|
||||
location = os.path.normpath(decl._location[0])
|
||||
if location == header and not self.IsInternalName(decl._name):
|
||||
# ok, check the type of the declaration and export it accordingly
|
||||
self.HandleDeclaration(decl, codeunit, exported_names)
|
||||
|
||||
@@ -57,9 +57,9 @@ class HeaderExporter(Exporter):
|
||||
|
||||
def HandleExporter(self, decl, exporter_type, codeunit, exported_names):
|
||||
# only export complete declarations
|
||||
if not getattr(decl, "incomplete", False):
|
||||
info = self.info[decl.name]
|
||||
info.name = decl.FullName()
|
||||
if not getattr(decl, "_incomplete", False):
|
||||
info = self.info[decl._name]
|
||||
info.name = decl._FullName()
|
||||
info.include = self.info.include
|
||||
exporter = exporter_type(info)
|
||||
exporter.SetDeclarations(self.declarations)
|
||||
@@ -69,7 +69,7 @@ class HeaderExporter(Exporter):
|
||||
|
||||
|
||||
def Unit(self):
|
||||
return None # doesn't write anything by himself
|
||||
return None # doesn't write anything by itself
|
||||
|
||||
|
||||
def Order(self):
|
||||
|
||||
@@ -16,7 +16,7 @@ class VarExporter(Exporter):
|
||||
def Export(self, codeunit, exported_names):
|
||||
if self.info.exclude: return
|
||||
decl = self.GetDeclaration(self.info.name)
|
||||
if not decl.type.const:
|
||||
if not decl._type._const:
|
||||
msg = '---> Warning: The global variable "%s" is non-const:\n' \
|
||||
' changes in Python will not reflect in C++.'
|
||||
print msg % self.info.name
|
||||
|
||||
@@ -1,305 +1,386 @@
|
||||
'''
|
||||
Module declarations
|
||||
|
||||
Defines classes that represent declarations found in C++ header files.
|
||||
Defines classes that represent declarations found in C++ header files.
|
||||
|
||||
'''
|
||||
|
||||
#==============================================================================
|
||||
# Declaration
|
||||
#==============================================================================
|
||||
class Declaration(object):
|
||||
'Represents a basic declaration.'
|
||||
'''Base class for all declarations.
|
||||
@ivar _name: The name of the declaration.
|
||||
@ivar _namespace: The namespace of the declaration.
|
||||
'''
|
||||
|
||||
def __init__(self, name, namespace):
|
||||
# the declaration name
|
||||
self.name = name
|
||||
# all the namespaces, separated by '::' = 'boost::inner'
|
||||
self.namespace = namespace
|
||||
# tuple (filename, line)
|
||||
self.location = '', -1
|
||||
# if a declaration is incomplete it means that it was
|
||||
# forward declared
|
||||
self.incomplete = False
|
||||
'''
|
||||
@type name: string
|
||||
@param name: The name of this declaration
|
||||
@type namespace: string
|
||||
@param namespace: the full namespace where this declaration resides.
|
||||
'''
|
||||
self._name = name
|
||||
self._namespace = namespace
|
||||
self._location = '', -1 # (filename, line)
|
||||
self._incomplete = False
|
||||
self._is_unique = True
|
||||
|
||||
|
||||
def FullName(self):
|
||||
'Returns the full qualified name: "boost::inner::Test"'
|
||||
namespace = self.namespace or ''
|
||||
#if not namespace:
|
||||
# namespace = ''
|
||||
def _FullName(self):
|
||||
'''
|
||||
Returns the full qualified name: "boost::inner::Test"
|
||||
@rtype: string
|
||||
@return: The full name of the declaration.
|
||||
'''
|
||||
namespace = self._namespace or ''
|
||||
if namespace and not namespace.endswith('::'):
|
||||
namespace += '::'
|
||||
return namespace + self.name
|
||||
return namespace + self._name
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '<Declaration %s at %s>' % (self.FullName(), id(self))
|
||||
return '<Declaration %s at %s>' % (self._FullName(), id(self))
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return 'Declaration of %s' % self.FullName()
|
||||
return 'Declaration of %s' % self._FullName()
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Class
|
||||
#==============================================================================
|
||||
class Class(Declaration):
|
||||
'The declaration of a class or struct.'
|
||||
'''
|
||||
Represents a C++ class or struct. Iteration through it yields its members.
|
||||
|
||||
@type _abstract: bool
|
||||
@ivar _abstract: if the class has any abstract methods.
|
||||
|
||||
@type _bases: tuple
|
||||
@ivar _bases: tuple with L{Base} instances, representing the most direct
|
||||
inheritance.
|
||||
|
||||
@type _hierarchy: list
|
||||
@ivar _hierarchy: a list of tuples of L{Base} instances, representing
|
||||
the entire hierarchy tree of this object. The first tuple is the parent
|
||||
classes, and the other ones go up in the hierarchy.
|
||||
'''
|
||||
|
||||
def __init__(self, name, namespace, members, abstract):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
# list of members
|
||||
self.members = members
|
||||
# whatever the class has any abstract methods
|
||||
self.abstract = abstract
|
||||
# instances of Base
|
||||
self.bases = ()
|
||||
self.hierarchy = ()
|
||||
self._members_count = {}
|
||||
self.__members = members
|
||||
self._abstract = abstract
|
||||
self._bases = ()
|
||||
self._hierarchy = ()
|
||||
self.operator = {}
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.members)
|
||||
'''iterates through the class' members.
|
||||
'''
|
||||
return iter(self.__members)
|
||||
|
||||
|
||||
def IsAbstract(self):
|
||||
'Returns True if any method of this class is abstract'
|
||||
for member in self.members:
|
||||
if isinstance(member, Method):
|
||||
if member.abstract:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def RawName(self):
|
||||
'Returns the raw name of a template class. name = Foo<int>, raw = Foo'
|
||||
lesspos = self.name.find('<')
|
||||
if lesspos != -1:
|
||||
return self.name[:lesspos]
|
||||
else:
|
||||
return self.name
|
||||
|
||||
|
||||
def Constructors(self, publics_only=True):
|
||||
def _Constructors(self, publics_only=True):
|
||||
'''Returns a list of the constructors for this class.
|
||||
@rtype: list
|
||||
'''
|
||||
constructors = []
|
||||
for member in self:
|
||||
if isinstance(member, Constructor):
|
||||
if publics_only and member.visibility != Scope.public:
|
||||
if publics_only and member._visibility != Scope.public:
|
||||
continue
|
||||
constructors.append(member)
|
||||
return constructors
|
||||
|
||||
|
||||
def HasCopyConstructor(self):
|
||||
for cons in self.Constructors():
|
||||
if cons.IsCopy():
|
||||
def _HasCopyConstructor(self):
|
||||
'''Returns true if this class has a public copy constructor.
|
||||
@rtype: bool
|
||||
'''
|
||||
for cons in self._Constructors():
|
||||
if cons._IsCopy():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def HasDefaultConstructor(self):
|
||||
def _HasDefaultConstructor(self):
|
||||
'''Returns true if this class has a public default constructor.
|
||||
@rtype: bool
|
||||
'''
|
||||
for cons in self.Constructors():
|
||||
if cons.IsDefault():
|
||||
if cons._IsDefault():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def IsUnique(self, member_name):
|
||||
if not self._members_count:
|
||||
for m in self:
|
||||
self._members_count[m.name] = self._members_count.get(m.name, 0) + 1
|
||||
try:
|
||||
return self._members_count[member_name] == 1
|
||||
except KeyError:
|
||||
print self._members_count
|
||||
print 'Key', member_name
|
||||
|
||||
def _AddMember(self, member):
|
||||
slot = getattr(self, member._name, [])
|
||||
if slot:
|
||||
member._is_unique = False
|
||||
for m in slot:
|
||||
m._is_unique = False
|
||||
slot.append(member)
|
||||
setattr(self, member._name, slot)
|
||||
self.__members.append(member)
|
||||
if isinstance(member, ClassOperator):
|
||||
self.operator[member._name] = member
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# NestedClass
|
||||
#==============================================================================
|
||||
class NestedClass(Class):
|
||||
'The declaration of a class/struct inside another class/struct.'
|
||||
'''The declaration of a class/struct inside another class/struct.
|
||||
|
||||
@type _class: string
|
||||
@ivar _class: fullname of the class where this class is contained.
|
||||
|
||||
def __init__(self, name, class_, visib, members, abstract):
|
||||
@type _visibility: L{Scope}
|
||||
@ivar _visibility: the visibility of this class.
|
||||
'''
|
||||
|
||||
def __init__(self, name, _class, visib, members, abstract):
|
||||
Class.__init__(self, name, None, members, abstract)
|
||||
self.class_ = class_
|
||||
self.visibility = visib
|
||||
self._class = _class
|
||||
self._visibility = visib
|
||||
|
||||
|
||||
def FullName(self):
|
||||
return '%s::%s' % (self.class_, self.name)
|
||||
def _FullName(self):
|
||||
'''The full name of this class, like ns::outer::inner.
|
||||
@rtype: string
|
||||
'''
|
||||
return '%s::%s' % (self._class, self._name)
|
||||
|
||||
|
||||
|
||||
class Base:
|
||||
'Represents a base class of another class.'
|
||||
|
||||
def __init__(self, name, visibility=None):
|
||||
# class_ is the full name of the base class
|
||||
self.name = name
|
||||
# visibility of the derivation
|
||||
if visibility is None:
|
||||
visibility = Scope.public
|
||||
self.visibility = visibility
|
||||
|
||||
|
||||
|
||||
class Scope:
|
||||
#==============================================================================
|
||||
# Scope
|
||||
#==============================================================================
|
||||
class Scope:
|
||||
'''Used to represent the visibility of various members inside a class.
|
||||
@cvar public: public visibility
|
||||
@cvar private: private visibility
|
||||
@cvar protected: protected visibility
|
||||
'''
|
||||
public = 'public'
|
||||
private = 'private'
|
||||
protected = 'protected'
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Base
|
||||
#==============================================================================
|
||||
class Base:
|
||||
'''Represents a base class of another class.
|
||||
@ivar _name: the full name of the base class.
|
||||
@ivar _visibility: the visibility of the derivation.
|
||||
'''
|
||||
|
||||
def __init__(self, name, visibility=Scope.public):
|
||||
self._name = name
|
||||
self._visibility = visibility
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Function
|
||||
#==============================================================================
|
||||
class Function(Declaration):
|
||||
'The declaration of a function.'
|
||||
'''The declaration of a function.
|
||||
@ivar _result: instance of L{Type} or None.
|
||||
@ivar _parameters: list of L{Type} instances.
|
||||
'''
|
||||
|
||||
def __init__(self, name, namespace, result, params):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
# the result type: instance of Type, or None (constructors)
|
||||
self.result = result
|
||||
self._result = result
|
||||
# the parameters: instances of Type
|
||||
self.parameters = params
|
||||
self._parameters = params
|
||||
|
||||
|
||||
def PointerDeclaration(self):
|
||||
'returns a declaration of a pointer to this function'
|
||||
result = self.result.FullName()
|
||||
params = ', '.join([x.FullName() for x in self.parameters])
|
||||
return '(%s (*)(%s))&%s' % (result, params, self.FullName())
|
||||
def _PointerDeclaration(self, force=False):
|
||||
'''Returns a declaration of a pointer to this function.
|
||||
@param force: If True, returns a complete pointer declaration regardless
|
||||
if this function is unique or not.
|
||||
'''
|
||||
if self._is_unique and not force:
|
||||
return '&%s' % self._FullName()
|
||||
else:
|
||||
result = self._result._FullName()
|
||||
params = ', '.join([x._FullName() for x in self._parameters])
|
||||
return '(%s (*)(%s))&%s' % (result, params, self._FullName())
|
||||
|
||||
|
||||
def _MinArgs(self):
|
||||
min = 0
|
||||
for arg in self.parameters:
|
||||
if arg.default is None:
|
||||
for arg in self._parameters:
|
||||
if arg._default is None:
|
||||
min += 1
|
||||
return min
|
||||
|
||||
minArgs = property(_MinArgs)
|
||||
_minArgs = property(_MinArgs)
|
||||
|
||||
|
||||
def _MaxArgs(self):
|
||||
return len(self.parameters)
|
||||
return len(self._parameters)
|
||||
|
||||
maxArgs = property(_MaxArgs)
|
||||
_maxArgs = property(_MaxArgs)
|
||||
|
||||
|
||||
def Copy(self):
|
||||
return self.__class__(
|
||||
self.name, self.namespace, self.result, self.params[:])
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Operator
|
||||
#==============================================================================
|
||||
class Operator(Function):
|
||||
'The declaration of a custom operator.'
|
||||
'''The declaration of a custom operator. Its name is the same as the
|
||||
operator name in C++, ie, the name of the declaration "operator+(..)" is
|
||||
"+".
|
||||
'''
|
||||
|
||||
def FullName(self):
|
||||
namespace = self.namespace or ''
|
||||
def _FullName(self):
|
||||
namespace = self._namespace or ''
|
||||
if not namespace.endswith('::'):
|
||||
namespace += '::'
|
||||
return namespace + 'operator' + self.name
|
||||
return namespace + 'operator' + self._name
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Method
|
||||
#==============================================================================
|
||||
class Method(Function):
|
||||
'The declaration of a method.'
|
||||
'''The declaration of a method.
|
||||
|
||||
@ivar _visibility: the visibility of this method.
|
||||
@ivar _virtual: if this method is declared as virtual.
|
||||
@ivar _abstract: if this method is virtual but has no default implementation.
|
||||
@ivar _static: if this method is static.
|
||||
@ivar _class: the full name of the class where this method was declared.
|
||||
@ivar _const: if this method is declared as const.
|
||||
'''
|
||||
|
||||
def __init__(self, name, class_, result, params, visib, virtual, abstract, static, const):
|
||||
Function.__init__(self, name, None, result, params)
|
||||
self.visibility = visib
|
||||
self.virtual = virtual
|
||||
self.abstract = abstract
|
||||
self.static = static
|
||||
self.class_ = class_
|
||||
self.const = const
|
||||
self._visibility = visib
|
||||
self._virtual = virtual
|
||||
self._abstract = abstract
|
||||
self._static = static
|
||||
self._class = class_
|
||||
self._const = const
|
||||
|
||||
|
||||
def FullName(self):
|
||||
return self.class_ + '::' + self.name
|
||||
def _FullName(self):
|
||||
return self._class + '::' + self._name
|
||||
|
||||
|
||||
def PointerDeclaration(self):
|
||||
'returns a declaration of a pointer to this function'
|
||||
if self.static:
|
||||
def _PointerDeclaration(self, force=False):
|
||||
'''Returns a declaration of a pointer to this member function.
|
||||
@param force: If True, returns a complete pointer declaration regardless
|
||||
if this function is unique or not.
|
||||
'''
|
||||
if self._static:
|
||||
# static methods are like normal functions
|
||||
return Function.PointerDeclaration(self)
|
||||
return Function._PointerDeclaration(self, force)
|
||||
if self._is_unique and not force:
|
||||
return '&%s' % self._FullName()
|
||||
else:
|
||||
# using syntax of methods
|
||||
result = self.result.FullName()
|
||||
params = ', '.join([x.FullName() for x in self.parameters])
|
||||
result = self._result._FullName()
|
||||
params = ', '.join([x._FullName() for x in self._parameters])
|
||||
const = ''
|
||||
if self.const:
|
||||
if self._const:
|
||||
const = 'const'
|
||||
return '(%s (%s::*)(%s) %s)&%s' %\
|
||||
(result, self.class_, params, const, self.FullName())
|
||||
(result, self._class, params, const, self._FullName())
|
||||
|
||||
|
||||
def Copy(self):
|
||||
return self.__class__(
|
||||
self.name,
|
||||
self.class_,
|
||||
self.result,
|
||||
self.parameters[:],
|
||||
self.visibility,
|
||||
self.virtual,
|
||||
self.abstract,
|
||||
self.static,
|
||||
self.const)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Constructor
|
||||
#==============================================================================
|
||||
class Constructor(Method):
|
||||
'A constructor of a class.'
|
||||
'''A class' constructor.
|
||||
'''
|
||||
|
||||
def __init__(self, name, class_, params, visib):
|
||||
Method.__init__(self, name, class_, None, params, visib, False, False, False, False)
|
||||
|
||||
|
||||
def IsDefault(self):
|
||||
return len(self.parameters) == 0
|
||||
def _IsDefault(self):
|
||||
'''Returns True if this constructor is a default constructor.
|
||||
'''
|
||||
return len(self._parameters) == 0 and self._visibility == Scope.public
|
||||
|
||||
|
||||
def IsCopy(self):
|
||||
if len(self.parameters) != 1:
|
||||
def _IsCopy(self):
|
||||
'''Returns True if this constructor is a copy constructor.
|
||||
'''
|
||||
if len(self._parameters) != 1:
|
||||
return False
|
||||
param = self.parameters[0]
|
||||
class_as_param = self.parameters[0].name == self.class_
|
||||
param = self._parameters[0]
|
||||
class_as_param = self._parameters[0]._name == self._class
|
||||
param_reference = isinstance(param, ReferenceType)
|
||||
return param_reference and class_as_param and param.const
|
||||
is_public = self._visibility = Scope.public
|
||||
return param_reference and class_as_param and param._const and is_public
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Destructor
|
||||
#==============================================================================
|
||||
class Destructor(Method):
|
||||
'The destructor of a class.'
|
||||
|
||||
def __init__(self, name, class_, visib, virtual):
|
||||
Method.__init__(self, name, class_, None, [], visib, virtual, False, False, False)
|
||||
|
||||
def FullName(self):
|
||||
return self.class_ + '::~' + self.name
|
||||
def _FullName(self):
|
||||
return self._class + '::~' + self._name
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# ClassOperator
|
||||
#==============================================================================
|
||||
class ClassOperator(Method):
|
||||
'The declaration of a custom operator in a class.'
|
||||
'A custom operator in a class.'
|
||||
|
||||
def FullName(self):
|
||||
return self.class_ + '::operator ' + self.name
|
||||
def _FullName(self):
|
||||
return self._class + '::operator ' + self._name
|
||||
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# ConverterOperator
|
||||
#==============================================================================
|
||||
class ConverterOperator(ClassOperator):
|
||||
'An operator in the form "operator OtherClass()".'
|
||||
|
||||
def FullName(self):
|
||||
return self.class_ + '::operator ' + self.result.FullName()
|
||||
def _FullName(self):
|
||||
return self._class + '::operator ' + self._result._FullName()
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Type
|
||||
#==============================================================================
|
||||
class Type(Declaration):
|
||||
'Represents a type.'
|
||||
'''Represents the type of a variable or parameter.
|
||||
@ivar _const: if the type is constant.
|
||||
@ivar _default: if this type has a default value associated with it.
|
||||
@ivar _volatile: if this type was declared with the keyword volatile.
|
||||
@ivar _restricted: if this type was declared with the keyword restricted.
|
||||
@ivar _suffix: Suffix to get the full type name. '*' for pointers, for
|
||||
example.
|
||||
'''
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False):
|
||||
def __init__(self, name, const=False, default=None, suffix=''):
|
||||
Declaration.__init__(self, name, None)
|
||||
# whatever the type is constant or not
|
||||
self.const = const
|
||||
self._const = const
|
||||
# used when the Type is a function argument
|
||||
self.default = default
|
||||
self.volatile = False
|
||||
self.restricted = False
|
||||
self.incomplete = incomplete
|
||||
self._default = default
|
||||
self._volatile = False
|
||||
self._restricted = False
|
||||
self._suffix = suffix
|
||||
|
||||
def __repr__(self):
|
||||
if self.const:
|
||||
@@ -309,166 +390,171 @@ class Type(Declaration):
|
||||
return '<Type ' + const + self.name + '>'
|
||||
|
||||
|
||||
def FullName(self):
|
||||
if self.const:
|
||||
def _FullName(self):
|
||||
if self._const:
|
||||
const = 'const '
|
||||
else:
|
||||
const = ''
|
||||
return const + self.name
|
||||
|
||||
|
||||
def Copy(self):
|
||||
t = self.__class__(self.name, self.const, self.default, self.incomplete)
|
||||
t.volatile = self.volatile
|
||||
t.restricted = self.restricted
|
||||
return t
|
||||
return const + self._name + self._suffix
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# ArrayType
|
||||
#==============================================================================
|
||||
class ArrayType(Type):
|
||||
'Represents an array.'
|
||||
'''Represents an array.
|
||||
@ivar min: the lower bound of the array, usually 0. Can be None.
|
||||
@ivar max: the upper bound of the array. Can be None.
|
||||
'''
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False):
|
||||
def __init__(self, name, const, min, max):
|
||||
'min and max can be None.'
|
||||
Type.__init__(self, name, const)
|
||||
self.min = None
|
||||
self.max = None
|
||||
|
||||
def Copy(self):
|
||||
t = Type.Copy(self)
|
||||
t.min = self.min
|
||||
t.max = self.max
|
||||
return t
|
||||
self.min = min
|
||||
self.max = max
|
||||
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# ReferenceType
|
||||
#==============================================================================
|
||||
class ReferenceType(Type):
|
||||
'A reference type.'
|
||||
'''A reference type.'''
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False, expandRef=True):
|
||||
Type.__init__(self, name, const, default, incomplete)
|
||||
self.expand = expandRef
|
||||
def __init__(self, name, const=False, default=None, expandRef=True, suffix=''):
|
||||
Type.__init__(self, name, const, default)
|
||||
if expandRef:
|
||||
self._suffix = suffix + '&'
|
||||
|
||||
|
||||
def FullName(self):
|
||||
'expand is False for function pointers'
|
||||
expand = ' &'
|
||||
if not self.expand:
|
||||
expand = ''
|
||||
return Type.FullName(self) + expand
|
||||
|
||||
|
||||
def Copy(self):
|
||||
t = Type.Copy(self)
|
||||
t.expand = self.expand
|
||||
return t
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# PointerType
|
||||
#==============================================================================
|
||||
class PointerType(Type):
|
||||
'A pointer type.'
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False, expandPointer=False):
|
||||
Type.__init__(self, name, const, default, incomplete)
|
||||
self.expand = expandPointer
|
||||
|
||||
|
||||
def FullName(self):
|
||||
'expand is False for function pointer'
|
||||
expand = ' *'
|
||||
if not self.expand:
|
||||
expand = ''
|
||||
return Type.FullName(self) + expand
|
||||
|
||||
def Copy(self):
|
||||
t = Type.Copy(self)
|
||||
t.expand = self.expand
|
||||
return t
|
||||
def __init__(self, name, const=False, default=None, expandPointer=False, suffix=''):
|
||||
Type.__init__(self, name, const, default)
|
||||
if expandPointer:
|
||||
self._suffix = suffix + '*'
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# FundamentalType
|
||||
#==============================================================================
|
||||
class FundamentalType(Type):
|
||||
'One of the fundamental types (int, void...).'
|
||||
'One of the fundamental types, like int, void, etc.'
|
||||
|
||||
def __init__(self, name, const=False, default=None, incomplete=False):
|
||||
Type.__init__(self, name, const, default, incomplete)
|
||||
def __init__(self, name, const=False, default=None):
|
||||
Type.__init__(self, name, const, default)
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# FunctionType
|
||||
#==============================================================================
|
||||
class FunctionType(Type):
|
||||
'A pointer to a function.'
|
||||
'''A pointer to a function.
|
||||
@ivar _result: the return value
|
||||
@ivar _parameters: a list of Types, indicating the parameters of the function.
|
||||
@ivar _name: the name of the function.
|
||||
'''
|
||||
|
||||
def __init__(self, result, parameters):
|
||||
Type.__init__(self, '', False)
|
||||
self.result = result
|
||||
self.parameters = parameters
|
||||
self.name = self.FullName()
|
||||
self._result = result
|
||||
self._parameters = parameters
|
||||
self._name = self._FullName()
|
||||
|
||||
|
||||
def FullName(self):
|
||||
full = '%s (*)' % self.result.FullName()
|
||||
params = [x.FullName() for x in self.parameters]
|
||||
def _FullName(self):
|
||||
full = '%s (*)' % self._result._FullName()
|
||||
params = [x._FullName() for x in self._parameters]
|
||||
full += '(%s)' % ', '.join(params)
|
||||
return full
|
||||
|
||||
|
||||
def Copy(self):
|
||||
return FunctionType(self.result, self.parameters[:])
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# MethodType
|
||||
#==============================================================================
|
||||
class MethodType(FunctionType):
|
||||
'A pointer to a member function of a class.'
|
||||
'''A pointer to a member function of a class.
|
||||
@ivar _class: The fullname of the class that the method belongs to.
|
||||
'''
|
||||
|
||||
def __init__(self, result, parameters, class_):
|
||||
Type.__init__(self, '', False)
|
||||
self.result = result
|
||||
self.parameters = parameters
|
||||
self.class_ = class_
|
||||
self.name = self.FullName()
|
||||
self._class = class_
|
||||
FunctionType.__init__(self, result, parameters)
|
||||
|
||||
def FullName(self):
|
||||
full = '%s (%s::*)' % (self.result.FullName(), self.class_)
|
||||
params = [x.FullName() for x in self.parameters]
|
||||
|
||||
def _FullName(self):
|
||||
full = '%s (%s::*)' % (self._result._FullName(), self._class)
|
||||
params = [x._FullName() for x in self._parameters]
|
||||
full += '(%s)' % ', '.join(params)
|
||||
return full
|
||||
|
||||
def Copy(self):
|
||||
return MethodType(self.result, self.parameters[:], self.class_)
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Variable
|
||||
#==============================================================================
|
||||
class Variable(Declaration):
|
||||
'Represents a global variable.'
|
||||
'''Represents a global variable.
|
||||
|
||||
@type _type: L{Type}
|
||||
@ivar _type: The type of the variable.
|
||||
'''
|
||||
|
||||
def __init__(self, type, name, namespace):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
# instance of Type
|
||||
self.type = type
|
||||
|
||||
self._type = type
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# ClassVariable
|
||||
#==============================================================================
|
||||
class ClassVariable(Variable):
|
||||
'Represents a class variable.'
|
||||
'''Represents a class variable.
|
||||
|
||||
@type _visibility: L{Scope}
|
||||
@ivar _visibility: The visibility of this variable within the class.
|
||||
|
||||
@type _static: bool
|
||||
@ivar _static: Indicates if the variable is static.
|
||||
|
||||
@ivar _class: Full name of the class that this variable belongs to.
|
||||
'''
|
||||
|
||||
def __init__(self, type, name, class_, visib, static):
|
||||
Variable.__init__(self, type, name, None)
|
||||
self.visibility = visib
|
||||
self.static = static
|
||||
self.class_ = class_
|
||||
self._visibility = visib
|
||||
self._static = static
|
||||
self._class = class_
|
||||
|
||||
|
||||
def FullName(self):
|
||||
return self.class_ + '::' + self.name
|
||||
def _FullName(self):
|
||||
return self._class + '::' + self._name
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Enumeration
|
||||
#==============================================================================
|
||||
class Enumeration(Declaration):
|
||||
'''Represents an enum.
|
||||
|
||||
@type _values: dict of str => int
|
||||
@ivar _values: holds the values for this enum.
|
||||
'''
|
||||
|
||||
def __init__(self, name, namespace):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
self.values = {} # dict of str => int
|
||||
self._values = {} # dict of str => int
|
||||
|
||||
def ValueFullName(self, name):
|
||||
assert name in self.values
|
||||
namespace = self.namespace
|
||||
|
||||
def _ValueFullName(self, name):
|
||||
'''Returns the full name for a value in the enum.
|
||||
'''
|
||||
assert name in self._values
|
||||
namespace = self._namespace
|
||||
if namespace:
|
||||
namespace += '::'
|
||||
return namespace + name
|
||||
@@ -476,45 +562,52 @@ class Enumeration(Declaration):
|
||||
|
||||
|
||||
class ClassEnumeration(Enumeration):
|
||||
'''Represents an enum inside a class.
|
||||
|
||||
@ivar _class: The full name of the class where this enum belongs.
|
||||
@ivar _visibility: The visibility of this enum inside his class.
|
||||
'''
|
||||
|
||||
def __init__(self, name, class_, visib):
|
||||
Enumeration.__init__(self, name, None)
|
||||
self.class_ = class_
|
||||
self.visibility = visib
|
||||
self._class = class_
|
||||
self._visibility = visib
|
||||
|
||||
|
||||
def FullName(self):
|
||||
return '%s::%s' % (self.class_, self.name)
|
||||
def _FullName(self):
|
||||
return '%s::%s' % (self._class, self._name)
|
||||
|
||||
|
||||
def ValueFullName(self, name):
|
||||
assert name in self.values
|
||||
return '%s::%s' % (self.class_, name)
|
||||
def _ValueFullName(self, name):
|
||||
assert name in self._values
|
||||
return '%s::%s' % (self._class, name)
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Typedef
|
||||
#==============================================================================
|
||||
class Typedef(Declaration):
|
||||
'''A Typedef declaration.
|
||||
|
||||
@type _type: L{Type}
|
||||
@ivar _type: The type of the typedef.
|
||||
|
||||
@type _visibility: L{Scope}
|
||||
@ivar _visibility: The visibility of this typedef.
|
||||
'''
|
||||
|
||||
def __init__(self, type, name, namespace):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
self.type = type
|
||||
self.visibility = Scope.public
|
||||
self._type = type
|
||||
self._visibility = Scope.public
|
||||
|
||||
|
||||
class Union(Declaration):
|
||||
'Shallow declaration, because Unions are not supported yet'
|
||||
def __init__(self, name, namespace):
|
||||
Declaration.__init__(self, name, namespace)
|
||||
|
||||
|
||||
class ClassUnion(Union):
|
||||
|
||||
def __init__(self, name, class_, visib):
|
||||
Union.__init__(self, name, None)
|
||||
self.class_ = class_
|
||||
self.visibility = visib
|
||||
|
||||
def FullName(self):
|
||||
return '%s::%s' % (self.class_, self.name)
|
||||
|
||||
#==============================================================================
|
||||
# Unknown
|
||||
#==============================================================================
|
||||
class Unknown(Declaration):
|
||||
'''A declaration that Pyste does not know how to handle.
|
||||
'''
|
||||
|
||||
def __init__(self, name):
|
||||
Declaration.__init__(self, name, None)
|
||||
|
||||
@@ -41,17 +41,17 @@ def HandlePolicy(function, policy):
|
||||
|
||||
def IsString(type):
|
||||
'Return True if the Type instance can be considered a string'
|
||||
return type.const and type.name == 'char' and isinstance(type, PointerType)
|
||||
return type._FullName() == 'const char*'
|
||||
|
||||
def IsPyObject(type):
|
||||
return type.FullName() == '_object *' # internal name of PyObject
|
||||
return type._FullName() == '_object *' # internal name of PyObject
|
||||
|
||||
result = function.result
|
||||
result = function._result
|
||||
# if the function returns const char*, a policy is not needed
|
||||
if IsString(result) or IsPyObject(result):
|
||||
return policy
|
||||
# if returns a const T&, set the default policy
|
||||
if policy is None and result.const and isinstance(result, ReferenceType):
|
||||
if policy is None and result._const and isinstance(result, ReferenceType):
|
||||
policy = return_value_policy(copy_const_reference)
|
||||
# basic test if the result type demands a policy
|
||||
needs_policy = isinstance(result, (ReferenceType, PointerType))
|
||||
@@ -59,7 +59,7 @@ def HandlePolicy(function, policy):
|
||||
if needs_policy and policy is None:
|
||||
global _printed_warnings
|
||||
warning = '---> Error: %s returns a pointer or a reference, ' \
|
||||
'but no policy was specified.' % function.FullName()
|
||||
'but no policy was specified.' % function._FullName()
|
||||
if warning not in _printed_warnings:
|
||||
print warning
|
||||
print
|
||||
@@ -69,23 +69,4 @@ def HandlePolicy(function, policy):
|
||||
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# WarnForwardDeclarations
|
||||
#==============================================================================
|
||||
def WarnForwardDeclarations(function):
|
||||
'''Checks if any of the parameters or the result of the function are
|
||||
incomplete types.'''
|
||||
|
||||
types = [function.result] + function.parameters
|
||||
types = [x for x in types if x]
|
||||
for type in types:
|
||||
if type.incomplete:
|
||||
msg = '---> Error: %s is forward declared. Please include the ' \
|
||||
'appropriate header with its definition' % type.name
|
||||
# disable this for now... it was reporting too many false
|
||||
# forward declarations to be useful
|
||||
if 0 and msg not in _printed_warnings:
|
||||
print msg
|
||||
print
|
||||
_printed_warnings[msg] = 1
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ from policies import *
|
||||
from CppParser import CppParser, CppParserError
|
||||
import time
|
||||
|
||||
__VERSION__ = '0.9.5'
|
||||
__VERSION__ = '0.9.6'
|
||||
|
||||
def RecursiveIncludes(include):
|
||||
'Return a list containg the include dir and all its subdirectories'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import generators
|
||||
import string
|
||||
import sys
|
||||
|
||||
#==============================================================================
|
||||
# enumerate
|
||||
@@ -45,3 +46,24 @@ def remove_duplicated_lines(text):
|
||||
def left_equals(s):
|
||||
s = '// %s ' % s
|
||||
return s + ('='*(80-len(s))) + '\n'
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# post_mortem
|
||||
#==============================================================================
|
||||
def post_mortem():
|
||||
|
||||
def info(type, value, tb):
|
||||
if hasattr(sys, 'ps1') or not sys.stderr.isatty():
|
||||
# we are in interactive mode or we don't have a tty-like
|
||||
# device, so we call the default hook
|
||||
sys.__excepthook__(type, value, tb)
|
||||
else:
|
||||
import traceback, pdb
|
||||
# we are NOT in interactive mode, print the exception...
|
||||
traceback.print_exception(type, value, tb)
|
||||
print
|
||||
# ...then start the debugger in post-mortem mode.
|
||||
pdb.pm()
|
||||
|
||||
sys.excepthook = info
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import sys
|
||||
sys.path.append('..')
|
||||
sys.path.append('../src')
|
||||
import unittest
|
||||
import tempfile
|
||||
import os.path
|
||||
@@ -11,36 +11,36 @@ class Tester(unittest.TestCase):
|
||||
|
||||
def TestConstructor(self, class_, method, visib):
|
||||
self.assert_(isinstance(method, Constructor))
|
||||
self.assertEqual(method.FullName(), class_.FullName() + '::' + method.name)
|
||||
self.assertEqual(method.result, None)
|
||||
self.assertEqual(method.visibility, visib)
|
||||
self.assert_(not method.virtual)
|
||||
self.assert_(not method.abstract)
|
||||
self.assert_(not method.static)
|
||||
self.assertEqual(method._FullName(), class_._FullName() + '::' + method._name)
|
||||
self.assertEqual(method._result, None)
|
||||
self.assertEqual(method._visibility, visib)
|
||||
self.assert_(not method._virtual)
|
||||
self.assert_(not method._abstract)
|
||||
self.assert_(not method._static)
|
||||
|
||||
def TestDefaultConstructor(self, class_, method, visib):
|
||||
self.TestConstructor(class_, method, visib)
|
||||
self.assert_(method.IsDefault())
|
||||
self.assert_(method._IsDefault())
|
||||
|
||||
def TestCopyConstructor(self, class_, method, visib):
|
||||
self.TestConstructor(class_, method, visib)
|
||||
self.assertEqual(len(method.parameters), 1)
|
||||
param = method.parameters[0]
|
||||
self.assertEqual(len(method._parameters), 1)
|
||||
param = method._parameters[0]
|
||||
self.TestType(
|
||||
param,
|
||||
ReferenceType,
|
||||
class_.FullName(),
|
||||
'const %s &' % class_.FullName(),
|
||||
class_._FullName(),
|
||||
'const %s&' % class_._FullName(),
|
||||
True)
|
||||
self.assert_(method.IsCopy())
|
||||
self.assert_(method._IsCopy())
|
||||
|
||||
|
||||
def TestType(self, type_, classtype_, name, fullname, const):
|
||||
self.assert_(isinstance(type_, classtype_))
|
||||
self.assertEqual(type_.name, name)
|
||||
self.assertEqual(type_.namespace, None)
|
||||
self.assertEqual(type_.FullName(), fullname)
|
||||
self.assertEqual(type_.const, const)
|
||||
self.assertEqual(type_._name, name)
|
||||
self.assertEqual(type_._namespace, None)
|
||||
self.assertEqual(type_._FullName(), fullname)
|
||||
self.assertEqual(type_._const, const)
|
||||
|
||||
|
||||
class ClassBaseTest(Tester):
|
||||
@@ -51,49 +51,48 @@ class ClassBaseTest(Tester):
|
||||
def testClass(self):
|
||||
'test the properties of the class Base'
|
||||
self.assert_(isinstance(self.base, Class))
|
||||
self.assert_(self.base.abstract)
|
||||
self.assertEqual(self.base.RawName(), 'Base')
|
||||
self.assert_(self.base._abstract)
|
||||
|
||||
|
||||
def testFoo(self):
|
||||
'test function foo in class Base'
|
||||
foo = GetMember(self.base, 'foo')
|
||||
self.assert_(isinstance(foo, Method))
|
||||
self.assertEqual(foo.visibility, Scope.public)
|
||||
self.assert_(foo.virtual)
|
||||
self.assert_(foo.abstract)
|
||||
self.failIf(foo.static)
|
||||
self.assertEqual(foo.class_, 'test::Base')
|
||||
self.failIf(foo.const)
|
||||
self.assertEqual(foo.FullName(), 'test::Base::foo')
|
||||
self.assertEqual(foo.result.name, 'void')
|
||||
self.assertEqual(len(foo.parameters), 1)
|
||||
param = foo.parameters[0]
|
||||
self.assertEqual(foo._visibility, Scope.public)
|
||||
self.assert_(foo._virtual)
|
||||
self.assert_(foo._abstract)
|
||||
self.failIf(foo._static)
|
||||
self.assertEqual(foo._class, 'test::Base')
|
||||
self.failIf(foo._const)
|
||||
self.assertEqual(foo._FullName(), 'test::Base::foo')
|
||||
self.assertEqual(foo._result._name, 'void')
|
||||
self.assertEqual(len(foo._parameters), 1)
|
||||
param = foo._parameters[0]
|
||||
self.TestType(param, FundamentalType, 'int', 'int', False)
|
||||
self.assertEqual(foo.namespace, None)
|
||||
self.assertEqual(foo._namespace, None)
|
||||
self.assertEqual(
|
||||
foo.PointerDeclaration(), '(void (test::Base::*)(int) )&test::Base::foo')
|
||||
foo._PointerDeclaration(1), '(void (test::Base::*)(int) )&test::Base::foo')
|
||||
|
||||
def testX(self):
|
||||
'test the member x in class Base'
|
||||
x = GetMember(self.base, 'x')
|
||||
self.assertEqual(x.class_, 'test::Base')
|
||||
self.assertEqual(x.FullName(), 'test::Base::x')
|
||||
self.assertEqual(x.namespace, None)
|
||||
self.assertEqual(x.visibility, Scope.private)
|
||||
self.TestType(x.type, FundamentalType, 'int', 'int', False)
|
||||
self.assertEqual(x.static, False)
|
||||
self.assertEqual(x._class, 'test::Base')
|
||||
self.assertEqual(x._FullName(), 'test::Base::x')
|
||||
self.assertEqual(x._namespace, None)
|
||||
self.assertEqual(x._visibility, Scope.private)
|
||||
self.TestType(x._type, FundamentalType, 'int', 'int', False)
|
||||
self.assertEqual(x._static, False)
|
||||
|
||||
def testConstructors(self):
|
||||
'test constructors in class Base'
|
||||
constructors = GetMembers(self.base, 'Base')
|
||||
for cons in constructors:
|
||||
if len(cons.parameters) == 0:
|
||||
if len(cons._parameters) == 0:
|
||||
self.TestDefaultConstructor(self.base, cons, Scope.public)
|
||||
elif len(cons.parameters) == 1: # copy constructor
|
||||
elif len(cons._parameters) == 1: # copy constructor
|
||||
self.TestCopyConstructor(self.base, cons, Scope.public)
|
||||
elif len(cons.parameters) == 2: # other constructor
|
||||
intp, floatp = cons.parameters
|
||||
elif len(cons._parameters) == 2: # other constructor
|
||||
intp, floatp = cons._parameters
|
||||
self.TestType(intp, FundamentalType, 'int', 'int', False)
|
||||
self.TestType(floatp, FundamentalType, 'float', 'float', False)
|
||||
|
||||
@@ -101,25 +100,25 @@ class ClassBaseTest(Tester):
|
||||
'test function simple in class Base'
|
||||
simple = GetMember(self.base, 'simple')
|
||||
self.assert_(isinstance(simple, Method))
|
||||
self.assertEqual(simple.visibility, Scope.protected)
|
||||
self.assertEqual(simple.FullName(), 'test::Base::simple')
|
||||
self.assertEqual(len(simple.parameters), 1)
|
||||
param = simple.parameters[0]
|
||||
self.TestType(param, ReferenceType, 'std::string', 'const std::string &', True)
|
||||
self.TestType(simple.result, FundamentalType, 'bool', 'bool', False)
|
||||
self.assertEqual(simple._visibility, Scope.protected)
|
||||
self.assertEqual(simple._FullName(), 'test::Base::simple')
|
||||
self.assertEqual(len(simple._parameters), 1)
|
||||
param = simple._parameters[0]
|
||||
self.TestType(param, ReferenceType, 'std::string', 'const std::string&', True)
|
||||
self.TestType(simple._result, FundamentalType, 'bool', 'bool', False)
|
||||
self.assertEqual(
|
||||
simple.PointerDeclaration(),
|
||||
'(bool (test::Base::*)(const std::string &) )&test::Base::simple')
|
||||
simple._PointerDeclaration(1),
|
||||
'(bool (test::Base::*)(const std::string&) )&test::Base::simple')
|
||||
|
||||
|
||||
def testZ(self):
|
||||
z = GetMember(self.base, 'z')
|
||||
self.assert_(isinstance(z, Variable))
|
||||
self.assertEqual(z.visibility, Scope.public)
|
||||
self.assertEqual(z.FullName(), 'test::Base::z')
|
||||
self.assertEqual(z.type.name, 'int')
|
||||
self.assertEqual(z.type.const, False)
|
||||
self.assert_(z.static)
|
||||
self.assertEqual(z._visibility, Scope.public)
|
||||
self.assertEqual(z._FullName(), 'test::Base::z')
|
||||
self.assertEqual(z._type._name, 'int')
|
||||
self.assertEqual(z._type._const, False)
|
||||
self.assert_(z._static)
|
||||
|
||||
|
||||
class ClassTemplateTest(Tester):
|
||||
@@ -130,19 +129,18 @@ class ClassTemplateTest(Tester):
|
||||
def testClass(self):
|
||||
'test the properties of the Template<int> class'
|
||||
self.assert_(isinstance(self.template, Class))
|
||||
self.assert_(not self.template.abstract)
|
||||
self.assertEqual(self.template.FullName(), 'Template<int>')
|
||||
self.assertEqual(self.template.namespace, '')
|
||||
self.assertEqual(self.template.name, 'Template<int>')
|
||||
self.assertEqual(self.template.RawName(), 'Template')
|
||||
self.assert_(not self.template._abstract)
|
||||
self.assertEqual(self.template._FullName(), 'Template<int>')
|
||||
self.assertEqual(self.template._namespace, '')
|
||||
self.assertEqual(self.template._name, 'Template<int>')
|
||||
|
||||
def testConstructors(self):
|
||||
'test the automatic constructors of the class Template<int>'
|
||||
constructors = GetMembers(self.template, 'Template')
|
||||
for cons in constructors:
|
||||
if len(cons.parameters) == 0:
|
||||
if len(cons._parameters) == 0:
|
||||
self.TestDefaultConstructor(self.template, cons, Scope.public)
|
||||
elif len(cons.parameters) == 1:
|
||||
elif len(cons._parameters) == 1:
|
||||
self.TestCopyConstructor(self.template, cons, Scope.public)
|
||||
|
||||
|
||||
@@ -150,21 +148,21 @@ class ClassTemplateTest(Tester):
|
||||
'test the class variable value'
|
||||
value = GetMember(self.template, 'value')
|
||||
self.assert_(isinstance(value, ClassVariable))
|
||||
self.assert_(value.name, 'value')
|
||||
self.TestType(value.type, FundamentalType, 'int', 'int', False)
|
||||
self.assert_(not value.static)
|
||||
self.assertEqual(value.visibility, Scope.public)
|
||||
self.assertEqual(value.class_, 'Template<int>')
|
||||
self.assertEqual(value.FullName(), 'Template<int>::value')
|
||||
self.assert_(value._name, 'value')
|
||||
self.TestType(value._type, FundamentalType, 'int', 'int', False)
|
||||
self.assert_(not value._static)
|
||||
self.assertEqual(value._visibility, Scope.public)
|
||||
self.assertEqual(value._class, 'Template<int>')
|
||||
self.assertEqual(value._FullName(), 'Template<int>::value')
|
||||
|
||||
def testBase(self):
|
||||
'test the superclasses of Template<int>'
|
||||
bases = self.template.bases
|
||||
bases = self.template._bases
|
||||
self.assertEqual(len(bases), 1)
|
||||
base = bases[0]
|
||||
self.assert_(isinstance(base, Base))
|
||||
self.assertEqual(base.name, 'test::Base')
|
||||
self.assertEqual(base.visibility, Scope.protected)
|
||||
self.assertEqual(base._name, 'test::Base')
|
||||
self.assertEqual(base._visibility, Scope.protected)
|
||||
|
||||
|
||||
|
||||
@@ -176,27 +174,27 @@ class FreeFuncTest(Tester):
|
||||
def testFunc(self):
|
||||
'test attributes of FreeFunc'
|
||||
self.assert_(isinstance(self.func, Function))
|
||||
self.assertEqual(self.func.name, 'FreeFunc')
|
||||
self.assertEqual(self.func.FullName(), 'test::FreeFunc')
|
||||
self.assertEqual(self.func.namespace, 'test')
|
||||
self.assertEqual(self.func._name, 'FreeFunc')
|
||||
self.assertEqual(self.func._FullName(), 'test::FreeFunc')
|
||||
self.assertEqual(self.func._namespace, 'test')
|
||||
self.assertEqual(
|
||||
self.func.PointerDeclaration(),
|
||||
'(const test::Base & (*)(const std::string &, int))&test::FreeFunc')
|
||||
self.func._PointerDeclaration(1),
|
||||
'(const test::Base& (*)(const std::string&, int))&test::FreeFunc')
|
||||
|
||||
|
||||
def testResult(self):
|
||||
'test the return value of FreeFunc'
|
||||
res = self.func.result
|
||||
self.TestType(res, ReferenceType, 'test::Base', 'const test::Base &', True)
|
||||
res = self.func._result
|
||||
self.TestType(res, ReferenceType, 'test::Base', 'const test::Base&', True)
|
||||
|
||||
def testParameters(self):
|
||||
'test the parameters of FreeFunc'
|
||||
self.assertEqual(len(self.func.parameters), 2)
|
||||
strp, intp = self.func.parameters
|
||||
self.TestType(strp, ReferenceType, 'std::string', 'const std::string &', True)
|
||||
self.assertEqual(strp.default, None)
|
||||
self.assertEqual(len(self.func._parameters), 2)
|
||||
strp, intp = self.func._parameters
|
||||
self.TestType(strp, ReferenceType, 'std::string', 'const std::string&', True)
|
||||
self.assertEqual(strp._default, None)
|
||||
self.TestType(intp, FundamentalType, 'int', 'int', False)
|
||||
self.assertEqual(intp.default, '10')
|
||||
self.assertEqual(intp._default, '10')
|
||||
|
||||
|
||||
|
||||
@@ -205,14 +203,14 @@ class testFunctionPointers(Tester):
|
||||
def testMethodPointer(self):
|
||||
'test declaration of a pointer-to-method'
|
||||
meth = GetDecl('MethodTester')
|
||||
param = meth.parameters[0]
|
||||
param = meth._parameters[0]
|
||||
fullname = 'void (test::Base::*)(int)'
|
||||
self.TestType(param, PointerType, fullname, fullname, False)
|
||||
|
||||
def testFunctionPointer(self):
|
||||
'test declaration of a pointer-to-function'
|
||||
func = GetDecl('FunctionTester')
|
||||
param = func.parameters[0]
|
||||
param = func._parameters[0]
|
||||
fullname = 'void (*)(int)'
|
||||
self.TestType(param, PointerType, fullname, fullname, False)
|
||||
|
||||
@@ -297,7 +295,7 @@ declarations = GetDeclarations()
|
||||
def GetDecl(name):
|
||||
'returns one of the top declarations given its name'
|
||||
for decl in declarations:
|
||||
if decl.name == name:
|
||||
if decl._name == name:
|
||||
return decl
|
||||
else:
|
||||
raise RuntimeError, 'Declaration not found: %s' % name
|
||||
@@ -309,7 +307,7 @@ def GetMember(class_, name):
|
||||
res = None
|
||||
multipleFound = False
|
||||
for member in class_:
|
||||
if member.name == name:
|
||||
if member._name == name:
|
||||
if res is not None:
|
||||
multipleFound = True
|
||||
break
|
||||
@@ -317,7 +315,7 @@ def GetMember(class_, name):
|
||||
if res is None or multipleFound:
|
||||
raise RuntimeError, \
|
||||
'No member or more than one member found in class %s: %s' \
|
||||
% (class_.name, name)
|
||||
% (class_._name, name)
|
||||
return res
|
||||
|
||||
|
||||
@@ -325,12 +323,12 @@ def GetMembers(class_, name):
|
||||
'gets the members of the given class by its name'
|
||||
res = []
|
||||
for member in class_:
|
||||
if member.name == name:
|
||||
if member._name == name:
|
||||
res.append(member)
|
||||
if len(res) in (0, 1):
|
||||
raise RuntimeError, \
|
||||
'GetMembers: 0 or 1 members found in class %s: %s' \
|
||||
% (class_.name, name)
|
||||
% (class_._name, name)
|
||||
return res
|
||||
|
||||
|
||||
|
||||
@@ -19,10 +19,12 @@ struct C
|
||||
return x+1;
|
||||
}
|
||||
|
||||
const std::string& name() { return _name; }
|
||||
void set_name(const std::string& name) { _name = name; }
|
||||
std::string _name;
|
||||
const std::string& get_name() { return name; }
|
||||
void set_name(const std::string& name) { this->name = name; }
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
// test data members
|
||||
static int static_value;
|
||||
static const int const_static_value;
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
#define OPERATORS_H
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace operators {
|
||||
|
||||
struct C
|
||||
|
||||
@@ -118,7 +118,7 @@ if __name__ == '__main__':
|
||||
else:
|
||||
module = None
|
||||
try:
|
||||
main('--multiple', module)
|
||||
#main('--multiple', module)
|
||||
main('', module)
|
||||
except RuntimeError, e:
|
||||
print e
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace unions {
|
||||
|
||||
class UnionTest
|
||||
{
|
||||
public:
|
||||
union // unions are not supported for now
|
||||
{
|
||||
int i;
|
||||
short s1;
|
||||
short s2;
|
||||
} mBad;
|
||||
|
||||
int mGood;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
UnionTest = Class('unions::UnionTest', 'unions.h')
|
||||
exclude(UnionTest.mBad)
|
||||
Reference in New Issue
Block a user