SLIFunctionWrapper - Define a SLI function with lots of comfort.
/funcname [/trietypes] [/variablenames] {procedure} SLIFunctionWrapper -> FunctionResult
/funcname [/trietypes /variablenames] {procedure} SLIFunctionWrapper -> FunctionResult


The following defines a function called "myfunc", taking two arguments
of type integer and double. The function will have a type trie for
parameter typechacking, as well as a local dictionary. The arguments
will be known as "x" and "y" inside the local dictionary of the

/myfunc [/integertype /x /doubletype /y]
(see how my local dictionary looks like:) = who
} SLIFunctionWrapper

The parameterlist could have also been specified like this:

/myfunc [/integertype /doubletype] [/x /y] {...} SLIFunctionWrapper

This defines functions expecting no parameters:

/f [] {...} SLIFunctionWrapper
/f2 [] [] {...} SLIFunctionWrapper

The routine can litter is local dictionary as it likes. The dictionary
will automatically be closed when the routine ends:

/f []
/this 23 def
/will 0.0 def
/be 1 def
/forgotten -3 def
} SLIFunctionWrapper

If the routine raises an error, the local dictionary is closed, and
the stack will be automatically restored to the condition it was
before the function call:

/f []
/myvar 0.0 def
% push rubbish on the stack:
1 2 3 4 5 6 7
% now raise an error:
funcname /Error raiseerror
} SLIFunctionWrapper

SLI ] (a) (b) f
Error: /Error in f
SLI [2] pstack

If a nested routine causes an error, the stack is NOT restored, and
the local dictionary is NOT closed:

/f []
/myvar 0.0 def
% push rubbish on the stack:
1 2 3 4 5 6 7
% now cause an error:
0 0 div
} SLIFunctionWrapper

SLI ] (a) (b) f
Error: /DivisionByZero in div_ii
SLI [12] who
Name Type Value
myvar doubletype 0
Total number of entries: 1

SLIFunctionWrapper provides a very convenient way to define and manage
a SLI function. Much like the command "def", it has a way to
define the parameter list of the function. In addition, before the
actual routine is called, its parameters will be popped from the
stack and assigned to names, which then are provided to the
routine in a local dictionary. Furthermore, SLIFunctionWrapper
rids the user from the need to restore the operand stack before
raising an error, the routine will take care of that.
All this is achieved by putting the actual user routine inside a
wrapper routine, which is assigned to the given name. The wrapper
routine will perform all sorts of bureaucracy, then call the
actual routine, and clean up the stack if necessary afterwards.

The function's definition resembles the ones in C++.
Please see examples below for demonstrations.

Please see remarks below for a SET OF RULES THE USER ROUTINE MUST

/funcname - The function name (will be assigned to the
wrpper function).
/variablenames] - List of parameters and their names. This may
either be two separate arrays of literals, the first one defining
the variable types, the second one their names, or
a single array of literals, consisting of pairs of
type and name. See examples below. The resulting call looks pretty
much like a function definition in C++.
{procedure} - The actual procedure to be called from the wrapper.

Several messages of priority M_DEBUG are issued to let the programmer
know what happens. They may be turned off using "setverbosity".

Rules the user routine MUST adhere to:
The user routine must not leave any "mark" on the stack if it fails.
The user routine must not make any assumptions on the contents of the
stack, that lie deeper than the level at which it took control
The user routine must not modify any contents of the operand stack,
that lie deeper than the level at which it took control.
The user routine must restore the dictionary stack to the state it was
when it took control, before it ends or fails.
The user routine must not re-define the variable /funcname.
When raising an error, /funcname must be specified as the routine name
(i.e., the name that was specified in the call to SLIFunctionWrapper).

No "bind" is performed on the procedure. If namebinding is wanted, the
user has to call "bind" explicitely before passing the procedure.

The type-specifyer-array(s) may be empty, indicating that the routine
does not expect any parameters.

The following names are known by the user routine, being defined in an
enclosing dictionary (not the routine's local dictionary):
/funcname - The wrapper's name, as specified in the call to
/localdict - The user routine's local dictionary.
It is already open when the routine takes control,
and shall not be closed by the user rotuine.
/n_params - Number of parameters to the user routine.
/rvarnames - Array containing the names of the local variables defined
in the local dictionary, in reversed order.
/function - The user routine object.

Convenience comes at a cost. The wrapper routine causes considerable
overhead. Do not use this technique for routines that will be used at
time-critical positions, e.g. inside loops.


[1] Ruediger Kupper, SLI library management,
HRI-EU Report 06/05, Honda Research Institute Europe GmbH, 2006.

Ruediger Kupper


SeeAlso: Source: