ExpressionManager Subroutines

The modules used by the ExpressionManager, are as follows:

\ExpressionManager\Start(Script, ExpressionParent, ExpressionCaller [, ReturnErrors, NewValue, IsScript] )

This method first attempts to cast Script to a number, then tries to scope it to a tag, then attempts to compile it into an expression module. If Script casts to a number or scopes to a tag, it is returned. If Script compiles successfully, it is returned. If Script compiles successfully, it is launched with ExpressionParent and ExpressionCaller as parent and caller respectively. If the cast, scope, and compile fail, it will return Invalid unless the optional parameter ReturnErrors is set to true, in which case a string describing the problem will be returned.

NewValue is an optional initial value for the expression

IsScript should be set to TRUE if the expression will be a script expression. Defaults to FALSE.

This interface is designed to behave in the same way as tag Refresh() methods do when interpreting strings that may be constants, tags, or expressions.

\ExpressionManager\IsExpression(ModuleRef)

This subroutine protects calling code from the design decision to mark ownership of expressions using a signature. It returns 1 if ModuleRef refers to a running module that the ExpressionManager launched, and 0 otherwise.

\ExpressionManager\ToString(Obj)

This subroutine will return a string representation of Obj. ToString() handles constants, tags, and expressions. \ExpressionManager\Start(ExpressionManager\ToString(Obj), … ) will return a new instance of a running expression, or a reference to the same tag, or the same constant.

\ExpressionManager\SafeAssign(PTarget, Source)

This convenience routine checks to see if PTarget is a pointer to a running expression. If it is, the expression is slain. Then *PTarget is set to Source (*PTarget is always set, regardless as to whether it points to an expression).

\ExpressionManager\SafeCopy(Obj, ExpressionParent, ExpressionCaller)

The same as \ExpressionManager\Start(\ExpressionManager\ToString(Obj), ExpressionParent, ExpressionCaller).

\ExpressionManager\SafeRefresh(PRefreshedVar, ParmVar[, NewValue])

  PRefreshedVar{ Variable that is being refreshed.     };
  ParmVar{ Previous value of variable being refreshed. };
  NewValue{ Optional initial value for expression      };

If a tag parameter holds a running expression rather than a variable, care must be taken in refreshing it. The SafeRefresh method provides a convenient way for developers to ensure that all parameters are correctly refreshed, and at the same time ensures that similar operations use the same code path.

Using the Function tag as an example, its refresh module starts as follows:

Refresh [
  If watch(1);
  [
    {***************************************************}
    { Parameters to the Function                        }
    {***************************************************}
   {***** Update variables *****}
    \ExpressionManager\SafeRefresh(&P1, Parm[#P1]);
    \ExpressionManager\SafeRefresh(&P2, Parm[#P2]);
    \ExpressionManager\SafeRefresh(&P3, Parm[#P3]);
    \ExpressionManager\SafeRefresh(&P4, Parm[#P4]);

Here, the variables P1 through P4 are all parameters to the tag. SafeRefresh will instantiate the expression if necessary and will set the parameter to that expression. If the parameter is a tag reference or a simple constant, those will be handled correctly as well.

\ExpressionManager\ToValue(Parm)

Takes the return value from SafeRefresh and returns the current value of the expression, tag or constant. \ExpressionManager\ToValue should always be called to safely use the value of a parameter in a module.

The Function tag uses the following to access the values of these four parameters:

  RawValue = PickValid(Cast(\ExpressionManager\ToValue(P1), 3), 
           Valid(P1) ? Invalid : 0) +
             PickValid(Cast(\ExpressionManager\ToValue(P2), 3), 
           Valid(P2) ? Invalid : 0) +
             PickValid(Cast(\ExpressionManager\ToValue(P3), 3), 
           Valid(P3) ? Invalid : 0) +
             PickValid(Cast(\ExpressionManager\ToValue(P4), 3), 
           Valid(P4) ? Invalid : 0);

If  the parameter is a constant or expression, the scope resolution references to the tag-Name and tag-Value variables would be undefined. Any addition of  variables, such as child tags starting or another application starting would cause the code to re-trigger. This behavior is intentional to catch the addition of child tags AFTER the instantiation of the  references to them.