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

/oosupport /SLI ($Revision: 9952 $) provide-component
/oosupport /C++ (1.4) require-component

%
/*BeginDocumentation
Name: call - Execute object from a dictionary.
Synopsis: dict /f call -> -
Description: In SLI, an object-oriented programming style can be
 implemented by using dictionaries as objects. 
 These object dictionaries then contain functions as well as data.
 The command call can be used to call a "member" of an object.

 In calling the member-functions, the following steps are performed:
 1. the object-dictionary is pushed on the dictionary stack
 2. the name is executed in the new dictionary context
 3. the object-dictionary is poped off the dictionary stack.
 Thus, during the execution of the function, the entire namespace of the
 object-dictionary is accessible.

 The invocation of call is, thus, comparable but not equivalent
 to the following sequence of SLI commands:
 /call
 { 
    exch
    begin
    load exec
    end
 } def	 

Diagnostics: If the called member is not part of the object dictionary,
  an UnknownMember error is raised.

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

SeeAlso: namespace, using
*/
/call_ /call load def
/call trie
 [/dictionarytype /literaltype] /call_ load addtotrie
def

/*BeginDocumentation
Name:cvo - Label a dictionary for usage as an object in oo-programming
Synopsis:dict cvo -> dict
Parameters:The operator modfies its argument
Description:In SLI dictionaries are used to represent the elements of the
object oriented programming paradigm. This is natural because the key value
pairs can specify functions as well as other data. Certain SLI operators like
SetStatus and GetStatus take C++ objects like nodes and random number distributions
as arguments but also SLI dictionaries. This enables the same algorithms to operate
on C++ and SLI objects. In order to avoid confusion with dictionaries not intended
to be used as an object, some operators require the dictionary to be labeld as 
an object. If the dictionary is not labeles an error is issued. The operator cvdict
removes the label; cvd is the inverse operator of cvo.
Examples:
<< /c 0 /inc {/c c 1 add def} >> cvo dup  << /c 3 >> SetStatus /c get --> 3

{<< /c 0 /inc {/c c 1 add def} >> << /c 3 >> SetStatus} stopped 
                                         {3 npop true} {false} ifelse --> true

Remarks:The labeling is done by inserting the key /__is_object with value true. 
The dictionary is only recognized as labeled if the key exists and its value is 
true. However, usage of this key is considered to be an implementation detail and
may change in future versions of SLI.

Author:Diesmann
FirstVersion: 2008-08-23
SeeAlso: cvdict, call, SetStatus, GetStatus
*/
/cvo [/dictionarytype] {dup /__is_object true put} def

/*BeginDocumentation
Name:cvdict - Convert argument to a dictionary
Synopsis:dict cvdict -> dict
Parameters: a dictionary which may be labeled for oo-programming
Description: In case the argument is labeled as a dictionary used as 
an object in oo-programming, this label is removed. cvdict does not
clone its argument. This is the inverse function of cvo.
Author:Diesmann
FirstVersion: 2008-08-23
SeeAlso: cvo, clonedict
*/
/cvdict [/dictionarytype] 
{
 dup /__is_object undef
}
def


/*BeginDocumentation
Name:SetStatus_dict - Modify a dictionary used as an object in oo-programming
Synopsis:dict dict SetStatus -> -
Parameters:The operator modfies the first argument
Description: The operator overloads SetStatus and inserts the key value pairs 
of the second dictionary into the first dictionary. This is the same functionality 
as the one of operator join. However, SetStatus raises an error if the first 
dictionary has not been labeled by operator cvo as an object of oo-programming 
before. The idea is that use of SetStatus should be reserved for objects of
oo-programming not regular dictionaries to enhance the readability of SLI code. 
See the documentation of operator cvo for more details.
Examples:
  << >> cvo dup << /c 1 >> SetStatus /c get --> 1
  << >>     dup << /c 1 >> join      /c get --> 1
{ << >>         << /c 1 >> SetStatus } stopped  
                   {3 npop true} {false} ifelse  --> true
Author:Helias, Diesmann
FirstVersion: 2006-06-26
SeeAlso: GetStatus_dict, cvo, cvd, call 
*/
/SetStatus_dict
{
 exch  % rdv parameters
 dup
 /__is_object known
 {dup /__is_object get} {false} ifelse  % check if value is true
 { % first dictionary is labeled for usage as an object 
  exch
  join_d
 }
 { % first dictionary is not used as a object
 exch                   % restore stack layout
 M_ERROR (SetStatus)
 (SetStatus was called on a dictionary which is not labeled as an object. )
 (Please use the operator join if your intention is to merge two dictionaries. ) join
 (If a dictionary contains functions and is intended to be used as an object, ) join
 (please use operator cvo to label it as an object) join message
 /SetStatus /ObjectDictionaryExpected raiseerror
 }
 ifelse
} def

% add new functions to trie if it exists, else create new
/SetStatus [/dictionarytype /dictionarytype] /SetStatus_dict load def


/*BeginDocumentation
Name:GetStatus_dict - Return status of a dictionary used as an object in oo-programming
Synopsis:dict GetStatus -> dict
Parameters:The argument is a dictionary used as an object in oo-programming
Description: The operator overloads GetStatus and returns a new dictionary with
the key value pairs of the argument. The functionality is similar to the one
of operator clonedict but the return value does not inherit the labeling as an
object. In this way the relationship between the output dictionary and the input 
dictionary is the same as for non dictionary arguments of GetStatus. However, 
GetStatus raises an error if the argument dictionary has not been labeled by 
operator cvo as an object of oo-programming before. The idea is that use of 
GetStatus should be reserved for objects of oo-programming not regular dictionaries 
to enhance the readability of SLI code. See the documentation of operator cvo for 
more details.
Examples:
<< /c 1 >> dup cvo GetStatus eq --> false
{ << /c 1 >> GetStatus } stopped
          {2 npop true} {pop false} ifelse  --> true

Author:Diesmann
FirstVersion: 2006-08-24
SeeAlso: SetStatus_dict, clonedict, cvo, cvdict, call 
*/

/GetStatus_dict
{
 dup
 /__is_object known
 {dup /__is_object get} {false} ifelse  % check if value is true
 { % dictionary is labeled for usage as an object 
 clonedict exch pop cvdict
 }
 { % dictionary is not used as a object
 M_ERROR (GetStatus)
 (GetStatus was called on a dictionary which is not labeled as an object. )
 (Please use the operator clonedict if your intention is to clone a dictionary. ) join
 (If a dictionary contains functions and is intended to be used as an object, ) join
 (please use operator cvo to label it as an object) join message
 /SetStatus /ObjectDictionaryExpected raiseerror
 }
 ifelse

}
def

/GetStatus [/dictionarytype] /GetStatus_dict load def