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