/***** * builtin.cc * Tom Prince 2004/08/25 * * Initialize builtins. *****/ #include #include "builtin.h" #include "entry.h" #include "runtime.h" #include "runpicture.h" #include "runlabel.h" #include "runhistory.h" #include "runarray.h" #include "runfile.h" #include "runsystem.h" #include "runstring.h" #include "runpair.h" #include "runtriple.h" #include "runpath.h" #include "runpath3d.h" #include "runmath.h" #include "types.h" #include "castop.h" #include "mathop.h" #include "arrayop.h" #include "vm.h" #include "coder.h" #include "exp.h" #include "refaccess.h" #include "settings.h" #ifdef HAVE_LIBGSL #include #include #include #endif using namespace types; using namespace camp; using namespace vm; namespace trans { using camp::transform; using camp::pair; using vm::bltin; using run::divide; using run::less; using run::greater; using run::plus; using run::minus; using namespace run; void gen_runtime_venv(venv &ve); void gen_runbacktrace_venv(venv &ve); void gen_runpicture_venv(venv &ve); void gen_runlabel_venv(venv &ve); void gen_runhistory_venv(venv &ve); void gen_runarray_venv(venv &ve); void gen_runfile_venv(venv &ve); void gen_runsystem_venv(venv &ve); void gen_runstring_venv(venv &ve); void gen_runpair_venv(venv &ve); void gen_runtriple_venv(venv &ve); void gen_runpath_venv(venv &ve); void gen_runpath3d_venv(venv &ve); void gen_runmath_venv(venv &ve); void addType(tenv &te, const char *name, ty *t) { te.enter(symbol::trans(name), new tyEntry(t,0,0,position())); } // The base environments for built-in types and functions void base_tenv(tenv &te) { #define PRIMITIVE(name,Name,asyName) addType(te, #asyName, prim##Name()); #include "primitives.h" #undef PRIMITIVE } const formal noformal(0); void addFunc(venv &ve, access *a, ty *result, symbol *id, formal f1=noformal, formal f2=noformal, formal f3=noformal, formal f4=noformal, formal f5=noformal, formal f6=noformal, formal f7=noformal, formal f8=noformal, formal f9=noformal, formal fA=noformal, formal fB=noformal, formal fC=noformal, formal fD=noformal, formal fE=noformal, formal fF=noformal, formal fG=noformal, formal fH=noformal, formal fI=noformal) { function *fun = new function(result); if (f1.t) fun->add(f1); if (f2.t) fun->add(f2); if (f3.t) fun->add(f3); if (f4.t) fun->add(f4); if (f5.t) fun->add(f5); if (f6.t) fun->add(f6); if (f7.t) fun->add(f7); if (f8.t) fun->add(f8); if (f9.t) fun->add(f9); if (fA.t) fun->add(fA); if (fB.t) fun->add(fB); if (fC.t) fun->add(fC); if (fD.t) fun->add(fD); if (fE.t) fun->add(fE); if (fF.t) fun->add(fF); if (fG.t) fun->add(fG); if (fH.t) fun->add(fH); if (fI.t) fun->add(fI); // NOTE: If the function is a field, we should encode the defining record in // the entry varEntry *ent = new varEntry(fun, a, 0, position()); ve.enter(id, ent); } // Add a function with one or more default arguments. void addFunc(venv &ve, bltin f, ty *result, const char *name, formal f1, formal f2, formal f3, formal f4, formal f5, formal f6, formal f7, formal f8, formal f9, formal fA, formal fB, formal fC, formal fD, formal fE, formal fF, formal fG, formal fH, formal fI) { REGISTER_BLTIN(f, name); access *a = new bltinAccess(f); addFunc(ve,a,result,symbol::trans(name),f1,f2,f3,f4,f5,f6,f7,f8,f9, fA,fB,fC,fD,fE,fF,fG,fH,fI); } void addFunc(venv &ve, access *a, ty *result, const char *name, formal f1) { addFunc(ve,a,result,symbol::trans(name),f1); } void addOpenFunc(venv &ve, bltin f, ty *result, const char *name) { function *fun = new function(result, signature::OPEN); REGISTER_BLTIN(f, name); access *a= new bltinAccess(f); varEntry *ent = new varEntry(fun, a, 0, position()); ve.enter(symbol::trans(name), ent); } // Add a rest function with zero or more default/explicit arguments. void addRestFunc(venv &ve, bltin f, ty *result, const char *name, formal frest, formal f1=noformal, formal f2=noformal, formal f3=noformal, formal f4=noformal, formal f5=noformal, formal f6=noformal, formal f7=noformal, formal f8=noformal, formal f9=noformal) { REGISTER_BLTIN(f, name); access *a = new bltinAccess(f); function *fun = new function(result); if (f1.t) fun->add(f1); if (f2.t) fun->add(f2); if (f3.t) fun->add(f3); if (f4.t) fun->add(f4); if (f5.t) fun->add(f5); if (f6.t) fun->add(f6); if (f7.t) fun->add(f7); if (f8.t) fun->add(f8); if (f9.t) fun->add(f9); if (frest.t) fun->addRest(frest); varEntry *ent = new varEntry(fun, a, 0, position()); ve.enter(symbol::trans(name), ent); } void addRealFunc0(venv &ve, bltin fcn, const char *name) { addFunc(ve, fcn, primReal(), name); } template void addRealFunc(venv &ve, const char* name) { addFunc(ve, realReal, primReal(), name, formal(primReal(),"x")); addFunc(ve, arrayFunc, realArray(), name, formal(realArray(),"a")); } #define addRealFunc(fcn) addRealFunc(ve, #fcn); void addRealFunc2(venv &ve, bltin fcn, const char *name) { addFunc(ve,fcn,primReal(),name,formal(primReal(),"a"), formal(primReal(),"b")); } template void realRealInt(vm::stack *s) { Int n = pop(s); double x = pop(s); s->push(func(x, intcast(n))); } template void addRealIntFunc(venv& ve, const char* name, const char* arg1, const char* arg2) { addFunc(ve, realRealInt, primReal(), name, formal(primReal(), arg1), formal(primInt(), arg2)); } #ifdef HAVE_LIBGSL bool GSLerror=false; types::dummyRecord *GSLModule; types::record *getGSLModule() { return GSLModule; } inline void checkGSLerror() { if(GSLerror) { GSLerror=false; throw handled_error(); } } template void realRealGSL(vm::stack *s) { double x=pop(s); s->push(func(x)); checkGSLerror(); } template void realRealDOUBLE(vm::stack *s) { double x=pop(s); s->push(func(x,GSL_PREC_DOUBLE)); checkGSLerror(); } template void realRealRealDOUBLE(vm::stack *s) { double y=pop(s); double x=pop(s); s->push(func(x,y,GSL_PREC_DOUBLE)); checkGSLerror(); } template void realIntGSL(vm::stack *s) { s->push(func(unsignedcast(pop(s)))); checkGSLerror(); } template void realIntRealGSL(vm::stack *s) { double x=pop(s); s->push(func(intcast(pop(s)),x)); checkGSLerror(); } template void realRealRealGSL(vm::stack *s) { double x=pop(s); double n=pop(s); s->push(func(n,x)); checkGSLerror(); } template void intRealRealRealGSL(vm::stack *s) { double x=pop(s); double n=pop(s); double a=pop(s); s->push(func(a,n,x)); checkGSLerror(); } template void realRealRealRealGSL(vm::stack *s) { double x=pop(s); double n=pop(s); double a=pop(s); s->push(func(a,n,x)); checkGSLerror(); } template void realRealIntGSL(vm::stack *s) { Int n=pop(s); double x=pop(s); s->push(func(x,unsignedcast(n))); checkGSLerror(); } // Add a GSL special function from the GNU GSL library template void addGSLRealFunc(const char* name, const char* arg1="x") { addFunc(GSLModule->e.ve, realRealGSL, primReal(), name, formal(primReal(),arg1)); } // Add a GSL_PREC_DOUBLE GSL special function. template void addGSLDOUBLEFunc(const char* name, const char* arg1="x") { addFunc(GSLModule->e.ve, realRealDOUBLE, primReal(), name, formal(primReal(),arg1)); } template void addGSLDOUBLE2Func(const char* name, const char* arg1="phi", const char* arg2="k") { addFunc(GSLModule->e.ve, realRealRealDOUBLE, primReal(), name, formal(primReal(),arg1), formal(primReal(),arg2)); } template void realRealRealRealDOUBLE(vm::stack *s) { double z=pop(s); double y=pop(s); double x=pop(s); s->push(func(x,y,z,GSL_PREC_DOUBLE)); checkGSLerror(); } template void addGSLDOUBLE3Func(const char* name, const char* arg1, const char* arg2, const char* arg3) { addFunc(GSLModule->e.ve, realRealRealRealDOUBLE, primReal(), name, formal(primReal(),arg1), formal(primReal(),arg2), formal(primReal(), arg3)); } template void realRealRealRealRealDOUBLE(vm::stack *s) { double z=pop(s); double y=pop(s); double x=pop(s); double w=pop(s); s->push(func(w,x,y,z,GSL_PREC_DOUBLE)); checkGSLerror(); } template void addGSLDOUBLE4Func(const char* name, const char* arg1, const char* arg2, const char* arg3, const char* arg4) { addFunc(GSLModule->e.ve, realRealRealRealRealDOUBLE, primReal(), name, formal(primReal(),arg1), formal(primReal(),arg2), formal(primReal(), arg3), formal(primReal(), arg4)); } template void addGSLIntFunc(const char* name) { addFunc(GSLModule->e.ve, realIntGSL, primReal(), name, formal(primInt(),"s")); } template void realSignedGSL(vm::stack *s) { Int a = pop(s); s->push(func(intcast(a))); checkGSLerror(); } template void addGSLSignedFunc(const char* name, const char* arg1) { addFunc(GSLModule->e.ve, realSignedGSL, primReal(), name, formal(primInt(),arg1)); } template void addGSLIntRealFunc(const char* name, const char *arg1="n", const char* arg2="x") { addFunc(GSLModule->e.ve, realIntRealGSL, primReal(), name, formal(primInt(),arg1), formal(primReal(),arg2)); } template void addGSLRealRealFunc(const char* name, const char* arg1="nu", const char* arg2="x") { addFunc(GSLModule->e.ve, realRealRealGSL, primReal(), name, formal(primReal(),arg1), formal(primReal(),arg2)); } template void addGSLRealRealRealFunc(const char* name, const char* arg1, const char* arg2, const char* arg3) { addFunc(GSLModule->e.ve, realRealRealRealGSL, primReal(), name, formal(primReal(),arg1), formal(primReal(),arg2), formal(primReal(), arg3)); } template void addGSLRealRealRealFuncInt(const char* name, const char* arg1, const char* arg2, const char* arg3) { addFunc(GSLModule->e.ve, intRealRealRealGSL, primInt(), name, formal(primReal(),arg1), formal(primReal(),arg2), formal(primReal(), arg3)); } template void addGSLRealIntFunc(const char* name, const char* arg1="nu", const char* arg2="s") { addFunc(GSLModule->e.ve, realRealIntGSL, primReal(), name, formal(primReal(),arg1), formal(primInt(),arg2)); } template void realRealSignedGSL(vm::stack *s) { Int b = pop(s); double a = pop(s); s->push(func(a, intcast(b))); checkGSLerror(); } template void addGSLRealSignedFunc(const char* name, const char* arg1, const char* arg2) { addFunc(GSLModule->e.ve, realRealSignedGSL, primReal(), name, formal(primReal(),arg1), formal(primInt(),arg2)); } template void realUnsignedUnsignedGSL(vm::stack *s) { Int b = pop(s); Int a = pop(s); s->push(func(unsignedcast(a), unsignedcast(b))); checkGSLerror(); } template void addGSLUnsignedUnsignedFunc(const char* name, const char* arg1, const char* arg2) { addFunc(GSLModule->e.ve, realUnsignedUnsignedGSL, primReal(), name, formal(primInt(), arg1), formal(primInt(), arg2)); } template void realIntRealRealGSL(vm::stack *s) { double c = pop(s); double b = pop(s); Int a = pop(s); s->push(func(intcast(a), b, c)); checkGSLerror(); } template void addGSLIntRealRealFunc(const char* name, const char* arg1, const char* arg2, const char* arg3) { addFunc(GSLModule->e.ve, realIntRealRealGSL, primReal(), name, formal(primInt(), arg1), formal(primReal(), arg2), formal(primReal(), arg3)); } template void realIntIntRealGSL(vm::stack *s) { double c = pop(s); Int b = pop(s); Int a = pop(s); s->push(func(intcast(a), intcast(b), c)); checkGSLerror(); } template void addGSLIntIntRealFunc(const char* name, const char* arg1, const char* arg2, const char* arg3) { addFunc(GSLModule->e.ve, realIntIntRealGSL, primReal(), name, formal(primInt(), arg1), formal(primInt(), arg2), formal(primReal(), arg3)); } template void realIntIntRealRealGSL(vm::stack *s) { double d = pop(s); double c = pop(s); Int b = pop(s); Int a = pop(s); s->push(func(intcast(a), intcast(b), c, d)); checkGSLerror(); } template void addGSLIntIntRealRealFunc(const char* name, const char* arg1, const char* arg2, const char* arg3, const char* arg4) { addFunc(GSLModule->e.ve, realIntIntRealRealGSL, primReal(), name, formal(primInt(), arg1), formal(primInt(), arg2), formal(primReal(), arg3), formal(primReal(), arg4)); } template void realRealRealRealRealGSL(vm::stack *s) { double d = pop(s); double c = pop(s); double b = pop(s); double a = pop(s); s->push(func(a, b, c, d)); checkGSLerror(); } template void addGSLRealRealRealRealFunc(const char* name, const char* arg1, const char* arg2, const char* arg3, const char* arg4) { addFunc(GSLModule->e.ve, realRealRealRealRealGSL, primReal(), name, formal(primReal(), arg1), formal(primReal(), arg2), formal(primReal(), arg3), formal(primReal(), arg4)); } template void realIntIntIntIntIntIntGSL(vm::stack *s) { Int f = pop(s); Int e = pop(s); Int d = pop(s); Int c = pop(s); Int b = pop(s); Int a = pop(s); s->push(func(intcast(a), intcast(b), intcast(c), intcast(d), intcast(e), intcast(f))); checkGSLerror(); } template void addGSLIntIntIntIntIntIntFunc(const char* name, const char* arg1, const char* arg2, const char* arg3, const char* arg4, const char* arg5, const char* arg6) { addFunc(GSLModule->e.ve, realIntIntIntIntIntIntGSL, primReal(), name, formal(primInt(), arg1), formal(primInt(), arg2), formal(primInt(), arg3), formal(primInt(), arg4), formal(primInt(), arg5), formal(primInt(), arg6)); } template void realIntIntIntIntIntIntIntIntIntGSL(vm::stack *s) { Int i = pop(s); Int h = pop(s); Int g = pop(s); Int f = pop(s); Int e = pop(s); Int d = pop(s); Int c = pop(s); Int b = pop(s); Int a = pop(s); s->push(func(intcast(a), intcast(b), intcast(c), intcast(d), intcast(e), intcast(f), intcast(g), intcast(h), intcast(i))); checkGSLerror(); } template void addGSLIntIntIntIntIntIntIntIntIntFunc(const char* name, const char* arg1, const char* arg2, const char* arg3, const char* arg4, const char* arg5, const char* arg6, const char* arg7, const char* arg8, const char* arg9) { addFunc(GSLModule->e.ve, realIntIntIntIntIntIntIntIntIntGSL, primReal(), name, formal(primInt(), arg1), formal(primInt(), arg2), formal(primInt(), arg3), formal(primInt(), arg4), formal(primInt(), arg5), formal(primInt(), arg6), formal(primInt(), arg7), formal(primInt(), arg8), formal(primInt(), arg9)); } // Handle GSL errors gracefully. void GSLerrorhandler(const char *reason, const char *, int, int) { if(!GSLerror) { vm::errornothrow(reason); GSLerror=true; } } #endif void addInitializer(venv &ve, ty *t, access *a) { addFunc(ve, a, t, symbol::initsym); } void addInitializer(venv &ve, ty *t, bltin f) { #ifdef DEBUG_BLTIN ostringstream s; s << "initializer for " << *t; REGISTER_BLTIN(f, s.str()); #endif access *a = new bltinAccess(f); addInitializer(ve, t, a); } // Specifies that source may be cast to target, but only if an explicit // cast expression is used. void addExplicitCast(venv &ve, ty *target, ty *source, access *a) { addFunc(ve, a, target, symbol::ecastsym, source); } // Specifies that source may be implicitly cast to target by the // function or instruction stores at a. void addCast(venv &ve, ty *target, ty *source, access *a) { //addExplicitCast(target,source,a); addFunc(ve, a, target, symbol::castsym, source); } void addExplicitCast(venv &ve, ty *target, ty *source, bltin f) { #ifdef DEBUG_BLTIN ostringstream s; s << "explicit cast from " << *source << " to " << *target; REGISTER_BLTIN(f, s.str()); #endif addExplicitCast(ve, target, source, new bltinAccess(f)); } void addCast(venv &ve, ty *target, ty *source, bltin f) { #ifdef DEBUG_BLTIN ostringstream s; s << "cast from " << *source << " to " << *target; REGISTER_BLTIN(f, s.str()); #endif addCast(ve, target, source, new bltinAccess(f)); } template void addVariable(venv &ve, T *ref, ty *t, const char *name, record *module=settings::getSettingsModule()) { access *a = new refAccess(ref); varEntry *ent = new varEntry(t, a, PUBLIC, module, 0, position()); ve.enter(symbol::trans(name), ent); } template void addVariable(venv &ve, T value, ty *t, const char *name, record *module=settings::getSettingsModule(), permission perm=PUBLIC) { item* ref=new item; *ref=value; access *a = new itemRefAccess(ref); varEntry *ent = new varEntry(t, a, perm, module, 0, position()); ve.enter(symbol::trans(name), ent); } template void addConstant(venv &ve, T value, ty *t, const char *name, record *module=settings::getSettingsModule()) { addVariable(ve,value,t,name,module,RESTRICTED); } // The identity access, i.e. no instructions are encoded for a cast or // operation, and no functions are called. identAccess id; function *IntRealFunction() { return new function(primInt(),primReal()); } function *realPairFunction() { return new function(primReal(),primPair()); } function *voidFileFunction() { return new function(primVoid(),primFile()); } void addInitializers(venv &ve) { addInitializer(ve, primBoolean(), boolFalse); addInitializer(ve, primInt(), IntZero); addInitializer(ve, primReal(), realZero); addInitializer(ve, primString(), emptyString); addInitializer(ve, primPair(), pairZero); addInitializer(ve, primTriple(), tripleZero); addInitializer(ve, primTransform(), transformIdentity); addInitializer(ve, primGuide(), nullGuide); addInitializer(ve, primPath(), nullPath); addInitializer(ve, primPath3(), nullPath3); addInitializer(ve, primPen(), newPen); addInitializer(ve, primPicture(), newPicture); addInitializer(ve, primFile(), nullFile); } void addCasts(venv &ve) { addExplicitCast(ve, primString(), primInt(), stringCast); addExplicitCast(ve, primString(), primReal(), stringCast); addExplicitCast(ve, primString(), primPair(), stringCast); addExplicitCast(ve, primString(), primTriple(), stringCast); addExplicitCast(ve, primInt(), primString(), castString); addExplicitCast(ve, primReal(), primString(), castString); addExplicitCast(ve, primPair(), primString(), castString); addExplicitCast(ve, primTriple(), primString(), castString); addExplicitCast(ve, primInt(), primReal(), castDoubleInt); addCast(ve, primReal(), primInt(), cast); addCast(ve, primPair(), primInt(), cast); addCast(ve, primPair(), primReal(), cast); addCast(ve, primPath(), primPair(), cast); addCast(ve, primGuide(), primPair(), pairToGuide); addCast(ve, primGuide(), primPath(), pathToGuide); addCast(ve, primPath(), primGuide(), guideToPath); addCast(ve, primFile(), primNull(), nullFile); // Vectorized casts. addExplicitCast(ve, IntArray(), realArray(), arrayToArray); addCast(ve, realArray(), IntArray(), arrayToArray); addCast(ve, pairArray(), IntArray(), arrayToArray); addCast(ve, pairArray(), realArray(), arrayToArray); } void addGuideOperators(venv &ve) { // The guide operators .. and -- take an array of guides, and turn them // into a single guide. addRestFunc(ve, dotsGuide, primGuide(), "..", guideArray()); addRestFunc(ve, dashesGuide, primGuide(), "--", guideArray()); } /* Avoid typing the same type three times. */ void addSimpleOperator(venv &ve, bltin f, ty *t, const char *name) { addFunc(ve,f,t,name,formal(t,"a"),formal(t,"b")); } void addBooleanOperator(venv &ve, bltin f, ty *t, const char *name) { addFunc(ve,f,primBoolean(),name,formal(t,"a"),formal(t,"b")); } template class op> void addOps(venv &ve, ty *t1, const char *name, ty *t2) { addSimpleOperator(ve,binaryOp,t1,name); addFunc(ve,opArray,t2,name,formal(t1,"a"),formal(t2,"b")); addFunc(ve,arrayOp,t2,name,formal(t2,"a"),formal(t1,"b")); addSimpleOperator(ve,arrayArrayOp,t2,name); } template class op> void addBooleanOps(venv &ve, ty *t1, const char *name, ty *t2) { addBooleanOperator(ve,binaryOp,t1,name); addFunc(ve,opArray, booleanArray(),name,formal(t1,"a"),formal(t2,"b")); addFunc(ve,arrayOp, booleanArray(),name,formal(t2,"a"),formal(t1,"b")); addFunc(ve,arrayArrayOp,booleanArray(),name,formal(t2,"a"), formal(t2,"b")); } void addWrite(venv &ve, bltin f, ty *t1, ty *t2) { addRestFunc(ve,f,primVoid(),"write",t2, formal(primFile(),"file",true),formal(primString(),"s",true), formal(t1,"x"),formal(voidFileFunction(),"suffix",true)); } template void addUnorderedOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4) { addBooleanOps(ve,t1,"==",t2); addBooleanOps(ve,t1,"!=",t2); addFunc(ve, run::array2Equals, primBoolean(), "==", formal(t3, "a"), formal(t3, "b")); addFunc(ve, run::array2NotEquals, primBoolean(), "!=", formal(t3, "a"), formal(t3, "b")); addCast(ve,t1,primFile(),read); addCast(ve,t2,primFile(),readArray); addCast(ve,t3,primFile(),readArray); addCast(ve,t4,primFile(),readArray); addWrite(ve,write,t1,t2); addRestFunc(ve,writeArray,primVoid(),"write",t3, formal(primFile(),"file",true),formal(primString(),"s",true), formal(t2,"a",false,true)); addFunc(ve,writeArray2,primVoid(),"write", formal(primFile(),"file",true),t3); addFunc(ve,writeArray3,primVoid(),"write", formal(primFile(),"file",true),t4); } inline double abs(pair z) { return z.length(); } inline double abs(triple v) { return v.length(); } template class op> void addBinOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4, const char *name) { addFunc(ve,binopArray,t1,name,formal(t2,"a")); addFunc(ve,binopArray2,t1,name,formal(t3,"a")); addFunc(ve,binopArray3,t1,name,formal(t4,"a")); } template void addOrderedOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4) { addBooleanOps(ve,t1,"<",t2); addBooleanOps(ve,t1,"<=",t2); addBooleanOps(ve,t1,">=",t2); addBooleanOps(ve,t1,">",t2); addOps(ve,t1,"min",t2); addOps(ve,t1,"max",t2); addBinOps(ve,t1,t2,t3,t4,"min"); addBinOps(ve,t1,t2,t3,t4,"max"); addFunc(ve,sortArray,t2,"sort",formal(t2,"a")); addFunc(ve,sortArray2,t3,"sort",formal(t3,"a")); addFunc(ve,searchArray,primInt(),"search",formal(t2,"a"), formal(t1,"key")); } template void addBasicOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4, bool integer=false, bool Explicit=false) { addOps(ve,t1,"+",t2); addOps(ve,t1,"-",t2); addFunc(ve,&id,t1,"+",formal(t1,"a")); addFunc(ve,&id,t2,"+",formal(t2,"a")); addFunc(ve,Negate,t1,"-",formal(t1,"a")); addFunc(ve,arrayNegate,t2,"-",formal(t2,"a")); if(!integer) addFunc(ve,interp,t1,"interp",formal(t1,"a",false,Explicit), formal(t1,"b",false,Explicit), formal(primReal(),"t")); addFunc(ve,sumArray,t1,"sum",formal(t2,"a")); addUnorderedOps(ve,t1,t2,t3,t4); } template void addOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4, bool integer=false, bool Explicit=false) { addBasicOps(ve,t1,t2,t3,t4,integer,Explicit); addOps(ve,t1,"*",t2); if(!integer) addOps(ve,t1,"/",t2); addOps(ve,t1,"^",t2); } // Adds standard functions for a newly added array type. void addArrayOps(venv &ve, types::array *t) { ty *ct = t->celltype; addFunc(ve, run::arrayAlias, primBoolean(), "alias", formal(t, "a"), formal(t, "b")); addFunc(ve, run::newDuplicateArray, t, "array", formal(primInt(), "n"), formal(ct, "value"), formal(primInt(), "depth", /*optional=*/ true)); switch (t->depth()) { case 1: addFunc(ve, run::arrayCopy, t, "copy", formal(t, "a")); addRestFunc(ve, run::arrayConcat, t, "concat", new types::array(t)); addFunc(ve, run::arraySequence, t, "sequence", formal(new function(ct, primInt()), "f"), formal(primInt(), "n")); addFunc(ve, run::arrayFunction, t, "map", formal(new function(ct, ct), "f"), formal(t, "a")); addFunc(ve, run::arraySort, t, "sort", formal(t, "a"), formal(new function(primBoolean(), ct, ct), "f")); break; case 2: addFunc(ve, run::array2Copy, t, "copy", formal(t, "a")); addFunc(ve, run::array2Transpose, t, "transpose", formal(t, "a")); break; case 3: addFunc(ve, run::array3Copy, t, "copy", formal(t, "a")); addFunc(ve, run::array3Transpose, t, "transpose", formal(t, "a"), formal(IntArray(),"perm")); break; default: break; } } void addRecordOps(venv &ve, record *r) { addFunc(ve, run::boolMemEq, primBoolean(), "alias", formal(r, "a"), formal(r, "b")); addFunc(ve, run::boolMemEq, primBoolean(), "==", formal(r, "a"), formal(r, "b")); addFunc(ve, run::boolMemNeq, primBoolean(), "!=", formal(r, "a"), formal(r, "b")); } void addFunctionOps(venv &ve, function *f) { addFunc(ve, run::boolFuncEq, primBoolean(), "==", formal(f, "a"), formal(f, "b")); addFunc(ve, run::boolFuncNeq, primBoolean(), "!=", formal(f, "a"), formal(f, "b")); } void addOperators(venv &ve) { addSimpleOperator(ve,binaryOp,primString(),"+"); addBooleanOps(ve,primBoolean(),"&",booleanArray()); addBooleanOps(ve,primBoolean(),"|",booleanArray()); addBooleanOps(ve,primBoolean(),"^",booleanArray()); addUnorderedOps(ve,primBoolean(),booleanArray(),booleanArray2(), booleanArray3()); addOps(ve,primInt(),IntArray(),IntArray2(),IntArray3(),true); addOps(ve,primReal(),realArray(),realArray2(),realArray3()); addOps(ve,primPair(),pairArray(),pairArray2(),pairArray3(),false,true); addBasicOps(ve,primTriple(),tripleArray(),tripleArray2(), tripleArray3()); addFunc(ve,opArray,tripleArray(),"*", formal(primReal(),"a"),formal(tripleArray(),"b")); addFunc(ve,arrayOp,tripleArray(),"*", formal(tripleArray(),"a"),formal(primReal(),"b")); addFunc(ve,arrayOp,tripleArray(),"/", formal(tripleArray(),"a"),formal(primReal(),"b")); addUnorderedOps(ve,primString(),stringArray(),stringArray2(), stringArray3()); addSimpleOperator(ve,binaryOp,primPair(),"minbound"); addSimpleOperator(ve,binaryOp,primPair(),"maxbound"); addSimpleOperator(ve,binaryOp,primTriple(),"minbound"); addSimpleOperator(ve,binaryOp,primTriple(),"maxbound"); addBinOps(ve,primPair(),pairArray(),pairArray2(),pairArray3(), "minbound"); addBinOps(ve,primPair(),pairArray(),pairArray2(),pairArray3(), "maxbound"); addBinOps(ve,primTriple(),tripleArray(),tripleArray2(), tripleArray3(),"minbound"); addBinOps(ve,primTriple(),tripleArray(),tripleArray2(), tripleArray3(),"maxbound"); addFunc(ve,arrayFunc,realArray(),"abs", formal(pairArray(),"a")); addFunc(ve,arrayFunc,realArray(),"abs", formal(tripleArray(),"a")); addFunc(ve,binaryOp,primReal(),"/", formal(primInt(),"a"),formal(primInt(),"b")); addFunc(ve,arrayOp,realArray(),"/", formal(IntArray(),"a"),formal(primInt(),"b")); addFunc(ve,opArray,realArray(),"/", formal(primInt(),"a"),formal(IntArray(),"b")); addFunc(ve,arrayArrayOp,realArray(),"/", formal(IntArray(),"a"),formal(IntArray(),"b")); addOrderedOps(ve,primInt(),IntArray(),IntArray2(),IntArray3()); addOrderedOps(ve,primReal(),realArray(),realArray2(),realArray3()); addOrderedOps(ve,primString(),stringArray(),stringArray2(), stringArray3()); addOps(ve,primInt(),"%",IntArray()); addOps(ve,primReal(),"%",realArray()); addRestFunc(ve,run::diagonal,realArray2(),"diagonal",realArray()); } dummyRecord *createDummyRecord(venv &ve, const char *name) { dummyRecord *r=new dummyRecord(name); #ifdef DEBUG_FRAME vm::frame *f = new vm::frame("dummy record " + string(name), 0); #else vm::frame *f = new vm::frame(0); #endif addConstant(ve, f, r, name); addRecordOps(ve, r); return r; } double identity(double x) {return x;} double pow10(double x) {return run::pow(10.0,x);} // An example of an open function. #ifdef OPENFUNCEXAMPLE void openFunc(stack *Stack) { vm::array *a=vm::pop(Stack); size_t numArgs=checkArray(a); for (size_t k=0; kpush((Int)numArgs); } #endif // NOTE: We should move all of these into a "builtin" module. void base_venv(venv &ve) { addInitializers(ve); addCasts(ve); addOperators(ve); addGuideOperators(ve); addRealFunc(sin); addRealFunc(cos); addRealFunc(tan); addRealFunc(asin); addRealFunc(acos); addRealFunc(atan); addRealFunc(exp); addRealFunc(log); addRealFunc(log10); addRealFunc(sinh); addRealFunc(cosh); addRealFunc(tanh); addRealFunc(asinh); addRealFunc(acosh); addRealFunc(atanh); addRealFunc(sqrt); addRealFunc(cbrt); addRealFunc(fabs); addRealFunc(ve,"abs"); addRealFunc(expm1); addRealFunc(log1p); addRealIntFunc(ve, "ldexp", "x", "e"); addRealFunc(pow10); addRealFunc(identity); #ifdef HAVE_LIBGSL GSLModule=new dummyRecord(symbol::trans("gsl")); gsl_set_error_handler(GSLerrorhandler); // Common functions addGSLRealRealFunc("hypot","x","y"); // addGSLRealRealRealFunc("hypot","x","y","z"); addGSLRealRealRealFuncInt("fcmp","x","y","epsilon"); // Airy functions addGSLDOUBLEFunc("Ai"); addGSLDOUBLEFunc("Bi"); addGSLDOUBLEFunc("Ai_scaled"); addGSLDOUBLEFunc("Bi_scaled"); addGSLDOUBLEFunc("Ai_deriv"); addGSLDOUBLEFunc("Bi_deriv"); addGSLDOUBLEFunc("Ai_deriv_scaled"); addGSLDOUBLEFunc("Bi_deriv_scaled"); addGSLIntFunc("zero_Ai"); addGSLIntFunc("zero_Bi"); addGSLIntFunc("zero_Ai_deriv"); addGSLIntFunc("zero_Bi_deriv"); // Bessel functions addGSLRealFunc("J0"); addGSLRealFunc("J1"); addGSLIntRealFunc("Jn"); addGSLRealFunc("Y0"); addGSLRealFunc("Y1"); addGSLIntRealFunc("Yn"); addGSLRealFunc("I0"); addGSLRealFunc("I1"); addGSLIntRealFunc("I"); addGSLRealFunc("I0_scaled"); addGSLRealFunc("I1_scaled"); addGSLIntRealFunc("I_scaled"); addGSLRealFunc("K0"); addGSLRealFunc("K1"); addGSLIntRealFunc("K"); addGSLRealFunc("K0_scaled"); addGSLRealFunc("K1_scaled"); addGSLIntRealFunc("K_scaled"); addGSLRealFunc("j0"); addGSLRealFunc("j1"); addGSLRealFunc("j2"); addGSLIntRealFunc("j","l"); addGSLRealFunc("y0"); addGSLRealFunc("y1"); addGSLRealFunc("y2"); addGSLIntRealFunc("y","l"); addGSLRealFunc("i0_scaled"); addGSLRealFunc("i1_scaled"); addGSLRealFunc("i2_scaled"); addGSLIntRealFunc("i_scaled","l"); addGSLRealFunc("k0_scaled"); addGSLRealFunc("k1_scaled"); addGSLRealFunc("k2_scaled"); addGSLIntRealFunc("k_scaled","l"); addGSLRealRealFunc("J"); addGSLRealRealFunc("Y"); addGSLRealRealFunc("I"); addGSLRealRealFunc("I_scaled"); addGSLRealRealFunc("K"); addGSLRealRealFunc("lnK"); addGSLRealRealFunc("K_scaled"); addGSLIntFunc("zero_J0"); addGSLIntFunc("zero_J1"); addGSLRealIntFunc("zero_J"); // Clausen functions addGSLRealFunc("clausen"); // Coulomb functions addGSLRealRealFunc("hydrogenicR_1","Z","r"); addGSLIntIntRealRealFunc("hydrogenicR","n","l","Z", "r"); // Missing: F_L(eta,x), G_L(eta,x), C_L(eta) // Coupling coefficients addGSLIntIntIntIntIntIntFunc("coupling_3j","two_ja", "two_jb","two_jc","two_ma", "two_mb","two_mc"); addGSLIntIntIntIntIntIntFunc("coupling_6j","two_ja", "two_jb","two_jc","two_jd", "two_je","two_jf"); addGSLIntIntIntIntIntIntIntIntIntFunc("coupling_9j", "two_ja","two_jb", "two_jc","two_jd", "two_je","two_jf", "two_jg","two_jh", "two_ji"); // Dawson function addGSLRealFunc("dawson"); // Debye functions addGSLRealFunc("debye_1"); addGSLRealFunc("debye_2"); addGSLRealFunc("debye_3"); addGSLRealFunc("debye_4"); addGSLRealFunc("debye_5"); addGSLRealFunc("debye_6"); // Dilogarithm addGSLRealFunc("dilog"); // Missing: complex dilogarithm // Elementary operations // we don't support errors at the moment // Elliptic integrals addGSLDOUBLEFunc("K","k"); addGSLDOUBLEFunc("E","k"); addGSLDOUBLE2Func("P","k","n"); addGSLDOUBLE2Func("F"); addGSLDOUBLE2Func("E"); addGSLDOUBLE3Func("P","phi","k","n"); addGSLDOUBLE3Func("D","phi","k","n"); addGSLDOUBLE2Func("RC","x","y"); addGSLDOUBLE3Func("RD","x","y","z"); addGSLDOUBLE3Func("RF","x","y","z"); addGSLDOUBLE4Func("RJ","x","y","z","p"); // Elliptic functions (Jacobi) // to be implemented // Error functions addGSLRealFunc("erf"); addGSLRealFunc("erfc"); addGSLRealFunc("log_erfc"); addGSLRealFunc("erf_Z"); addGSLRealFunc("erf_Q"); addGSLRealFunc("hazard"); // Exponential functions addGSLRealRealFunc("exp_mult","x","y"); // addGSLRealFunc("expm1"); addGSLRealFunc("exprel"); addGSLRealFunc("exprel_2"); addGSLIntRealFunc("exprel","n","x"); // Exponential integrals addGSLRealFunc("E1"); addGSLRealFunc("E2"); // addGSLIntRealFunc("En","n","x"); addGSLRealFunc("Ei"); addGSLRealFunc("Shi"); addGSLRealFunc("Chi"); addGSLRealFunc("Ei3"); addGSLRealFunc("Si"); addGSLRealFunc("Ci"); addGSLRealFunc("atanint"); // Fermi--Dirac function addGSLRealFunc("FermiDiracM1"); addGSLRealFunc("FermiDirac0"); addGSLRealFunc("FermiDirac1"); addGSLRealFunc("FermiDirac2"); addGSLIntRealFunc("FermiDirac","j","x"); addGSLRealFunc("FermiDiracMHalf"); addGSLRealFunc("FermiDiracHalf"); addGSLRealFunc("FermiDirac3Half"); addGSLRealRealFunc("FermiDiracInc0","x","b"); // Gamma and beta functions addGSLRealFunc("gamma"); addGSLRealFunc("lngamma"); addGSLRealFunc("gammastar"); addGSLRealFunc("gammainv"); addGSLIntFunc("fact"); addGSLIntFunc("doublefact"); addGSLIntFunc("lnfact"); addGSLIntFunc("lndoublefact"); addGSLUnsignedUnsignedFunc("choose","n","m"); addGSLUnsignedUnsignedFunc("lnchoose","n","m"); addGSLIntRealFunc("taylorcoeff","n","x"); addGSLRealRealFunc("poch","a","x"); addGSLRealRealFunc("lnpoch","a","x"); addGSLRealRealFunc("pochrel","a","x"); addGSLRealRealFunc("gamma","a","x"); addGSLRealRealFunc("gamma_Q","a","x"); addGSLRealRealFunc("gamma_P","a","x"); addGSLRealRealFunc("beta","a","b"); addGSLRealRealFunc("lnbeta","a","b"); addGSLRealRealRealFunc("beta","a","b","x"); // Gegenbauer functions addGSLRealRealFunc("gegenpoly_1","lambda","x"); addGSLRealRealFunc("gegenpoly_2","lambda","x"); addGSLRealRealFunc("gegenpoly_3","lambda","x"); addGSLIntRealRealFunc("gegenpoly","n","lambda","x"); // Hypergeometric functions addGSLRealRealFunc("hy0F1","c","x"); addGSLIntIntRealFunc("hy1F1","m","n","x"); addGSLRealRealRealFunc("hy1F1","a","b","x"); addGSLIntIntRealFunc("U","m","n","x"); addGSLRealRealRealFunc("U","a","b","x"); addGSLRealRealRealRealFunc("hy2F1","a","b","c","x"); addGSLRealRealRealRealFunc("hy2F1_conj","aR","aI","c", "x"); addGSLRealRealRealRealFunc("hy2F1_renorm","a","b", "c","x"); addGSLRealRealRealRealFunc("hy2F1_conj_renorm", "aR","aI","c","x"); addGSLRealRealRealFunc("hy2F0","a","b","x"); // Laguerre functions addGSLRealRealFunc("L1","a","x"); addGSLRealRealFunc("L2","a","x"); addGSLRealRealFunc("L3","a","x"); addGSLIntRealRealFunc("L","n","a","x"); // Lambert W functions addGSLRealFunc("W0"); addGSLRealFunc("Wm1"); // Legendre functions and spherical harmonics addGSLRealFunc("P1"); addGSLRealFunc("P2"); addGSLRealFunc("P3"); addGSLIntRealFunc("Pl","l"); addGSLRealFunc("Q0"); addGSLRealFunc("Q1"); addGSLIntRealFunc("Ql","l"); addGSLIntIntRealFunc("Plm","l","m","x"); addGSLIntIntRealFunc("sphPlm","l","m","x"); addGSLRealRealFunc("conicalP_half","lambda","x"); addGSLRealRealFunc("conicalP_mhalf","lambda","x"); addGSLRealRealFunc("conicalP_0","lambda","x"); addGSLRealRealFunc("conicalP_1","lambda","x"); addGSLIntRealRealFunc("conicalP_sph_reg","l", "lambda","x"); addGSLIntRealRealFunc("conicalP_cyl_reg","m", "lambda","x"); addGSLRealRealFunc("H3d0","lambda","eta"); addGSLRealRealFunc("H3d1","lambda","eta"); addGSLIntRealRealFunc("H3d","l","lambda","eta"); // Logarithm and related functions addGSLRealFunc("logabs"); // addGSLRealFunc("log1p"); addGSLRealFunc("log1pm"); // Matthieu functions // to be implemented // Power function addGSLRealSignedFunc("pow","x","n"); // Psi (digamma) function addGSLSignedFunc("psi","n"); addGSLRealFunc("psi"); addGSLRealFunc("psi_1piy","y"); addGSLSignedFunc("psi1","n"); addGSLRealFunc("psi1","x"); addGSLIntRealFunc("psi","n","x"); // Synchrotron functions addGSLRealFunc("synchrotron_1"); addGSLRealFunc("synchrotron_2"); // Transport functions addGSLRealFunc("transport_2"); addGSLRealFunc("transport_3"); addGSLRealFunc("transport_4"); addGSLRealFunc("transport_5"); // Trigonometric functions addGSLRealFunc("sinc"); addGSLRealFunc("lnsinh"); addGSLRealFunc("lncosh"); // Zeta functions addGSLSignedFunc("zeta","n"); addGSLRealFunc("zeta","s"); addGSLSignedFunc("zetam1","n"); addGSLRealFunc("zetam1","s"); addGSLRealRealFunc("hzeta","s","q"); addGSLSignedFunc("eta","n"); addGSLRealFunc("eta","s"); #endif #ifdef STRUCTEXAMPLE dummyRecord *fun=createDummyRecord(ve, "test"); addFunc(fun->e.ve,realReal,primReal(),"f",formal(primReal(),"x")); addVariable(fun->e.ve,1,primInt(),"x"); #endif addFunc(ve,writestring,primVoid(),"write", formal(primFile(),"file",true), formal(primString(),"s"), formal(voidFileFunction(),"suffix",true)); addWrite(ve,write,primTransform(),transformArray()); addWrite(ve,write,primGuide(),guideArray()); addWrite(ve,write,primPen(),penArray()); addFunc(ve,arrayArrayOp,booleanArray(),"==", formal(penArray(),"a"),formal(penArray(),"b")); addFunc(ve,arrayArrayOp,booleanArray(),"!=", formal(penArray(),"a"),formal(penArray(),"b")); addFunc(ve,arrayFunction,realArray(),"map", formal(realPairFunction(),"f"), formal(pairArray(),"a")); addFunc(ve,arrayFunction,IntArray(),"map", formal(IntRealFunction(),"f"), formal(realArray(),"a")); addConstant(ve, Int_MAX, primInt(), "intMax"); addConstant(ve, Int_MIN, primInt(), "intMin"); addConstant(ve, HUGE_VAL, primReal(), "inf"); addConstant(ve, run::infinity, primReal(), "infinity"); addConstant(ve, DBL_MAX, primReal(), "realMax"); addConstant(ve, DBL_MIN, primReal(), "realMin"); addConstant(ve, DBL_EPSILON, primReal(), "realEpsilon"); addConstant(ve, DBL_DIG, primInt(), "realDigits"); addConstant(ve, RAND_MAX, primInt(), "randMax"); addConstant(ve, PI, primReal(), "pi"); addConstant(ve, string(settings::VERSION)+string(SVN_REVISION), primString(),"VERSION"); addVariable(ve, &processData().currentpen, primPen(), "currentpen"); #ifdef OPENFUNCEXAMPLE addOpenFunc(ve, openFunc, primInt(), "openFunc"); #endif gen_runtime_venv(ve); gen_runbacktrace_venv(ve); gen_runpicture_venv(ve); gen_runlabel_venv(ve); gen_runhistory_venv(ve); gen_runarray_venv(ve); gen_runfile_venv(ve); gen_runsystem_venv(ve); gen_runstring_venv(ve); gen_runpair_venv(ve); gen_runtriple_venv(ve); gen_runpath_venv(ve); gen_runpath3d_venv(ve); gen_runmath_venv(ve); } } //namespace trans namespace run { double infinity=cbrt(DBL_MAX); // Reduced for tension atleast infinity void arrayDeleteHelper(stack *Stack) { array *a=pop(Stack); item itj=pop(Stack); bool jdefault=isdefault(itj); item iti=pop(Stack); Int i,j; if(isdefault(iti)) { if(jdefault) { (*a).clear(); return; } else i=j=get(itj); } else { i=get(iti); j=jdefault ? i : get(itj); } size_t asize=checkArray(a); if(a->cyclic() && asize > 0) { if(j-i+1 >= (Int) asize) { (*a).clear(); return; } i=imod(i,asize); j=imod(j,asize); if(j >= i) (*a).erase((*a).begin()+i,(*a).begin()+j+1); else { (*a).erase((*a).begin()+i,(*a).end()); (*a).erase((*a).begin(),(*a).begin()+j+1); } return; } if(i < 0 || i >= (Int) asize || i > j || j >= (Int) asize) { ostringstream buf; buf << "delete called on array of length " << (Int) asize << " with out-of-bounds index range [" << i << "," << j << "]"; error(buf); } (*a).erase((*a).begin()+i,(*a).begin()+j+1); } }