Merge remote-tracking branch 'origin/fix/BAD_wrap' into fix/BAD_wrap_checkpoint

Conflicts:
	wrap/Module.cpp
release/4.3a0
dellaert 2014-11-12 19:22:03 +01:00
commit 67ab69d5ba
10 changed files with 210 additions and 252 deletions

View File

@ -360,7 +360,7 @@ void Class::comment_fragment(FileWriter& proxyFile) const {
proxyFile.oss << "%"; proxyFile.oss << "%";
argList.emit_prototype(proxyFile, m.name); argList.emit_prototype(proxyFile, m.name);
proxyFile.oss << " : returns " proxyFile.oss << " : returns "
<< m.returnVals[0].return_type(false, m.returnVals[0].pair) << endl; << m.returnVals[0].return_type(false) << endl;
} }
} }
@ -372,7 +372,7 @@ void Class::comment_fragment(FileWriter& proxyFile) const {
proxyFile.oss << "%"; proxyFile.oss << "%";
argList.emit_prototype(proxyFile, m.name); argList.emit_prototype(proxyFile, m.name);
proxyFile.oss << " : returns " proxyFile.oss << " : returns "
<< m.returnVals[0].return_type(false, m.returnVals[0].pair) << endl; << m.returnVals[0].return_type(false) << endl;
} }
} }

View File

