/* * 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