/* * slidata.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's data access functions */ #include <vector> #include "slidata.h" #include "namedatum.h" #include "arraydatum.h" #include "stringdatum.h" #include "integerdatum.h" #include "doubledatum.h" #include "dictdatum.h" #include "iteratordatum.h" #include "tokenutils.h" #include <climits> #include <sstream> /*BeginDocumentation Name: allocations - Return the number of array reallocations. Synopsis: - allocations -> int Description: This function returns the total number of array-allocations which have occured during the run-time of the SLI interpreter. This number is important in the context of benchmarking and optimization. */ void Allocations_aFunction::execute(SLIInterpreter *i) const { Token at(new IntegerDatum(TokenArrayObj::getallocations())); i->OStack.push_move(at); i->EStack.pop(); } void Get_aFunction::execute(SLIInterpreter *i) const { // call: array int get_a assert(i->OStack.load()>1); IntegerDatum *idx = dynamic_cast<IntegerDatum *>(i->OStack.top().datum()); assert(idx != NULL); ArrayDatum *obj = dynamic_cast<ArrayDatum *>(i->OStack.pick(1).datum()); assert(obj != NULL); if((idx->get()>=0) && ( (size_t)idx->get() < obj->size())) { i->EStack.pop(); Token objT(obj->get(idx->get())); i->OStack.pop(2); i->OStack.push_move(objT); } else i->raiseerror(i->RangeCheckError); } void Get_a_aFunction::execute(SLIInterpreter *i) const { // call: array int get_a assert(i->OStack.load()>1); ArrayDatum *idx = dynamic_cast<ArrayDatum *>(i->OStack.top().datum()); if(idx==NULL) { i->message(SLIInterpreter::M_ERROR, "get_a_a","Second argument must be an array of indices."); i->message(SLIInterpreter::M_ERROR, "get_a_a","Usage: [a] [i1 .. in] get -> [a[i1] ... a[in]]"); i->raiseerror(i->ArgumentTypeError); return; } ArrayDatum *obj = dynamic_cast<ArrayDatum *>(i->OStack.pick(1).datum()); if(obj==NULL) { i->message(SLIInterpreter::M_ERROR, "get_a_a","Usage: [a] [i1 .. in] get -> [a[i1] ... a[in]]"); i->message(SLIInterpreter::M_ERROR, "get_a_a","First argument must be an array."); i->raiseerror(i->ArgumentTypeError); return; } std::vector<size_t> indices; indices.reserve(idx->size()); for(Token *t=idx->begin(); t != idx->end(); ++t) { IntegerDatum *id=dynamic_cast<IntegerDatum *>(t->datum()); if(id == NULL) { std::ostringstream sout; sout << "Index at position " << (size_t)(t-idx->begin()) << " ignored." << std::ends; i->message(SLIInterpreter::M_INFO, "get_a_a",sout.str().c_str()); i->message(SLIInterpreter::M_INFO, "get_a_a","Index must be an integer."); continue; } if(!((id->get()>=0) && ( (size_t)id->get() < obj->size()))) { std::ostringstream sout; sout << "At position " << (size_t)(t-idx->begin()) << "." << std::ends; i->message(SLIInterpreter::M_ERROR, "get_a_a",sout.str().c_str()); i->message(SLIInterpreter::M_ERROR, "get_a_a","Index out of range."); i->raiseerror(i->RangeCheckError); return; } indices.push_back(id->get()); } TokenArray result; result.reserve(idx->size()); for(size_t j=0; j< indices.size(); ++j) { result.push_back(obj->get(indices[j])); } assert(result.size() == indices.size()); i->OStack.pop(2); i->OStack.push(ArrayDatum(result)); i->EStack.pop(); } void Get_pFunction::execute(SLIInterpreter *i) const { // call: array int get_a assert(i->OStack.load()>1); IntegerDatum *idx = dynamic_cast<IntegerDatum *>(i->OStack.top().datum()); assert(idx != NULL); ProcedureDatum *obj = dynamic_cast<ProcedureDatum *>(i->OStack.pick(1).datum()); assert(obj != NULL); if((idx->get()>=0) && ( (size_t)idx->get() < obj->size())) { i->EStack.pop(); Token objT(obj->get(idx->get())); i->OStack.pop(2); i->OStack.push_move(objT); } else i->raiseerror(i->RangeCheckError); } void Get_lpFunction::execute(SLIInterpreter *i) const { // call: array int get_a assert(i->OStack.load()>1); IntegerDatum *idx = dynamic_cast<IntegerDatum *>(i->OStack.top().datum()); assert(idx != NULL); LitprocedureDatum *obj = dynamic_cast<LitprocedureDatum *>(i->OStack.pick(1).datum()); assert(obj != NULL); if((idx->get()>=0) && ( (size_t)idx->get() < obj->size())) { i->EStack.pop(); Token objT(obj->get(idx->get())); i->OStack.pop(2); i->OStack.push_move(objT); } else i->raiseerror(i->RangeCheckError); } void Append_aFunction::execute(SLIInterpreter *i) const { i->EStack.pop(); assert(i->OStack.load()>1); ArrayDatum *obj = dynamic_cast<ArrayDatum *>(i->OStack.pick(1).datum()); assert(obj != NULL); obj->push_back_move(i->OStack.top()); i->OStack.pop(); } void Append_pFunction::execute(SLIInterpreter *i) const { i->EStack.pop(); assert(i->OStack.load()>1); ProcedureDatum *obj = dynamic_cast<ProcedureDatum *>(i->OStack.pick(1).datum()); assert(obj != NULL); obj->push_back_move(i->OStack.top()); i->OStack.pop(); } /*BeginDocumentation Name: append - Append an object to a string or array. Synopsis: (string) int append -> string [array] obj append -> array Examples: (hello) 44 append -> (hello,) (44 is ASCII value for ,) [1 2 3] (hello) append -> [1 2 3 (hello)] [1 2 3] 44 append -> [1 2 3 44] Author: docu by Sirko Straube, Marc-Oliver Gewaltig SeeAlso: prepend, insert */ void Append_sFunction::execute(SLIInterpreter *i) const { // call: string integer append_s string i->EStack.pop(); assert(i->OStack.load()>1); StringDatum *sd = dynamic_cast<StringDatum *>(i->OStack.pick(1).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(sd != NULL && id != NULL); (*sd)+=static_cast<char>(id->get()); i->OStack.pop(); } /*BeginDocumentation Name: join - Join two strings or arrays. Synopsis: (string1) (string2) join -> (string1string2) [array1] [array2] -> [array1 array2] << dict1 >> << dict2 >> -> << contents of dict2 assigned to dict1 >> Examples: (spike) (train) join -> (spiketrain) [1 2] [3 4] join -> [1 2 3 4] /j << /C_m 250.0 /Tau_m 10.0 >> def j << /Tau_m 25.0 /I_e 130.0 >> join j -> << /C_m 250.0 /Tau_m 25.0 /I_e 130.0 >> Author: docu edited by Sirko Straube SeeAlso: append, getinterval, get */ void Join_sFunction::execute(SLIInterpreter *i) const { // call: string string join_s string i->EStack.pop(); assert(i->OStack.load()>1); StringDatum *s1 = dynamic_cast<StringDatum *>(i->OStack.pick(1).datum()); StringDatum *s2 = dynamic_cast<StringDatum *>(i->OStack.pick(0).datum()); if(s1 == NULL || s2 ==NULL) { i->message(SLIInterpreter::M_ERROR, "join_s","Usage: (string1) (string2) join_s"); i->raiseerror(i->ArgumentTypeError); return; } s1->append(*s2); i->OStack.pop(); } void Join_aFunction::execute(SLIInterpreter *i) const { // call: array array join_a array i->EStack.pop(); assert(i->OStack.load()>1); ArrayDatum *a1 = dynamic_cast<ArrayDatum *>(i->OStack.pick(1).datum()); ArrayDatum *a2 = dynamic_cast<ArrayDatum *>(i->OStack.pick(0).datum()); assert(a1 != NULL && a2 !=NULL); a1->append_move(*a2); i->OStack.pop(); } void Join_pFunction::execute(SLIInterpreter *i) const { // call: proc proc join_p proc i->EStack.pop(); assert(i->OStack.load()>1); ProcedureDatum *a1 = dynamic_cast<ProcedureDatum *>(i->OStack.pick(1).datum()); ProcedureDatum *a2 = dynamic_cast<ProcedureDatum *>(i->OStack.pick(0).datum()); assert(a1 != NULL && a2 !=NULL); a1->append_move(*a2); i->OStack.pop(); } /*BeginDocumentation Name: insert - Insert all elements of one container in another container. Synopsis: (string1) n (string2) insert -> (string3) Inserts string2 into string1, starting at position n. [array1] n [array2] insert-> [array3] Inserts all elements of array2 into array1, starting at position n Examples: (spikesimulation) 5 (train) insert -> (spiketrainsimulation) [20 21 22 24 25 26] 3 [23] insert -> [20 21 22 23 24 25 26] SeeAlso: join, insertelement, append, prepend */ void Insert_sFunction::execute(SLIInterpreter *i) const { // call: string index string insert_s string assert(i->OStack.load()>2); StringDatum *s1 = dynamic_cast<StringDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); StringDatum *s2 = dynamic_cast<StringDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && id !=NULL && s2 !=NULL); if((id->get()>=0) && ( (size_t)id->get() < s1->size())) { i->EStack.pop(); s1->insert(id->get(),*s2); i->OStack.pop(2); } else i->raiseerror(i->RangeCheckError); } /*BeginDocumentation Name: insertelement - insert an element to a container at a specific position Synopsis: (string1) n c insertelement -> (string2) Inserts the character c into string1, starting at position n. [array1] n any insertelement -> [array3] Inserts element any into array1, starting at position n Examples:(hello) 3 44 insertelement -> (hel,lo) [1 2 3] 1 (hello) insertelement -> [1 (hello) 2 3] SeeAlso: join, insert, append, prepend */ void InsertElement_sFunction::execute(SLIInterpreter *i) const { // call: string integer integer insertelement_s string assert(i->OStack.load()>2); StringDatum *s1 = dynamic_cast<StringDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); IntegerDatum *c = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && id !=NULL && c !=NULL); if((id->get()>=0) && ( (size_t)id->get() < s1->size())) { i->EStack.pop(); s1->insert(id->get(),1, static_cast<char>(c->get())); i->OStack.pop(2); } else i->raiseerror(i->RangeCheckError); } /*BeginDocumentation: Name: prepend - Attach an object to the front of an array or string. Synopsis: (string) int prepend -> string [array] any prepend -> array Examples: (hello) 44 prepend -> (,hello) (44 is ASCII value for ,) [1 2 3] (hello) prepend -> [(hello) 1 2 3] [1 2 3] 44 prepend -> [44 1 2 3] Author: docu edited by Sirko Straube SeeAlso: append, insertelement */ void Prepend_sFunction::execute(SLIInterpreter *i) const { // call: string integer prepend_s string i->EStack.pop(); assert(i->OStack.load()>1); StringDatum *s1 = dynamic_cast<StringDatum *>(i->OStack.pick(1).datum()); IntegerDatum *c = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && c !=NULL); s1->insert((size_t)0,1, static_cast<char>(c->get())); i->OStack.pop(1); } void Insert_aFunction::execute(SLIInterpreter *i) const { // call: array index array insert_a array assert(i->OStack.load()>2); ArrayDatum *a1 = dynamic_cast<ArrayDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); ArrayDatum *a2 = dynamic_cast<ArrayDatum *>(i->OStack.pick(0).datum()); assert(a1 != NULL && id !=NULL && a2 !=NULL); if((id->get()>=0) && ( (size_t)id->get() < a1->size())) { i->EStack.pop(); a1->insert_move(id->get(),*a2); // ArrayDatum is a TokenArray. i->OStack.pop(2); // insert_move empties TokenArray *a2 } else i->raiseerror(i->RangeCheckError); } void InsertElement_aFunction::execute(SLIInterpreter *i) const { // call: array index any insertelement_a array assert(i->OStack.load()>2); ArrayDatum *a1 = dynamic_cast<ArrayDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); assert(a1 != NULL && id !=NULL); if((id->get()>=0) && ( (size_t)id->get() < a1->size())) { i->EStack.pop(); a1->insert_move(id->get(), i->OStack.top()); i->OStack.pop(2); } else i->raiseerror(i->RangeCheckError); } void Prepend_aFunction::execute(SLIInterpreter *i) const { // call: array any prepend_a array i->EStack.pop(); assert(i->OStack.load()>1); ArrayDatum *a1 = dynamic_cast<ArrayDatum *>(i->OStack.pick(1).datum()); assert(a1 != NULL); a1->insert_move(0, i->OStack.top()); i->OStack.pop(1); } void Prepend_pFunction::execute(SLIInterpreter *i) const { // call: array any prepend_a array i->EStack.pop(); assert(i->OStack.load()>1); ProcedureDatum *a1 = dynamic_cast<ProcedureDatum *>(i->OStack.pick(1).datum()); assert(a1 != NULL); a1->insert_move(0, i->OStack.top()); i->OStack.pop(1); } /*BeginDocumentation Name: replace - Replace a section of a string or array by a new sequence. Synopsis: (string1) a b (string2) replace -> (string3) [array1] a b [array2] replace -> [array3] Description: Replaces the elements a through b in container1 by container2. Examples: [1 2 3 4 5 6 7] 2 3 [99 99 99 99] replace -> [1 2 99 99 99 99 6 7] (computer) 1 5 (are) replace ->(career) SeeAlso: ReplaceOccurrences */ void Replace_sFunction::execute(SLIInterpreter *i) const { // call: string integer integer string replace_s string assert(i->OStack.load()>3); StringDatum *s1 = dynamic_cast<StringDatum *>(i->OStack.pick(3).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(2).datum()); IntegerDatum *n = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); StringDatum *s2 = dynamic_cast<StringDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && id !=NULL && n !=NULL && s2 !=NULL); if((id->get()>=0) && ( (size_t)id->get() < s1->size())) { if (n->get()>=0) { i->EStack.pop(); s1->replace(id->get(), n->get(),*s2); i->OStack.pop(3); } else i->raiseerror(i->PositiveIntegerExpectedError); } else i->raiseerror(i->RangeCheckError); } void Replace_aFunction::execute(SLIInterpreter *i) const { // call: array integer integer array replace_a array assert(i->OStack.load()>3); ArrayDatum *s1 = dynamic_cast<ArrayDatum *>(i->OStack.pick(3).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(2).datum()); IntegerDatum *n = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); ArrayDatum *s2 = dynamic_cast<ArrayDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && id !=NULL && n !=NULL && s2 !=NULL); if((id->get()>=0) && ( (size_t)id->get() < s1->size())) { if (n->get()>=0) { i->EStack.pop(); s1->replace_move(id->get(), n->get(),*s2); i->OStack.pop(3); } else i->raiseerror(i->PositiveIntegerExpectedError); } else i->raiseerror(i->RangeCheckError); } /*BeginDocumentation Name: erase - Deletes a subsequece of a string or array. Synopsis: (string1) a n erase -> (string2) [array1] a n erase -> [array2] Parameters: a - index of the first element to be removed, starting with 0. n - number of element to be removed. Description: Erases n elements from the container, starting with element a. Examples: SLI ] [1 2 3 4 5 6] 5 1 erase == [1 2 3 4 5] SeeAlso: getinterval */ void Erase_sFunction::execute(SLIInterpreter *i) const { // call: string integer integer erase_s string assert(i->OStack.load()>2); StringDatum *s1 = dynamic_cast<StringDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); IntegerDatum *n = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && id !=NULL && n !=NULL); if((id->get()>=0) && ( (size_t)id->get() < s1->size())) { if (n->get()>=0) { i->EStack.pop(); s1->erase(id->get(), n->get()); i->OStack.pop(2); } else i->raiseerror(i->PositiveIntegerExpectedError); } else i->raiseerror(i->RangeCheckError); } void Erase_aFunction::execute(SLIInterpreter *i) const { // call: array integer integer erase_a array assert(i->OStack.load()>2); ArrayDatum *s1 = dynamic_cast<ArrayDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); IntegerDatum *n = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && id !=NULL && n !=NULL); if((id->get()>=0) && ( (size_t)id->get() < s1->size())) { if (n->get()>=0) { i->EStack.pop(); s1->erase(id->get(), n->get()); i->OStack.pop(2); } else i->raiseerror(i->PositiveIntegerExpectedError); } else i->raiseerror(i->RangeCheckError); } void Erase_pFunction::execute(SLIInterpreter *i) const { // call: proc integer integer erase_p proc assert(i->OStack.load()>2); ProcedureDatum *s1 = dynamic_cast<ProcedureDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); IntegerDatum *n = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && id !=NULL && n !=NULL); if((id->get()>=0) && ( (size_t)id->get() < s1->size())) { if (n->get()>=0) { i->EStack.pop(); s1->erase(id->get(), n->get()); i->OStack.pop(2); } else i->raiseerror(i->PositiveIntegerExpectedError); } else i->raiseerror(i->RangeCheckError); } void Put_sFunction::execute(SLIInterpreter *i) const { // call: string index integer put_s string assert(i->OStack.load()>2); StringDatum *s1 = dynamic_cast<StringDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); IntegerDatum *cd = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && id !=NULL && cd !=NULL); if((id->get()>=0) && ( (size_t)id->get() < s1->size())) { i->EStack.pop(); (*s1)[id->get()]=static_cast<char>(cd->get()); i->OStack.pop(2); } else i->raiseerror(i->RangeCheckError); } void Put_aFunction::execute(SLIInterpreter *i) const { // call: array index any put_a array assert(i->OStack.load()>2); ArrayDatum *ad = dynamic_cast<ArrayDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); assert(ad != NULL && id !=NULL); if((id->get()>=0) && ( (size_t)id->get() < ad->size())) { i->EStack.pop(); ad->assign_move(id->get(),i->OStack.top()); // its safe to empty top() because i->OStack.pop(2); // it will be poped. } else i->raiseerror(i->RangeCheckError); } void Put_pFunction::execute(SLIInterpreter *i) const { // call: array index any put_a array assert(i->OStack.load()>2); ProcedureDatum *ad = dynamic_cast<ProcedureDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); assert(ad != NULL && id !=NULL); if((id->get()>=0) && ( (size_t)id->get() < ad->size())) { i->EStack.pop(); ad->assign_move(id->get(),i->OStack.top()); // its safe to empty top() because i->OStack.pop(2); // it will be poped. } else i->raiseerror(i->RangeCheckError); } void Put_lpFunction::execute(SLIInterpreter *i) const { // call: array index any put_a array assert(i->OStack.load()>2); LitprocedureDatum *ad = dynamic_cast<LitprocedureDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); assert(ad != NULL && id !=NULL); if((id->get()>=0) && ( (size_t)id->get() < ad->size())) { i->EStack.pop(); ad->assign_move(id->get(),i->OStack.top()); // its safe to empty top() because i->OStack.pop(2); // it will be poped. } else i->raiseerror(i->RangeCheckError); } /* BeginDocumentation Name: length_s - counts elements of a string Synopsis: string length -> int Examples: (Hello world!) length --> 12 Author: docu by Sirko Straube Remarks: Use length if you are not sure of the data type. SeeAlso: length */ void Length_sFunction::execute(SLIInterpreter *i) const { i->EStack.pop(); assert(i->OStack.load()>0); StringDatum *s = dynamic_cast<StringDatum *>(i->OStack.top().datum()); assert(s != NULL); Token t(new IntegerDatum(s->length())); i->OStack.pop(); i->OStack.push_move(t); } /* BeginDocumentation Name: length_a - counts elements of an array Synopsis: array length_a -> int Examples: [1 2 3 4 6 7] length_a --> 6 Author: docu by Sirko Straube Remarks: Use length if you are not sure of the data type. SeeAlso: length */ void Length_aFunction::execute(SLIInterpreter *i) const { i->EStack.pop(); assert(i->OStack.load()>0); ArrayDatum *s = dynamic_cast<ArrayDatum *>(i->OStack.top().datum()); assert(s != NULL); Token t(new IntegerDatum(s->size())); i->OStack.pop(); i->OStack.push_move(t); } /* BeginDocumentation Name: length_p - counts elements of a procedure Synopsis: procedure length_p -> int Examples: {mul dup} length_p --> 2 Author: docu by Sirko Straube Remarks: Use length if you are not sure of the data type. SeeAlso: length */ void Length_pFunction::execute(SLIInterpreter *i) const { i->EStack.pop(); assert(i->OStack.load()>0); ProcedureDatum *s = dynamic_cast<ProcedureDatum *>(i->OStack.top().datum()); assert(s != NULL); Token t(new IntegerDatum(s->size())); i->OStack.pop(); i->OStack.push_move(t); } /* BeginDocumentation Name: length_lp - counts elements of a literal procedure Synopsis: literal procedure length_lp -> int Examples: { {1 2 3} } 0 get length_lp -> 3 Remarks: 0 get is needed to make sure that procedure is still literal procedure, when it is evaluated. Use length if you are not sure of the data type. Author: docu by Sirko Straube SeeAlso: length */ void Length_lpFunction::execute(SLIInterpreter *i) const { i->EStack.pop(); assert(i->OStack.load()>0); LitprocedureDatum *s = dynamic_cast<LitprocedureDatum *>(i->OStack.top().datum()); assert(s != NULL); Token t(new IntegerDatum(s->size())); i->OStack.pop(); i->OStack.push_move(t); } /*BeginDocumentation Name: capacity - Returns the capacity of an array. Synopsis: array capacity -> n Description: Returns the number of elements that a given array can hold without being re-sized. Examples: [1] capacity -> 100 101 array capacity -> 200 Remarks: The default size for an array is 100. If it is bigger, its size is readjusted to a factor of 100. The number of elements in an array is given by length. Author: docu by Sirko Straube SeeAlso: reserve, shrink, allocations, length, size */ void Capacity_aFunction::execute(SLIInterpreter *i) const { // call: array capacity_a array integer i->EStack.pop(); assert(i->OStack.load()>0); ArrayDatum *s = dynamic_cast<ArrayDatum *>(i->OStack.top().datum()); assert(s != NULL); Token t(new IntegerDatum(s->capacity())); i->OStack.push_move(t); } /*BeginDocumentation Name: size - Returns the size of an array/string. Synopsis: array size -> n array string size -> n string Description: Returns the number of elements (similar to length) of an object and additionally the object itself. Examples: [1 2] size -> 2 [1 2] (hello) size -> 5 (hello) Author: docu by Sirko Straube SeeAlso: reserve, shrink, allocations, length, capacity */ void Size_aFunction::execute(SLIInterpreter *i) const { // call: array size_a array integer i->EStack.pop(); assert(i->OStack.load()>0); ArrayDatum *s = dynamic_cast<ArrayDatum *>(i->OStack.top().datum()); assert(s != NULL); Token t(new IntegerDatum(s->size())); i->OStack.push_move(t); } /*BeginDocumentation Name: reserve - Prepare an array or string to hold a given number of elements. Synopsis: array n reserve -> array Description: reserve makes sure that the array can hold at least n objects. If the current capacity of the array is lower than n, it will be resized. Note that if the current capacity is larger than n, no resize will take place. SeeAlso: capacity, shrink, allocations */ void Reserve_aFunction::execute(SLIInterpreter *i) const { // call: array integer reserve_a array assert(i->OStack.load()>1); ArrayDatum *ad = dynamic_cast<ArrayDatum *>(i->OStack.pick(1).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(ad != NULL && id !=NULL); if (id->get()>=0) { i->EStack.pop(); ad->reserve(id->get()); i->OStack.pop(); } else i->raiseerror(i->PositiveIntegerExpectedError); } /*BeginDocumentation Name: :resize - Change the internal size of an array. Synopsis: array n resize -> array. Description: resize changes the size of the supplied array independent of the current capacity. resize is used to free memory by shrinking arrays whose capacity has grown too large. If the new size is smaller than the array, the trailing elements are lost. SeeAlso: capacity, reserve, shrink */ void Resize_aFunction::execute(SLIInterpreter *i) const { // call: array integer resize_a array assert(i->OStack.load()>1); ArrayDatum *ad = dynamic_cast<ArrayDatum *>(i->OStack.pick(1).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(ad != NULL && id !=NULL); if (id->get()>=0) { i->EStack.pop(); ad->resize(id->get()); i->OStack.pop(); } else i->raiseerror(i->PositiveIntegerExpectedError); } void Empty_aFunction::execute(SLIInterpreter *i) const { // call: array empty_a array bool i->EStack.pop(); assert(i->OStack.load()>0); ArrayDatum *ad = dynamic_cast<ArrayDatum *>(i->OStack.top().datum()); assert(ad != NULL); if (ad->empty()) i->OStack.push(i->baselookup(i->true_name)); else i->OStack.push(i->baselookup(i->false_name)); } void References_aFunction::execute(SLIInterpreter *i) const { // call: array references_a array integer i->EStack.pop(); assert(i->OStack.load()>0); ArrayDatum *ad = dynamic_cast<ArrayDatum *>(i->OStack.top().datum()); assert(ad != NULL); Token t(new IntegerDatum(ad->references())); i->OStack.push_move(t); } /*BeginDocumentation Name: shrink - Reduce the capacity of an array or string to its minimum. Synopsis: array shrink -> array bool Description: Shrink reduces the capacity of an array or string to its minimum. The boolean return value indicates whether a re-sizing of the array was done. SeeAlso: capacity, reserve, allocations */ void Shrink_aFunction::execute(SLIInterpreter *i) const { // call: array shrink_a array bool i->EStack.pop(); assert(i->OStack.load()>0); ArrayDatum *ad = dynamic_cast<ArrayDatum *>(i->OStack.top().datum()); assert(ad != NULL); if (ad->shrink()) i->OStack.push(i->baselookup(i->true_name)); else i->OStack.push(i->baselookup(i->false_name)); } void Capacity_sFunction::execute(SLIInterpreter *i) const { // call: string capacity_s string integer i->EStack.pop(); assert(i->OStack.load()>0); StringDatum *s = dynamic_cast<StringDatum *>(i->OStack.top().datum()); assert(s != NULL); Token t(new IntegerDatum(s->capacity())); i->OStack.push_move(t); } void Size_sFunction::execute(SLIInterpreter *i) const { // call: string size_a string integer i->EStack.pop(); assert(i->OStack.load()>0); StringDatum *s = dynamic_cast<StringDatum *>(i->OStack.top().datum()); assert(s != NULL); Token t(new IntegerDatum(s->size())); i->OStack.push_move(t); } void Reserve_sFunction::execute(SLIInterpreter *i) const { // call: string integer reserve_a string assert(i->OStack.load()>1); StringDatum *ad = dynamic_cast<StringDatum *>(i->OStack.pick(1).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(ad != NULL && id !=NULL); if (id->get()>=0) { i->EStack.pop(); ad->reserve(id->get()); i->OStack.pop(); } else i->raiseerror(i->PositiveIntegerExpectedError); } void Resize_sFunction::execute(SLIInterpreter *i) const { // call: string integer resize_a string assert(i->OStack.load()>1); StringDatum *ad = dynamic_cast<StringDatum *>(i->OStack.pick(1).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(ad != NULL && id !=NULL); if (id->get()>=0) { i->EStack.pop(); ad->resize(id->get(),' '); // space as default char i->OStack.pop(); } else i->raiseerror(i->PositiveIntegerExpectedError); } void Empty_sFunction::execute(SLIInterpreter *i) const { // call: string empty_a string bool i->EStack.pop(); assert(i->OStack.load()>0); StringDatum *ad = dynamic_cast<StringDatum *>(i->OStack.top().datum()); assert(ad != NULL); if (ad->empty()) i->OStack.push(i->baselookup(i->true_name)); else i->OStack.push(i->baselookup(i->false_name)); } /*BeginDocumentation Name: getinterval - Return a subsequence of a string or array. Synopsis: (string1) a b getinterval -> (string2) [array1] a b getinterval -> [array2] Description: getinterval returns a new container with b elements starting at element a Examples: (spiketrainsimulation) 5 5 getinterval -> train (spiketrainsimulation) 0 5 getinterval -> spike [23 24 25 26 27 30] 0 2 getinterval -> [23 24] [23 24 25 26 27 30] 2 3 getinterval -> [25 26 27] Author: docu edited by Sirko Straube SeeAlso: get, put, putinterval */ void Getinterval_sFunction::execute(SLIInterpreter *i) const { // call: string index count getinterval_s string assert(i->OStack.load()>1); StringDatum *sd = dynamic_cast<StringDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); IntegerDatum *cd = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(sd != NULL && id !=NULL && cd !=NULL); if((id->get()>=0) && ( (size_t)id->get() < sd->size())) { if (cd->get()>=0) { i->EStack.pop(); sd->assign(*sd, id->get(),cd->get()); i->OStack.pop(2); } else i->raiseerror(i->PositiveIntegerExpectedError); } else i->raiseerror(i->RangeCheckError); } void Getinterval_aFunction::execute(SLIInterpreter *i) const { // call: array index count getinterval_a array assert(i->OStack.load()>1); ArrayDatum *sd = dynamic_cast<ArrayDatum *>(i->OStack.pick(2).datum()); IntegerDatum *id = dynamic_cast<IntegerDatum *>(i->OStack.pick(1).datum()); IntegerDatum *cd = dynamic_cast<IntegerDatum *>(i->OStack.pick(0).datum()); assert(sd != NULL && id !=NULL && cd !=NULL); if (cd->get()>0) { long index = (id->get()>=0)? id->get(): (sd->size()+id->get()); if(index >= 0 && (size_t)index < sd->size()) { i->EStack.pop(); sd->reduce(index,cd->get()); i->OStack.pop(2); } else i->raiseerror(i->RangeCheckError); } else { i->EStack.pop(); sd->clear(); i->OStack.pop(2); } } void Cvx_aFunction::execute(SLIInterpreter *i) const { Name caller(i->getcurrentname()); i->EStack.pop(); assert(i->OStack.load()>0); ArrayDatum *obj = dynamic_cast<ArrayDatum *>(i->OStack.top().datum()); assert(obj != NULL); Token t( new ProcedureDatum(*obj)); t->set_executable(); i->OStack.top().swap(t); } void Cvlit_nFunction::execute(SLIInterpreter *i) const { assert(i->OStack.load()>0); NameDatum *obj = dynamic_cast<NameDatum *>(i->OStack.top().datum()); assert(obj != NULL); Token t( new LiteralDatum(*obj)); i->OStack.top().swap(t); i->EStack.pop(); } void Cvn_lFunction::execute(SLIInterpreter *i) const { assert(i->OStack.load()>0); LiteralDatum *obj = dynamic_cast<LiteralDatum *>(i->OStack.top().datum()); assert(obj != NULL); Token t( new NameDatum(*obj)); i->OStack.top().swap(t); i->EStack.pop(); } void Cvn_sFunction::execute(SLIInterpreter *i) const { assert(i->OStack.load()>0); StringDatum *obj = dynamic_cast<StringDatum *>(i->OStack.top().datum()); assert(obj != NULL); Token t( new NameDatum(*obj)); i->OStack.top().swap(t); i->EStack.pop(); } void Cvlit_pFunction::execute(SLIInterpreter *i) const { assert(i->OStack.load()>0); ProcedureDatum *obj = dynamic_cast<ProcedureDatum *>(i->OStack.top().datum()); assert(obj != NULL); Token t( new ArrayDatum(*obj)); i->OStack.top().swap(t); i->EStack.pop(); } // // { } cvlp /{ } // void Cvlp_pFunction::execute(SLIInterpreter *i) const { assert(i->OStack.load()>0); ProcedureDatum *obj = dynamic_cast<ProcedureDatum *>(i->OStack.top().datum()); assert(obj != NULL); Token t( new LitprocedureDatum(*obj)); t->set_executable(); i->OStack.top().swap(t); i->EStack.pop(); } // ---- begin iterator experimental section void RangeIterator_aFunction::execute(SLIInterpreter *i) const { assert(i->OStack.load()>0); ArrayDatum *a = dynamic_cast<ArrayDatum *>(i->OStack.top().datum()); assert(a != NULL); const long start = getValue<long>(a->get(0)); const long stop = getValue<long>(a->get(1)); const long di = getValue<long>(a->get(2)); Token t( new IteratorDatum(start,stop,di)); i->OStack.top().swap(t); i->EStack.pop(); } void IteratorSize_iterFunction::execute(SLIInterpreter *i) const { assert(i->OStack.load()>0); IteratorDatum *iter = dynamic_cast<IteratorDatum *>(i->OStack.top().datum()); assert(iter != NULL); Token t( new IntegerDatum(iter->size())); i->OStack.push_move(t); i->EStack.pop(); } // ---- end iterator experimental section void Cvi_sFunction::execute(SLIInterpreter *i) const { assert(i->OStack.load()>0); StringDatum *obj = dynamic_cast<StringDatum *>(i->OStack.top().datum()); assert(obj != NULL); Token t( new IntegerDatum( std::atoi( obj->c_str()) ) ); i->OStack.top().swap(t); i->EStack.pop(); } void Cvd_sFunction::execute(SLIInterpreter *i) const { assert(i->OStack.load()>0); StringDatum *obj = dynamic_cast<StringDatum *>(i->OStack.top().datum()); assert(obj != NULL); Token t( new DoubleDatum( std::atof( obj->c_str()) ) ); i->OStack.top().swap(t); i->EStack.pop(); } void Get_sFunction::execute(SLIInterpreter *i) const { // call: string int get_s assert(i->OStack.load()>1); IntegerDatum *idx = dynamic_cast<IntegerDatum *>(i->OStack.top().datum()); assert(idx != NULL); StringDatum *obj = dynamic_cast<StringDatum *>(i->OStack.pick(1).datum()); assert(obj != NULL); if((idx->get()>=0) && ( (size_t)idx->get() < obj->size())) { i->EStack.pop(); Token objT( new IntegerDatum((*obj)[idx->get()])); i->OStack.pop(2); i->OStack.push_move(objT); } else i->raiseerror(i->RangeCheckError); } /*BeginDocumentation Name: search - Search for a sequence in an array or string. Synopsis: (string) (seek) search -> (post) (match) (pre) true -> (string) false [array] [seek] search -> [post] [match] [pre] true -> [array] false Examples: (hamburger) (burg) search -> true (ham) (burg) (er) SeeAlso: searchif */ void Search_sFunction::execute(SLIInterpreter *i) const { // call: string seek search_s post match pre true // string false i->EStack.pop(); assert(i->OStack.load()>1); StringDatum *s1 = dynamic_cast<StringDatum *>(i->OStack.pick(1).datum()); StringDatum *s2 = dynamic_cast<StringDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && s2 != NULL); size_t p=s1->find(*s2); if (p==ULONG_MAX) // what we realy want is MAX of size_type { // as soon as C++ limits are supported i->OStack.pop(); // (see Stroustrup 3rd ed. p. 586) i->OStack.push(i->baselookup(i->false_name)); } else { StringDatum *s3 = new StringDatum(); size_t n = p; // number of pre elements s3->assign(*s1,(size_t)0,n); s1->erase(0,n+s2->size()); Token pre(s3); i->OStack.push_move(pre); i->OStack.push(i->baselookup(i->true_name)); } } void Search_aFunction::execute(SLIInterpreter *i) const { // call: array array search_a post match pre true // array false i->EStack.pop(); assert(i->OStack.load()>1); ArrayDatum *s1 = dynamic_cast<ArrayDatum *>(i->OStack.pick(1).datum()); ArrayDatum *s2 = dynamic_cast<ArrayDatum *>(i->OStack.pick(0).datum()); assert(s1 != NULL && s2 != NULL); Token *p=std::search(s1->begin(),s1->end(),s2->begin(),s2->end()); if (p==s1->end()) { i->OStack.pop(); i->OStack.push(i->baselookup(i->false_name)); } else { ArrayDatum *s3 = new ArrayDatum(); size_t n = p - s1->begin(); // number of pre elements s3->assign_move(*s1,(size_t)0,n); // _move members may invalidate s1->erase(0,n+s2->size()); // argument iterators Token pre(s3); i->OStack.push_move(pre); i->OStack.push(i->baselookup(i->true_name)); } } /**********************************************/ /* %repeatany */ /* call: mark count any %repeatany */ /* pick 3 2 1 0 */ // This version repeats any object n times. /**********************************************/ void IrepeatanyFunction::execute(SLIInterpreter *i) const { IntegerDatum *loopcount= static_cast<IntegerDatum *>(i->EStack.pick(2).datum()); if( loopcount->get() > 0 ) { i->EStack.push(i->EStack.pick(1)); --(loopcount->get()); } else i->EStack.pop(4); } void RepeatanyFunction::execute(SLIInterpreter *i) const { // level 1 0 // stack: n proc repeat i->EStack.pop(); // if(proc->size() >0) // { i->EStack.push(i->baselookup(i->mark_name)); i->EStack.push_move(i->OStack.pick(1)); i->EStack.push_move(i->OStack.pick(0)); i->EStack.push(i->baselookup(Name("::repeatany"))); // } i->OStack.pop(2); } const Allocations_aFunction allocations_afunction; const Get_a_aFunction get_a_afunction; const Get_aFunction get_afunction; const Get_pFunction get_pfunction; const Get_lpFunction get_lpfunction; const Append_aFunction append_afunction; const Append_pFunction append_pfunction; const Append_sFunction append_sfunction; const Prepend_aFunction prepend_afunction; const Prepend_pFunction prepend_pfunction; const Prepend_sFunction prepend_sfunction; const Join_sFunction join_sfunction; const Join_aFunction join_afunction; const Join_pFunction join_pfunction; const Insert_sFunction insert_sfunction; const Insert_aFunction insert_afunction; const InsertElement_aFunction insertelement_afunction; const InsertElement_sFunction insertelement_sfunction; const Replace_sFunction replace_sfunction; const Replace_aFunction replace_afunction; const Erase_sFunction erase_sfunction; const Erase_aFunction erase_afunction; const Erase_pFunction erase_pfunction; const Length_sFunction length_sfunction; const Length_aFunction length_afunction; const Length_lpFunction length_lpfunction; const Length_pFunction length_pfunction; const Getinterval_sFunction getinterval_sfunction; const Getinterval_aFunction getinterval_afunction; const Cvx_aFunction cvx_afunction; const Cvlit_nFunction cvlit_nfunction; const Cvlit_pFunction cvlit_pfunction; const Cvlp_pFunction cvlp_pfunction; const RangeIterator_aFunction rangeiterator_afunction; const IteratorSize_iterFunction iteratorsize_iterfunction; const Cvn_lFunction cvn_lfunction; const Cvn_sFunction cvn_sfunction; const Cvi_sFunction cvi_sfunction; const Cvd_sFunction cvd_sfunction; const Get_sFunction get_sfunction; const Put_sFunction put_sfunction; const Put_aFunction put_afunction; const Put_pFunction put_pfunction; const Put_lpFunction put_lpfunction; const Search_sFunction search_sfunction; const Search_aFunction search_afunction; const Capacity_aFunction capacity_afunction; const Size_aFunction size_afunction; const Reserve_aFunction reserve_afunction; const Resize_aFunction resize_afunction; const Empty_aFunction empty_afunction; const References_aFunction references_afunction; const Shrink_aFunction shrink_afunction; const Capacity_sFunction capacity_sfunction; const Size_sFunction size_sfunction; const Reserve_sFunction reserve_sfunction; const Resize_sFunction resize_sfunction; const Empty_sFunction empty_sfunction; const IrepeatanyFunction irepeatanyfunction; const RepeatanyFunction repeatanyfunction; void init_slidata(SLIInterpreter *i) { i->createcommand("allocations", &allocations_afunction); i->createcommand("get_s", &get_sfunction); i->createcommand("get_a", &get_afunction); i->createcommand("get_a_a", &get_a_afunction); i->createcommand("get_p", &get_pfunction); i->createcommand("get_lp", &get_lpfunction); i->createcommand("append_a", &append_afunction); i->createcommand("append_p", &append_pfunction); i->createcommand("append_s", &append_sfunction); i->createcommand("prepend_a", &prepend_afunction); i->createcommand("prepend_p", &prepend_pfunction); i->createcommand("prepend_s", &prepend_sfunction); i->createcommand("join_s", &join_sfunction); i->createcommand("join_a", &join_afunction); i->createcommand("join_p", &join_pfunction); i->createcommand("insert_s", &insert_sfunction); i->createcommand("insert_a", &insert_afunction); i->createcommand("insertelement_s", &insertelement_sfunction); i->createcommand("insertelement_a", &insertelement_afunction); i->createcommand("replace_s", &replace_sfunction); i->createcommand("replace_a", &replace_afunction); i->createcommand("erase_s", &erase_sfunction); i->createcommand("erase_a", &erase_afunction); i->createcommand("erase_p", &erase_pfunction); i->createcommand("length_s", &length_sfunction); i->createcommand("length_a", &length_afunction); i->createcommand("length_p", &length_pfunction); i->createcommand("length_lp", &length_lpfunction); i->createcommand("getinterval_s", &getinterval_sfunction); i->createcommand("getinterval_a", &getinterval_afunction); i->createcommand("cvx_a", &cvx_afunction); i->createcommand("cvlit_n", &cvlit_nfunction); i->createcommand("cvlit_p", &cvlit_pfunction); i->createcommand("cvlp_p", &cvlp_pfunction); i->createcommand("RangeIterator_a", &rangeiterator_afunction); i->createcommand("size_iter", &iteratorsize_iterfunction); i->createcommand("cvn_l", &cvn_lfunction); i->createcommand("cvn_s", &cvn_sfunction); i->createcommand("cvi_s", &cvi_sfunction); i->createcommand("cvd_s", &cvd_sfunction); i->createcommand("put_s", &put_sfunction); i->createcommand("put_a", &put_afunction); i->createcommand("put_p", &put_pfunction); i->createcommand("put_lp", &put_lpfunction); i->createcommand("search_s", &search_sfunction); i->createcommand("search_a", &search_afunction); i->createcommand("capacity_a", &capacity_afunction); i->createcommand("size_a", &size_afunction); i->createcommand("reserve_a", &reserve_afunction); i->createcommand(":resize_a", &resize_afunction); i->createcommand("empty_a", &empty_afunction); i->createcommand("references_a", &references_afunction); i->createcommand("shrink_a", &shrink_afunction); i->createcommand("capacity_s", &capacity_sfunction); i->createcommand("size_s", &size_sfunction); i->createcommand("reserve_s", &reserve_sfunction); i->createcommand(":resize_s", &resize_sfunction); i->createcommand("empty_s", &empty_sfunction); i->createcommand("::repeatany", &irepeatanyfunction); i->createcommand("repeatany", &repeatanyfunction); }