@ -36,7 +36,10 @@ struct Class : public Qualified {
typedef std::map<std::string, StaticMethod> StaticMethods; typedef std::map<std::string, StaticMethod> StaticMethods;
/// Constructor creates an empty class /// Constructor creates an empty class
Class(bool verbose=true) : isVirtual(false), isSerializable(false), hasSerialization(false), verbose_(verbose) {} Class(bool verbose = true) :
isVirtual(false), isSerializable(false), hasSerialization(false), deconstructor(
verbose), verbose_(verbose) {
}
// Then the instance variables are set directly by the Module constructor // Then the instance variables are set directly by the Module constructor
std::vector<std::string> templateArgs; ///< Template arguments std::vector<std::string> templateArgs; ///< Template arguments

View File

@ -58,7 +58,7 @@ void Method::proxy_wrapper_fragments(FileWriter& file, FileWriter& wrapperFile,
file.oss << ", "; file.oss << ", ";
else else
file.oss << " : returns " file.oss << " : returns "
<< returnVals[0].return_type(false, returnVals[0].pair) << endl; << returnVals[0].return_type(false) << endl;
argLCount++; argLCount++;
} }
@ -137,18 +137,7 @@ string Method::wrapper_fragment(FileWriter& file, const string& cppClassName,
// start // start
file.oss << "{\n"; file.oss << "{\n";
if (returnVal.isPair) { returnVal.wrapTypeUnwrap(file);
if (returnVal.category1 == ReturnValue::CLASS)
file.oss << " typedef boost::shared_ptr<"
<< returnVal.qualifiedType1("::") << "> Shared" << returnVal.type1.name
<< ";" << endl;
if (returnVal.category2 == ReturnValue::CLASS)
file.oss << " typedef boost::shared_ptr<"
<< returnVal.qualifiedType2("::") << "> Shared" << returnVal.type2.name
<< ";" << endl;
} else if (returnVal.category1 == ReturnValue::CLASS)
file.oss << " typedef boost::shared_ptr<" << returnVal.qualifiedType1("::")
<< "> Shared" << returnVal.type1.name << ";" << endl;
file.oss << " typedef boost::shared_ptr<" << cppClassName << "> Shared;" file.oss << " typedef boost::shared_ptr<" << cppClassName << "> Shared;"
<< endl; << endl;

View File

@ -100,23 +100,9 @@ Module::Module(const string& interfacePath,
/* ************************************************************************* */ /* ************************************************************************* */
void Module::parseMarkup(const std::string& data) { void Module::parseMarkup(const std::string& data) {
// these variables will be imperatively updated to gradually build [cls] // The parse imperatively :-( updates variables gradually during parse
// The one with postfix 0 are used to reset the variables after parse. // The one with postfix 0 are used to reset the variables after parse.
bool isConst, isConst0 = false; vector<string> namespaces; // current namespace tag
ReturnValue retVal0, retVal;
Argument arg0, arg;
ArgumentList args;
vector<string> arg_dup; ///keep track of duplicates
Constructor constructor0(verbose), constructor(verbose);
Deconstructor deconstructor0(verbose), deconstructor(verbose);
StaticMethod static_method0(verbose), static_method(verbose);
Class cls0(verbose),cls(verbose);
GlobalFunction globalFunc0(verbose), globalFunc(verbose);
ForwardDeclaration fwDec0, fwDec;
vector<string> namespaces, /// current namespace tag
namespaces_return; /// namespace for current return type
string include_path = "";
const string null_str = "";
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Grammar with actions that build the Class object. Actions are // Grammar with actions that build the Class object. Actions are
@ -145,7 +131,9 @@ void Module::parseMarkup(const std::string& data) {
Rule namespace_name_p = lexeme_d[lower_p >> *(alnum_p | '_')] - keywords_p; Rule namespace_name_p = lexeme_d[lower_p >> *(alnum_p | '_')] - keywords_p;
Rule namespace_arg_p = namespace_name_p[push_back_a(arg.type.namespaces)] >> str_p("::"); Argument arg0, arg;
Rule namespace_arg_p = namespace_name_p
[push_back_a(arg.type.namespaces)] >> str_p("::");
Rule argEigenType_p = Rule argEigenType_p =
eigenType_p[assign_a(arg.type.name)]; eigenType_p[assign_a(arg.type.name)];
@ -163,6 +151,8 @@ void Module::parseMarkup(const std::string& data) {
Rule name_p = lexeme_d[alpha_p >> *(alnum_p | '_')]; Rule name_p = lexeme_d[alpha_p >> *(alnum_p | '_')];
// TODO, do we really need cls here? Non-local
Class cls0(verbose),cls(verbose);
Rule classParent_p = Rule classParent_p =
*(namespace_name_p[push_back_a(cls.qualifiedParent.namespaces)] >> str_p("::")) >> *(namespace_name_p[push_back_a(cls.qualifiedParent.namespaces)] >> str_p("::")) >>
className_p[assign_a(cls.qualifiedParent.name)]; className_p[assign_a(cls.qualifiedParent.name)];
@ -213,6 +203,7 @@ void Module::parseMarkup(const std::string& data) {
'>'); '>');
// NOTE: allows for pointers to all types // NOTE: allows for pointers to all types
ArgumentList args;
Rule argument_p = Rule argument_p =
((basisType_p[assign_a(arg.type.name)] | argEigenType_p | eigenRef_p | classArg_p) ((basisType_p[assign_a(arg.type.name)] | argEigenType_p | eigenRef_p | classArg_p)
>> !ch_p('*')[assign_a(arg.is_ptr,true)] >> !ch_p('*')[assign_a(arg.is_ptr,true)]
@ -222,82 +213,78 @@ void Module::parseMarkup(const std::string& data) {
Rule argumentList_p = !argument_p >> * (',' >> argument_p); Rule argumentList_p = !argument_p >> * (',' >> argument_p);
// parse class constructor
Constructor constructor0(verbose), constructor(verbose);
Rule constructor_p = Rule constructor_p =
(className_p >> '(' >> argumentList_p >> ')' >> ';' >> !comments_p) (className_p >> '(' >> argumentList_p >> ')' >> ';' >> !comments_p)
[push_back_a(constructor.args_list, args)] [push_back_a(constructor.args_list, args)]
[clear_a(args)]; [clear_a(args)];
//[assign_a(constructor.args,args)]
//[assign_a(constructor.name,cls.name)]
//[push_back_a(cls.constructors, constructor)]
//[assign_a(constructor,constructor0)];
vector<string> namespaces_return; /// namespace for current return type
Rule namespace_ret_p = namespace_name_p[push_back_a(namespaces_return)] >> str_p("::"); Rule namespace_ret_p = namespace_name_p[push_back_a(namespaces_return)] >> str_p("::");
// HACK: use const values instead of using enums themselves - somehow this doesn't result in values getting assigned to gibberish // HACK: use const values instead of using enums themselves - somehow this doesn't result in values getting assigned to gibberish
static const ReturnValue::return_category RETURN_EIGEN = ReturnValue::EIGEN; static const ReturnType::return_category RETURN_EIGEN = ReturnType::EIGEN;
static const ReturnValue::return_category RETURN_BASIS = ReturnValue::BASIS; static const ReturnType::return_category RETURN_BASIS = ReturnType::BASIS;
static const ReturnValue::return_category RETURN_CLASS = ReturnValue::CLASS; static const ReturnType::return_category RETURN_CLASS = ReturnType::CLASS;
static const ReturnValue::return_category RETURN_VOID = ReturnValue::VOID; static const ReturnType::return_category RETURN_VOID = ReturnType::VOID;
Rule returnType1_p = ReturnType retType0, retType;
(basisType_p[assign_a(retVal.type1.name)][assign_a(retVal.category1, RETURN_BASIS)]) | Rule returnType_p =
((*namespace_ret_p)[assign_a(retVal.type1.namespaces, namespaces_return)][clear_a(namespaces_return)] (basisType_p[assign_a(retType.name)][assign_a(retType.category, RETURN_BASIS)]) |
>> (className_p[assign_a(retVal.type1.name)][assign_a(retVal.category1, RETURN_CLASS)]) >> ((*namespace_ret_p)[assign_a(retType.namespaces, namespaces_return)][clear_a(namespaces_return)]
!ch_p('*')[assign_a(retVal.isPtr1,true)]) | >> (className_p[assign_a(retType.name)][assign_a(retType.category, RETURN_CLASS)]) >>
(eigenType_p[assign_a(retVal.type1.name)][assign_a(retVal.category1, RETURN_EIGEN)]); !ch_p('*')[assign_a(retType.isPtr,true)]) |
(eigenType_p[assign_a(retType.name)][assign_a(retType.category, RETURN_EIGEN)]);
Rule returnType2_p = ReturnValue retVal0, retVal;
(basisType_p[assign_a(retVal.type2.name)][assign_a(retVal.category2, RETURN_BASIS)]) | Rule returnType1_p = returnType_p[assign_a(retVal.type1,retType)][assign_a(retType,retType0)];
((*namespace_ret_p)[assign_a(retVal.type2.namespaces, namespaces_return)][clear_a(namespaces_return)] Rule returnType2_p = returnType_p[assign_a(retVal.type2,retType)][assign_a(retType,retType0)];
>> (className_p[assign_a(retVal.type2.name)][assign_a(retVal.category2, RETURN_CLASS)]) >>
!ch_p('*') [assign_a(retVal.isPtr2,true)]) |
(eigenType_p[assign_a(retVal.type2.name)][assign_a(retVal.category2, RETURN_EIGEN)]);
Rule pair_p = Rule pair_p =
(str_p("pair") >> '<' >> returnType1_p >> ',' >> returnType2_p >> '>') (str_p("pair") >> '<' >> returnType1_p >> ',' >> returnType2_p >> '>')
[assign_a(retVal.isPair,true)]; [assign_a(retVal.isPair,true)];
Rule void_p = str_p("void")[assign_a(retVal.type1.name)][assign_a(retVal.category1, RETURN_VOID)]; Rule void_p = str_p("void")[assign_a(retVal.type1.name)][assign_a(retVal.type1.category, RETURN_VOID)];
Rule returnType_p = void_p | pair_p | returnType1_p; Rule returnValue_p = void_p | pair_p | returnType1_p;
Rule methodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; Rule methodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')];
// gtsam::Values retract(const gtsam::VectorValues& delta) const; // gtsam::Values retract(const gtsam::VectorValues& delta) const;
string methodName; string methodName;
bool isConst, isConst0 = false;
vector<Qualified> methodInstantiations; vector<Qualified> methodInstantiations;
Rule method_p = Rule method_p =
!templateArgValues_p !templateArgValues_p
[assign_a(methodInstantiations,templateArgValues)][clear_a(templateArgValues)] >> [assign_a(methodInstantiations,templateArgValues)][clear_a(templateArgValues)] >>
(returnType_p >> methodName_p[assign_a(methodName)] >> (returnValue_p >> methodName_p[assign_a(methodName)] >>
'(' >> argumentList_p >> ')' >> '(' >> argumentList_p >> ')' >>
!str_p("const")[assign_a(isConst,true)] >> ';' >> *comments_p) !str_p("const")[assign_a(isConst,true)] >> ';' >> *comments_p)
[bl::bind(&Method::addOverload, [bl::bind(&Method::addOverload,
bl::var(cls.methods)[bl::var(methodName)], verbose, bl::var(cls.methods)[bl::var(methodName)], verbose,
bl::var(isConst), bl::var(methodName), bl::var(args), bl::var(retVal))] bl::var(isConst), bl::var(methodName), bl::var(args), bl::var(retVal))]
[assign_a(isConst,isConst0)] [assign_a(retVal,retVal0)]
[clear_a(args)] [clear_a(args)]
[assign_a(retVal,retVal0)]; [assign_a(isConst,isConst0)];
Rule staticMethodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; Rule staticMethodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')];
Rule static_method_p = Rule static_method_p =
(str_p("static") >> returnType_p >> staticMethodName_p[assign_a(methodName)] >> (str_p("static") >> returnValue_p >> staticMethodName_p[assign_a(methodName)] >>
'(' >> argumentList_p >> ')' >> ';' >> *comments_p) '(' >> argumentList_p >> ')' >> ';' >> *comments_p)
[bl::bind(&StaticMethod::addOverload, [bl::bind(&StaticMethod::addOverload,
bl::var(cls.static_methods)[bl::var(methodName)], bl::var(cls.static_methods)[bl::var(methodName)],
verbose, verbose, bl::var(methodName), bl::var(args), bl::var(retVal))]
bl::var(methodName), [assign_a(retVal,retVal0)]
bl::var(args), [clear_a(args)];
bl::var(retVal))]
[clear_a(args)]
[assign_a(retVal,retVal0)];
Rule functions_p = constructor_p | method_p | static_method_p; Rule functions_p = constructor_p | method_p | static_method_p;
// parse a full class
vector<Qualified> templateInstantiations; vector<Qualified> templateInstantiations;
Rule class_p = Rule class_p =
(str_p("")[assign_a(cls,cls0)]) eps_p[assign_a(cls,cls0)]
>> (!(templateArgValues_p >> (!(templateArgValues_p
[push_back_a(cls.templateArgs, templateArgName)] [push_back_a(cls.templateArgs, templateArgName)]
[assign_a(templateInstantiations,templateArgValues)] [assign_a(templateInstantiations,templateArgValues)]
@ -312,29 +299,25 @@ void Module::parseMarkup(const std::string& data) {
[assign_a(constructor.name, cls.name)] [assign_a(constructor.name, cls.name)]
[assign_a(cls.constructor, constructor)] [assign_a(cls.constructor, constructor)]
[assign_a(cls.namespaces, namespaces)] [assign_a(cls.namespaces, namespaces)]
[assign_a(deconstructor.name,cls.name)] [assign_a(cls.deconstructor.name,cls.name)]
[assign_a(cls.deconstructor, deconstructor)]
[bl::bind(&handle_possible_template, bl::var(classes), bl::var(cls), [bl::bind(&handle_possible_template, bl::var(classes), bl::var(cls),
bl::var(templateInstantiations))] bl::var(templateInstantiations))]
[assign_a(deconstructor,deconstructor0)] [clear_a(templateInstantiations)]
[assign_a(constructor, constructor0)] [assign_a(constructor, constructor0)]
[assign_a(cls,cls0)] [assign_a(cls,cls0)];
[clear_a(templateInstantiations)];
// parse a global function
Qualified globalFunction; Qualified globalFunction;
Rule global_function_p = Rule global_function_p =
(returnType_p >> staticMethodName_p[assign_a(globalFunction.name)] >> (returnValue_p >> staticMethodName_p[assign_a(globalFunction.name)] >>
'(' >> argumentList_p >> ')' >> ';' >> *comments_p) '(' >> argumentList_p >> ')' >> ';' >> *comments_p)
[assign_a(globalFunction.namespaces,namespaces)] [assign_a(globalFunction.namespaces,namespaces)]
[bl::bind(&GlobalFunction::addOverload, [bl::bind(&GlobalFunction::addOverload,
bl::var(global_functions)[bl::var(globalFunction.name)], bl::var(global_functions)[bl::var(globalFunction.name)],
verbose, verbose, bl::var(globalFunction), bl::var(args), bl::var(retVal))]
bl::var(globalFunction), [assign_a(retVal,retVal0)]
bl::var(args),
bl::var(retVal))]
[clear_a(globalFunction)] [clear_a(globalFunction)]
[clear_a(args)] [clear_a(args)];
[assign_a(retVal,retVal0)];
Rule include_p = str_p("#include") >> ch_p('<') >> (*(anychar_p - '>'))[push_back_a(includes)] >> ch_p('>'); Rule include_p = str_p("#include") >> ch_p('<') >> (*(anychar_p - '>'))[push_back_a(includes)] >> ch_p('>');
@ -355,6 +338,8 @@ void Module::parseMarkup(const std::string& data) {
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif
// parse forward declaration
ForwardDeclaration fwDec0, fwDec;
Rule forward_declaration_p = Rule forward_declaration_p =
!(str_p("virtual")[assign_a(fwDec.isVirtual, true)]) !(str_p("virtual")[assign_a(fwDec.isVirtual, true)])
>> str_p("class") >> str_p("class")
@ -382,7 +367,7 @@ void Module::parseMarkup(const std::string& data) {
BOOST_SPIRIT_DEBUG_NODE(returnType2_p); BOOST_SPIRIT_DEBUG_NODE(returnType2_p);
BOOST_SPIRIT_DEBUG_NODE(pair_p); BOOST_SPIRIT_DEBUG_NODE(pair_p);
BOOST_SPIRIT_DEBUG_NODE(void_p); BOOST_SPIRIT_DEBUG_NODE(void_p);
BOOST_SPIRIT_DEBUG_NODE(returnType_p); BOOST_SPIRIT_DEBUG_NODE(returnValue_p);
BOOST_SPIRIT_DEBUG_NODE(methodName_p); BOOST_SPIRIT_DEBUG_NODE(methodName_p);
BOOST_SPIRIT_DEBUG_NODE(method_p); BOOST_SPIRIT_DEBUG_NODE(method_p);
BOOST_SPIRIT_DEBUG_NODE(class_p); BOOST_SPIRIT_DEBUG_NODE(class_p);
@ -453,15 +438,15 @@ void verifyArguments(const vector<string>& validArgs, const map<string,T>& vt) {
/* ************************************************************************* */ /* ************************************************************************* */
template<class T> template<class T>
void verifyReturnTypes(const vector<string>& validtypes, const map<string,T>& vt) { void verifyReturnTypes(const vector<string>& validtypes,
typedef typename map<string,T>::value_type Name_Method; const map<string, T>& vt) {
typedef typename map<string, T>::value_type Name_Method;
BOOST_FOREACH(const Name_Method& name_method, vt) { BOOST_FOREACH(const Name_Method& name_method, vt) {
const T& t = name_method.second; const T& t = name_method.second;
BOOST_FOREACH(const ReturnValue& retval, t.returnVals) { BOOST_FOREACH(const ReturnValue& retval, t.returnVals) {
if (find(validtypes.begin(), validtypes.end(), retval.qualifiedType1("::")) == validtypes.end()) retval.type1.verify(validtypes, t.name);
throw DependencyMissing(retval.qualifiedType1("::"), t.name); if (retval.isPair)
if (retval.isPair && find(validtypes.begin(), validtypes.end(), retval.qualifiedType2("::")) == validtypes.end()) retval.type2.verify(validtypes, t.name);
throw DependencyMissing(retval.qualifiedType2("::"), t.name);
} }
} }
} }

View File

@ -16,138 +16,90 @@ using namespace std;
using namespace wrap; using namespace wrap;
/* ************************************************************************* */ /* ************************************************************************* */
string ReturnValue::return_type(bool add_ptr, pairing p) const { string ReturnType::str(bool add_ptr) const {
if (p == pair && isPair) { return maybe_shared_ptr(add_ptr && isPtr, qualifiedName("::"), name);
string str = "pair< " }
+ maybe_shared_ptr(add_ptr || isPtr1, qualifiedType1("::"), type1.name)
+ ", " /* ************************************************************************* */
+ maybe_shared_ptr(add_ptr || isPtr2, qualifiedType2("::"), type2.name) void ReturnType::wrap_result(const string& out, const string& result,
+ " >"; FileWriter& file, const TypeAttributesTable& typeAttributes) const {
return str;
} else string cppType = qualifiedName("::"), matlabType = qualifiedName(".");
return maybe_shared_ptr(add_ptr && isPtr1,
(p == arg2) ? qualifiedType2("::") : qualifiedType1("::"), if (category == CLASS) {
(p == arg2) ? type2.name : type1.name); string objCopy, ptrType;
ptrType = "Shared" + name;
const bool isVirtual = typeAttributes.at(cppType).isVirtual;
if (isVirtual) {
if (isPtr)
objCopy = result;
else
objCopy = result + ".clone()";
} else {
if (isPtr)
objCopy = result;
else
objCopy = ptrType + "(new " + cppType + "(" + result + "))";
}
file.oss << out << " = wrap_shared_ptr(" << objCopy << ",\"" << matlabType
<< "\", " << (isVirtual ? "true" : "false") << ");\n";
} else if (isPtr) {
file.oss << " Shared" << name << "* ret = new Shared" << name << "("
<< result << ");" << endl;
file.oss << out << " = wrap_shared_ptr(ret,\"" << matlabType << "\");\n";
} else if (matlabType != "void")
file.oss << out << " = wrap< " << str(false) << " >(" << result << ");\n";
}
/* ************************************************************************* */
void ReturnType::wrapTypeUnwrap(FileWriter& file) const {
if (category == CLASS)
file.oss << " typedef boost::shared_ptr<" << qualifiedName("::")
<< "> Shared" << name << ";" << endl;
}
/* ************************************************************************* */
string ReturnValue::return_type(bool add_ptr) const {
if (isPair)
return "pair< " + type1.str(add_ptr) + ", " + type2.str(add_ptr) + " >";
else
return type1.str(add_ptr);
} }
/* ************************************************************************* */ /* ************************************************************************* */
string ReturnValue::matlab_returnType() const { string ReturnValue::matlab_returnType() const {
return isPair? "[first,second]" : "result"; return isPair ? "[first,second]" : "result";
} }
/* ************************************************************************* */ /* ************************************************************************* */
string ReturnValue::qualifiedType1(const string& delim) const { void ReturnValue::wrap_result(const string& result, FileWriter& file,
return type1.qualifiedName(delim); const TypeAttributesTable& typeAttributes) const {
}
/* ************************************************************************* */
string ReturnValue::qualifiedType2(const string& delim) const {
return type2.qualifiedName(delim);
}
/* ************************************************************************* */
//TODO:Fix this
void ReturnValue::wrap_result(const string& result, FileWriter& file, const TypeAttributesTable& typeAttributes) const {
string cppType1 = qualifiedType1("::"), matlabType1 = qualifiedType1(".");
string cppType2 = qualifiedType2("::"), matlabType2 = qualifiedType2(".");
if (isPair) { if (isPair) {
// For a pair, store the returned pair so we do not evaluate the function twice // For a pair, store the returned pair so we do not evaluate the function twice
file.oss << " " << return_type(false, pair) << " pairResult = " << result << ";\n"; file.oss << " " << return_type(true) << " pairResult = " << result
<< ";\n";
// first return value in pair type1.wrap_result(" out[0]", "pairResult.first", file, typeAttributes);
if (category1 == ReturnValue::CLASS) { // if we are going to make one type2.wrap_result(" out[1]", "pairResult.second", file, typeAttributes);
string objCopy, ptrType;
ptrType = "Shared" + type1.name;
const bool isVirtual = typeAttributes.at(cppType1).isVirtual;
if(isVirtual) {
if(isPtr1)
objCopy = "pairResult.first";
else
objCopy = "pairResult.first.clone()";
} else {
if(isPtr1)
objCopy = "pairResult.first";
else
objCopy = ptrType + "(new " + cppType1 + "(pairResult.first))";
}
file.oss << " out[0] = wrap_shared_ptr(" << objCopy << ",\"" << matlabType1 << "\", " << (isVirtual ? "true" : "false") << ");\n";
} else if(isPtr1) {
file.oss << " Shared" << type1.name <<"* ret = new Shared" << type1.name << "(pairResult.first);" << endl;
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\", false);\n";
} else // if basis type
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(pairResult.first);\n";
// second return value in pair
if (category2 == ReturnValue::CLASS) { // if we are going to make one
string objCopy, ptrType;
ptrType = "Shared" + type2.name;
const bool isVirtual = typeAttributes.at(cppType2).isVirtual;
if(isVirtual) {
if(isPtr2)
objCopy = "pairResult.second";
else
objCopy = "pairResult.second.clone()";
} else {
if(isPtr2)
objCopy = "pairResult.second";
else
objCopy = ptrType + "(new " + cppType2 + "(pairResult.second))";
}
file.oss << " out[1] = wrap_shared_ptr(" << objCopy << ",\"" << matlabType2 << "\", " << (isVirtual ? "true" : "false") << ");\n";
} else if(isPtr2) {
file.oss << " Shared" << type2.name <<"* ret = new Shared" << type2.name << "(pairResult.second);" << endl;
file.oss << " out[1] = wrap_shared_ptr(ret,\"" << matlabType2 << "\");\n";
} else
file.oss << " out[1] = wrap< " << return_type(true,arg2) << " >(pairResult.second);\n";
} else { // Not a pair } else { // Not a pair
type1.wrap_result(" out[0]", result, file, typeAttributes);
if (category1 == ReturnValue::CLASS) {
string objCopy, ptrType;
ptrType = "Shared" + type1.name;
const bool isVirtual = typeAttributes.at(cppType1).isVirtual;
if(isVirtual) {
if(isPtr1)
objCopy = result;
else
objCopy = result + ".clone()";
} else {
if(isPtr1)
objCopy = result;
else
objCopy = ptrType + "(new " + cppType1 + "(" + result + "))";
}
file.oss << " out[0] = wrap_shared_ptr(" << objCopy << ",\"" << matlabType1 << "\", " << (isVirtual ? "true" : "false") << ");\n";
} else if(isPtr1) {
file.oss << " Shared" << type1.name <<"* ret = new Shared" << type1.name << "(" << result << ");" << endl;
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
} else if (matlabType1!="void")
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(" << result << ");\n";
} }
} }
/* ************************************************************************* */ /* ************************************************************************* */
void ReturnValue::wrapTypeUnwrap(FileWriter& wrapperFile) const { void ReturnValue::wrapTypeUnwrap(FileWriter& file) const {
if(isPair) type1.wrapTypeUnwrap(file);
{ if (isPair)
if(category1 == ReturnValue::CLASS) type2.wrapTypeUnwrap(file);
wrapperFile.oss << " typedef boost::shared_ptr<" << qualifiedType1("::") << "> Shared" << type1.name << ";"<< endl;
if(category2 == ReturnValue::CLASS)
wrapperFile.oss << " typedef boost::shared_ptr<" << qualifiedType2("::") << "> Shared" << type2.name << ";"<< endl;
}
else {
if (category1 == ReturnValue::CLASS)
wrapperFile.oss << " typedef boost::shared_ptr<" << qualifiedType1("::") << "> Shared" << type1.name << ";"<< endl;
}
} }
/* ************************************************************************* */ /* ************************************************************************* */
void ReturnValue::emit_matlab(FileWriter& file) const { void ReturnValue::emit_matlab(FileWriter& file) const {
string output; string output;
if (isPair) if (isPair)
file.oss << "[ varargout{1} varargout{2} ] = "; file.oss << "[ varargout{1} varargout{2} ] = ";
else if (category1 != ReturnValue::VOID) else if (type1.category != ReturnType::VOID)
file.oss << "varargout{1} = "; file.oss << "varargout{1} = ";
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -8,9 +8,10 @@
* @author Richard Roberts * @author Richard Roberts
*/ */
#include "Qualified.h"
#include "FileWriter.h" #include "FileWriter.h"
#include "TypeAttributesTable.h" #include "TypeAttributesTable.h"
#include "Qualified.h" #include "utilities.h"
#pragma once #pragma once
@ -19,31 +20,61 @@ namespace wrap {
/** /**
* Encapsulates return value of a method or function * Encapsulates return value of a method or function
*/ */
struct ReturnValue { struct ReturnType: Qualified {
/// the different supported return value categories /// the different supported return value categories
typedef enum { typedef enum {
CLASS = 1, EIGEN = 2, BASIS = 3, VOID = 4 CLASS = 1, EIGEN = 2, BASIS = 3, VOID = 4
} return_category; } return_category;
bool isPtr1, isPtr2, isPair; bool isPtr;
return_category category1, category2; return_category category;
Qualified type1, type2;
ReturnType() :
isPtr(false), category(CLASS) {
}
ReturnType(const Qualified& q) :
Qualified(q), isPtr(false), category(CLASS) {
}
/// Check if this type is in a set of valid types
template<class TYPES>
void verify(TYPES validtypes, const std::string& s) const {
std::string key = qualifiedName("::");
if (find(validtypes.begin(), validtypes.end(), key) == validtypes.end())
throw DependencyMissing(key, s);
}
private:
friend struct ReturnValue;
std::string str(bool add_ptr) const;
/// Example: out[1] = wrap_shared_ptr(pairResult.second,"Test", false);
void wrap_result(const std::string& out, const std::string& result,
FileWriter& file, const TypeAttributesTable& typeAttributes) const;
/// Creates typedef
void wrapTypeUnwrap(FileWriter& wrapperFile) const;
};
/**
* Encapsulates return value of a method or function, possibly a pair
*/
struct ReturnValue {
bool isPair;
ReturnType type1, type2;
/// Constructor /// Constructor
ReturnValue() : ReturnValue() :
isPtr1(false), isPtr2(false), isPair(false), category1(CLASS), category2( isPair(false) {
CLASS) {
} }
typedef enum { std::string return_type(bool add_ptr) const;
arg1, arg2, pair
} pairing;
std::string return_type(bool add_ptr, pairing p) const;
std::string qualifiedType1(const std::string& delim = "") const;
std::string qualifiedType2(const std::string& delim = "") const;
std::string matlab_returnType() const; std::string matlab_returnType() const;

View File

@ -59,7 +59,7 @@ void StaticMethod::proxy_wrapper_fragments(FileWriter& file,
file.oss << ", "; file.oss << ", ";
else else
file.oss << " : returns " file.oss << " : returns "
<< returnVals[0].return_type(false, returnVals[0].pair) << endl; << returnVals[0].return_type(false) << endl;
argLCount++; argLCount++;
} }

View File

@ -7,8 +7,8 @@
% %
%-------Methods------- %-------Methods-------
%arg_EigenConstRef(Matrix value) : returns void %arg_EigenConstRef(Matrix value) : returns void
%create_MixedPtrs() : returns pair< Test, SharedTest > %create_MixedPtrs() : returns pair< Test, Test >
%create_ptrs() : returns pair< SharedTest, SharedTest > %create_ptrs() : returns pair< Test, Test >
%print() : returns void %print() : returns void
%return_Point2Ptr(bool value) : returns Point2 %return_Point2Ptr(bool value) : returns Point2
%return_Test(Test value) : returns Test %return_Test(Test value) : returns Test
@ -20,7 +20,7 @@
%return_matrix1(Matrix value) : returns Matrix %return_matrix1(Matrix value) : returns Matrix
%return_matrix2(Matrix value) : returns Matrix %return_matrix2(Matrix value) : returns Matrix
%return_pair(Vector v, Matrix A) : returns pair< Vector, Matrix > %return_pair(Vector v, Matrix A) : returns pair< Vector, Matrix >
%return_ptrs(Test p1, Test p2) : returns pair< SharedTest, SharedTest > %return_ptrs(Test p1, Test p2) : returns pair< Test, Test >
%return_size_t(size_t value) : returns size_t %return_size_t(size_t value) : returns size_t
%return_string(string value) : returns string %return_string(string value) : returns string
%return_vector1(Vector value) : returns Vector %return_vector1(Vector value) : returns Vector
@ -64,13 +64,13 @@ classdef Test < handle
end end
function varargout = create_MixedPtrs(this, varargin) function varargout = create_MixedPtrs(this, varargin)
% CREATE_MIXEDPTRS usage: create_MixedPtrs() : returns pair< Test, SharedTest > % CREATE_MIXEDPTRS usage: create_MixedPtrs() : returns pair< Test, Test >
% Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html % Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html
[ varargout{1} varargout{2} ] = geometry_wrapper(22, this, varargin{:}); [ varargout{1} varargout{2} ] = geometry_wrapper(22, this, varargin{:});
end end
function varargout = create_ptrs(this, varargin) function varargout = create_ptrs(this, varargin)
% CREATE_PTRS usage: create_ptrs() : returns pair< SharedTest, SharedTest > % CREATE_PTRS usage: create_ptrs() : returns pair< Test, Test >
% Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html % Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html
[ varargout{1} varargout{2} ] = geometry_wrapper(23, this, varargin{:}); [ varargout{1} varargout{2} ] = geometry_wrapper(23, this, varargin{:});
end end
@ -166,7 +166,7 @@ classdef Test < handle
end end
function varargout = return_ptrs(this, varargin) function varargout = return_ptrs(this, varargin)
% RETURN_PTRS usage: return_ptrs(Test p1, Test p2) : returns pair< SharedTest, SharedTest > % RETURN_PTRS usage: return_ptrs(Test p1, Test p2) : returns pair< Test, Test >
% Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html % Doxygen can be found at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html
if length(varargin) == 2 && isa(varargin{1},'Test') && isa(varargin{2},'Test') if length(varargin) == 2 && isa(varargin{1},'Test') && isa(varargin{2},'Test')
[ varargout{1} varargout{2} ] = geometry_wrapper(35, this, varargin{:}); [ varargout{1} varargout{2} ] = geometry_wrapper(35, this, varargin{:});

View File

@ -104,9 +104,9 @@ TEST( wrap, small_parse ) {
ReturnValue rv1 = m1.returnVals.front(); ReturnValue rv1 = m1.returnVals.front();
EXPECT(!rv1.isPair); EXPECT(!rv1.isPair);
EXPECT(!rv1.isPtr1); EXPECT(!rv1.type1.isPtr);
EXPECT(assert_equal("double", rv1.type1.name)); EXPECT(assert_equal("double", rv1.type1.name));
EXPECT_LONGS_EQUAL(ReturnValue::BASIS, rv1.category1); EXPECT_LONGS_EQUAL(ReturnType::BASIS, rv1.type1.category);
// Method 2 // Method 2
Method m2 = cls.methods.at("returnMatrix"); Method m2 = cls.methods.at("returnMatrix");
@ -117,9 +117,9 @@ TEST( wrap, small_parse ) {
ReturnValue rv2 = m2.returnVals.front(); ReturnValue rv2 = m2.returnVals.front();
EXPECT(!rv2.isPair); EXPECT(!rv2.isPair);
EXPECT(!rv2.isPtr1); EXPECT(!rv2.type1.isPtr);
EXPECT(assert_equal("Matrix", rv2.type1.name)); EXPECT(assert_equal("Matrix", rv2.type1.name));
EXPECT_LONGS_EQUAL(ReturnValue::EIGEN, rv2.category1); EXPECT_LONGS_EQUAL(ReturnType::EIGEN, rv2.type1.category);
// Method 3 // Method 3
Method m3 = cls.methods.at("returnPoint2"); Method m3 = cls.methods.at("returnPoint2");
@ -130,9 +130,9 @@ TEST( wrap, small_parse ) {
ReturnValue rv3 = m3.returnVals.front(); ReturnValue rv3 = m3.returnVals.front();
EXPECT(!rv3.isPair); EXPECT(!rv3.isPair);
EXPECT(!rv3.isPtr1); EXPECT(!rv3.type1.isPtr);
EXPECT(assert_equal("Point2", rv3.type1.name)); EXPECT(assert_equal("Point2", rv3.type1.name));
EXPECT_LONGS_EQUAL(ReturnValue::CLASS, rv3.category1); EXPECT_LONGS_EQUAL(ReturnType::CLASS, rv3.type1.category);
// Static Method 1 // Static Method 1
// static Vector returnVector(); // static Vector returnVector();
@ -143,9 +143,9 @@ TEST( wrap, small_parse ) {
ReturnValue rv4 = sm1.returnVals.front(); ReturnValue rv4 = sm1.returnVals.front();
EXPECT(!rv4.isPair); EXPECT(!rv4.isPair);
EXPECT(!rv4.isPtr1); EXPECT(!rv4.type1.isPtr);
EXPECT(assert_equal("Vector", rv4.type1.name)); EXPECT(assert_equal("Vector", rv4.type1.name));
EXPECT_LONGS_EQUAL(ReturnValue::EIGEN, rv4.category1); EXPECT_LONGS_EQUAL(ReturnType::EIGEN, rv4.type1.category);
} }
@ -166,7 +166,7 @@ TEST( wrap, parse_geometry ) {
LONGS_EQUAL(7, module.classes.size()); LONGS_EQUAL(7, module.classes.size());
// Key for ReturnValue::return_category // Key for ReturnType::return_category
// CLASS = 1, // CLASS = 1,
// EIGEN = 2, // EIGEN = 2,
// BASIS = 3, // BASIS = 3,
@ -197,7 +197,7 @@ TEST( wrap, parse_geometry ) {
Method m1 = cls.methods.find("returnChar")->second; Method m1 = cls.methods.find("returnChar")->second;
LONGS_EQUAL(1, m1.returnVals.size()); LONGS_EQUAL(1, m1.returnVals.size());
EXPECT(assert_equal("char", m1.returnVals.front().type1.name)); EXPECT(assert_equal("char", m1.returnVals.front().type1.name));
EXPECT_LONGS_EQUAL(ReturnValue::BASIS, m1.returnVals.front().category1); EXPECT_LONGS_EQUAL(ReturnType::BASIS, m1.returnVals.front().type1.category);
EXPECT(!m1.returnVals.front().isPair); EXPECT(!m1.returnVals.front().isPair);
EXPECT(assert_equal("returnChar", m1.name)); EXPECT(assert_equal("returnChar", m1.name));
LONGS_EQUAL(1, m1.argLists.size()); LONGS_EQUAL(1, m1.argLists.size());
@ -211,7 +211,7 @@ TEST( wrap, parse_geometry ) {
Method m1 = cls.methods.find("vectorConfusion")->second; Method m1 = cls.methods.find("vectorConfusion")->second;
LONGS_EQUAL(1, m1.returnVals.size()); LONGS_EQUAL(1, m1.returnVals.size());
EXPECT(assert_equal("VectorNotEigen", m1.returnVals.front().type1.name)); EXPECT(assert_equal("VectorNotEigen", m1.returnVals.front().type1.name));
EXPECT_LONGS_EQUAL(ReturnValue::CLASS, m1.returnVals.front().category1); EXPECT_LONGS_EQUAL(ReturnType::CLASS, m1.returnVals.front().type1.category);
EXPECT(!m1.returnVals.front().isPair); EXPECT(!m1.returnVals.front().isPair);
EXPECT(assert_equal("vectorConfusion", m1.name)); EXPECT(assert_equal("vectorConfusion", m1.name));
LONGS_EQUAL(1, m1.argLists.size()); LONGS_EQUAL(1, m1.argLists.size());
@ -254,7 +254,7 @@ TEST( wrap, parse_geometry ) {
Method m1 = cls.methods.find("norm")->second; Method m1 = cls.methods.find("norm")->second;
LONGS_EQUAL(1, m1.returnVals.size()); LONGS_EQUAL(1, m1.returnVals.size());
EXPECT(assert_equal("double", m1.returnVals.front().type1.name)); EXPECT(assert_equal("double", m1.returnVals.front().type1.name));
EXPECT_LONGS_EQUAL(ReturnValue::BASIS, m1.returnVals.front().category1); EXPECT_LONGS_EQUAL(ReturnType::BASIS, m1.returnVals.front().type1.category);
EXPECT(assert_equal("norm", m1.name)); EXPECT(assert_equal("norm", m1.name));
LONGS_EQUAL(1, m1.argLists.size()); LONGS_EQUAL(1, m1.argLists.size());
EXPECT_LONGS_EQUAL(0, m1.argLists.front().size()); EXPECT_LONGS_EQUAL(0, m1.argLists.front().size());
@ -280,9 +280,9 @@ TEST( wrap, parse_geometry ) {
Method m2 = testCls.methods.find("return_pair")->second; Method m2 = testCls.methods.find("return_pair")->second;
LONGS_EQUAL(1, m2.returnVals.size()); LONGS_EQUAL(1, m2.returnVals.size());
EXPECT(m2.returnVals.front().isPair); EXPECT(m2.returnVals.front().isPair);
EXPECT_LONGS_EQUAL(ReturnValue::EIGEN, m2.returnVals.front().category1); EXPECT_LONGS_EQUAL(ReturnType::EIGEN, m2.returnVals.front().type1.category);
EXPECT(assert_equal("Vector", m2.returnVals.front().type1.name)); EXPECT(assert_equal("Vector", m2.returnVals.front().type1.name));
EXPECT_LONGS_EQUAL(ReturnValue::EIGEN, m2.returnVals.front().category2); EXPECT_LONGS_EQUAL(ReturnType::EIGEN, m2.returnVals.front().type2.category);
EXPECT(assert_equal("Matrix", m2.returnVals.front().type2.name)); EXPECT(assert_equal("Matrix", m2.returnVals.front().type2.name));
// checking pointer args and return values // checking pointer args and return values

View File

@ -112,8 +112,6 @@ string maybe_shared_ptr(bool add, const string& qtype, const string& type) {
string str = add? "Shared" : ""; string str = add? "Shared" : "";
if (add) str += type; if (add) str += type;
else str += qtype; else str += qtype;
//if (add) str += ">";
return str; return str;
} }