The GME pattern based generator-interpreter



The pattern based generator-interpreter is probably the most convenient way to provide simple interpretation (e.g. data export to different file formats) of  GME models. The pattern based generator is paradigm-independent, so it can be used with any kind of models, only a pattern file needs to be created

The generator-interpreter reads a pattern file, and based on its contents generates output to one or several files. The pattern file may contain plain text, which is copied to the output verbatim, and special pattern instructions (funtions like $!EVAL_FORALL and macros like $Name), that are evaluated, and their result is inserted into the output. Pattern instructions have arguments. An significant type of arguments are text arguments, which can again contain any mixture of plain text or pattern instructions.

The pattern is always evaluated in the context of an FCO, which is used when evaluating pattern instructions.
Sme pattern instructions ($!EVAL_WITH, and $!EVAL_FORALL) change the context when evaluating their text arguments.
 
 

$<varname>
 Evaluate variable or attribute vname and return its value in the output.

First, the set of variables is searched for vname (variables are defined by $!DEFINE, see below)
Next if vname is “name”, return the name of the current object
Otherwise read and return current object's the attribute identified by vname
If none is defined, report error.

$!EVAL_FORALL(<fieldspec>, <textarg>)
 Get any number (including 0) of objects identified by fieldspec iterate through them,
 and evaluate arg2 in their context.
<fieldspec> may contain one of the following specifications:

R:<rolename>

the children of this role

K:<kindname> 

the children of this kind

Parent 

 the parent of this object if any

Type 

 the basetype of this object if any

Ref 

the target of a reference object if any

Members:<kindname>

the members of a set object

Dst:<rolename> 

the destination peer(s) of all connections to the current object with corresponding

Src:<rolename> 

the souce peer(s) of all connections to the current object with corresponding

$!EVAL_WITH(<fieldspec>, <textarg>)
 Get the single object identified by fieldspec and evaluate arg2 in its context, return the result
See above the specification of <fieldspec>

$!IFEMPTY(<textarg1>, <textarg2>)
 If arg1 evaluates to an empty string, evaluate arg2 and return the result

$!TO_FILE(<arg>)
 Close current output file, and start writing to the file specified by arg

$!DEFINE(<varname>, <textarg>)
 Create or redefine the variable identified by varname to contain the current value of textarg

$!POSTINCR(<varname>)
 Increment variable varname by 1, and return its original value (its value must be legible as a number)

$!SEQ(<textarg1>, <textarg2>, ...)
 Evaluate textargs one by one and append their result

$!PAD(<width>, <textarg>)
Make sure the output of textarg is at least ABS(<width>) characters wide. The string is left-justified if <width>  > 0, and right justified if
< 0

Separating verbatim text and pattern instructions

The text of the pattern file is copied verbatim to the output, unless a pattern instruction (beginning with $) is detected. A pattern instruction must fit into a single line, but physical lines can be merged into a single logical one by specifying \ as the last character of the first line. ‘$’ and ‘\’ characters are produced using ‘\$’ and ‘\\’ respectively.

Text arguments within functions are evaluated in a similar fashion, but
1. they may be surrounded by double quotes ( “ “ ) to indicate the borders of the string. Otherwise, a string is terminated by the first unquoted ‘,’ or ‘)’
2. ‘\t’ and ‘\n’ is converted to tab and newline characters in the generated output.

 

Example

The following pattern file generates C++ source code (for a Corba execution enviroonment)
 

$!DEFINE("_FILENAMEBASE", "$!IFDEFAULT("FileNameBase","$(Name)")")
$!TO_FILE("$!IFDEFAULT("OutputPath","")$(_FILENAMEBASE).h")
#include <stdio.h>
#include "gtsec/sigman/sigman.h"

#include "SimpleSignal.h"
 

int main(int, char**)
{
 gtsec::sigman::BsMechanism bs($_SYSPOS, $_SYSCNT);  // create boldstroke
 gtsec::sigman::SignalManager_i sm(&bs);// create signal manager 
 sm.AddUUId(10,10,"outputport1");
 sm.AddUUId(10,20,"inputport1");
$!DEFINE("_PORTINDEX","100");
$!EVAL_FORALL("R:OutputPorts","    sm.AddUUId($_SYSPOS,$!POSTINCR("_PORTINDEX"),"$Name");\n")
$!EVAL_FORALL("R:InputPorts", "       sm.AddUUId($_SYSPOS,$!POSTINCR("_PORTINDEX"),"$Name");\n")

 // create output ports here
 // the data type must be specified 
$!EVAL_FORALL("R:OutputPorts","    gtsec::sigman::BsOutputPort\
<$!EVAL_WITH("Dst:SigTypConns","$!EVAL_WITH("Ref","$!EVAL_WITH("Parent","$Name")")")>\
 outp("$Name",&sm);\n")
 sm.DeclareOutputs();
 // create input ports here 
 // here we create an input port "inputport1" and hook it to "outputport1" 
 // again, the data type must be specified 
$!EVAL_FORALL("R:InputPorts","    gtsec::sigman::BsInputPort\
<$!EVAL_WITH("Src:PortConns","$!EVAL_WITH("Dst:SigTypConns","$!EVAL_WITH("Ref","$!EVAL_WITH("Parent","$Name")")")")>\
 inpp("$Name",&sm, $!EVAL_WITH("Src:PortConns","\"$Name\""));\n")
 sm.DeclareInputs();

$!EVAL_FORALL("R:Components","   !!!!!!SimpleComponent component(&sm);
 comp = &component;
 GraphComponent graph(&sm, 120);
 GraphComponent graph2(&sm, 250, "Enhanced graph display");
 GeneratorComponent gcomponent(&sm);

 component.On();
 graph.On();
 graph2.On();
 gcomponent.On();
    if(_beginthreadex(NULL, 1000, boldstroke, NULL, 0, NULL) == NULL) { 
      printf("Cannot thread\n");
    }

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
//  TranslateMessag
   

e(&msg);
  DispatchMessage(&msg);
 }
 return 0;
}