From 40da298f68445e2e673ab55047096aeabee3ad41 Mon Sep 17 00:00:00 2001 From: Duy-Nguyen Ta Date: Fri, 9 Sep 2016 07:26:11 -0400 Subject: [PATCH] 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_. --- wrap/Class.cpp | 66 +++++++++++++++++++++++++++++++---------- wrap/Class.h | 12 ++++++-- wrap/Method.cpp | 14 +++++++++ wrap/Method.h | 3 ++ wrap/TemplateMethod.cpp | 50 +++++++++++++++++++++++++++++++ wrap/TemplateMethod.h | 43 +++++++++++++++++++++++++++ 6 files changed, 170 insertions(+), 18 deletions(-) create mode 100644 wrap/TemplateMethod.cpp create mode 100644 wrap/TemplateMethod.h diff --git a/wrap/Class.cpp b/wrap/Class.cpp index 5e41dfaf0..6a56338ee 100644 --- a/wrap/Class.cpp +++ b/wrap/Class.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -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& validTypes, bool& hasSerialiable) const { //TODO:verifyArguments(validTypes, constructor.args_list); verifyArguments(validTypes, static_methods); verifyArguments(validTypes, methods_); + verifyArguments(validTypes, expandedTemplateMethods_); // verify function return types verifyReturnTypes(validTypes, static_methods); verifyReturnTypes(validTypes, methods_); + verifyReturnTypes(validTypes, expandedTemplateMethods_); // verify parents boost::optional 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; iqualifiedName("_") << ")"; 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()); } /* ************************************************************************* */ diff --git a/wrap/Class.h b/wrap/Class.h index 2864c7c66..c4a0367ef 100644 --- a/wrap/Class.h +++ b/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 Methods; typedef std::map StaticMethods; + typedef std::map TemplateMethods; private: boost::optional parentClass; ///< The *single* parent Methods methods_; ///< Class methods + TemplateMethods templateMethods_; + Methods expandedTemplateMethods_; // Method& mutableMethod(Str key); public: @@ -87,13 +91,15 @@ public: boost::optional 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; } diff --git a/wrap/Method.cpp b/wrap/Method.cpp index f8c03b0c6..b65200737 100644 --- a/wrap/Method.cpp +++ b/wrap/Method.cpp @@ -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"; + } + +} + +/* ************************************************************************* */ diff --git a/wrap/Method.h b/wrap/Method.h index 33ff7072e..fcceed7a1 100644 --- a/wrap/Method.h +++ b/wrap/Method.h @@ -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 diff --git a/wrap/TemplateMethod.cpp b/wrap/TemplateMethod.cpp new file mode 100644 index 000000000..84c2f3ecc --- /dev/null +++ b/wrap/TemplateMethod.cpp @@ -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; +} + +/* ************************************************************************* */ diff --git a/wrap/TemplateMethod.h b/wrap/TemplateMethod.h new file mode 100644 index 000000000..b1827f2d5 --- /dev/null +++ b/wrap/TemplateMethod.h @@ -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 +