emit methods to pxd, change the way template methods are handled
pxd allows template methods, whereas the current scheme instantiates/expands all template methods and add them to the same methods_ container. The new scheme treats them all separately: nontemplated methods in methods_, template methods in templateMethods_, and template methods after instantiation in expandedTemplateMethods_.release/4.3a0
parent
6e96e095f3
commit
40da298f68
|
@ -23,6 +23,7 @@
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/range/adaptor/map.hpp>
|
#include <boost/range/adaptor/map.hpp>
|
||||||
#include <boost/range/algorithm/copy.hpp>
|
#include <boost/range/algorithm/copy.hpp>
|
||||||
|
#include <boost/range/join.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -70,9 +71,13 @@ static void handleException(const out_of_range& oor,
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
const Method& Class::method(Str key) const {
|
const Method& Class::method(Str key) const {
|
||||||
try {
|
try {
|
||||||
return methods_.at(key);
|
if (methods_.find(key) != methods_.end())
|
||||||
|
return methods_.at(key);
|
||||||
|
else
|
||||||
|
return expandedTemplateMethods_.at(key);
|
||||||
} catch (const out_of_range& oor) {
|
} catch (const out_of_range& oor) {
|
||||||
handleException(oor, methods_);
|
handleException(oor, methods_);
|
||||||
|
handleException(oor, expandedTemplateMethods_);
|
||||||
throw runtime_error("Internal error in wrap");
|
throw runtime_error("Internal error in wrap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +161,7 @@ void Class::matlab_proxy(Str toolboxPath, Str wrapperName,
|
||||||
<< " function disp(obj), obj.display; end\n %DISP Calls print on the object\n";
|
<< " function disp(obj), obj.display; end\n %DISP Calls print on the object\n";
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
for(const Methods::value_type& name_m: methods_) {
|
for(const Methods::value_type& name_m: boost::join(methods_, expandedTemplateMethods_)) {
|
||||||
const Method& m = name_m.second;
|
const Method& m = name_m.second;
|
||||||
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabQualName,
|
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabQualName,
|
||||||
matlabUniqueName, wrapperName, typeAttributes, functionNames);
|
matlabUniqueName, wrapperName, typeAttributes, functionNames);
|
||||||
|
@ -339,9 +344,13 @@ void Class::addMethod(bool verbose, bool is_const, Str methodName,
|
||||||
const Template& tmplate) {
|
const Template& tmplate) {
|
||||||
// Check if templated
|
// Check if templated
|
||||||
if (tmplate.valid()) {
|
if (tmplate.valid()) {
|
||||||
// Create method to expand
|
templateMethods_[methodName].addOverload(methodName, argumentList,
|
||||||
// For all values of the template argument, create a new method
|
returnValue, is_const,
|
||||||
|
tmplate.argName(), verbose);
|
||||||
|
// Create method to expand
|
||||||
|
// For all values of the template argument, create a new method
|
||||||
for(const Qualified& instName: tmplate.argValues()) {
|
for(const Qualified& instName: tmplate.argValues()) {
|
||||||
|
|
||||||
const TemplateSubstitution ts(tmplate.argName(), instName, *this);
|
const TemplateSubstitution ts(tmplate.argName(), instName, *this);
|
||||||
// substitute template in arguments
|
// substitute template in arguments
|
||||||
ArgumentList expandedArgs = argumentList.expandTemplate(ts);
|
ArgumentList expandedArgs = argumentList.expandTemplate(ts);
|
||||||
|
@ -350,7 +359,7 @@ void Class::addMethod(bool verbose, bool is_const, Str methodName,
|
||||||
// Now stick in new overload stack with expandedMethodName key
|
// Now stick in new overload stack with expandedMethodName key
|
||||||
// but note we use the same, unexpanded methodName in overload
|
// but note we use the same, unexpanded methodName in overload
|
||||||
string expandedMethodName = methodName + instName.name();
|
string expandedMethodName = methodName + instName.name();
|
||||||
methods_[expandedMethodName].addOverload(methodName, expandedArgs,
|
expandedTemplateMethods_[expandedMethodName].addOverload(methodName, expandedArgs,
|
||||||
expandedRetVal, is_const, instName, verbose);
|
expandedRetVal, is_const, instName, verbose);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -392,10 +401,12 @@ void Class::verifyAll(vector<string>& validTypes, bool& hasSerialiable) const {
|
||||||
//TODO:verifyArguments<ArgumentList>(validTypes, constructor.args_list);
|
//TODO:verifyArguments<ArgumentList>(validTypes, constructor.args_list);
|
||||||
verifyArguments<StaticMethod>(validTypes, static_methods);
|
verifyArguments<StaticMethod>(validTypes, static_methods);
|
||||||
verifyArguments<Method>(validTypes, methods_);
|
verifyArguments<Method>(validTypes, methods_);
|
||||||
|
verifyArguments<Method>(validTypes, expandedTemplateMethods_);
|
||||||
|
|
||||||
// verify function return types
|
// verify function return types
|
||||||
verifyReturnTypes<StaticMethod>(validTypes, static_methods);
|
verifyReturnTypes<StaticMethod>(validTypes, static_methods);
|
||||||
verifyReturnTypes<Method>(validTypes, methods_);
|
verifyReturnTypes<Method>(validTypes, methods_);
|
||||||
|
verifyReturnTypes<Method>(validTypes, expandedTemplateMethods_);
|
||||||
|
|
||||||
// verify parents
|
// verify parents
|
||||||
boost::optional<string> parent = qualifiedParent();
|
boost::optional<string> parent = qualifiedParent();
|
||||||
|
@ -416,6 +427,8 @@ void Class::appendInheritedMethods(const Class& cls,
|
||||||
// We found a parent class for our parent, TODO improve !
|
// We found a parent class for our parent, TODO improve !
|
||||||
if (parent.name() == cls.parentClass->name()) {
|
if (parent.name() == cls.parentClass->name()) {
|
||||||
methods_.insert(parent.methods_.begin(), parent.methods_.end());
|
methods_.insert(parent.methods_.begin(), parent.methods_.end());
|
||||||
|
expandedTemplateMethods_.insert(parent.expandedTemplateMethods_.begin(),
|
||||||
|
parent.expandedTemplateMethods_.end());
|
||||||
appendInheritedMethods(parent, classes);
|
appendInheritedMethods(parent, classes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,9 +456,9 @@ void Class::comment_fragment(FileWriter& proxyFile) const {
|
||||||
|
|
||||||
constructor.comment_fragment(proxyFile);
|
constructor.comment_fragment(proxyFile);
|
||||||
|
|
||||||
if (!methods_.empty())
|
if (!methods_.empty() || !expandedTemplateMethods_.empty())
|
||||||
proxyFile.oss << "%\n%-------Methods-------\n";
|
proxyFile.oss << "%\n%-------Methods-------\n";
|
||||||
for(const Methods::value_type& name_m: methods_)
|
for(const Methods::value_type& name_m: boost::join(methods_, expandedTemplateMethods_))
|
||||||
name_m.second.comment_fragment(proxyFile);
|
name_m.second.comment_fragment(proxyFile);
|
||||||
|
|
||||||
if (!static_methods.empty())
|
if (!static_methods.empty())
|
||||||
|
@ -656,31 +669,52 @@ void Class::python_wrapper(FileWriter& wrapperFile) const {
|
||||||
m.python_wrapper(wrapperFile, name());
|
m.python_wrapper(wrapperFile, name());
|
||||||
for(const Method& m: methods_ | boost::adaptors::map_values)
|
for(const Method& m: methods_ | boost::adaptors::map_values)
|
||||||
m.python_wrapper(wrapperFile, name());
|
m.python_wrapper(wrapperFile, name());
|
||||||
|
for(const Method& m: expandedTemplateMethods_ | boost::adaptors::map_values)
|
||||||
|
m.python_wrapper(wrapperFile, name());
|
||||||
wrapperFile.oss << ";\n\n";
|
wrapperFile.oss << ";\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void Class::cython_wrapper(FileWriter& pxdFile, FileWriter& pyxFile) const {
|
void Class::cython_wrapper(FileWriter& pxdFile, FileWriter& pyxFile) const {
|
||||||
|
string cythonClassName = qualifiedName("_");
|
||||||
pxdFile.oss << "cdef extern from \"" << includeFile << "\" namespace \""
|
pxdFile.oss << "cdef extern from \"" << includeFile << "\" namespace \""
|
||||||
<< qualifiedNamespaces("::") << "\":" << endl;
|
<< qualifiedNamespaces("::") << "\":" << endl;
|
||||||
pxdFile.oss << "\tcdef cppclass " << qualifiedName("_") << " \"" << qualifiedName("::") << "\"";
|
pxdFile.oss << "\tcdef cppclass " << cythonClassName << " \"" << qualifiedName("::") << "\"";
|
||||||
|
if (templateArgs.size()>0) {
|
||||||
|
pxdFile.oss << "[";
|
||||||
|
for(size_t i = 0; i<templateArgs.size(); ++i) {
|
||||||
|
pxdFile.oss << templateArgs[i];
|
||||||
|
if (i<templateArgs.size()-1) pxdFile.oss << ",";
|
||||||
|
}
|
||||||
|
pxdFile.oss << "]";
|
||||||
|
}
|
||||||
if (parentClass) pxdFile.oss << "(" << parentClass->qualifiedName("_") << ")";
|
if (parentClass) pxdFile.oss << "(" << parentClass->qualifiedName("_") << ")";
|
||||||
pxdFile.oss << ":\n";
|
pxdFile.oss << ":\n";
|
||||||
|
|
||||||
pyxFile.oss << "cdef class " << name();
|
pyxFile.oss << "cdef class " << name();
|
||||||
if (parentClass) pyxFile.oss << "(" << parentClass->name() << ")";
|
if (parentClass) pyxFile.oss << "(" << parentClass->name() << ")";
|
||||||
pyxFile.oss << ":\n";
|
pyxFile.oss << ":\n";
|
||||||
pyxFile.oss << "\tcdef shared_ptr[" << qualifiedName("_") << "] "
|
pyxFile.oss << "\tcdef shared_ptr[" << cythonClassName << "] "
|
||||||
<< "gt" << name() << "_\n";
|
<< "gt" << name() << "_\n";
|
||||||
|
|
||||||
constructor.cython_wrapper(pxdFile, pyxFile, qualifiedName("_"));
|
constructor.cython_wrapper(pxdFile, pyxFile, cythonClassName);
|
||||||
|
if (constructor.nrOverloads()>0) pxdFile.oss << "\n";
|
||||||
|
|
||||||
|
for(const StaticMethod& m: static_methods | boost::adaptors::map_values)
|
||||||
|
m.emit_cython_pxd(pxdFile);
|
||||||
|
if (static_methods.size()>0) pxdFile.oss << "\n";
|
||||||
|
|
||||||
|
for(const Method& m: methods_ | boost::adaptors::map_values)
|
||||||
|
m.emit_cython_pxd(pxdFile);
|
||||||
|
for(const TemplateMethod& m: templateMethods_ | boost::adaptors::map_values)
|
||||||
|
m.emit_cython_pxd(pxdFile);
|
||||||
|
size_t numMethods = constructor.nrOverloads() + static_methods.size() +
|
||||||
|
methods_.size() + templateMethods_.size();
|
||||||
|
if (numMethods == 0)
|
||||||
|
pxdFile.oss << "\t\tpass";
|
||||||
|
pxdFile.oss << "\n\n";
|
||||||
|
|
||||||
pxdFile.oss << "\n";
|
|
||||||
pyxFile.oss << "\n";
|
pyxFile.oss << "\n";
|
||||||
// for(const StaticMethod& m: static_methods | boost::adaptors::map_values)
|
|
||||||
// m.cython_wrapper(pxdFile, pyxFile, name());
|
|
||||||
// for(const Method& m: methods_ | boost::adaptors::map_values)
|
|
||||||
// m.cython_wrapper(pxdFile, pyxFile, name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
12
wrap/Class.h
12
wrap/Class.h
|
@ -25,6 +25,7 @@
|
||||||
#include "Deconstructor.h"
|
#include "Deconstructor.h"
|
||||||
#include "Method.h"
|
#include "Method.h"
|
||||||
#include "StaticMethod.h"
|
#include "StaticMethod.h"
|
||||||
|
#include "TemplateMethod.h"
|
||||||
#include "TypeAttributesTable.h"
|
#include "TypeAttributesTable.h"
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
|
@ -54,11 +55,14 @@ public:
|
||||||
typedef const std::string& Str;
|
typedef const std::string& Str;
|
||||||
typedef std::map<std::string, Method> Methods;
|
typedef std::map<std::string, Method> Methods;
|
||||||
typedef std::map<std::string, StaticMethod> StaticMethods;
|
typedef std::map<std::string, StaticMethod> StaticMethods;
|
||||||
|
typedef std::map<std::string, TemplateMethod> TemplateMethods;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::optional<Qualified> parentClass; ///< The *single* parent
|
boost::optional<Qualified> parentClass; ///< The *single* parent
|
||||||
Methods methods_; ///< Class methods
|
Methods methods_; ///< Class methods
|
||||||
|
TemplateMethods templateMethods_;
|
||||||
|
Methods expandedTemplateMethods_;
|
||||||
// Method& mutableMethod(Str key);
|
// Method& mutableMethod(Str key);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -87,13 +91,15 @@ public:
|
||||||
boost::optional<std::string> qualifiedParent() const;
|
boost::optional<std::string> qualifiedParent() const;
|
||||||
|
|
||||||
size_t nrMethods() const {
|
size_t nrMethods() const {
|
||||||
return methods_.size();
|
return methods_.size() + expandedTemplateMethods_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Method& method(Str key) const;
|
const Method& method(Str key) const;
|
||||||
|
|
||||||
bool exists(Str name) const {
|
bool exists(Str name) const {
|
||||||
return methods_.find(name) != methods_.end();
|
return methods_.find(name) != methods_.end() ||
|
||||||
|
expandedTemplateMethods_.find(name) !=
|
||||||
|
expandedTemplateMethods_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
// And finally MATLAB code is emitted, methods below called by Module::matlab_code
|
// And finally MATLAB code is emitted, methods below called by Module::matlab_code
|
||||||
|
@ -152,6 +158,8 @@ public:
|
||||||
os << m << ";\n";
|
os << m << ";\n";
|
||||||
for(const Method& m: cls.methods_ | boost::adaptors::map_values)
|
for(const Method& m: cls.methods_ | boost::adaptors::map_values)
|
||||||
os << m << ";\n";
|
os << m << ";\n";
|
||||||
|
for(const Method& m: cls.expandedTemplateMethods_ | boost::adaptors::map_values)
|
||||||
|
os << m << ";\n";
|
||||||
os << "};" << std::endl;
|
os << "};" << std::endl;
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,3 +76,17 @@ string Method::wrapper_call(FileWriter& wrapperFile, Str cppClassName,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
void Method::emit_cython_pxd(FileWriter& file) const {
|
||||||
|
for(size_t i = 0; i < nrOverloads(); ++i) {
|
||||||
|
file.oss << "\t\t";
|
||||||
|
returnVals_[i].emit_cython_pxd(file);
|
||||||
|
file.oss << name_ << "(";
|
||||||
|
argumentList(i).emit_cython_pxd(file);
|
||||||
|
file.oss << ")";
|
||||||
|
if (is_const_) file.oss << " const";
|
||||||
|
file.oss << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace wrap {
|
||||||
/// Method class
|
/// Method class
|
||||||
class Method: public MethodBase {
|
class Method: public MethodBase {
|
||||||
|
|
||||||
|
protected:
|
||||||
bool is_const_;
|
bool is_const_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -50,6 +51,8 @@ public:
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void emit_cython_pxd(FileWriter& file) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Emit method header
|
// Emit method header
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
||||||
|
* Atlanta, Georgia 30332-0415
|
||||||
|
* All Rights Reserved
|
||||||
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
||||||
|
|
||||||
|
* See LICENSE for the license information
|
||||||
|
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file TemplateMethod.ccp
|
||||||
|
* @author Duy-Nguyen Ta
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "TemplateMethod.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace wrap;
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
void TemplateMethod::emit_cython_pxd(FileWriter& file) const {
|
||||||
|
for(size_t i = 0; i < nrOverloads(); ++i) {
|
||||||
|
file.oss << "\t\t";
|
||||||
|
returnVals_[i].emit_cython_pxd(file);
|
||||||
|
file.oss << name_ << "[" << argName << "]" << "(";
|
||||||
|
argumentList(i).emit_cython_pxd(file);
|
||||||
|
file.oss << ")\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
bool TemplateMethod::addOverload(Str name, const ArgumentList& args,
|
||||||
|
const ReturnValue& retVal, bool is_const,
|
||||||
|
std::string _argName, bool verbose) {
|
||||||
|
argName = _argName;
|
||||||
|
bool first = MethodBase::addOverload(name, args, retVal, boost::none, verbose);
|
||||||
|
if (first)
|
||||||
|
is_const_ = is_const;
|
||||||
|
else if (is_const && !is_const_)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Method::addOverload now designated as const whereas before it was not");
|
||||||
|
else if (!is_const && is_const_)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Method::addOverload now designated as non-const whereas before it was");
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
||||||
|
* Atlanta, Georgia 30332-0415
|
||||||
|
* All Rights Reserved
|
||||||
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
||||||
|
|
||||||
|
* See LICENSE for the license information
|
||||||
|
|
||||||
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file StaticMethod.h
|
||||||
|
* @brief describes and generates code for static methods
|
||||||
|
* @author Duy-Nguyen Ta
|
||||||
|
**/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Method.h"
|
||||||
|
|
||||||
|
namespace wrap {
|
||||||
|
|
||||||
|
/// StaticMethod class
|
||||||
|
struct TemplateMethod: public Method {
|
||||||
|
std::string argName; // name of template argument
|
||||||
|
|
||||||
|
bool addOverload(Str name, const ArgumentList& args,
|
||||||
|
const ReturnValue& retVal, bool is_const,
|
||||||
|
std::string argName, bool verbose = false);
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const TemplateMethod& m) {
|
||||||
|
for (size_t i = 0; i < m.nrOverloads(); i++)
|
||||||
|
os << "template <" << m.argName << "> " << m.returnVals_[i] << " " << m.name_ << m.argLists_[i];
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit_cython_pxd(FileWriter& file) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // \namespace wrap
|
||||||
|
|
Loading…
Reference in New Issue