
Evaluation of the MHPCC Engine (IPP.c)

- for every module & for the engine itself, there are a set of
  functions which may be unique to that component.  These include:
  malloc, free, warning handler, addDescriptor, addDataItem,
  deleteDataItem, and getDataItem.  

  It is very unclear why this level of flexibility and abstraction is
  helpful or useful.  The only one of these which is obvious to
  encapsulate with the module is the warning handler.  Clearly, it is
  important to the system, IPP.c, to define its unique value of malloc
  and free, but why should this be allowed to vary for each module?
  Also, why should the methods to interact with the I/O data
  structures be allowed to vary from module to module.  This
  implementations seems to add a layer of complexity that is not
  justified.  

- a module is invoked in the config file like this:

moduleName    par1=value1 par2=value2 par3=value3;

  there is no data typing at the script level; typing is implicit in
  the module's usage of a parameter name.

- two IPP data structures carry the information about the modules:
  char *moduleNames and DataItemList *params.  The list 'params'
  contains the par=value entries is a set of data structures with name
  and value pairs.  When the parameter list is parsed, the types are
  identified (int/float/string) and cast to those value types in the
  dataItem structure.  An additional data type is available to the
  module programmer, cell.  A cell data type may be created in the
  script language by a call to a module which returns a cell-type,
  such as readFITS.

- there is also the global parameter data structure which acts like an
  environment variable stack: these are always passed to the modules. 

- there is an IPP variable stack 'dataSpace' which contains data
  currently in use by IPP.  Modules share data through the dataSpace
  stack, either leaving output data on the stack or pulling required
  data from the stack.

- basic steps of IPP.c:

  - define engine functions (initEngine) 
    this sets the values of the abstracted engine functions discussed
    above.
  - parse config file (ParseConfigurationFile)
    this reads the config file and sets up the moduleName/params
    structures.
  - load the identified modules (a loop in main)
    this calls 'loadModule' for each module identified in the config
    file, which in turn creates a Module structure for the module,
    loads the library file associated with the named module, assigns
    the parameter list to the module structure, and calls the module's
    init function.  The init function makes the association between
    module parameters and module data descriptors.  Note that not all
    parameters are associated with a data descriptor; the module
    programmer may choose this association on whatever basis.
  - execute each module (a loop in main)

    * determine the module type: this simply loops over the module
      data descriptors and identifies the data type, but gives an
      error if a module defines multiple data types.

    * identify the required data in the dataSpace.  this section will
      automatically create a MAJOR_FRAME data item in the dataSpace if
      required.  ** a strange choice here **

    * call the module 
      callModule iterates through data type levels to match the given
      data entry with the given module data level. 

    * free temporary data

    
