/*
* library.sli
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
SLI library management initalization
*/
systemdict begin
/* BeginDocumentation
Name: namespace - Open a namespace
Synopsis:
/name namespace ...your.code... end -> -
Description:
"namespace" provides to SLI the concept of namespaces,
as known from C++.
The command changes the current scope to the namespace of the given
name, i.e.,
- all following symbol definitions go to this namespace
- all symbols that were previously defined in this namespace become
known
The namespace must be closed by an "end" statement.
The symbols defined in a namespace persist across closing and
re-opening of the namespace. Namespaces can be nested.
For alternative ways of accessing a namespace,
see "using" and "call".
Parameters:
/name - the namespace to open
Examples:
/myspace namespace % this opens namespace "myspace"
/var 23 def % this creates the variable "myspace::var"
/func {(This is stupid.) =} def % this creates the function "myspace::func"
end % this closes the namespace "myspace"
/myspace namespace % this re-opens the namespace "myspace"
who % this shows the variables defined in the namespace
end % this closes the namespace "myspace"
myspace /func call % this calls "myspace::func"
Diagnostics:
If the named object is not a dictionary, TypeMismatchError is raised.
Author:
Ruediger Kupper
FirstVersion:
21-jul-2003
Remarks:
Currently, namespaces are implemented as
dictionaries. Namespaces may become more tightly
integrated with the SLI interpreter in future.
The idea is to define a set of symbols not in the global user
dictionary, but in a separate dictionary that has the name of the
namespace. Thus, symbols in different namespaces can have
identical names, and are effectively disambiguated by the current
dictionary context.
Note that the namespace dictionary is looked up and created in the
current scope. This is to allow for nested namespaces.
Availability: SLI2.0
References:
[1] Ruediger Kupper, SLI library management,
HRI-EU Report 06/05, Honda Research Institute Europe GmbH, 2006.
SeeAlso: call, using, endusing
*/
/namespace[/literaltype]
{
%stack: /name
dup
lookup
{%stack: /name dict
dup type /dictionarytype neq
{
pop
M_ERROR (namespace) (Object is not a dictionary.) message
/namespace /TypeMismatchError raiseerror
} if
begin
pop
}
{%stack: /name
<< >> dup rolld Set
begin
} ifelse
} bind def
/* BeginDocumentation
Name: using - Make symbols of a namespace or dictionary available in the current scope.
Synopsis:
/namespace using ...your.code... endusing -> -
<<dictionary>> using ...your.code... endusing -> -
Description:
The 'using' statement provides read access to a namespace or
dictionary, without changing the current scope for new symbol
definitions.
The 'using' statement must be closed by 'endusing'.
**********************************************************************
* IMPORTANT: *
* The 'using' statement puts the specified namespace *
* or dictionary in the second position of the dictionary stack. This *
* means that LOCAL SYMBOLS WILL SHADOW SYMBOLS OF THE SAME NAME FROM *
* THE SPECIFIED NAMESPACE OR DICTIONARY. This makes the 'using' *
* statement unsafe in all situations where you do not have explicit *
* control of the current dictionary. YOU MAY END UP CALLING A *
* FOREIGN SYMBOL. *
* There are two ways to avoid this problem: *
* (a) use 'namespace' or 'call', which provide read/write access to *
* the namespace or dictionary and don't have the shadowing *
* problem. *
* (b) put an empty dictionary on the dictionary stack at the *
* beginning of your routine, providing a local symbol *
* scope for your routine. The 'SLIFunctionWrapper' *
* command does this for you automatically. *
**********************************************************************
Parameters:
/name - name of the the namespace to use
<<dictionary>> - dictionary to use
Examples:
% the following makes the routines of the unittest library available to the current scope:
(unittest) (6688) require
/unittest using
..your code..
endusing
% the following makes the models in modeldict available to the current scope:
modeldict using
..your code..
endusing
% alternatively, you can also use the literal name:
/modeldict using
..your code..
endusing
Diagnostics:
If the name is not known, UndefinedNameError is raised.
If the name is not bound to a dictionary, TypeMismatchError is raised.
Author: Ruediger Kupper
FirstVersion: 6-aug-2003
Remarks:
Please note that 'using'/'endusing' is implemented by the opening and
closing of dictionaries. Code between 'using' and 'endusing' should
hence have completely matched 'begin' and 'end' statements, or special
care must be taken when using non-matched 'begin'/'end' constructs
inside a 'using' context.
Availability: SLI2.0
References:
[1] Ruediger Kupper, SLI library management,
HRI-EU Report 06/05, Honda Research Institute Europe GmbH, 2006.
SeeAlso: endusing, namespace, call
*/
/using[/dictionarytype]
{
%stack: dict
currentdict
exch begin begin
} bind def
/using[/literaltype]
{
%stack: /name
dup
lookup not
{
M_ERROR (using) (A namespace or dictionary of the given name is not known.) message
/using /UndefinedNameError raiseerror
} if
%stack: /name dict
dup type /dictionarytype neq
{
pop
M_ERROR (using) (Object is not a namespace or dictionary.) message
/using /TypeMismatchError raiseerror
} if
%stack: /name dict
exch pop
%stack: dict
% call the dictionary variant
using
} bind def
/* BeginDocumentation
Name: endusing - Close the scope of a 'using' context.
Synopsis: /namespacename using ...your.code... endusing -> -
Description:
'endusing' must be used to close a 'using' statement.
For further information, see 'using'.
Examples:
% the following makes the routines of the unittest library available to the current scope:
(unittest) (6688) require
/unittest using
..your code..
endusing
Author: Ruediger Kupper
FirstVersion: 6-aug-2003
Remarks:
Please note that 'using'/'endusing' is implemented by the opening and
closing of dictionaries. Code between 'using' and 'endusing' should
hence have completely matched 'begin' and 'end' statements, or special
care must be taken when using non-matched 'begin'/'end' constructs
inside a 'using' context.
Availability: SLI2.0
References:
[1] Ruediger Kupper, SLI library management,
HRI-EU Report 06/05, Honda Research Institute Europe GmbH, 2006.
SeeAlso: using, namespace, call
*/
/endusing
{
end
end
} bind def
% ========= Implementation of :: begins here =========
% (sorry, this is a length piece of code)
/* BeginDocumentation
Name: :: - execute a symbol from a nested namespace
Synopsis: A/name :: -> executes A::name (symbol "name" from namespace "A")
A/B/name :: -> executes A::B::name
A/B/C/name :: -> executes A::B::C::name
A/B/C/D/name :: -> executes A::B::C::D::name
Description:
The :: operator looks up and executes a symbol from a nested namespace.
The normal rules for symbol execution apply, i.e.
- if the symbol is a variable, its value is returned.
- if the symbol is a routine, it is executed.
The symbol is executed in the full nested context, i.e.
if you call a routine "A/B/C/routine ::", the routine can
access symbols from namespaces "A", "B" and "C" as if
the namespaces had been opened in this order.
"A/B/.../name ::" is equivalent to:
/A namespace
/B namespace
...
name
...
end
end
The lookup is safe in the sense that, if the symbol cannot be found,
the scope will stay unchanged, so that the user can safely recover
from the error. If however the called symbol is a routine and this
routine raises an error, the user will find the interpreter at the
scope of the nested routine.
Parameters:
A,B,C,D: nested namespaces
name: name of the symbol to look up and execute
Examples:
SLI ] /A namespace
SLI ] /B namespace
SLI ] /myvar 23 def
SLI ] end
SLI ] end
SLI ] A/B/myvar :: =
-> 23
SLI ] /X namespace
SLI ] /var_in_x 23.5 def
SLI ] /Y namespace
SLI ] /func {var_in_x =} def
SLI ] end
SLI ] end
SLI ] X/Y/func ::
-> 23.5
Diagnostics:
If the symbol cannot be found at the specified nested position,
/UnknownMember is raised. In this case, the operand and dictionary
stacks will stay unchanged, so that the user can safely recover from
the error.
If the called symbol is a routine and this routine raises an error,
the scope will be that of the nested routine.
Author: Ruediger Kupper
FirstVersion: 17-jun-2008
Remarks:
Currently implemented up to a depth of four nested namespaces.
SeeAlso: namespace, call
*/
% --------- parameter checking routines for :: ----------------
/::checknestedlookup[/dictionarytype /A
/arraytype /symbols]
% Returns true if the nested lookup worked for all symbols.
% Prints a message and returns false if the nested symbol cannot be looked up.
{
% all members of the array must be literals
/result true def
/ns A def % current namespace
% first check the namspaces:
symbols Most % all but last symbol (the namespaces)
{
1 add /depth Set
/nextnslit Set
% check if /nextnslit is a member of ns and if ot refers to a dictionary:
% The following test yields true if symbol is known and a dictionary, false, else.
ns nextnslit known
{
ns nextnslit get type /dictionarytype eq
}
{
false
} ifelse
not { % symbol is either unknown or not a dictionary
M_ERROR (Nested symbol lookup (::))
(At depth )
depth cvs join
(: /) join
nextnslit cvs join
( is not a nested namespace.) join
message
% set result to false and exit the forall loop:
/result false def
exit
} if
% okay, iterate:
/ns ns nextnslit get def
} forallindexed
% continue only if result is still true:
result {
% now check the last symbol:
ns symbols Last known not
{ % symbol is not known
M_ERROR (Nested symbol lookup (::))
(At depth )
depth 1 add cvs join
(: /) join
symbols Last cvs join
( is not a member of this nested namespace.) join
message
% set result to false:
/result false def
} if
} if
% leave the result on the stack
result
} bind SLIFunctionWrapper
/::checknestedlookupandraise
% Call ::checknestedlookup appropriately and raise an error if it returns false.
{
% <<A>> /literals.../literals n_literals
arraystore
% <<A>> [/literals.../literals]
2 copy
% <<A>> [/literals.../literals] <<A>> [/literals.../literals]
::checknestedlookup not
{ % check not passed. restore stack and raise error
% <<A>> [/literals.../literals]
arrayload pop
/:: /UnknownMember raiseerror
} if
% test passed, restore stack:
arrayload pop
} bind def
% --------- :: routines that really do the work ----------------
/::depth1_%[/dictionarytype /literaltype]
/call load def
/::depth2_%[/dictionarytype /literaltype /literaltype]
% <<A>> /B /C
{
3 -2 roll
% /C <<A>> /B
1 index begin %open namespace A
% /C <<A>> /B
get % get /B from <<A>>
% /C <<B>>
exch
% <<B>> /C
::depth1_ %recurse
end %close namespace A
} bind def
/::depth3_%[/dictionarytype /literaltype /literaltype /literaltype]
% <<A>> /B /C /D
{
4 -2 roll
% /C /D <<A>> /B
1 index begin %open namespace A
% /C /D <<A>> /B
get %get /B from <<A>>
% /C /D <<B>>
rollu
% <<B>> /C /D
::depth2_ %recurse
end %close namespace A
} bind def
/::depth4_%[/dictionarytype /literaltype /literaltype /literaltype /literaltype]
% <<A>> /B /C /D /E
{
5 -2 roll
% /C /D /E <<A>> /B
1 index begin %open namespace A
% /C /D /E <<A>> /B
get %get /B from <<A>>
% /C /D /E <<B>>
4 1 roll
% <<B>> /C /D /E
::depth3_ %recurse
end %close namespace A
} bind def
% --------- safe type tries for the different variants of :: ----------------
/::[/dictionarytype /literaltype]
/::depth1_ load def
/::[/dictionarytype /literaltype /literaltype]
{2 ::checknestedlookupandraise ::depth2_} bind def
/::[/dictionarytype /literaltype /literaltype /literaltype]
{3 ::checknestedlookupandraise ::depth3_} bind def
/::[/dictionarytype /literaltype /literaltype /literaltype /literaltype]
{4 ::checknestedlookupandraise ::depth4_} bind def
% ========= Implementation of :: ends here =========
/* BeginDocumentation
Name: libdict - Dictionary of provided libraries and their components.
Description:
This dictionary is used to implement the functionality of the commands
provide, provide-component, require and require-component.
The user needs never and should never access this dictionary directly.
Remarks:
The user needs never and should never access this dictionary directly.
Author:
Ruediger Kupper
FirstVersion:
28-Jul-2003
Availability: SLI2.0
References:
[1] Ruediger Kupper, SLI library management,
HRI-EU Report 06/05, Honda Research Institute Europe GmbH, 2006.
SeeAlso: provide, provide-component, require, require-component
*/
/libdict << /__autoloaded_files << >> >> def
/* BeginDocumentation
Name: provide-component - State that code provides a subcomponent of a library.
Synopsis:
/libname /component [version] provide-component -> -
/libname /component (version) provide-component -> -
special case (see below):
/libname /component ($Revision: 9952 $) provide -> -
Description:
This command is an extended version of "provide". Unless you are a
developer of SLI modules, you will almost certainly want to use the
simpler "provide" command.
This command will usually be used once in a .sli-File that implements
the SLI part of a multipart SLI library, or in the initilizer string for the
C++ part of a multipart SLI library. There might by additional use-cases.
This command states that the file it appears in provides the component
/component of the library /libname. The version number specified is
the version of the respective component.
Use cases:
The implementation of SLI modules usually consist not only of SLI code, but also of
associated C++-code. Usually, the C++ part is linked into the SLI
executable, and the SLI part is called at interpreter startup to do
additional initialization, type-tries, etc.
The two are seen as two components of one library.
Standard names for the two components are /SLI and /C++.
Each library is required to have at least a /SLI component.
Normal libraries (e.g., collections of SLI routines for a certain purpose)
have only a /SLI component. Use the simpler "provide" command for
these libraries. For more complex SLI-only libraries, you can use
"provide-component" to give independent version numbers to different
parts of your library (e.g., the user interface), but this is usually
not required.
Note that for the 'require'/'require-component' command to work
correctly, the SLI file defining a library
must itself be named accordingly: A file containing the command
/libname ... provide-component
shall be named
libname.sli
Parameters:
/libname - Name of the library.
/component - Name of a component that makes up the library, e.q. /SLI, /C++, etc.
version - Version number of the respective component (string or array of int,
for details on the format of version specifiers, see the
command version::s2v, or the help desk (todo).)
In CVS-controlled files, it is advisable to set this to
'(<dollar>Revision<dollar>)'.
Examples:
/mylibrary /SLI (1.0) provide-component
/mylibrary /FancyUserInterface [23 5] provide-component
Diagnostics:
If a component of the given name in the given library has already been earlier
provided, /LibraryExistsError is raised, regardless of version number.
Remarks:
For details on the format of version specifiers, see the help desk (todo).
In CVS-controlled files, it is advisable to set the version argument to
'(<dollar>Revision<dollar>)'.
Note that for the 'require' and 'require-component' commands to work
correctly, the SLI file defining a library
must itself be named accordingly: A SLI file containing the command
/libname ... provide-component
shall be named
libname.sli
Author:
Ruediger Kupper
FirstVersion:
28-jul-2003
Availability: SLI2.0
References:
[1] Ruediger Kupper, SLI library management,
HRI-EU Report 06/05, Honda Research Institute Europe GmbH, 2006.
SeeAlso: libdict, provide, require, require-component, version::s2v
*/
/provide-component[/literaltype /literaltype /stringtype]
{
% convert string to version array, then call array variant:
version /s2v call
provide-component
} bind def
/provide-component[/literaltype /literaltype /arraytype]
{
%stack: /libname /compname version
% safety check: is version a valid version number array?
dup version /validate call
%stack: /libname /compname version
% safety-check:
% was a component of this library already provided?
systemdict /libdict get dup
%stack: /libname /compname version <<libdict>> <<libdict>>
4 index known not
{% library is not know, so create it:
%stack: /libname /compname version <<libdict>>
dup 4 index << >> put
} if
% library is (now) known
%stack: /libname /compname version <<libdict>>
3 index get dup
%stack: /libname /compname version <<lib>> <<lib>>
3 index known
{% component was already previously defined!
%stack: /libname /compname version <<lib>>
begin % libname
%stack: /libname /compname version
M_ERROR (provide-component)
(Component /) 4 index cvs join ( of library ') join 5 index cvs join (' was already provided with version number ) join
4 index load version /v2s call join
(.) join message
end % libname
/provide-component /LibraryExistsError raiseerror
} if
% end safety check.
% library is (now) known
%stack: /libname /compname version <<lib>>
2 index 2 index put
%stack: /libname /compname version
M_STATUS (provide-component) (Providing library ') 5 index cvs join (', component /) join 4 index cvs join (, version ) join
3 index version /v2s call join
(.) join message
3 npop
} bind def
/* BeginDocumentation
Name: provide - State that code provides (the SLI part of) a library.
Synopsis:
/libname [version] provide -> -
/libname (version) provide -> -
special case (see below):
/libname ($Revision: 9952 $) provide -> -
Description:
This command will usually be used once in each *.sli file that
implements a library. Use this command for a libraries that are
collections of SLI-routines for a certain purpose.
This command states that the file it appears in defines provides the
given version of the library /libname.
Additional information:
This command states that the file it appears in defines the /SLI
component of the library /libname. The version number specified is
the version of the /SLI component (which for SLI-only libraries can be
thought of as the library version).
See 'provide-component' for a variant of this command that can be
used for libraries that consist of multiple parts or a mixture of SLI
and C++ code.
Note that for the 'require' command to work correctly, the library
file itself must be named accordingly: A file containing the command
/libname ... provide
shall be named
libname.sli
Parameters:
/libname - Name of the library.
version - Version number of the respective component (string or array of int,
for details on the format of version specifiers, see the
command version::s2v, or the help desk (todo).)
In CVS-controlled files, it is advisable to set this to
'(<dollar>Revision<dollar>)'.
Examples:
/mylibrary (1.0) provide
/newlibrary ($Revision: 9952 $) provide
Diagnostics:
If a component of name /SLI in the given library has already been earlier
provided, /LibraryExistsError is raised, regardless of version number.
Remarks:
For details on the format of version specifiers, see the help desk (todo).
In CVS-controlled files, it is advisable to set the version argument to
'(<dollar>Revision<dollar>)'.
Author:
Ruediger Kupper
FirstVersion:
28-jul-2003
Availability: SLI2.0
References:
[1] Ruediger Kupper, SLI library management,
HRI-EU Report 06/05, Honda Research Institute Europe GmbH, 2006.
SeeAlso: libdict, provide-component, require, require-component, version::s2v
*/
/provide[/literaltype /stringtype]
{
% convert string to version array, then call array variant:
version /s2v call
provide
} bind def
/provide[/literaltype /arraytype]
{
/SLI exch provide-component
} bind def
%%%%%
%
% :library-autoload-file
% 1. look if file was already loaded. if yes, return true
% 2. if no, try to find it
% 3. if it exists, execute it and register it. return true
% 4. if it does not exist, return false.
%
% The routine returns true, if the file was (perhaps formerly) loaded.
% It ensures, that each file is loaded only once.
%
%%%%
/:library-autoload-file[/stringtype]
{
% see if the file was already loaded:
%stack: (file)
systemdict /libdict get /__autoloaded_files get
%stack: (file) <<__autoloaded_files>>
1 index cvlit known
{% the file was already loaded, return true
% stack: (file)
M_DEBUG (:library-autoload-file) (File ) 4 -1 roll join ( was already loaded.) join message
true
}
{% the file was not yet loaded,
% so try to find and run it:
% stack: (file)
M_DEBUG (:library-autoload-file) (Trying to run file ) 3 index join (...) join message
% stack: (file)
dup searchifstream
{% the file was found and already opened, so execute its contents
%stack: (file) ifstream
M_DEBUG (:library-autoload-file) (File found. Executing...) message
cvx exec
%stack: (file)
% register that the file was loaded:
%stack: (file)
systemdict /libdict get /__autoloaded_files get
%stack: (file) <<__autoloaded_files>>
exch cvlit true put
%stack: -
% return true
true
}
{% the file was not found, return false
%stack: (file)
M_FATAL (:library-autoload-file) (Library or component unknown, and file ') 4 -1 roll join (' was not found!) join message
false
} ifelse
} ifelse
} bind def
%%%%
% :library-knownQ
%
% check if library is known in libdict.
% produce messages according to what happens
% and then return true or false.
% (undocumented)
%%%%
/:library-knownQ[/literaltype]
{
%stack: /libname
% check: is the library known?
systemdict /libdict get
%stack: /libname <<libdict>>
1 index known
{% library is already known, everything is okay.
%stack: /libname
M_DEBUG (:library-knownQ) (Library ') 4 -1 roll cvs join (' is known.) join message
%stack: -
% return value:
true
%stack: boolean
}
{% library is NOT known.
%stack: /libname
M_DEBUG (:library-knownQ) (Library ') 4 -1 roll cvs join (' is unknown.) join message
%stack: -
% return value:
false
%stack: boolean
} ifelse
%stack: boolean
} bind def
%%%%
% :component-knownQ
%
% check if component of a library is known in libdict.
% The library itself must be known (see :library-knownQ).
% produce messages according to what happens
% and then return true or false.
% (undocumented)
%%%%
/:component-knownQ[/literaltype /literaltype]
{
%stack: /libname /componentname
1 index 1 index
%stack: /libname /componentname /libname /componentname
systemdict /libdict get
%stack: /libname /componentname /libname /componentname <<libdict>>
rolld get
%stack: /libname /componentname /componentname <<libinfo>>
exch known
{% component is known.
%stack: /libname /componentname
M_DEBUG (:component-knownQ) (Library ') 5 -1 roll cvs join (' provides component /) join 4 -1 roll cvs join (.) join message
%stack: -
% return value:
true
%stack: boolean
}
{% library is NOT known.
%stack: /libname /componentname
M_DEBUG (:component-knownQ) (Library ') 5 -1 roll cvs join (' does not provide component /) join 4 -1 roll cvs join (.) join message
%stack: -
% return value:
false
%stack: boolean
} ifelse
%stack: boolean
} bind def
%%%%
% :library-and-component-knownQ
%
% check if a library and a component is known in libdict.
% 1. Check if the library is known.
% 2. If so, check, if the component is known, too.
% produce messages according to what happens
% and then return true or false.
% (undocumented)
%%%%
/:library-and-component-knownQ[/literaltype /literaltype]
{
%stack: /libname /componentname
1 index :library-knownQ
{% library is known
% check, if component is known, too
% stack: /libname /componentname
:component-knownQ
%stack: boolean
}
{% library is not known
% stack: /libname /componentname
pop pop
false
%stack: boolean
} ifelse
%stack: boolean
} bind def
%%%%
% :require-library-and-component
%
% check if library and component is known in libdict.
% If not, run the file libname.sli and re-check.
% produce messages according to what happens
% and then return true or false.
% (undocumented)
%%%%
/:require-library-and-component[/literaltype /literaltype]
{
%stack: /libname /componentname
1 index 1 index
%stack: /libname /componentname /libname /componentname
% check: is the library and component known?
:library-and-component-knownQ
%stack: /libname /componentname boolean
{% library and component are already known, everything is okay.
%stack: /libname /componentname
pop pop
% return value:
true
%stack: boolean
}
{% either the library or the componenet is NOT known,
%so try to find and run the sli file:
%stack: /libname /componentname
1 index cvs (.sli) join
%stack: /libname /componentname (libname.sli)
:library-autoload-file
%stack: /libname /componentname boolean
% the boolean is true, if the file was now or previously loaded.
% it is false, if the file was not found.
{% the file was now or previously loaded
% check again, if the library and component is known:
%stack: /libname /componentname
1 index 1 index
%stack: /libname /componentname /libname /componentname
:library-and-component-knownQ
% stack: /libname /componentname boolean
{% library was loaded, and now is known, all is okay.
% stack: /libname /componentname
M_DEBUG (:require-library-and-component) (Component was provided. Okay.) message
pop pop
% return value:
true
%stack: boolean
}
{% file was loaded, but library and component is STILL NOT known!
% stack: /libname /componentname
M_FATAL (:require-library-and-component) (Library ') 4 index cvs join (' or its component /) join 4 -1 roll cvs join ( is unknown, and file ') join 4 -1 roll cvs join (.sli) join (' did not provide it!) join message
% stack: -
% return value:
false
} ifelse
%stack: boolean
}
{% the file was not found
%stack: /libname /componentname
M_FATAL (:require-library-and-component) (Library ') 4 index cvs join (' or its component /) join 4 -1 roll cvs join ( is unknown, and file ') join 4 -1 roll cvs join (.sli) join (' was not found!) join message
% stack: -
% return value:
false
%stack: boolean
} ifelse
} ifelse
%stack: boolean
} bind def
/* BeginDocumentation
Name: require-component - State that code requires a certain subcomponent of a library.
Synopsis:
/libname /component [version] require-component -> -
/libname /component (version) require-component -> -
Description:
This command is an extended version of "require". Unless you are a
developer of SLI modules, you will almost certainly want to use the
simpler "require" command.
This command will usually be used once in each *.sli file that
requires a certain component of a multipart SLI library.
This command states that the file it appears in requires the component
/component of the library /libname. The version number specified is
the MINIMAL required version of the respective component.
Use cases:
The implementation of SLI modules usually consist not only of SLI code, but also of
associated C++-code. Usually, the C++ part is linked into the SLI
executable, and the SLI part is called at interpreter startup to do
additional initialization, type-tries, etc.
The two are seen as two components of one library.
Standard names for the two components are /SLI and /C++.
Each library is required to have at least a /SLI component.
Normal libraries (e.g., collections of SLI routines for a certain purpose)
have only a /SLI component. Use the simpler "require" command for
these libraries. For more complex SLI-only libraries, you can use
"provide-component"/"require-component" to give independent version
numbers to different parts of your library (e.g., the user
interface), but this is usually not required.
The command works as follows:
If the specified component of the specified library has not been
provided up to this point, a file named 'libname.sli' will be run (see
command 'run'). The code contained in this file MUST provide the
specified component of the specified library, using the command
'provide' or 'provide-component'. If not, an error will be raised.
After possibly running libname.sli, the version number of the
respective component is checked. If the provided version is
smaller than the required version, an error is raised.
Parameters:
/libname - Name of the library.
/component - Name of a component that makes up the library, e.q. /SLI, /C++, etc.
version - Minimal required version number of the respective component
(string or array of int, for details on the format of version
specifiers, see the help desk (todo).)
Examples:
/mylibrary /SLI (1.0) require-component
/mylibrary /FancyUserInterface [23 5] require-component
Diagnostics:
- If the specified component of the specified library has not been provided up to
this point, a file named 'libname.sli' will be run. If this code
does not provide the specified component of the specified library,
/LibraryNotProvidedError will be raised.
- If (possibly after running the file), the specified component of the
specified library has not been provided, /LibraryNotProvidedError will
be raised.
- If (possibly after running the file), the specified component of the
specified library has been provided, but the required version number
is higher than the provided one, /LibraryNotProvidedError will be
raised.
Remarks:
For the search path for file execution, see 'run'.
Author:
Ruediger Kupper
FirstVersion:
28-jul-2003
Availability: SLI2.0
References:
[1] Ruediger Kupper, SLI library management,
HRI-EU Report 06/05, Honda Research Institute Europe GmbH, 2006.
SeeAlso: libdict, provide, provide-component, require, run
*/
/require-component[/literaltype /literaltype /stringtype]
{
% convert string to version array, then call array variant:
version /s2v call
require-component
} bind def
/require-component[/literaltype /literaltype /arraytype]
{
%stack: /libname /componentname version
% safety check: is version a valid version number array?
dup version /validate call
%stack: /libname /componentname version
2 index 2 index
%stack: /libname /componentname version /libname /componentname
:require-library-and-component
not
{
%stack: /libname /componentname version
/require-component /LibraryNotProvidedError raiseerror
} if
% if we get here, we know that the library dict exists in libdict,
% and that the required component is known, too.
% We now have to check if it is the correct version.
%stack: /libname /componentname version
systemdict /libdict get 3 index get
%stack: /libname /componentname version <<lib>>
% % is a component of the given name provided?
% dup 3 index known not
% {%no, its not provided
% %stack: /libname /componentname version <<lib>>
% pop
% M_FATAL (require-component) (A component of name /) 4 index cvs join ( is not provided for library ') join 5 index cvs join ('.) join message
% /require-component /LibraryNotProvidedError raiseerror
% } if
% % yes it is provided
%stack: /libname /componentname version <<lib>>
% is it a recent enough version?
2 index get dup
%stack: /libname /componentname version presentversion presentversion
rollu
%stack: /libname /componentname presentversion version presentversion
1 index version /vlt call
{%no, version is too small!
%stack: /libname /componentname presentversion version
M_FATAL (require-component) (Component /) 5 index cvs join ( of library ') join 6 index cvs join (' has version ) join
/version namespace
4 index v2s join
(, but ) join
3 index v2s join ( was required.) join message
exch pop
end
/require-component /LibraryNotProvidedError raiseerror
} if
%stack: /libname /componentname presentversion version
4 npop
} bind def
/* BeginDocumentation
Name: require - State that code requires a certain library.
Synopsis:
/libname [SLIversion] require -> -
/libname (SLIversion) require -> -
/libname [SLIversion] [C++version] require -> -
/libname (SLIversion) (C++version) require -> -
/libname (SLIversion) [C++version] require -> -
/libname [SLIversion] (C++version) require -> -
Description:
This command will usually be used once in each *.sli file that
requires a certain library of commands.
This command states that the file it appears in requires the library
/libname. The version number specified is the MINIMAL required
version.
Additional information:
The two first versions given in the Synopsis section state that the
file the command appears in requires the /SLI component of the library
/libname. The version number specified is the MINIMAL required version
of the /SLI component (which, for SLI-only libraries, may be thought
of as the library version).
The other versions given in the Synopsis section state that the file
the command appears in requires the /SLI and the /C++ component of the
multipart library /libname. (See "require-component" for details on
library components.) The version numbers specified are the MINIMAL
required versions of the /SLI and /C++ components.
See 'require-component' for a variant of this command that can be
used for libraries that consist of multiple parts or a mixture of SLI
and C++ code.
The command works as follows:
If the repective component of the specified library has not been
provided up to this point, a file named 'libname.sli' will be run (see
command 'run'). The code contained in this file MUST provide the
respective component of the specified library, using the command
'provide' or 'provide-component'. If not, an error will be raised.
After possibly running libname.sli, the version number of the
respective component is checked. If the provided version is
smaller than the required version, an error is raised.
Parameters:
/libname - Name of the library.
SLIversion - Minimal required version number of the /SLI component.
(string or array of int, for details on the format of version
specifiers, see the help desk (todo).)
C++version - Minimal required version number of the /C++ component.
(string or array of int, for details on the format of version
specifiers, see the help desk (todo).)
Examples:
/mylibrary (1.0) require
Diagnostics:
- If the respective component of the specified library has not been
provided up to this point, a file named 'libname.sli' will be run.
If this code does not provide the respective component of the specified
library, /LibraryNotProvidedError will be raised.
- If (possibly after running the file), the respective component of the
specified library has not been provided, /LibraryNotProvidedError will
be raised.
- If (possibly after running the file), the respective component of the
specified library has been provided, but the required version number
is higher than the provided one, /LibraryNotProvidedError will be
raised.
Remarks:
For the search path for file execution, see 'run'.
Author:
Ruediger Kupper
FirstVersion:
28-jul-2003
Availability: SLI2.0
References:
[1] Ruediger Kupper, SLI library management,
HRI-EU Report 06/05, Honda Research Institute Europe GmbH, 2006.
SeeAlso: libdict, provide, provide-component, require-component, run
*/
/require[/literaltype /arraytype /stringtype]
{
% convert string to version array, then call array variant:
version /s2v call
require
} bind def
/require[/literaltype /stringtype /arraytype]
{
% convert string to version array, then call array variant:
exch version /s2v call exch
require
} bind def
/require[/literaltype /stringtype /stringtype]
{
% convert string to version array, then call array variant:
/version namespace
s2v
exch s2v exch
end
require
} bind def
/require[/literaltype /arraytype /arraytype]
{
2 index 2 index /SLI exch require-component
2 index 1 index /C++ exch require-component
3 npop
} bind def
/require[/literaltype /stringtype]
{
% convert string to version array, then call array variant:
version /s2v call
require
} bind def
/require[/literaltype /arraytype]
{
/SLI exch require-component
} bind def
/* BeginDocumentation
Name: initialize_module - Initialize module by executing commandstring
Synopsis:
commandstring initialize_module -> -
Description:
Executes the command string provided by a module to initialize it.
*/
/initialize_module[/stringtype]
{
<< >> begin
/initializer Set
systemdict begin
{ initializer
M_DEBUG (sli-init) (Executing module initializer: ) 3 index join message
cvx exec } stopped
{
M_FATAL (sli-init) (While executing module initializer: {) initializer join (}) join message
handleerror
start
} if
end end
} bind def
end % systemdict