| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |  * GTSAM Copyright 2010, Georgia Tech Research Corporation, | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  |  * 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2011-10-14 11:23:14 +08:00
										 |  |  |  * @file Method.ccp | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							| 
									
										
										
										
											2012-07-13 06:28:28 +08:00
										 |  |  |  * @author Richard Roberts | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  |  **/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-26 01:22:10 +08:00
										 |  |  | #include "Method.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-10 06:37:48 +08:00
										 |  |  | #include "Class.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-26 01:22:10 +08:00
										 |  |  | #include "utilities.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-05 22:04:36 +08:00
										 |  |  | #include <boost/lexical_cast.hpp>
 | 
					
						
							| 
									
										
										
										
											2014-05-26 01:22:10 +08:00
										 |  |  | #include <boost/algorithm/string.hpp>
 | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-26 01:22:10 +08:00
										 |  |  | #include <iostream>
 | 
					
						
							|  |  |  | #include <fstream>
 | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							| 
									
										
										
										
											2011-12-03 00:43:15 +08:00
										 |  |  | using namespace wrap; | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-14 05:11:23 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2016-09-14 19:45:26 +08:00
										 |  |  | /// Cython: Rename functions which names are python keywords
 | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  | static const std::array<std::string, 2> pythonKeywords{{"print", "lambda"}}; | 
					
						
							| 
									
										
										
										
											2016-09-14 05:11:23 +08:00
										 |  |  | static std::string pyRename(const std::string& name) { | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |   if (std::find(pythonKeywords.begin(), pythonKeywords.end(), name) == | 
					
						
							|  |  |  |       pythonKeywords.end()) | 
					
						
							|  |  |  |     return name; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return name + "_"; | 
					
						
							| 
									
										
										
										
											2016-09-14 05:11:23 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2014-11-14 23:43:53 +08:00
										 |  |  | bool Method::addOverload(Str name, const ArgumentList& args, | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |                          const ReturnValue& retVal, bool is_const, | 
					
						
							|  |  |  |                          boost::optional<const Qualified> instName, | 
					
						
							|  |  |  |                          bool verbose) { | 
					
						
							| 
									
										
										
										
											2014-11-29 22:31:29 +08:00
										 |  |  |   bool first = MethodBase::addOverload(name, args, retVal, instName, verbose); | 
					
						
							| 
									
										
										
										
											2014-11-14 23:43:53 +08:00
										 |  |  |   if (first) | 
					
						
							|  |  |  |     is_const_ = is_const; | 
					
						
							|  |  |  |   else if (is_const && !is_const_) | 
					
						
							|  |  |  |     throw std::runtime_error( | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |         "Method::addOverload now designated as const whereas before it was " | 
					
						
							|  |  |  |         "not"); | 
					
						
							| 
									
										
										
										
											2014-11-14 23:43:53 +08:00
										 |  |  |   else if (!is_const && is_const_) | 
					
						
							|  |  |  |     throw std::runtime_error( | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |         "Method::addOverload now designated as non-const whereas before it " | 
					
						
							|  |  |  |         "was"); | 
					
						
							| 
									
										
										
										
											2014-11-14 23:43:53 +08:00
										 |  |  |   return first; | 
					
						
							| 
									
										
										
										
											2012-07-05 22:05:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-28 03:03:19 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2014-11-14 00:28:05 +08:00
										 |  |  | void Method::proxy_header(FileWriter& proxyFile) const { | 
					
						
							| 
									
										
										
										
											2014-11-14 23:43:53 +08:00
										 |  |  |   proxyFile.oss << "    function varargout = " << matlabName() | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |                 << "(this, varargin)\n"; | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2014-11-14 00:34:33 +08:00
										 |  |  | string Method::wrapper_call(FileWriter& wrapperFile, Str cppClassName, | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |                             Str matlabUniqueName, | 
					
						
							|  |  |  |                             const ArgumentList& args) const { | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  |   // check arguments
 | 
					
						
							|  |  |  |   // extra argument obj -> nargin-1 is passed !
 | 
					
						
							|  |  |  |   // example: checkArguments("equals",nargout,nargin-1,2);
 | 
					
						
							| 
									
										
										
										
											2014-11-30 02:34:46 +08:00
										 |  |  |   wrapperFile.oss << "  checkArguments(\"" << matlabName() | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |                   << "\",nargout,nargin-1," << args.size() << ");\n"; | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // get class pointer
 | 
					
						
							|  |  |  |   // example: shared_ptr<Test> = unwrap_shared_ptr< Test >(in[0], "Test");
 | 
					
						
							| 
									
										
										
										
											2014-11-13 03:51:47 +08:00
										 |  |  |   wrapperFile.oss << "  Shared obj = unwrap_shared_ptr<" << cppClassName | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |                   << ">(in[0], \"ptr_" << matlabUniqueName << "\");" << endl; | 
					
						
							| 
									
										
										
										
											2014-11-14 00:28:05 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // unwrap arguments, see Argument.cpp, we start at 1 as first is obj
 | 
					
						
							| 
									
										
										
										
											2014-11-13 03:51:47 +08:00
										 |  |  |   args.matlab_unwrap(wrapperFile, 1); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-10 04:19:37 +08:00
										 |  |  |   // call method and wrap result
 | 
					
						
							| 
									
										
										
										
											2014-11-14 00:28:05 +08:00
										 |  |  |   // example: out[0]=wrap<bool>(obj->return_field(t));
 | 
					
						
							| 
									
										
										
										
											2014-11-13 19:52:41 +08:00
										 |  |  |   string expanded = "obj->" + name_; | 
					
						
							| 
									
										
										
										
											2014-11-30 17:38:24 +08:00
										 |  |  |   if (templateArgValue_) | 
					
						
							|  |  |  |     expanded += ("<" + templateArgValue_->qualifiedName("::") + ">"); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-14 00:28:05 +08:00
										 |  |  |   return expanded; | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2016-09-12 06:14:19 +08:00
										 |  |  | void Method::emit_cython_pxd(FileWriter& file, const Class& cls) const { | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |   for (size_t i = 0; i < nrOverloads(); ++i) { | 
					
						
							| 
									
										
										
										
											2016-09-09 19:26:11 +08:00
										 |  |  |     file.oss << "\t\t"; | 
					
						
							| 
									
										
										
										
											2016-11-23 01:13:33 +08:00
										 |  |  |     returnVals_[i].emit_cython_pxd(file, cls.pxdClassName()); | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |     file.oss << pyRename(name_) + " \"" + name_ + "\"" | 
					
						
							|  |  |  |              << "("; | 
					
						
							| 
									
										
										
										
											2016-11-23 01:13:33 +08:00
										 |  |  |     argumentList(i).emit_cython_pxd(file, cls.pxdClassName()); | 
					
						
							| 
									
										
										
										
											2016-09-09 19:26:11 +08:00
										 |  |  |     file.oss << ")"; | 
					
						
							|  |  |  |     if (is_const_) file.oss << " const"; | 
					
						
							|  |  |  |     file.oss << "\n"; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  | void Method::emit_cython_pyx_no_overload(FileWriter& file, | 
					
						
							|  |  |  |                                          const Class& cls) const { | 
					
						
							| 
									
										
										
										
											2016-09-14 05:11:23 +08:00
										 |  |  |   string funcName = pyRename(name_); | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |   // leverage python's special treatment for print
 | 
					
						
							| 
									
										
										
										
											2016-11-17 06:37:33 +08:00
										 |  |  |   if (funcName == "print_") | 
					
						
							|  |  |  |     file.oss << "\tdef __str__(self):\n\t\tself.print_('')\n\t\treturn ''\n"; | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Function definition
 | 
					
						
							|  |  |  |   file.oss << "\tdef " << funcName; | 
					
						
							|  |  |  |   // modify name of function instantiation as python doesn't allow overloads
 | 
					
						
							|  |  |  |   // e.g. template<T={A,B,C}> funcName(...) --> funcNameA, funcNameB, funcNameC
 | 
					
						
							|  |  |  |   if (templateArgValue_) file.oss << templateArgValue_->name(); | 
					
						
							|  |  |  |   // funtion arguments
 | 
					
						
							|  |  |  |   file.oss << "(self"; | 
					
						
							|  |  |  |   if (argumentList(0).size() > 0) file.oss << ", "; | 
					
						
							|  |  |  |   argumentList(0).emit_cython_pyx(file); | 
					
						
							|  |  |  |   file.oss << "):\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /// Call cython corresponding function and return
 | 
					
						
							| 
									
										
										
										
											2016-11-23 01:13:33 +08:00
										 |  |  |   string caller = "self." + cls.shared_pxd_obj_in_pyx() + ".get()"; | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |   string ret = pyx_functionCall(caller, funcName, 0); | 
					
						
							|  |  |  |   if (!returnVals_[0].isVoid()) { | 
					
						
							|  |  |  |     file.oss << "\t\tcdef " << returnVals_[0].pyx_returnType() | 
					
						
							|  |  |  |              << " ret = " << ret << "\n"; | 
					
						
							|  |  |  |     file.oss << "\t\treturn " << returnVals_[0].pyx_casting("ret") << "\n"; | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     file.oss << "\t\t" << ret << "\n"; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | void Method::emit_cython_pyx(FileWriter& file, const Class& cls) const { | 
					
						
							|  |  |  |   string funcName = pyRename(name_); | 
					
						
							|  |  |  |   // For template function: modify name of function instantiation as python
 | 
					
						
							|  |  |  |   // doesn't allow overloads
 | 
					
						
							|  |  |  |   // e.g. template<T={A,B,C}> funcName(...) --> funcNameA, funcNameB, funcNameC
 | 
					
						
							|  |  |  |   string instantiatedName = | 
					
						
							|  |  |  |       (templateArgValue_) ? funcName + templateArgValue_->name() : funcName; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-10 06:37:48 +08:00
										 |  |  |   size_t N = nrOverloads(); | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |   // It's easy if there's no overload
 | 
					
						
							|  |  |  |   if (N == 1) { | 
					
						
							|  |  |  |     emit_cython_pyx_no_overload(file, cls); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Dealing with overloads..
 | 
					
						
							|  |  |  |   file.oss << "\tdef " << instantiatedName << "(self, *args, **kwargs):\n"; | 
					
						
							|  |  |  |   file.oss << pyx_checkDuplicateNargsKwArgs(); | 
					
						
							|  |  |  |   for (size_t i = 0; i < N; ++i) { | 
					
						
							|  |  |  |     file.oss << "\t\tsuccess, results = self." << instantiatedName << "_" << i | 
					
						
							|  |  |  |              << "(*args, **kwargs)\n"; | 
					
						
							|  |  |  |     file.oss << "\t\tif success:\n\t\t\treturn results\n"; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   file.oss << "\t\traise TypeError('Could not find the correct overload')\n"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (size_t i = 0; i < N; ++i) { | 
					
						
							|  |  |  |     ArgumentList args = argumentList(i); | 
					
						
							|  |  |  |     file.oss << "\tdef " + instantiatedName + "_" + to_string(i) + | 
					
						
							|  |  |  |                     "(self, *args, **kwargs):\n"; | 
					
						
							| 
									
										
										
										
											2016-11-22 06:14:30 +08:00
										 |  |  |     file.oss << pyx_resolveOverloadParams(args, false); // lazy: always return None even if it's a void function
 | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /// Call cython corresponding function
 | 
					
						
							| 
									
										
										
										
											2016-11-23 01:13:33 +08:00
										 |  |  |     string caller = "self." + cls.shared_pxd_obj_in_pyx() + ".get()"; | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     string ret = pyx_functionCall(caller, funcName, i); | 
					
						
							| 
									
										
										
										
											2016-11-22 06:14:30 +08:00
										 |  |  |     if (!returnVals_[i].isVoid()) { | 
					
						
							| 
									
										
										
										
											2016-11-20 22:24:43 +08:00
										 |  |  |       file.oss << "\t\tcdef " << returnVals_[i].pyx_returnType() | 
					
						
							|  |  |  |               << " ret = " << ret << "\n"; | 
					
						
							|  |  |  |       file.oss << "\t\treturn True, " << returnVals_[i].pyx_casting("ret") << "\n"; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       file.oss << "\t\t" << ret << "\n"; | 
					
						
							|  |  |  |       file.oss << "\t\treturn True, None\n"; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-09-10 06:37:48 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | /* ************************************************************************* */ |