Sorry, forgot to add the compile.cc attachment.
JD
------------------------------------------------------------------------
#include <octave/oct.h>
#include <pt-all.h>
#include <pt-emit-cplusplus.h>
#include <parse.h>
using namespace std;
DEFUN_DLD(compile, args, , "compile")
{
// Make sure that the argument passed exists and is a string
if(args.length() > 0
&& args(0).is_string())
{
// Lookup this name in the symbol tables, this will either find
// the name or cause Octave to load the similarly named .m (or .oct)
symbol_record *s = lookup_by_name(args(0).string_value(),false);
// Make sure the file was found and it's a function
if (s && s->is_function())
{
// Create a tree_walker structure
tree_emit_cplusplus tpc(cout);
// Print out the numbered debug info
tpc.set_debug_mode ();
// Get a pointer to the function
octave_user_function *f =
(octave_user_function*)s->def().function_value();
// The body of the function is the main portion we want to convert,
// bodies are composed of a singe statement list...this is effectively
// the top of the parse tree for the body of the function
tree_statement_list *bd = f->body();
// Throw in the apropriate header information
cout << "#include <octave/oct.h>\n\n";
// And start the function call
cout
<< "extern void\n"
<< f->function_name()<<" (";
// A list of the parameters passed IN to the function
tree_parameter_list *pl = f->parameter_list ();
// A ist of the parameters passed OUT of the function
tree_parameter_list *rl = f->return_list ();
// Find matching parameter variables
// I match the parameter values here so that they can be used
// as "INOUT" variable in the function header, i.e. if a variable
// is used as both input and output. The values which are only
// passed in are labeled "const"
// =================== sTart the parameter matching stuff ===========
// This is ugly code and really not too necessary to get compiler
// stuff rolling, probably more energy should be put into the
// actual code converting
int pl_len = 0;
int rl_len = 0;
if(pl)
pl_len = pl->length();
if (rl)
rl_len = rl->length();
bool pl_match[pl_len];
bool rl_match[rl_len];
int pl_index = 0;
// Set up a table which indicates which parameters have
// been matched so far
if (pl)
{
for (unsigned int i = 0; i< pl->length(); i++)
pl_match[i] = false;
}
if (rl)
{
for (unsigned int i = 0; i< rl->length(); i++)
rl_match[i] = false;
}
// If there are inputs and outputs, then continue, if not
// we don't have to worry about matching
if (pl && rl)
{
// We're going to iterate through the parameter list
tree_parameter_list::iterator plp = pl->begin();
// Until the end
while (plp != pl->end())
{
// Check this parameter name
tree_identifier *pid = *plp;
plp++;
// This is "clean" code, make sure the parameter
// identifier exists
if (pid)
{
// Now iterate through the return list to find
// potential matches
tree_parameter_list::iterator rlp = rl->begin();
int rl_index = 0;
while (rlp != rl->end())
{
tree_identifier *rid = *rlp;
rlp++;
if (rid)
{
// Basically these lines just plug in true or
// false if a name has been matched, they use
// bitwise OR (logically identical to logical OR)
// because we don't want to over write a
previously
// determined true with a false
pl_match[pl_index] |= (pid->name() == rid->name());
rl_match[rl_index] |= (pid->name() ==
rid->name());
}
// Check the next return item
rl_index++;
}
}
// check the next parameter
pl_index++;
}
}
// now it's time to print them out, we're going to start with
// the parameter list (they go on the first line in the output
// immediately following the function name)
if(pl)
{
// This should be familiar...think iteration
tree_parameter_list::iterator p = pl->begin ();
pl_index = 0;
if(p != pl->end ())
{
tree_identifier *elt = *p;
while (p != pl->end ())
{
p++;
if(elt)
{
// If a matched entry was found, don't
// use const
if(pl_match[pl_index])
cout << "octave_value& ";
else
cout << "const octave_value& ";
cout << elt->name();
// In the symbol list (which will be used later)
// mark all the parameters as existing/true
tpc.symbol_used (elt->name(), true);
}
if(p == pl->end ())
break;
elt = *p;
if (elt)
cout<< ", ";
pl_index++;
}
}
}
// Now print out the remaining return list items, that is, those
// that didn't have matches to parameters
if(rl)
{
// These is just pretty indenting for a second line of values
if (pl)
{
cout<<",\n";
for (unsigned int i= 0;i< f->function_name().length();i++)
cout<<" ";
cout<<" ";
}
// Let's iterate
tree_parameter_list::iterator p = rl->begin ();
int rl_index = 0;
if(p != rl->end ())
{
tree_identifier *elt = *p;
while (p != rl->end ())
{
p++;
if(elt)
{
// Only print if there was no match
if(!rl_match[rl_index])
{
cout << "octave_value& ";
cout << elt->name();
tpc.symbol_used (elt->name(), true);
}
}
if(p == rl->end ())
break;
elt = *p;
// Don't put a comma on the last one
if (elt && rl_match[rl_index])
cout<< ", ";
rl_index++;
}
}
}
// complete the function preamble and start the body
cout<<")\n{\n";
// ====================== End the paremeter matching stuff ========
// It's pretty ugly code and probably isn't that relevant to the
// initial compiler work.
// Start the pt_emit_cplusplus on the body of the loop, this will
// "emit" C++ to standard output (stdout or cout)
bd->accept(tpc);
// end the function body
cout<<"}"<<endl;
}
}
return octave_value();
}