TRACING

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

TRACING

Jens Ruecknagel-2
Hi JD Cole,

Thanks to you I am tracing through Octave and your .oct File - so the
debugger looks up which header file a function comes from.

I Compiled Octave with -O0 and your oct file with -O0 (had to screw
around in mkoctfile) - but now it works

By the way - somehow your code does not compile with octave 2.54 - so I
downgraded to 2.50 - thats good enougth for right now
in 2.54 the compiler complains about a not defined symbol in compile.cc
f->functionname - didn`t want to look around for it.
I think there is no need for it right now.

Jens


Reply | Threaded
Open this post in threaded view
|

Re: TRACING

JD Cole
It's quite possible that that variable has gone away, there have been
some big changse to Octave internals since I wrote that code. You might
try comparing that file, i.e. pt-emit-cplusplus.cc, to the 2.1.55 of
Octave's pt-pr-code.cc---that file was the basis of
pt-emit-cplusplus.cc. Basically pt-pr-code gives you a good overview of
variables contained in each class of the parse tree, variable that will
be usefull in creating the code converter we've been talking about.

Another thing you could do to get a better feel for overall Octave code
is to use a code doc system like Doxygen to generate nicely format
documentation of the code. Especially valuable is the way in which
doxygen displays class dependencies. Check out www.doxygen.org, if you
need help, get back to me.

JD

Jens Ruecknagel wrote:

> Hi JD Cole,
>
> Thanks to you I am tracing through Octave and your .oct File - so the
> debugger looks up which header file a function comes from.
>
> I Compiled Octave with -O0 and your oct file with -O0 (had to screw
> around in mkoctfile) - but now it works
>
> By the way - somehow your code does not compile with octave 2.54 - so
> I downgraded to 2.50 - thats good enougth for right now
> in 2.54 the compiler complains about a not defined symbol in
> compile.cc f->functionname - didn`t want to look around for it.
> I think there is no need for it right now.
>
> Jens
>



Reply | Threaded
Open this post in threaded view
|

Re: TRACING

JD Cole
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();
}
Reply | Threaded
Open this post in threaded view
|

Re: TRACING

Jens Ruecknagel-2
Hi JD,

thanks to your comments I just found a bug:
If the returnlist is fully included in parameterlist then there are no
out parameters to print - but a "," as separator is printed before the
empty list of out parameters.

run compile("problem")  //problem.m attached

don't get up to Fix it - Ill do it. Just want to show, I passed your
test ;-)

JD Cole wrote:

> 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();
> }


Reply | Threaded
Open this post in threaded view
|

Re: TRACING

Jens Ruecknagel-2
In reply to this post by Jens Ruecknagel-2
Hi JD,

thanks to your comments I just found a bug:
If the returnlist is fully included in parameterlist then there are no
out parameters to print - but a "," as separator is printed before the
empty list of out parameters.

run compile("problem")  //problem.m attached

don't get up to Fix it - Ill do it. Just want to show, I passed your
test ;-)

function [a,b] = problem(a, b)
a= a+1;
b= b-1;
endfunction

JD Cole wrote:

> 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();
> }



Reply | Threaded
Open this post in threaded view
|

Octave compiler

Paul Thomas-10
JD and Jens,

Have you given any thought yet as to how you will do the C++ generation?  

I suppose that a first order approach would be, in essence, to output
the octave evaluator code.  However, I suspect that the performance
improvement over that of the interpreter/evaluator will not be as
impressive as writing .oct files "by hand".  Therefore, the trick is
going to be to improve on the evaluator, particularly where type
identification, indirect referencing and bound checking is concerned.
 Once you do that, the strategy you have adopted should allow to
similarly improve octave's evaluator, should it not?

Paul Thomas


Reply | Threaded
Open this post in threaded view
|

Re: Octave compiler

Paul Kienzle
In lieu of intelligence, one can always use pragmas to identify types.
E.g.,
        %% int i
        %% double t, x[]
        t=0; for i=1:n, t += x(i); end

