diff --git a/wrap/Argument.cpp b/wrap/Argument.cpp index 689ca6d88..2ee705c5b 100644 --- a/wrap/Argument.cpp +++ b/wrap/Argument.cpp @@ -32,14 +32,14 @@ using namespace wrap; string Argument::matlabClass(const string& delim) const { string result; BOOST_FOREACH(const string& ns, namespaces) - result += ns + delim; - if (type=="string" || type=="unsigned char" || type=="char") + result += ns + delim; + if (type == "string" || type == "unsigned char" || type == "char") return result + "char"; - if (type=="Vector" || type=="Matrix") + if (type == "Vector" || type == "Matrix") return result + "double"; - if (type=="int" || type=="size_t") + if (type == "int" || type == "size_t") return result + "numeric"; - if (type=="bool") + if (type == "bool") return result + "logical"; return result + type; } @@ -53,7 +53,8 @@ void Argument::matlab_unwrap(FileWriter& file, const string& matlabName) const { if (is_ptr) // A pointer: emit an "unwrap_shared_ptr" call which returns a pointer - file.oss << "boost::shared_ptr<" << cppType << "> " << name << " = unwrap_shared_ptr< "; + file.oss << "boost::shared_ptr<" << cppType << "> " << name + << " = unwrap_shared_ptr< "; else if (is_ref) // A reference: emit an "unwrap_shared_ptr" call and de-reference the pointer file.oss << cppType << "& " << name << " = *unwrap_shared_ptr< "; @@ -66,23 +67,28 @@ void Argument::matlab_unwrap(FileWriter& file, const string& matlabName) const { file.oss << cppType << " " << name << " = unwrap< "; file.oss << cppType << " >(" << matlabName; - if (is_ptr || is_ref) file.oss << ", \"ptr_" << matlabUniqueType << "\""; + if (is_ptr || is_ref) + file.oss << ", \"ptr_" << matlabUniqueType << "\""; file.oss << ");" << endl; } /* ************************************************************************* */ string Argument::qualifiedType(const string& delim) const { string result; - BOOST_FOREACH(const string& ns, namespaces) result += ns + delim; + BOOST_FOREACH(const string& ns, namespaces) + result += ns + delim; return result + type; } /* ************************************************************************* */ string ArgumentList::types() const { string str; - bool first=true; + bool first = true; BOOST_FOREACH(Argument arg, *this) { - if (!first) str += ","; str += arg.type; first=false; + if (!first) + str += ","; + str += arg.type; + first = false; } return str; } @@ -90,16 +96,17 @@ string ArgumentList::types() const { /* ************************************************************************* */ string ArgumentList::signature() const { string sig; - bool cap=false; + bool cap = false; BOOST_FOREACH(Argument arg, *this) { BOOST_FOREACH(char ch, arg.type) - if(isupper(ch)) { - sig += ch; - //If there is a capital letter, we don't want to read it below - cap=true; - } - if(!cap) sig += arg.type[0]; + if (isupper(ch)) { + sig += ch; + //If there is a capital letter, we don't want to read it below + cap = true; + } + if (!cap) + sig += arg.type[0]; //Reset to default cap = false; } @@ -110,9 +117,12 @@ string ArgumentList::signature() const { /* ************************************************************************* */ string ArgumentList::names() const { string str; - bool first=true; + bool first = true; BOOST_FOREACH(Argument arg, *this) { - if (!first) str += ","; str += arg.name; first=false; + if (!first) + str += ","; + str += arg.name; + first = false; } return str; } @@ -123,7 +133,7 @@ void ArgumentList::matlab_unwrap(FileWriter& file, int start) const { BOOST_FOREACH(Argument arg, *this) { stringstream buf; buf << "in[" << index << "]"; - arg.matlab_unwrap(file,buf.str()); + arg.matlab_unwrap(file, buf.str()); index++; } } @@ -133,11 +143,44 @@ void ArgumentList::emit_prototype(FileWriter& file, const string& name) const { file.oss << name << "("; bool first = true; BOOST_FOREACH(Argument arg, *this) { - if (!first) file.oss << ", "; + if (!first) + file.oss << ", "; file.oss << arg.type << " " << arg.name; first = false; } file.oss << ")"; } /* ************************************************************************* */ +void ArgumentList::emit_conditional_call(FileWriter& file, + const ReturnValue& returnVal, const string& wrapperName, int id, + bool staticMethod) const { + // Check nr of arguments + file.oss << "if length(varargin) == " << size(); + if (size() > 0) + file.oss << " && "; + // ...and their types + bool first = true; + for (size_t i = 0; i < size(); i++) { + if (!first) + file.oss << " && "; + file.oss << "isa(varargin{" << i + 1 << "},'" << (*this)[i].matlabClass(".") + << "')"; + first = false; + } + file.oss << "\n"; + + // output call to C++ wrapper + string output; + if (returnVal.isPair) + output = "[ varargout{1} varargout{2} ] = "; + else if (returnVal.category1 == ReturnValue::VOID) + output = ""; + else + output = "varargout{1} = "; + file.oss << " " << output << wrapperName << "(" << id; + if (!staticMethod) + file.oss << ", this"; + file.oss << ", varargin{:});\n"; +} +/* ************************************************************************* */ diff --git a/wrap/Argument.h b/wrap/Argument.h index 2a989713b..da6a733bb 100644 --- a/wrap/Argument.h +++ b/wrap/Argument.h @@ -20,6 +20,7 @@ #pragma once #include "FileWriter.h" +#include "ReturnValue.h" #include #include @@ -75,6 +76,14 @@ struct ArgumentList: public std::vector { */ void emit_prototype(FileWriter& file, const std::string& name) const; + /** + * emit conditional MATLAB call (checking arguments first) + * @param file output stream + * @param returnVal the return value + * @param wrapperName of method or function + */ + void emit_conditional_call(FileWriter& file, const ReturnValue& returnVal, + const std::string& wrapperName, int id, bool staticMethod=false) const; }; } // \namespace wrap diff --git a/wrap/Method.cpp b/wrap/Method.cpp index ae50a36ae..7018ad138 100644 --- a/wrap/Method.cpp +++ b/wrap/Method.cpp @@ -39,99 +39,67 @@ void Method::addOverload(bool verbose, bool is_const, const std::string& name, } /* ************************************************************************* */ -void Method::proxy_wrapper_fragments(FileWriter& proxyFile, - FileWriter& wrapperFile, const string& cppClassName, - const std::string& matlabQualName, const std::string& matlabUniqueName, - const string& wrapperName, const TypeAttributesTable& typeAttributes, +void Method::proxy_wrapper_fragments(FileWriter& file, FileWriter& wrapperFile, + const string& cppClassName, const std::string& matlabQualName, + const std::string& matlabUniqueName, const string& wrapperName, + const TypeAttributesTable& typeAttributes, vector& functionNames) const { // Create function header - proxyFile.oss << " function varargout = " << name << "(this, varargin)\n"; + file.oss << " function varargout = " << name << "(this, varargin)\n"; // Emit comments for documentation string up_name = boost::to_upper_copy(name); - proxyFile.oss << " % " << up_name << " usage: "; + file.oss << " % " << up_name << " usage: "; unsigned int argLCount = 0; BOOST_FOREACH(ArgumentList argList, argLists) { - argList.emit_prototype(proxyFile, name); + argList.emit_prototype(file, name); if (argLCount != argLists.size() - 1) - proxyFile.oss << ", "; + file.oss << ", "; else - proxyFile.oss << " : returns " + file.oss << " : returns " << returnVals[0].return_type(false, returnVals[0].pair) << endl; argLCount++; } // Emit URL to Doxygen page - proxyFile.oss << " % " + file.oss << " % " << "Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html" << endl; // Document all overloads, if any if (argLists.size() > 1) { - proxyFile.oss << " % " << "" << endl; - proxyFile.oss << " % " << "Method Overloads" << endl; + file.oss << " % " << "" << endl; + file.oss << " % " << "Method Overloads" << endl; BOOST_FOREACH(ArgumentList argList, argLists) { - proxyFile.oss << " % "; - argList.emit_prototype(proxyFile, name); - proxyFile.oss << endl; + file.oss << " % "; + argList.emit_prototype(file, name); + file.oss << endl; } } - // For all overloads, check the number of arguments + // Check arguments for all overloads for (size_t overload = 0; overload < argLists.size(); ++overload) { - const ArgumentList& args = argLists[overload]; - const ReturnValue& returnVal = returnVals[overload]; - size_t nrArgs = args.size(); - - const int id = functionNames.size(); // Output proxy matlab code - - // check for number of arguments... - proxyFile.oss << " " << (overload == 0 ? "" : "else") - << "if length(varargin) == " << nrArgs; - if (nrArgs > 0) - proxyFile.oss << " && "; - // ...and their types - bool first = true; - for (size_t i = 0; i < nrArgs; i++) { - if (!first) - proxyFile.oss << " && "; - proxyFile.oss << "isa(varargin{" << i + 1 << "},'" - << args[i].matlabClass(".") << "')"; - first = false; - } - proxyFile.oss << "\n"; - - // output call to C++ wrapper - string output; - if (returnVal.isPair) - output = "[ varargout{1} varargout{2} ] = "; - else if (returnVal.category1 == ReturnValue::VOID) - output = ""; - else - output = "varargout{1} = "; - proxyFile.oss << " " << output << wrapperName << "(" << id - << ", this, varargin{:});\n"; + file.oss << " " << (overload == 0 ? "" : "else"); + const int id = (int) functionNames.size(); + argLists[overload].emit_conditional_call(file, returnVals[overload], + wrapperName, id); // Output C++ wrapper code - const string wrapFunctionName = wrapper_fragment(wrapperFile, cppClassName, matlabUniqueName, overload, id, typeAttributes); // Add to function list functionNames.push_back(wrapFunctionName); - } - - proxyFile.oss << " else\n"; - proxyFile.oss - << " error('Arguments do not match any overload of function " + file.oss << " else\n"; + file.oss << " error('Arguments do not match any overload of function " << matlabQualName << "." << name << "');" << endl; + file.oss << " end\n"; - proxyFile.oss << " end\n"; - proxyFile.oss << " end\n"; + file.oss << " end\n"; } /* ************************************************************************* */ diff --git a/wrap/StaticMethod.cpp b/wrap/StaticMethod.cpp index 29b3b12df..0c4cc7d75 100644 --- a/wrap/StaticMethod.cpp +++ b/wrap/StaticMethod.cpp @@ -39,7 +39,7 @@ void StaticMethod::addOverload(bool verbose, const std::string& name, } /* ************************************************************************* */ -void StaticMethod::proxy_wrapper_fragments(FileWriter& proxyFile, +void StaticMethod::proxy_wrapper_fragments(FileWriter& file, FileWriter& wrapperFile, const string& cppClassName, const std::string& matlabQualName, const std::string& matlabUniqueName, const string& wrapperName, const TypeAttributesTable& typeAttributes, @@ -48,85 +48,54 @@ void StaticMethod::proxy_wrapper_fragments(FileWriter& proxyFile, string upperName = name; upperName[0] = std::toupper(upperName[0], std::locale()); - proxyFile.oss << " function varargout = " << upperName << "(varargin)\n"; + file.oss << " function varargout = " << upperName << "(varargin)\n"; //Comments for documentation string up_name = boost::to_upper_copy(name); - proxyFile.oss << " % " << up_name << " usage: "; + file.oss << " % " << up_name << " usage: "; unsigned int argLCount = 0; BOOST_FOREACH(ArgumentList argList, argLists) { - argList.emit_prototype(proxyFile, name); + argList.emit_prototype(file, name); if (argLCount != argLists.size() - 1) - proxyFile.oss << ", "; + file.oss << ", "; else - proxyFile.oss << " : returns " + file.oss << " : returns " << returnVals[0].return_type(false, returnVals[0].pair) << endl; argLCount++; } - proxyFile.oss << " % " + file.oss << " % " << "Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html" << endl; - proxyFile.oss << " % " << "" << endl; - proxyFile.oss << " % " << "Usage" << endl; + file.oss << " % " << "" << endl; + file.oss << " % " << "Usage" << endl; BOOST_FOREACH(ArgumentList argList, argLists) { - proxyFile.oss << " % "; - argList.emit_prototype(proxyFile, up_name); - proxyFile.oss << endl; + file.oss << " % "; + argList.emit_prototype(file, up_name); + file.oss << endl; } + // Check arguments for all overloads for (size_t overload = 0; overload < argLists.size(); ++overload) { - const ArgumentList& args = argLists[overload]; - const ReturnValue& returnVal = returnVals[overload]; - size_t nrArgs = args.size(); - - const int id = (int) functionNames.size(); // Output proxy matlab code - - // check for number of arguments... - proxyFile.oss << " " << (overload == 0 ? "" : "else") - << "if length(varargin) == " << nrArgs; - if (nrArgs > 0) - proxyFile.oss << " && "; - // ...and their types - bool first = true; - for (size_t i = 0; i < nrArgs; i++) { - if (!first) - proxyFile.oss << " && "; - proxyFile.oss << "isa(varargin{" << i + 1 << "},'" - << args[i].matlabClass(".") << "')"; - first = false; - } - proxyFile.oss << "\n"; - - // output call to C++ wrapper - string output; - if (returnVal.isPair) - output = "[ varargout{1} varargout{2} ] = "; - else if (returnVal.category1 == ReturnValue::VOID) - output = ""; - else - output = "varargout{1} = "; - proxyFile.oss << " " << output << wrapperName << "(" << id - << ", varargin{:});\n"; + file.oss << " " << (overload == 0 ? "" : "else"); + const int id = (int) functionNames.size(); + argLists[overload].emit_conditional_call(file, returnVals[overload], + wrapperName, id, true); // last bool is to indicate static ! // Output C++ wrapper code - const string wrapFunctionName = wrapper_fragment(wrapperFile, cppClassName, matlabUniqueName, (int) overload, id, typeAttributes); // Add to function list functionNames.push_back(wrapFunctionName); - } - - proxyFile.oss << " else\n"; - proxyFile.oss - << " error('Arguments do not match any overload of function " + file.oss << " else\n"; + file.oss << " error('Arguments do not match any overload of function " << matlabQualName << "." << upperName << "');" << endl; + file.oss << " end\n"; - proxyFile.oss << " end\n"; - proxyFile.oss << " end\n"; + file.oss << " end\n"; } /* ************************************************************************* */