Re-factored matlab_code only emits code: it does not post-process the classes anymore. That is now done in parse_Markup, i.e., the constructor....

release/4.3a0
dellaert 2014-11-14 17:04:45 +01:00
parent 7a4748d3dc
commit e07402a58a
3 changed files with 71 additions and 64 deletions

View File

@ -394,51 +394,35 @@ void Module::parseMarkup(const std::string& data) {
// Explicitly add methods to the classes from parents so it shows in documentation
BOOST_FOREACH(Class& cls, classes)
cls.appendInheritedMethods(cls, classes);
}
/* ************************************************************************* */
void Module::generateIncludes(FileWriter& file) const {
// collect includes
vector<string> all_includes(includes);
// sort and remove duplicates
sort(all_includes.begin(), all_includes.end());
vector<string>::const_iterator last_include = unique(all_includes.begin(), all_includes.end());
vector<string>::const_iterator it = all_includes.begin();
// add includes to file
for (; it != last_include; ++it)
file.oss << "#include <" << *it << ">" << endl;
file.oss << "\n";
}
/* ************************************************************************* */
void Module::matlab_code(const string& toolboxPath, const string& headerPath) const {
fs::create_directories(toolboxPath);
// Expand templates - This is done first so that template instantiations are
// counted in the list of valid types, have their attributes and dependencies
// checked, etc.
vector<Class> expandedClasses = ExpandTypedefInstantiations(classes, templateInstantiationTypedefs);
expandedClasses = ExpandTypedefInstantiations(classes,
templateInstantiationTypedefs);
// Dependency check list
vector<string> validTypes = GenerateValidTypes(expandedClasses, forward_declarations);
vector<string> validTypes = GenerateValidTypes(expandedClasses,
forward_declarations);
// Check that all classes have been defined somewhere
verifyArguments<GlobalFunction>(validTypes, global_functions);
verifyReturnTypes<GlobalFunction>(validTypes, global_functions);
bool hasSerialiable = false;
hasSerialiable = false;
BOOST_FOREACH(const Class& cls, expandedClasses)
cls.verifyAll(validTypes,hasSerialiable);
// Create type attributes table and check validity
TypeAttributesTable typeAttributes;
typeAttributes.addClasses(expandedClasses);
typeAttributes.addForwardDeclarations(forward_declarations);
typeAttributes.checkValidity(expandedClasses);
}
/* ************************************************************************* */
void Module::matlab_code(const string& toolboxPath) const {
fs::create_directories(toolboxPath);
// create the unified .cpp switch file
const string wrapperName = name + "_wrapper";
@ -459,19 +443,18 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
// Generate includes while avoiding redundant includes
generateIncludes(wrapperFile);
// create typedef classes - we put this at the top of the wrap file so that collectors and method arguments can use these typedefs
BOOST_FOREACH(const Class& cls, expandedClasses) {
// create typedef classes - we put this at the top of the wrap file so that
// collectors and method arguments can use these typedefs
BOOST_FOREACH(const Class& cls, expandedClasses)
if(!cls.typedefName.empty())
wrapperFile.oss << cls.getTypedef() << "\n";
}
wrapperFile.oss << "\n";
// Generate boost.serialization export flags (needs typedefs from above)
if (hasSerialiable) {
BOOST_FOREACH(const Class& cls, expandedClasses) {
BOOST_FOREACH(const Class& cls, expandedClasses)
if(cls.isSerializable)
wrapperFile.oss << cls.getSerializationExport() << "\n";
}
wrapperFile.oss << "\n";
}
@ -484,14 +467,12 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
vector<string> functionNames; // Function names stored by index for switch
// create proxy class and wrapper code
BOOST_FOREACH(const Class& cls, expandedClasses) {
BOOST_FOREACH(const Class& cls, expandedClasses)
cls.matlab_proxy(toolboxPath, wrapperName, typeAttributes, wrapperFile, functionNames);
}
// create matlab files and wrapper code for global functions
BOOST_FOREACH(const GlobalFunctions::value_type& p, global_functions) {
BOOST_FOREACH(const GlobalFunctions::value_type& p, global_functions)
p.second.matlab_proxy(toolboxPath, wrapperName, typeAttributes, wrapperFile, functionNames);
}
// finish wrapper file
wrapperFile.oss << "\n";
@ -501,6 +482,23 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
}
/* ************************************************************************* */
void Module::generateIncludes(FileWriter& file) const {
// collect includes
vector<string> all_includes(includes);
// sort and remove duplicates
sort(all_includes.begin(), all_includes.end());
vector<string>::const_iterator last_include = unique(all_includes.begin(), all_includes.end());
vector<string>::const_iterator it = all_includes.begin();
// add includes to file
for (; it != last_include; ++it)
file.oss << "#include <" << *it << ">" << endl;
file.oss << "\n";
}
/* ************************************************************************* */
void Module::finish_wrapper(FileWriter& file, const std::vector<std::string>& functionNames) const {
file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
file.oss << "{\n";

View File

@ -37,40 +37,50 @@ struct Module {
typedef std::map<std::string, GlobalFunction> GlobalFunctions;
typedef std::map<std::string, Method> Methods;
std::string name; ///< module name
bool verbose; ///< verbose flag
// Filled during parsing:
std::string name; ///< module name
bool verbose; ///< verbose flag
std::vector<Class> classes; ///< list of classes
std::vector<TemplateInstantiationTypedef> templateInstantiationTypedefs; ///< list of template instantiations
std::vector<ForwardDeclaration> forward_declarations;
std::vector<std::string> includes; ///< Include statements
std::vector<std::string> includes; ///< Include statements
GlobalFunctions global_functions;
// After parsing:
std::vector<Class> expandedClasses;
bool hasSerialiable;
TypeAttributesTable typeAttributes;
/// constructor that parses interface file
Module(const std::string& interfacePath,
const std::string& moduleName,
bool enable_verbose=true);
Module(const std::string& interfacePath, const std::string& moduleName,
bool enable_verbose = true);
/// Dummy constructor that does no parsing - use only for testing
Module(const std::string& moduleName, bool enable_verbose=true);
/// MATLAB code generation:
void matlab_code(
const std::string& path,
const std::string& headerPath) const; // FIXME: headerPath not actually used?
void finish_wrapper(FileWriter& file, const std::vector<std::string>& functionNames) const;
void generateIncludes(FileWriter& file) const;
Module(const std::string& moduleName, bool enable_verbose = true);
/// non-const function that performs parsing - typically called by constructor
/// Throws exception on failure
void parseMarkup(const std::string& data);
/// MATLAB code generation:
void matlab_code(const std::string& path) const;
void generateIncludes(FileWriter& file) const;
void finish_wrapper(FileWriter& file,
const std::vector<std::string>& functionNames) const;
private:
static std::vector<Class> ExpandTypedefInstantiations(const std::vector<Class>& classes, const std::vector<TemplateInstantiationTypedef> instantiations);
static std::vector<std::string> GenerateValidTypes(const std::vector<Class>& classes, const std::vector<ForwardDeclaration> forwardDeclarations);
static void WriteCollectorsAndCleanupFcn(FileWriter& wrapperFile, const std::string& moduleName, const std::vector<Class>& classes);
static void WriteRTTIRegistry(FileWriter& wrapperFile, const std::string& moduleName, const std::vector<Class>& classes);
static std::vector<Class> ExpandTypedefInstantiations(
const std::vector<Class>& classes,
const std::vector<TemplateInstantiationTypedef> instantiations);
static std::vector<std::string> GenerateValidTypes(
const std::vector<Class>& classes,
const std::vector<ForwardDeclaration> forwardDeclarations);
static void WriteCollectorsAndCleanupFcn(FileWriter& wrapperFile,
const std::string& moduleName, const std::vector<Class>& classes);
static void WriteRTTIRegistry(FileWriter& wrapperFile,
const std::string& moduleName, const std::vector<Class>& classes);
};
} // \namespace wrap

