C++ Composition Tools |
AHEAD supports a provisional set of tools for composing C++ files, specifically .cpp and .h files. These tools, mix and unmix, approximate a counterpart to the mixin and unmixin tools of AHEAD. In the following, we sketch the basic design of how C++ files can be composed, and then describe the mix and unmix tools themselves. This material and the tools themselves are subject to change.
Design |
Our goal is to be able to compose C++ files. To do this easily and quickly, we require the following constraints.
With the above constraints, we can integrate the mix tool with composer, and use AHEAD tools and design techniques to synthesize applications in C++. Examples of all the above will be given shortly.
.h Files |
An example of a .h file for a base class is listed below:
import_ "Param.h" class class_ { public: class_(Param& b); string GetName(); int Dof() const; bool SetServoValue(const RRVector& v); protected: int m_dof; string m_name; RRVector m_vals; };
Note the use of the class_ and import_ identifiers. In general, class_ is used to designate the name of the class, class constructor(s) and class destructor(s). An example of a .h file for a refinement class is:
import_ "Param.h" class class_ : super_ { public: class_(Param& b); bool SetServoValue(const RRVector& v); protected: RRVector m_minLimits; RRVector m_maxLimits; };
Note the use of class_, super_, and import_ identifiers.
.cpp Files |
An example of a .cpp file of a base class is:
import_ "Servo.h" class_::class_(Param& b) { m_dof = b.dof; m_name = b.name; } string class_::GetName() { return m_name; } int class_::Dof() const { return m_dof; } bool class_::SetServoValue(const RRVector& v) { m_vals = v; cout<<v<<endl; return true; }
Note that class constructors are always defined as class_::class_ and destructors are class_::class_~. An example of a .cpp file of a refinement is:
class_::class_(Param& b) : super_(b) { m_minLimits = b.minLimits; m_maxLimits = b.maxLimits; } bool class_::SetServoValue(const RRVector& v) { bool isInLimits = true; //check limits here for(int i=0; i< m_dof; i++) { ... }//end check limits return super_::SetServoValue(v); }
Note how class_ and super_ are used.
The mix Tool |
mix is a tool that composes .cpp and .h files. It is really never called directly by users. Rather, AHEAD users simply invoke composer, and composer invokes mix. In this section, we explain how mix works so that users can better understand its mechanics. When mix composes a set of .cpp or .h files, it does the following:
Suppose the base and refinement .h files defined above are composed. The result is:
#ifndef _import_ (1) #include "Param.h" #define _import_ #endif class Servo; (2) #ifdef class_ (3) #undef class_ #undef super_ #undef namespace_ #endif #define super_ Servo__0 #define class_ Servo__1 #define namespace_ test2 //SoUrCe ../Base/Servo.h (4) //import_ "Param.h" (5) class class_ { (6) ... }; //EnDSoUrCe (7) class Servo; #ifdef class_ #undef class_ #undef super_ #undef namespace_ #endif #define super_ Servo__1 #define class_ Servo #define namespace_ test2 //SoUrCe ../Limits/Servo.h //import_ "Param.h" class class_ : super_ { ... }; //EnDSoUrCe
Note the following, which corresponds to the numbering above
Thus, when each .h file is composed, new names are given to the class_ and super_ identifiers.
Note: at the time of this writing, it is becoming obvious that this design can be improved, such as the elimination of the #ifdef _import_, the generation of only a single #define namespace_ statement, and maybe the generation of only a single forward reference. Once further improvements have been decided upon, the tool and its documentation will be updated.
As stated earlier, the mix tool really isn't called directly by users. Instead, users invoke composer and composer calls mix. The standard way is:
Base Logging Limits
> composer --equation=test3
If you insist on calling mix directly, do so as:
>mix Error: must specify at least one input file Usage: java mix.Main [options] baseFile extensionFile1 extensionFile2 ... -a <layerName> name of layer to generate -f <fileName> name file to generate -output same as -f
The unmix Tool |
After files are composed, they are compiled, and a debugging cycle ensues: composed C++ files are edited, recompiled, etc. Manually backpropagating changes to the original .cpp and .h files is both tedious, slow, and error prone. Instead, you can use the unmix tool to do so automatically. unmix takes any number of .h and .cpp files produced by mix as input, and backpropagates their changes:
> unmix *.h *.cpp> unmix Error: must specify at least one input file Usage: java unmix.Main [options] file1 file2 ... -verbose
Use the -verbose option to see what files have changed. unmix does not propagate changes to source files that have not been changed.
When editing files, all text between //SoUrCe and //EnDSoUrCe comments defines a file. If unmix detects that changes to this file have been made, it backpropagates the entire file text. Note that it automatically uncomments import_ statements as part of this backpropagation effort.
Copyright © Software Systems Generator Research Group.
All rights reserved.
Revised: February 08, 2006.