SLIFunctionWrapper

Command: SLIFunctionWrapper


Description

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.

IMPORTANT:
Please see remarks below for a SET OF RULES THE USER ROUTINE MUST
ADHERE TO!

Parameters

/funcname - The function name (will be assigned to the
wrpper function).
[/trietypes
/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.

Author

Ruediger Kupper

Availability

SLI2.0

Synopsis

/funcname [/trietypes] [/variablenames] {procedure} SLIFunctionWrapper -> FunctionResult
/funcname [/trietypes /variablenames] {procedure} SLIFunctionWrapper -> FunctionResult

References

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

Examples


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
function.

/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
(b)
(a)

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

File
lib/sli/misc_helpers.sli
Diagnostics

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

Remarks

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
SLIFunctionWrapper.
/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.