View File

@ -64,12 +64,11 @@ TEST( wrap, check_exception ) {
THROWS_EXCEPTION(Module("/notarealpath", "geometry",enable_verbose));
CHECK_EXCEPTION(Module("/alsonotarealpath", "geometry",enable_verbose), CantOpenFile);
// clean out previous generated code
fs::remove_all("actual_deps");
string path = topdir + "/wrap/tests";
Module module(path.c_str(), "testDependencies",enable_verbose);
CHECK_EXCEPTION(module.matlab_code("actual_deps", headerPath), DependencyMissing);
// // TODO: matlab_code does not throw this anymore, so check constructor
// fs::remove_all("actual_deps"); // clean out previous generated code
// string path = topdir + "/wrap/tests";
// Module module(path.c_str(), "testDependencies",enable_verbose);
// CHECK_EXCEPTION(module.matlab_code("actual_deps"), DependencyMissing);
}
/* ************************************************************************* */
@ -413,7 +412,7 @@ TEST( wrap, matlab_code_namespaces ) {
// emit MATLAB code
string exp_path = path + "/tests/expected_namespaces/";
string act_path = "actual_namespaces/";
module.matlab_code("actual_namespaces", headerPath);
module.matlab_code("actual_namespaces");
EXPECT(files_equal(exp_path + "ClassD.m", act_path + "ClassD.m" ));
@ -441,7 +440,7 @@ TEST( wrap, matlab_code_geometry ) {
// emit MATLAB code
// make_geometry will not compile, use make testwrap to generate real make
module.matlab_code("actual", headerPath);
module.matlab_code("actual");
#ifndef WRAP_DISABLE_SERIALIZE
string epath = path + "/tests/expected/";
#else