You can even do this in octave code instead of special syntax:

        x=double(x);
        t=double(0); for i=int(1:n), t += x(i); end

but you need some way to make sure that double, int, etc. always
return values of the right type, even in the presence of dispatch, oct
files, user defined types, etc.

- Paul
       
On Feb 22, 2004, at 10:46 AM, Paul Thomas wrote:

> JD and Jens,
>
> Have you given any thought yet as to how you will do the C++
> generation?
> I suppose that a first order approach would be, in essence, to output
> the octave evaluator code.  However, I suspect that the performance
> improvement over that of the interpreter/evaluator will not be as
> impressive as writing .oct files "by hand".  Therefore, the trick is
> going to be to improve on the evaluator, particularly where type
> identification, indirect referencing and bound checking is concerned.
> Once you do that, the strategy you have adopted should allow to
> similarly improve octave's evaluator, should it not?
>
> Paul Thomas
>


Reply | Threaded
Open this post in threaded view
|

Re: Octave compiler

Paul Thomas-10
Yes, that is what I was getting at - or explicit type declaration.  I
had more than once wondered if the language would benefit from optional
type assertion in some shape or form.  This, however, brings to mind the
discussion,a few months back, of passing arguments by reference or by
value. Compatability with the other product makes them very undesirable.
 Equally, to judge by the other products performance on basic
interpretation/evaluation, intelligence must exist.....  I have started
analysing typical .m functions to see how intelligence might be
manifested in either interpreters or compilers.

Paul T

Paul Kienzle wrote:

> In lieu of intelligence, one can always use pragmas to identify types.
> E.g.,
>     %% int i
>     %% double t, x[]
>     t=0; for i=1:n, t += x(i); end
>
> You can even do this in octave code instead of special syntax:
>
>     x=double(x);
>     t=double(0); for i=int(1:n), t += x(i); end
>
> but you need some way to make sure that double, int, etc. always
> return values of the right type, even in the presence of dispatch, oct
> files, user defined types, etc.
>
> - Paul
>    
> On Feb 22, 2004, at 10:46 AM, Paul Thomas wrote:
>
>> JD and Jens,
>>
>> Have you given any thought yet as to how you will do the C++ generation?
>> I suppose that a first order approach would be, in essence, to output
>> the octave evaluator code.  However, I suspect that the performance
>> improvement over that of the interpreter/evaluator will not be as
>> impressive as writing .oct files "by hand".  Therefore, the trick is
>> going to be to improve on the evaluator, particularly where type
>> identification, indirect referencing and bound checking is concerned.
>> Once you do that, the strategy you have adopted should allow to
>> similarly improve octave's evaluator, should it not?
>>
>> Paul Thomas
>>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: Octave compiler

JD Cole
Well,
    One possibility would be to do some nifty type dependency analysis.
For my parallel processing musings I'm in the process of implementing
control and data dependency graphs. This kind of program representation
should facilitate determining variable types throughout the .m. However,
it may be necessary to impose at least some restrictions on the user.
I'm thinking of a snippet like the following which would cause bumps in
streamlining C++:

a = 10;
b = 23 * a;

a = "My name is George";
printf("%s",a);

As you all are aware, multiple uses for variables is highly frowned upon
when they are the same type, let alone when they are different, e.g.
integer and string. But this a comonly used feature in Octave/Matlab so
perhaps variables such as these are just left "generic" in the converted
code.

JD

Paul Thomas wrote:

> Yes, that is what I was getting at - or explicit type declaration.  I
> had more than once wondered if the language would benefit from
> optional type assertion in some shape or form.  This, however, brings
> to mind the discussion,a few months back, of passing arguments by
> reference or by value. Compatability with the other product makes them
> very undesirable. Equally, to judge by the other products performance
> on basic interpretation/evaluation, intelligence must exist.....  I
> have started analysing typical .m functions to see how intelligence
> might be manifested in either interpreters or compilers.
>
> Paul T