diff --git a/gtsam.h b/gtsam.h index 0878d831b..215431848 100644 --- a/gtsam.h +++ b/gtsam.h @@ -45,8 +45,10 @@ /** * Status: * - TODO: global functions + * - TODO: type dependencies only apply to arguments * - TODO: default values for arguments * - TODO: overloaded functions + * - TODO: signatures for constructors can be ambiguous if two types have the same first letter * - TODO: Handle Rot3M conversions to quaternions */ @@ -195,7 +197,7 @@ class SharedDiagonal { #include class SharedNoiseModel { - // FIXME: this generates only one constructor + // FIXME: this generates only one constructor because "SharedDiagonal" and "SharedGaussian" both start with 'S' SharedNoiseModel(const SharedDiagonal& model); SharedNoiseModel(const SharedGaussian& model); }; diff --git a/wrap/Module.cpp b/wrap/Module.cpp index af8bd6696..06d745609 100644 --- a/wrap/Module.cpp +++ b/wrap/Module.cpp @@ -56,6 +56,7 @@ Module::Module(const string& interfacePath, namespace_includes, /// current set of includes namespaces_return; /// namespace for current return type string include_path = ""; + string class_name = ""; const string null_str = ""; //---------------------------------------------------------------------------- @@ -79,7 +80,7 @@ Module::Module(const string& interfacePath, Rule eigenType_p = (str_p("Vector") | "Matrix"); - Rule className_p = lexeme_d[upper_p >> *(alnum_p | '_')] - eigenType_p - keywords_p; + Rule className_p = (lexeme_d[upper_p >> *(alnum_p | '_')] - eigenType_p - keywords_p)[assign_a(class_name)]; Rule namespace_name_p = lexeme_d[lower_p >> *(alnum_p | '_')] - keywords_p; @@ -199,10 +200,14 @@ Module::Module(const string& interfacePath, [pop_a(namespaces)] [pop_a(namespace_includes)]; - Rule using_namespace_p = str_p("using") >> str_p("namespace") + Rule using_namespace_p = + str_p("using") >> str_p("namespace") >> namespace_name_p[push_back_a(using_namespaces)] >> ch_p(';'); - Rule module_content_p = comments_p | using_namespace_p | class_p | namespace_def_p ; + Rule forward_delcaration_p = + (str_p("class") >> className_p >> ch_p(';'))[push_back_a(forward_declarations, class_name)]; + + Rule module_content_p = comments_p | using_namespace_p | forward_delcaration_p | class_p | namespace_def_p ; Rule module_p = *module_content_p >> !end_p; @@ -255,6 +260,18 @@ void verifyArguments(const vector& validArgs, const vector& vt) { } } +/* ************************************************************************* */ +template +void verifyReturnTypes(const vector& validtypes, const vector& vt) { + BOOST_FOREACH(const T& t, vt) { + const ReturnValue& retval = t.returnVal; + if (find(validtypes.begin(), validtypes.end(), retval.qualifiedType1("::")) == validtypes.end()) + throw DependencyMissing(retval.qualifiedType1("::"), t.name); + if (retval.isPair && find(validtypes.begin(), validtypes.end(), retval.qualifiedType2("::")) == validtypes.end()) + throw DependencyMissing(retval.qualifiedType2("::"), t.name); + } +} + /* ************************************************************************* */ void Module::matlab_code(const string& toolboxPath, const string& mexExt, const string& mexFlags) const { @@ -286,22 +303,23 @@ void Module::matlab_code(const string& toolboxPath, make_ofs << "MEXENDING = " << mexExt << "\n"; make_ofs << "mex_flags = " << mexFlags << "\n\n"; - //Dependency check list - vector validArgs; - validArgs.push_back("string"); - validArgs.push_back("int"); - validArgs.push_back("bool"); - validArgs.push_back("size_t"); - validArgs.push_back("double"); - validArgs.push_back("Vector"); - validArgs.push_back("Matrix"); + // Dependency check list + vector validTypes = forward_declarations; + validTypes.push_back("void"); + validTypes.push_back("string"); + validTypes.push_back("int"); + validTypes.push_back("bool"); + validTypes.push_back("size_t"); + validTypes.push_back("double"); + validTypes.push_back("Vector"); + validTypes.push_back("Matrix"); // add 'all' to Makefile make_ofs << "all: "; BOOST_FOREACH(Class cls, classes) { make_ofs << cls.qualifiedName() << " "; //Create a list of parsed classes for dependency checking - validArgs.push_back(cls.qualifiedName("::")); + validTypes.push_back(cls.qualifiedName("::")); } make_ofs << "\n\n"; @@ -317,9 +335,13 @@ void Module::matlab_code(const string& toolboxPath, cls.matlab_proxy(classFile); // verify all of the function arguments - verifyArguments(validArgs, cls.constructors); - verifyArguments(validArgs, cls.static_methods); - verifyArguments(validArgs, cls.methods); + verifyArguments(validTypes, cls.constructors); + verifyArguments(validTypes, cls.static_methods); + verifyArguments(validTypes, cls.methods); + + // verify function return types + verifyReturnTypes(validTypes, cls.static_methods); + verifyReturnTypes(validTypes, cls.methods); // create constructor and method wrappers cls.matlab_constructors(toolboxPath,using_namespaces); diff --git a/wrap/Module.h b/wrap/Module.h index ec057b644..a900310eb 100644 --- a/wrap/Module.h +++ b/wrap/Module.h @@ -32,6 +32,7 @@ struct Module { std::vector classes; ///< list of classes bool verbose; ///< verbose flag std::vector using_namespaces; ///< all default namespaces + std::vector forward_declarations; /// constructor that parses interface file Module(const std::string& interfacePath, diff --git a/wrap/tests/geometry.h b/wrap/tests/geometry.h index 9e50beb0b..92e23692a 100644 --- a/wrap/tests/geometry.h +++ b/wrap/tests/geometry.h @@ -4,6 +4,8 @@ // location of namespace isn't significant using namespace geometry; +class VectorNotEigen; + class Point2 { Point2(); Point2(double x, double y); diff --git a/wrap/tests/testWrap1.h b/wrap/tests/testDependencies.h similarity index 93% rename from wrap/tests/testWrap1.h rename to wrap/tests/testDependencies.h index 0cc16fc71..429bb5a2a 100644 --- a/wrap/tests/testWrap1.h +++ b/wrap/tests/testDependencies.h @@ -13,6 +13,7 @@ class Pose3 { double x() const; double y() const; double z() const; + Rot3 testReturnType() const; // Throw here Matrix matrix() const; Matrix adjointMap() const; Pose3 compose(const Pose3& p2); diff --git a/wrap/tests/testWrap.cpp b/wrap/tests/testWrap.cpp index 65edc11b5..c716b0379 100644 --- a/wrap/tests/testWrap.cpp +++ b/wrap/tests/testWrap.cpp @@ -57,12 +57,12 @@ TEST( wrap, check_exception ) { CHECK_EXCEPTION(Module("/alsonotarealpath", "geometry",enable_verbose), CantOpenFile); // clean out previous generated code - string cleanCmd = "rm -rf actual"; + string cleanCmd = "rm -rf actual_deps"; system(cleanCmd.c_str()); string path = topdir + "/wrap/tests"; - Module module(path.c_str(), "testWrap1",enable_verbose); - CHECK_EXCEPTION(module.matlab_code("actual", "mexa64", "-O5"), DependencyMissing); + Module module(path.c_str(), "testDependencies",enable_verbose); + CHECK_EXCEPTION(module.matlab_code("actual_deps", "mexa64", "-O5"), DependencyMissing); } /* ************************************************************************* */ @@ -72,8 +72,12 @@ TEST( wrap, parse ) { EXPECT_LONGS_EQUAL(3, module.classes.size()); // check using declarations - EXPECT_LONGS_EQUAL(1, module.using_namespaces.size()); - EXPECT(assert_equal("geometry", module.using_namespaces.front())); + strvec exp_using; exp_using += "geometry"; + EXPECT(assert_equal(exp_using, module.using_namespaces)); + + // forward declarations + strvec exp_forward; exp_forward += "VectorNotEigen"; + EXPECT(assert_equal(exp_forward, module.forward_declarations)); // check first class, Point2 {