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/range/adaptor/map.hpp>
|
||||
#include <boost/range/algorithm/copy.hpp>
|
||||
#include <boost/range/join.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
@ -70,9 +71,13 @@ static void handleException(const out_of_range& oor,
|
|||
/* ************************************************************************* */
|
||||
const Method& Class::method(Str key) const {
|
||||
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) {
|
||||
handleException(oor, methods_);
|
||||
handleException(oor, expandedTemplateMethods_);
|
||||
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";
|
||||
|
||||
// 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;
|
||||
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabQualName,
|
||||
matlabUniqueName, wrapperName, typeAttributes, functionNames);
|
||||
|
@ -339,9 +344,13 @@ void Class::addMethod(bool verbose, bool is_const, Str methodName,
|
|||
const Template& tmplate) {
|
||||
// Check if templated
|
||||
if (tmplate.valid()) {
|
||||
// Create method to expand
|
||||
// For all values of the template argument, create a new method
|
||||
templateMethods_[methodName].addOverload(methodName, argumentList,
|
||||
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()) {
|
||||
|
||||
const TemplateSubstitution ts(tmplate.argName(), instName, *this);
|
||||
// substitute template in arguments
|
||||
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
|
||||
// but note we use the same, unexpanded methodName in overload
|
||||
string expandedMethodName = methodName + instName.name();
|
||||
methods_[expandedMethodName].addOverload(methodName, expandedArgs,
|
||||
expandedTemplateMethods_[expandedMethodName].addOverload(methodName, expandedArgs,
|
||||
expandedRetVal, is_const, instName, verbose);
|
||||
}
|
||||
} else
|
||||
|
@ -392,10 +401,12 @@ void Class::verifyAll(vector<string>& validTypes, bool& hasSerialiable) const {
|
|||
//TODO:verifyArguments<ArgumentList>(validTypes, constructor.args_list);
|
||||
verifyArguments<StaticMethod>(validTypes, static_methods);
|
||||
verifyArguments<Method>(validTypes, methods_);
|
||||
verifyArguments<Method>(validTypes, expandedTemplateMethods_);
|
||||
|
||||
// verify function return types
|
||||
verifyReturnTypes<StaticMethod>(validTypes, static_methods);
|
||||
verifyReturnTypes<Method>(validTypes, methods_);
|
||||
verifyReturnTypes<Method>(validTypes, expandedTemplateMethods_);
|
||||
|
||||
// verify parents
|
||||
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 !
|
||||
if (parent.name() == cls.parentClass->name()) {
|
||||
methods_.insert(parent.methods_.begin(), parent.methods_.end());
|
||||
expandedTemplateMethods_.insert(parent.expandedTemplateMethods_.begin(),
|
||||
parent.expandedTemplateMethods_.end());
|
||||
appendInheritedMethods(parent, classes);
|
||||
}
|
||||
}
|
||||
|
@ -443,9 +456,9 @@ void Class::comment_fragment(FileWriter& proxyFile) const {
|
|||
|
||||
constructor.comment_fragment(proxyFile);
|
||||
|
||||
if (!methods_.empty())
|
||||
if (!methods_.empty() || !expandedTemplateMethods_.empty())
|
||||
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);
|
||||
|
||||
if (!static_methods.empty())
|
||||
|
@ -656,31 +669,52 @@ void Class::python_wrapper(FileWriter& wrapperFile) const {
|
|||
m.python_wrapper(wrapperFile, name());
|
||||
for(const Method& m: methods_ | boost::adaptors::map_values)
|
||||
m.python_wrapper(wrapperFile, name());
|
||||
for(const Method& m: expandedTemplateMethods_ | boost::adaptors::map_values)
|
||||
m.python_wrapper(wrapperFile, name());
|
||||
wrapperFile.oss << ";\n\n";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Class::cython_wrapper(FileWriter& pxdFile, FileWriter& pyxFile) const {
|
||||
string cythonClassName = qualifiedName("_");
|
||||
pxdFile.oss << "cdef extern from \"" << includeFile << "\" namespace \""
|
||||
<< 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("_") << ")";
|
||||
pxdFile.oss << ":\n";
|
||||
|
||||
pyxFile.oss << "cdef class " << name();
|
||||
if (parentClass) pyxFile.oss << "(" << parentClass->name() << ")";
|
||||
pyxFile.oss << ":\n";
|
||||
pyxFile.oss << "\tcdef shared_ptr[" << qualifiedName("_") << "] "
|
||||
pyxFile.oss << "\tcdef shared_ptr[" << cythonClassName << "] "
|
||||
<< "gt" << name() << "_\n";
|
||||
|
||||
constructor.cython_wrapper(pxdFile, pyxFile, qualifiedName("_"));
|
||||
|
||||
pxdFile.oss << "\n";
|
||||
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";
|
||||
|
||||
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 "Method.h"
|
||||
#include "StaticMethod.h"
|
||||
#include "TemplateMethod.h"
|
||||
#include "TypeAttributesTable.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -54,11 +55,14 @@ public:
|
|||
typedef const std::string& Str;
|
||||
typedef std::map<std::string, Method> Methods;
|
||||
typedef std::map<std::string, StaticMethod> StaticMethods;
|
||||
typedef std::map<std::string, TemplateMethod> TemplateMethods;
|
||||
|
||||
private:
|
||||
|
||||
boost::optional<Qualified> parentClass; ///< The *single* parent
|
||||
Methods methods_; ///< Class methods
|
||||
TemplateMethods templateMethods_;
|
||||
Methods expandedTemplateMethods_;
|
||||
// Method& mutableMethod(Str key);
|
||||
|
||||
public:
|
||||
|
@ -87,13 +91,15 @@ public:
|
|||
boost::optional<std::string> qualifiedParent() const;
|
||||
|
||||
size_t nrMethods() const {
|
||||
return methods_.size();
|
||||
return methods_.size() + expandedTemplateMethods_.size();
|
||||
}
|
||||
|
||||
const Method& method(Str key) 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
|
||||
|
@ -152,6 +158,8 @@ public:
|
|||
os << m << ";\n";
|
||||
for(const Method& m: cls.methods_ | boost::adaptors::map_values)
|
||||
os << m << ";\n";
|
||||
for(const Method& m: cls.expandedTemplateMethods_ | boost::adaptors::map_values)
|
||||
os << m << ";\n";
|
||||
os << "};" << std::endl;
|
||||
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
|
||||
class Method: public MethodBase {
|
||||
|
||||
protected:
|
||||
bool is_const_;
|
||||
|
||||
public:
|
||||
|
@ -50,6 +51,8 @@ public:
|
|||
return os;
|
||||
}
|
||||
|
||||
void emit_cython_pxd(FileWriter& file) const;
|
||||
|
||||
private:
|
||||
|
||||
// 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