/* * slibuiltins.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/>. * */ /* Interpreter builtins */ #include "slibuiltins.h" #include "interpret.h" #include "callbackdatum.h" #include "arraydatum.h" #include "integerdatum.h" #include "stringdatum.h" #include "iteratordatum.h" #include "functiondatum.h" void IlookupFunction::execute(SLIInterpreter *i) const { i->EStack.pop(2); } void IsetcallbackFunction::execute(SLIInterpreter *i) const { // move the hopefully present callback action // into the interpreters callback token. i->EStack.pop(); assert(dynamic_cast<CallbackDatum *>(i->EStack.top().datum()) !=NULL); i->EStack.pop_move(i->ct); } void IiterateFunction::backtrace(SLIInterpreter *i, int p) const { ProcedureDatum const *pd= dynamic_cast<ProcedureDatum *>(i->EStack.pick(p+2).datum()); assert(pd != NULL); IntegerDatum *id= dynamic_cast<IntegerDatum *>(i->EStack.pick(p+1).datum()); assert(id !=NULL); std::cerr << "In procedure:" << std::endl; pd->list(std::cerr," ",id->get()-1); std::cerr << std::endl; } void IiterateFunction::execute(SLIInterpreter *i) const { /* This function is responsible for executing a procedure object. Iiterate expects the procedure to execute as first and the iteration counter as second argument. Like in all internal function, no error checking is done. */ /* Stack Layout: 3 2 1 <proc> <pos> %iterate */ ProcedureDatum const *pd= static_cast<ProcedureDatum *>(i->EStack.pick(2).datum()); long &pos=static_cast<IntegerDatum *>(i->EStack.pick(1).datum())->get(); while( pd->index_is_valid(pos)) { const Token &t=pd->get(pos); ++pos; i->code_executed++; // code coverage if( t->is_executable()) { i->EStack.push(t); return; } i->OStack.push(t); } i->EStack.pop(3); i->dec_call_depth(); } void IloopFunction::execute(SLIInterpreter *i) const { // stack: mark procedure n %loop // level: 4 3 2 1 ProcedureDatum const *proc= static_cast<ProcedureDatum *>(i->EStack.pick(2).datum()); long &pos=static_cast<IntegerDatum *>(i->EStack.pick(1).datum())->get(); while( proc->index_is_valid(pos)) { const Token &t(proc->get(pos)); ++pos; if( t->is_executable()) { i->EStack.push(t); return; } i->OStack.push(t); } pos =0; } void IloopFunction::backtrace(SLIInterpreter *i, int p) const { ProcedureDatum const *pd= dynamic_cast<ProcedureDatum *>(i->EStack.pick(p+2).datum()); assert(pd !=NULL); IntegerDatum *id= dynamic_cast<IntegerDatum *>(i->EStack.pick(p+1).datum()); assert(id != NULL); std::cerr << "During loop:" << std::endl; pd->list(std::cerr," ",id->get()-1); std::cerr <<std::endl; } /**********************************************/ /* %repeat */ /* call: mark count proc n %repeat */ /* pick 5 4 3 2 1 */ /**********************************************/ void IrepeatFunction::execute(SLIInterpreter *i) const { ProcedureDatum *proc= static_cast<ProcedureDatum *>(i->EStack.pick(2).datum()); long &pos=static_cast<IntegerDatum *>(i->EStack.pick(1).datum())->get(); while( proc->index_is_valid(pos)) { const Token &t=proc->get(pos); ++pos; if( t->is_executable()) { i->EStack.push(t); return; } i->OStack.push(t); } long &lc=static_cast<IntegerDatum *>(i->EStack.pick(3).datum())->get(); if( lc > 0 ) { pos=0; // reset procedure iterator --lc; } else { i->EStack.pop(5); i->dec_call_depth(); } } void IrepeatFunction::backtrace(SLIInterpreter *i, int p) const { IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(p+3).datum()); assert(count != NULL); ProcedureDatum const *pd= static_cast<ProcedureDatum *>(i->EStack.pick(p+2).datum()); assert(pd!= NULL); IntegerDatum *id= static_cast<IntegerDatum *>(i->EStack.pick(p+1).datum()); assert(id != NULL); std::cerr << "During repeat with " << count->get() << " iterations remaining." << std::endl; pd->list(std::cerr," ",id->get()-1); std::cerr <<std::endl; } /*****************************************************/ /* %for */ /* call: mark incr limit count proc n %for */ /* pick 6 5 4 3 2 1 0 */ /*****************************************************/ void IforFunction::execute(SLIInterpreter *i) const { IntegerDatum *proccount= static_cast<IntegerDatum *>(i->EStack.pick(1).datum()); ProcedureDatum const *proc= static_cast<ProcedureDatum *>(i->EStack.pick(2).datum()); long &pos=proccount->get(); while( proc->index_is_valid(pos)) { const Token &t= proc->get(pos); ++pos; if( t->is_executable()) { i->EStack.push(t); return; } i->OStack.push(t); } IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(3).datum()); IntegerDatum *lim = static_cast<IntegerDatum *>(i->EStack.pick(4).datum()); IntegerDatum *inc = static_cast<IntegerDatum *>(i->EStack.pick(5).datum()); if(( (inc->get()> 0) && (count->get() <= lim->get())) || ( (inc->get()< 0) && (count->get() >= lim->get()))) { pos=0; // reset procedure interator i->OStack.push(i->EStack.pick(3)); // push counter to user (count->get()) += (inc->get()); // increment loop counter } else { i->EStack.pop(7); i->dec_call_depth(); } } void IforFunction::backtrace(SLIInterpreter *i, int p) const { IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(p+3).datum()); assert(count!=NULL); ProcedureDatum const *pd= static_cast<ProcedureDatum *>(i->EStack.pick(p+2).datum()); assert(pd != NULL); IntegerDatum *id= static_cast<IntegerDatum *>(i->EStack.pick(p+1).datum()); assert(id != NULL); std::cerr << "During for at iterator value " << count->get() << "." << std::endl; pd->list(std::cerr," ",id->get()-1); std::cerr <<std::endl; } /*********************************************************/ /* %forallarray */ /* call: mark object count proc n %forallarray */ /* pick 5 4 3 2 1 0 */ /*********************************************************/ void IforallarrayFunction::execute(SLIInterpreter *i) const { IntegerDatum *proccount= static_cast<IntegerDatum *>(i->EStack.pick(1).datum()); ProcedureDatum const *proc= static_cast<ProcedureDatum *>(i->EStack.pick(2).datum()); long &pos=proccount->get(); while( proc->index_is_valid(pos)) { const Token &t= proc->get(pos); ++pos; if( t->is_executable()) { i->EStack.push(t); return; } i->OStack.push(t); } IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(3).datum()); ArrayDatum *ad = static_cast<ArrayDatum *>(i->EStack.pick(4).datum()); long &idx=count->get(); if(ad->index_is_valid(idx)) { pos=0; // reset procedure interator i->OStack.push(ad->get(idx)); // push counter to user ++idx; } else { i->EStack.pop(6); i->dec_call_depth(); } } void IforallarrayFunction::backtrace(SLIInterpreter *i, int p) const { IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(p+3).datum()); assert(count!=NULL); std::cerr << "During forall (array) at iteration " << count->get() << "." << std::endl; } /*********************************************************/ /* %foralliter */ /* call: mark iterator proc %foralliter */ /* pick 3 2 1 0 */ /*********************************************************/ void IforalliterFunction::execute(SLIInterpreter *i) const { IteratorDatum *iter= static_cast<IteratorDatum *>(i->EStack.pick(2).datum()); if(iter->pos() < iter->end()) { i->OStack.push(iter->pos()); // push current element to operand stack iter->incr(); i->EStack.push(i->EStack.pick(1)); if(i->step_mode()) { std::cerr << "foralliter:" << " Limit: " << iter->end() << " Pos: " << iter->pos() ; i->OStack.pick(0).pprint(std::cerr); std::cerr << std::endl; } } else { i->EStack.pop(4); i->dec_call_depth(); } } void IforalliterFunction::backtrace(SLIInterpreter *i, int p) const { IteratorDatum *iter= static_cast<IteratorDatum *>(i->EStack.pick(p+2).datum()); std::cerr << "During forall (iterator) at iteration " << iter->pos() << "." << std::endl; } /*********************************************************/ /* %forallindexedarray */ /* call: mark object limit count proc forallindexedarray */ /* pick 5 4 3 2 1 0 */ /*********************************************************/ void IforallindexedarrayFunction::execute(SLIInterpreter *i) const { IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(2).datum()); IntegerDatum *limit= static_cast<IntegerDatum *>(i->EStack.pick(3).datum()); long &cnt=count->get(); if( cnt< limit->get()) { ArrayDatum *obj= static_cast<ArrayDatum *>(i->EStack.pick(4).datum()); i->OStack.push(obj->get(cnt)); // push element to user i->OStack.push_by_pointer(new IntegerDatum(cnt)); // push index to user ++cnt; i->EStack.push(i->EStack.pick(1)); // if(i->step_mode()) // { // std::cerr << "forallindexed:" // << " Limit: " << limit->get() // << " Pos: " << count->get() -1 // << " Iterator: "; // i->OStack.pick(1).pprint(std::cerr); // std::cerr << std::endl; // } } else { i->EStack.pop(6); i->dec_call_depth(); } } void IforallindexedarrayFunction::backtrace(SLIInterpreter *i, int p) const { IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(p+2).datum()); assert(count!=NULL); std::cerr << "During forallindexed (array) at iteration " << count->get()-1 << "." << std::endl; } void IforallindexedstringFunction::backtrace(SLIInterpreter *i, int p) const { IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(p+2).datum()); assert(count!=NULL); std::cerr << "During forallindexed (string) at iteration " << count->get()-1 << "." << std::endl; } /*********************************************************/ /* %forallindexedarray */ /* call: mark object limit count proc forallindexedarray */ /* pick 5 4 3 2 1 0 */ /*********************************************************/ void IforallindexedstringFunction::execute(SLIInterpreter *i) const { IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(2).datum()); IntegerDatum *limit= static_cast<IntegerDatum *>(i->EStack.pick(3).datum()); if(count->get() < limit->get()) { StringDatum const *obj= static_cast<StringDatum *>(i->EStack.pick(4).datum()); i->OStack.push((*obj)[count->get()]); // push element to user i->OStack.push(count->get()); // push index to user ++(count->get()); i->EStack.push(i->EStack.pick(1)); if(i->step_mode()) { std::cerr << "forallindexed:" << " Limit: " << limit->get() << " Pos: " << count->get() << " Iterator: "; i->OStack.pick(1).pprint(std::cerr); std::cerr << std::endl; } } else { i->EStack.pop(6); i->dec_call_depth(); } } void IforallstringFunction::backtrace(SLIInterpreter *i, int p) const { IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(p+2).datum()); assert(count!=NULL); std::cerr << "During forall (string) at iteration " << count->get()-1 << "." << std::endl; } /*********************************************************/ /* %forallstring */ /* call: mark object limit count proc %forallarray */ /* pick 5 4 3 2 1 0 */ /*********************************************************/ void IforallstringFunction::execute(SLIInterpreter *i) const { IntegerDatum *count= static_cast<IntegerDatum *>(i->EStack.pick(2).datum()); IntegerDatum *limit= static_cast<IntegerDatum *>(i->EStack.pick(3).datum()); if(count->get() < limit->get()) { StringDatum const *obj= static_cast<StringDatum *>(i->EStack.pick(4).datum()); i->OStack.push_by_pointer(new IntegerDatum((*obj)[count->get()])); // push element to user ++(count->get()); i->EStack.push(i->EStack.pick(1)); if(i->step_mode()) { std::cerr << "forall:" << " Limit: " << limit->get() << " Pos: " << count->get() << " Iterator: "; i->OStack.top().pprint(std::cerr); std::cerr << std::endl; } } else { i->EStack.pop(6); i->dec_call_depth(); } }