/***** * castop.h * Tom Prince 2005/3/18 * * Defines some runtime functions used by the stack machine. * *****/ #ifndef CASTOP_H #define CASTOP_H #include #include "common.h" #include "stack.h" #include "fileio.h" #include "lexical.h" #include "mathop.h" #include "array.h" namespace run { using vm::read; using vm::pop; template void cast(vm::stack *s) { s->push((S) pop(s)); } void castDoubleInt(vm::stack *s) { double x=pop(s); s->push(Intcast(x)); } template void stringCast(vm::stack *s) { ostringstream buf; buf.precision(DBL_DIG); buf << pop(s); s->push(buf.str()); } template void castString(vm::stack *s) { string *S=pop(s); if(S->empty()) { T x=0; s->push(x); } else { try { s->push(lexical::cast(*S)); } catch (lexical::bad_cast&) { ostringstream buf; buf << "invalid cast from string \"" << *S << "\""; vm::error(buf); } } } template void arrayToArray(vm::stack *s) { vm::array *a = pop(s); checkArray(a); size_t size=(size_t) a->size(); vm::array *c=new vm::array(size); for(size_t i=0; i < size; i++) (*c)[i]=(S) read(a,i); s->push(c); } template void read(vm::stack *s) { camp::file *f = pop(s); T val=T(); if(f->isOpen()) { f->read(val); if(f->LineMode()) f->nexteol(); if(interact::interactive) f->purgeStandard(val); } s->push(val); } inline Int Limit(Int nx) {return nx == 0 ? Int_MAX : nx;} inline void reportEof(camp::file *f, Int count) { if(count > 0) { ostringstream buf; buf << "EOF after reading " << count << " values from file '" << f->filename() << "'."; vm::error(buf); } } template void readArray(vm::stack *s) { camp::file *f = pop(s); vm::array *c=new vm::array(0); if(f->isOpen()) { Int nx=f->Nx(); if(nx == -2) {f->read(nx); f->Nx(-1); if(nx == 0) {s->push(c); return;}} Int ny=f->Ny(); if(ny == -2) {f->read(ny); f->Ny(-1); if(ny == 0) {s->push(c); return;}} Int nz=f->Nz(); if(nz == -2) {f->read(nz); f->Nz(-1); if(nz == 0) {s->push(c); return;}} T v; if(nx >= 0) { for(Int i=0; i < Limit(nx); i++) { if(ny >= 0) { vm::array *ci=new vm::array(0); for(Int j=0; j < Limit(ny); j++) { if(nz >= 0) { vm::array *cij=new vm::array(0); bool break2=false; for(Int k=0; k < Limit(nz); k++) { f->read(v); if(f->error()) { if(nx && ny && nz) reportEof(f,(i*ny+j)*nz+k); s->push(c); return; } if(k == 0) { if(j == 0) c->push(ci); ci->push(cij); } cij->push(v); if(f->LineMode() && f->nexteol()) { if(f->nexteol()) break2=true; break; } } if(break2) break; } else { f->read(v); if(f->error()) { if(nx && ny) reportEof(f,i*ny+j); s->push(c); return; } if(j == 0) c->push(ci); ci->push(v); if(f->LineMode() && f->nexteol()) break; } } } else { f->read(v); if(f->error()) { if(nx) reportEof(f,i); s->push(c); return; } c->push(v); if(f->LineMode() && f->nexteol()) break; } } } else { for(;;) { f->read(v); if(f->error()) break; c->push(v); if(f->LineMode() && f->nexteol()) break; } } if(interact::interactive) f->purgeStandard(v); } s->push(c); } } // namespace run #endif // CASTOP_H