/*
* slidict.cc
*
* 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 Dictionary access
*/
#include <typeinfo>
#include "slidict.h"
#include "dictdatum.h"
#include "namedatum.h"
#include "dictstack.h"
#include "iostreamdatum.h"
#include "integerdatum.h"
#include "arraydatum.h"
#include "booldatum.h"
#include "tokenutils.h"
/*
BeginDocumentation
Name: dict - Create new, empty dictionary
Synopsis: dict -> <<>>
Description:
dict creates a new dictionary with no entries. This command is
equivalent to
<<>>
Diagnostics: No errors are raised.
Author: Marc-Oliver Gewaltig
SeeAlso: <<>>, clonedict, cleardict
*/
void DictFunction::execute(SLIInterpreter *i) const
{
// create a new dictionary
i->EStack.pop(); // never forget me
i->OStack.push(DictionaryDatum(new Dictionary));
}
/*
BeginDocumentation
Name: put_d - Add an entry to a dictionary
Synopsis: <<dict>> /key val -> <<dict>>
Description:
put_d adds the pair /key value to the supplied dictionary.
If /key was already defined in that dictionary, its old
value is lost.
In contrast to PostScript dictionaries, only literal names can
be used as keys in a dictionary.
Parameters:
dict - a dictionary
/key - a literal name
val - an object of arbitrary type
Examples:
userdict /a 1 put_d
<< >> /a 1 put_d
Diagnostics:
No errors are raised.
Author:
Marc-Oliver Gewaltig
SeeAlso: get_d, known, dict, <<>>, clonedict
*/
void DictputFunction::execute(SLIInterpreter *i) const
{
if(i->OStack.load()>=3)
{
// call: dict key val
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.pick(2).datum());
if(dict!=0)
{
LiteralDatum *key =
dynamic_cast<LiteralDatum *>(i->OStack.pick(1).datum());
if(key!=0)
{
(*dict)->insert_move(*key, i->OStack.top());
#ifdef DICTSTACK_CACHE
if((*dict)->is_on_dictstack())
i->DStack->clear_token_from_cache(*key);
#endif
i->OStack.pop(3);
i->EStack.pop(); // never forget me
return;
}
else throw ArgumentType(1);
}
else throw ArgumentType(2);
}
else throw StackUnderflow(3,i->OStack.load());
}
/*
BeginDocumentation
Name: get_d - look a name up in a dictionary
Synopsis: dict /key get_d -> any
Description:
get_d tries to find /key in the supplied dictionary. If it
is present, the associated value is returned. If /key is
not in the dictionary, an UndefinedNameError is raised
Parameters:
dict - a dictionary
/key - a literal name
Examples:
systemdict /PI get_d -> 3.1415...
<</a 1>> /a get -> 1
Diagnostics:
UndefinedNameError
Author:
Marc-Oliver Gewaltig
SeeAlso: put_d, lookup, known
*/
void DictgetFunction::execute(SLIInterpreter *i) const
{
// call: dict key -> val
if(i->OStack.load()>=2)
{
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.pick(1).datum());
if(dict!=0)
{
LiteralDatum *key =
dynamic_cast<LiteralDatum *>(i->OStack.pick(0).datum());
if(key!=0)
{
Token value=(*dict)->lookup2(*key);
i->EStack.pop(); // never forget me
i->OStack.pop(2);
i->OStack.push_move(value);
return;
}
else throw ArgumentType(0);
}
else throw ArgumentType(1);
}else throw StackUnderflow(2,i->OStack.load());
}
/*
BeginDocumentation
Name: info - Display the contents of a dictionary
Synopsis: ostream dict info -> -
Description:
Prints the contents of the dictionary to the supplied stream.
Parameters:
dict - a dictionary
No return values are given.
Examples:
std::cout <</a 1 /b 2.5 /c (Hallo World)>> info
shows
--------------------------------------------------
Name Type Value
--------------------------------------------------
a integertype 1
b doubletype 2.5
c stringtype Hallo World
--------------------------------------------------
Total number of dictionary entries: 3
SeeAlso: info_ds, topinfo_d, who, whos
*/
void DictinfoFunction::execute(SLIInterpreter *i) const
{
// call: ostream dict
assert(i->OStack.load()>1);
OstreamDatum *outd = dynamic_cast<OstreamDatum*>(i->OStack.pick(1).datum());
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.top().datum());
assert(dict != NULL); assert(outd != NULL);
i->EStack.pop();
(*dict)->info(**outd);
i->OStack.pop(2);
}
/* BeginDocumentation
Name: length_d - counts elements of a dictionary
Synopsis: dict length_d -> int
Examples: <</a 1 /b 2>> length_d -> 2
modeldict length_d --> 34
Author: docu by Sirko Straube
Remarks: Use length if you are not sure of the data type.
SeeAlso: length
*/
void Length_dFunction::execute(SLIInterpreter *i) const
{
// call: dict length_d -> int
assert(i->OStack.load()>0);
DictionaryDatum *dict = dynamic_cast<DictionaryDatum *>(i->OStack.top().datum());
assert(dict != NULL);
i->EStack.pop();
Token st(new IntegerDatum( (*dict)->size()));
i->OStack.pop();
i->OStack.push_move(st);
}
void Empty_DFunction::execute(SLIInterpreter *i) const
{
// call: dict empty_D dict bool
assert(i->OStack.load()>0);
DictionaryDatum const * const dd =
dynamic_cast<DictionaryDatum const * const>(i->OStack.top().datum());
assert(dd != NULL);
i->OStack.push_by_pointer(new BoolDatum((*dd)->empty() ));
i->EStack.pop();
}
/*
BeginDocumentation
Name: countdictstack - return number of dictionaries on the dictionary stack.
Synopsis:
No arguments.
Description:
Returns the current load of the dictionary stack. The default
value is 2.
Parameters:
None.
SeeAlso: dictstack, cleardictstack, whos
*/
void CountdictstackFunction::execute(SLIInterpreter *i) const
{
// call: Countdictstack -> int
i->EStack.pop();
Token st(new IntegerDatum(i->DStack->size()));
i->OStack.push_move(st);
}
/*
BeginDocumentation
Name: dictstack - return current dictionary stack as array
Synopsis: dictstack -> array
Description: Returns an array whose entries are references to the dictionaries
on the dictionary stack. The dictionaries are stored from bottom to top,
such that the first array element refers to the bottom of the stack and the
last array element to the top.
SeeAlso: currentdict, countdictstack, cleardictstack, whos
*/
void DictstackFunction::execute(SLIInterpreter *i) const
{
// call: - dictstack -> array
i->EStack.pop();
TokenArray ta;
i->DStack->toArray(ta);
Token st(new ArrayDatum(ta));
i->OStack.push_move(st);
}
/*
BeginDocumentation
Name: currentdict - return topmost dictionary of the dictionary stack
Synopsis: currentdict -> dict
Description: Returns a reference to the current dictionary.
SeeAlso: dictstack, begin, end, cleardictstack, who, whos
*/
void CurrentdictFunction::execute(SLIInterpreter *i) const
{
// call: - currentdict -> dict
i->EStack.pop();
Token dt;
i->DStack->top(dt);
i->OStack.push_move(dt);
}
/*
BeginDocumentation
Name: cleardictstack - Pop all non standard dictionaries off the dictionary stack.
Description: Removes all non standard dictionaries off the dictionary stack.
After this, only the systemdict and the userdict dictionaries remain on the
dictionary stack.
SeeAlso: dictstack, begin, end, currentdict, who, whos
*/
void CleardictstackFunction::execute(SLIInterpreter *i) const
{
// Pop all non-permanent dictionaries
i->EStack.pop();
while(i->DStack->size() > 2)
i->DStack->pop();
}
/*
BeginDocumentation
Name: topinfo_d - print contents of top dictionary to stream
Synopsis: ostream topinfo_d -> -
Description: Print the contents of the top dictionary on the
dictionary stack to the supplied stream.
Parameters:
ostream - a valid output stream
Examples:
Diagnostics:
Bugs:
Author:
FirstVersion:
Remarks:
SeeAlso: dictstack, currentdict, info, who, whos
*/
void DicttopinfoFunction::execute(SLIInterpreter *i) const
{
// call: ostream Dicttopinfo
assert(i->OStack.load()>0);
OstreamDatum *outd = dynamic_cast<OstreamDatum*>(i->OStack.top().datum());
assert(outd != NULL);
i->EStack.pop();
i->DStack->top_info(**outd);
i->OStack.pop();
}
/*
BeginDocumentation
Name: info_ds - print contents of all dictionaries on the dicitonary stack to stream
Synopsis: ostream info_ds -> -
Description:
info_ds prints the contents of all dictionaries on the dictionary
stack to the supplied ostream. Dictionaries are printed from
bottom to top.
Parameters:
ostream - a valid output stream
SeeAlso: dictstack, info, topinfo_d, who, whos
*/
void WhoFunction::execute(SLIInterpreter *i) const
{
// call: ostream
assert(i->OStack.load()>0);
OstreamDatum *outd = dynamic_cast<OstreamDatum*>(i->OStack.top().datum());
assert(outd != NULL);
i->EStack.pop();
i->DStack->info(**outd);
i->OStack.pop();
}
/*
BeginDocumentation
Name: begin - Make a dictionary the current dictionary.
Synopsis: dict begin -> -
Parameters:
dict - a dictionary object
Description:
begin opens a dictionary by pushing it on the dictionary stack.
After begin, the opened dictionary is searched first whenever
a name is resolved.
SeeAlso: end, get_d, dictstack, cleardictstack, countdictstack
*/
void DictbeginFunction::execute(SLIInterpreter *i) const
{
// call: dict
if(i->OStack.load()>0)
{
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.top().datum());
if(dict != NULL)
{
i->EStack.pop();
i->DStack->push(*dict);
i->OStack.pop();
return;
}
else i->raiseerror(i->ArgumentTypeError);
} else i->raiseerror(i->StackUnderflowError);
}
/*
BeginDocumentation
Name: end - Close the current (topmost) dictionary.
Synopsis: - end -> -
Description:
Closes the current dictionary by removing the top element
of the dictionary stack.
Note that end cannot pop the dictionary stack beyond the two
standard dictionaries systemdict and userdict. If this is tried,
a DictStackUnderflow Error is raised.
Diagnostics:
DictStackUnderflow
SeeAlso: begin, dictstack, cleardictstack, countdictstack
*/
void DictendFunction::execute(SLIInterpreter *i) const
{
if(i->DStack->size()>2) // keep at least systemdict and userdict
{ // see sli-init.sli for details
i->DStack->pop();
i->EStack.pop();
}
else
i->raiseerror("DictStackUnderflow");
}
/*
BeginDocumentation
Name: undef - Remove a key from a dictionary.
Synopsis: dict key undef -> -
Parameters:
dict - a (possibly empty) dictionary
key - a literal name to be removed.
Description:
undef removes the definition of a name from the supplied dictionary.
The name does not have to be present in the dicitonary.
Examples:
SLI ] /d << /a 1 /b 2 >> def
SLI ] d info
- --------------------------------------------------
Name Type Value
- --------------------------------------------------
a integertype 1
b integertype 2
- --------------------------------------------------
Total number of entries: 2
SLI ] d /b undef
SLI ] d info
- --------------------------------------------------
Name Type Value
- --------------------------------------------------
a integertype 1
- --------------------------------------------------
Total number of entries: 1
Diagnostics:
None.
Author: docu edited by Marc Oliver Gewaltig and Sirko Straube
SeeAlso: get_d, put_d, known, lookup, info
*/
void UndefFunction::execute(SLIInterpreter *i) const
{
// call: dict key -> -
if(i->OStack.load()>1)
{
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.pick(1).datum());
if(dict != NULL)
{
LiteralDatum *key =
dynamic_cast<LiteralDatum *>(i->OStack.pick(0).datum());
if(key != NULL)
{
i->EStack.pop();
#ifdef DICTSTACK_CACHE
if((*dict)->is_on_dictstack())
i->DStack->clear_token_from_cache(*key);
#endif
(*dict)->erase(*key);
i->OStack.pop(2);
return;
}
else
throw ArgumentType(0);
}
else
throw ArgumentType(1);
}
else
throw StackUnderflow(2,i->OStack.load());
}
/*
BeginDocumentation
Name: <<>> - Create a new dictionary.
Synopsis: << /key1 val1 ... /keyn valn >> -> dict
Parameters: /key - literal name
val - Object of any type
Description: Constructs a dictionary with the entries which are specified
by key-value pairs.
Note that the key-value pairs are evaluated BEFORE the dictionary is
constructed.
<< >> operates the following way:
The characters << correspond to a mark which is pushed on the stack.
Next, all following key-value pairs are evaluated.
>> finally counts the number of pairs on the stack and constructs a
new dictionary.
Examples:
<pre>
SLI ] << /a 1 /b 2 >> info
--------------------------------------------------
Name Type Value
--------------------------------------------------
a integertype 1
b integertype 2
--------------------------------------------------
Total number of entries: 2
SLI ] << (a) (b) join cvlit 2 3 mul 2 add >> info
--------------------------------------------------
Name Type Value
--------------------------------------------------
ab integertype 8
--------------------------------------------------
Total number of entries: 1
</pre>
Diagnostics: An ArgumentType error is raised if the
initializer list does not consist of proper /key value
pairs.
References: The Red Book
SeeAlso: clonedict, begin, cleardictstack, dict, dictstack, info, end
*/
void DictconstructFunction::execute(SLIInterpreter *i) const
{
// call: mark key1 val1 ... keyn valn -> dict
size_t l = i->OStack.load();
if(l == 0)
throw StackUnderflow(1,0);
DictionaryDatum *dictd=new DictionaryDatum(new Dictionary);
Token dict(dictd);
LiteralDatum *key=NULL;
static Token mark=i->baselookup(i->mark_name);
size_t n = 0; //!< pick(1) is the first literal, then we count in steps of 2
while( ( n < l ) &&
!(i->OStack.pick(n) == mark ))
{
Token &val= (i->OStack.pick(n));
key = dynamic_cast<LiteralDatum *>(i->OStack.pick(n+1).datum());
if(key == NULL)
{
i->message(30, "DictConstruct",
"Literal expected. Maybe initializer list is in the wrong order.");
i->raiseerror(i->ArgumentTypeError);
delete dictd;
return;
}
(*dictd)->insert_move(*key, val);
n+=2; // count number of elements
}
if (n==l)
{
i->message(30, "DictConstruct", "<< expected.");
i->raiseerror(i->ArgumentTypeError);
return;
}
if( n%2 != 0 ) // there must be an even number of objects
{ // above the mark
i->message(30, "DictConstruct",
"Initializer list must be pairs of literal and value.");
i->raiseerror(i->ArgumentTypeError);
return;
}
i->EStack.pop();
i->OStack.pop(n);
i->OStack.top().move(dict);
}
/*
BeginDocumentation
Name: known - check whether a name is defined in a dictionary or object
Synopsis: dict /key known -> bool
int /key known -> bool
Examples:
modeldict /iaf_neuron known -> true
modeldict /parkinson_neuron known -> false
/iaf_psc_alpha_presc Create /Interpol_Order know -> true
Author: docu edited by Sirko Straube
SeeAlso: lookup
*/
void KnownFunction::execute(SLIInterpreter *i) const
{
// call: dict key -> bool
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.pick(1).datum());
LiteralDatum *key =
dynamic_cast<LiteralDatum *>(i->OStack.pick(0).datum());
bool known=(*dict)->known(*key);
i->EStack.pop(); // never forget me
i->OStack.pop(1);
i->OStack.top()=new BoolDatum(known);
}
/*
BeginDocumentation
Name: cleardict - Clears the contents of a dictionary
Synopsis: dict cleardict
SeeAlso: <<>>, clonedict, dictstack
*/
void CleardictFunction::execute(SLIInterpreter *i) const
{
// call: dict -> -
assert(i->OStack.load()>0);
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.top().datum());
assert(dict != NULL);
#ifdef DICTSTACK_CACHE
if((*dict)->is_on_dictstack())
i->DStack->clear_dict_from_cache(*dict);
#endif
(*dict)->clear();
i->EStack.pop(); // never forget me
i->OStack.pop();
}
/*
BeginDocumentation
Name: clonedict - create a copy of a dictionary
Synopsis: dict1 clonedict -> dict1 dict2
Description:
clonedict creates a new dictionary dict2 with the
same entries as dict1.
Parameters:
dict1 - a dictionary
Examples:
<< /a 1 >> clonedict
Diagnostics:
None.
Author:
Marc-Oliver Gewaltig
SeeAlso: <<>>, dict, cleardict
*/
void ClonedictFunction::execute(SLIInterpreter *i) const
{
// Clone a given dictionary (real copy)
// call: dict clonedict -> dict1 dict2
assert(i->OStack.load()>0);
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.top().datum());
assert(dict != NULL);
i->OStack.push(DictionaryDatum(new Dictionary(*(*dict))));
i->EStack.pop(); // never forget me
}
/*
BeginDocumentation
Name: cva_d - Convert dictionary to array
Synopsis: dict cva_d -> array
Description: cda converts a given dictionary to an array.
The contents of the dictionay is mapped to the array in a
form which is similar to the construction of an array, namely
<< key1 val1 ... keyn valn>> cva_d -> [key1 val1 ... keyn valn]
Parameters:
dict is a dictionary which may be empty
Examples:
<< /a 1 /b 2>> cva_d -> [/a 1 /b 2]
Diagnostics:
no errors are issued.
Remarks:
The name follows the convention of PostScript and stands for
ConVert to Array.
Implementation:
Class TokenMap provides an iterator which allows to step through the
elements stored in the TokenMap. Member function begin() returns an
iterator which points to the "first" element in the TokenMap and end()
to the "last" element. operator ++ moves the iterator from one element
to the next. Note, the iteration process itself does not define any
order of the elements, e.g. in terms of the comparison operators. The
only guaranteed function is that during the iteration from begin() to
end() all elements in the TokenMap are accessed.
Operator * applied to the iterator returns a pair. Member first of the
pair is the key and member second is the value of the element the iterator
points to.
See
@Book{Musser96,
author = "Musser, David R. and Saini, Atul",
title = "STL Tutorial and Reference Guide: {C++} Programming
with the Standard Template Library",
publisher = "Addison Wesley",
year = 1996,
isbn = "0-201-63398-1",
pages = 432,
address = {Reading Massachusetts},
note = "(hardcover)"
}
for a discussion of the definition and use of iterators in combination
with containers.
Author:
Marc-oliver Gewaltig
SeeAlso: keys, values, <<>>, cva
*/
void Cva_dFunction::execute(SLIInterpreter *i) const
{
i->EStack.pop();
assert(i->OStack.load()>0);
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.top().datum());
assert(dict != NULL);
ArrayDatum *ad = new ArrayDatum();
ad->reserve((*dict)->size() * 2);
for(TokenMap::const_iterator t = (*dict)->begin(); t != (*dict)->end(); t ++)
{
Token nt(new LiteralDatum((*t).first));
ad->push_back_move(nt);
ad->push_back((*t).second);
}
i->OStack.pop();
i->OStack.push(ad);
}
/*
BeginDocumentation
Name: keys - Return array of keys in a dictionary
Synopsis:
dict keys -> array
<</key1 val1 ... /keyn valn>> keys -> [/key1 ... /keyn]
Description:
"keys" converts the keys in a given dictionary to an array.
The order of elements is the same as for the "values" command.
Parameters:
dict is a dictionary which may be empty
Examples:
<< /a 1 /b 2>> keys -> [/a /b]
Diagnostics:
no errors are issued.
Remarks:
The commands "keys" and "values" return the same order of
elements, when applied to the same dictionary. Apart from that,
there is no particular order of elements in the returned array.
Author: Ruediger Kupper
First Version: 27-jun-2008
SeeAlso: keys, values, <<>>, cva
*/
void KeysFunction::execute(SLIInterpreter *i) const
{
i->EStack.pop();
assert(i->OStack.load()>0);
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.top().datum());
assert(dict != NULL);
ArrayDatum *ad = new ArrayDatum();
for(TokenMap::const_iterator t = (*dict)->begin(); t != (*dict)->end(); t ++)
{
Token nt(new LiteralDatum((*t).first));
assert(! nt.empty());
ad->push_back_move(nt);
}
i->OStack.pop();
i->OStack.push(ad);
}
/*
BeginDocumentation
Name: values - Return array of values in a dictionary
Synopsis:
dict values -> array
<</key1 val1 ... /keyn valn>> values -> [val1 ... valn]
Description:
"values" converts the values in a given dictionary to an array.
The order of elements is the same as for the "keys" command.
Parameters:
dict is a dictionary which may be empty
Examples:
<< /a 1 /b 2>> values -> [1 2]
Diagnostics:
no errors are issued.
Remarks:
The commands "keys" and "values" return the same order of
elements, when applied to the same dictionary. Apart from that,
there is no particular order of elements in the returned array.
Author: Ruediger Kupper
First Version: 27-jun-2008
SeeAlso: keys, values, <<>>, cva
*/
void ValuesFunction::execute(SLIInterpreter *i) const
{
i->EStack.pop();
assert(i->OStack.load()>0);
DictionaryDatum *dict =
dynamic_cast<DictionaryDatum *>(i->OStack.top().datum());
assert(dict != NULL);
ArrayDatum *ad = new ArrayDatum();
for(TokenMap::const_iterator t = (*dict)->begin(); t != (*dict)->end(); t ++)
{
ad->push_back((*t).second);
}
i->OStack.pop();
i->OStack.push(ad);
}
void RestoredstackFunction::execute(SLIInterpreter *i) const
{
assert(i->OStack.load()>0);
ArrayDatum *ad= dynamic_cast<ArrayDatum *>(i->OStack.top().datum());
assert(ad != NULL);
TokenArray ta = *ad;
DictionaryStack *olddstack =i->DStack; // copy current dstack
i->DStack= new DictionaryStack;
for(size_t j=0; j< ta.size(); ++j)
{
try{
DictionaryDatum dict = getValue<DictionaryDatum>(ta[j]);
i->DStack->push(ta[j]);
}
catch(...)
{
delete i->DStack;
i->DStack = olddstack;
i->raiseerror(i->ArgumentTypeError);
return;
}
}
i->OStack.pop();
i->EStack.pop();
}
const DictFunction dictfunction;
const DictputFunction dictputfunction;
const DictgetFunction dictgetfunction;
const DictinfoFunction dictinfofunction;
const DicttopinfoFunction dicttopinfofunction;
const WhoFunction whofunction;
const DictbeginFunction dictbeginfunction;
const DictendFunction dictendfunction;
const DictconstructFunction dictconstructfunction;
const Length_dFunction length_dfunction;
const Empty_DFunction empty_Dfunction;
const DictstackFunction dictstackfunction;
const CountdictstackFunction countdictstackfunction;
const CleardictstackFunction cleardictstackfunction;
const CurrentdictFunction currentdictfunction;
const KnownFunction knownfunction;
const UndefFunction undeffunction;
const CleardictFunction cleardictfunction;
const ClonedictFunction clonedictfunction;
const Cva_dFunction cva_dfunction;
const KeysFunction keysfunction;
const ValuesFunction valuesfunction;
const RestoredstackFunction restoredstackfunction;
void init_slidict(SLIInterpreter *i)
{
i->createcommand("dict", &dictfunction);
i->createcommand("put_d", &dictputfunction);
i->createcommand("get_d", &dictgetfunction);
i->createcommand("info_d", &dictinfofunction);
i->createcommand("length_d", &length_dfunction);
i->createcommand("empty_D", &empty_Dfunction);
i->createcommand("topinfo_d", &dicttopinfofunction);
i->createcommand("info_ds", &whofunction);
i->createcommand("begin", &dictbeginfunction);
i->createcommand(i->end_name,&dictendfunction);
i->createcommand("undef",&undeffunction);
i->createcommand(">>", &dictconstructfunction);
i->createcommand("dictstack",&dictstackfunction);
i->createcommand("countdictstack",&countdictstackfunction);
i->createcommand("cleardictstack",&cleardictstackfunction);
i->createcommand("currentdict",¤tdictfunction);
i->createcommand("known",&knownfunction);
i->createcommand("cleardict",&cleardictfunction);
i->createcommand("clonedict",&clonedictfunction);
i->createcommand("cva_d",&cva_dfunction);
i->createcommand("keys",&keysfunction);
i->createcommand("values",&valuesfunction);
i->createcommand("restoredstack",&restoredstackfunction);
}