Name: SLIFunctionWrapper - Define a SLI function with lots of comfort.

Synopsis:

/funcname [/trietypes] [/variablenames] {procedure} SLIFunctionWrapper -&gt; FunctionResult 
/funcname [/trietypes   /variablenames] {procedure} SLIFunctionWrapper -&gt; FunctionResult


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


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.


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.


Availability:

SLI2.0


References:

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


Author:

Ruediger Kupper


FirstVersion:

21.3.2003


SeeAlso:

def
raiseerror
setverbosity
SFWdumpparameters

Source:

/var/www/debian/nest/nest-simulator-2.20.0/lib/sli/misc_helpers.sli
