summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/builtin.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/builtin.cc')
-rw-r--r--Build/source/utils/asymptote/builtin.cc966
1 files changed, 966 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/builtin.cc b/Build/source/utils/asymptote/builtin.cc
new file mode 100644
index 00000000000..36af37d4d5e
--- /dev/null
+++ b/Build/source/utils/asymptote/builtin.cc
@@ -0,0 +1,966 @@
+/*****
+ * builtin.cc
+ * Tom Prince 2004/08/25
+ *
+ * Initialize builtins.
+ *****/
+
+#include <cmath>
+
+#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"
+
+#include "opsymbols.h"
+
+#ifndef NOSYM
+#include "builtin.symbols.h"
+#endif
+
+namespace vm {
+// Defined in stack.cc
+extern vm::frame *make_dummyframe(string name);
+}
+
+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 gen_rungsl_venv(venv &ve);
+
+void addType(tenv &te, symbol name, ty *t)
+{
+ te.enter(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, symbol::trans(#asyName), prim##Name());
+#include "primitives.h"
+#undef PRIMITIVE
+}
+
+const formal noformal(0);
+
+function *functionFromFormals(ty *result,
+ 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);
+
+ return fun;
+}
+
+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 = functionFromFormals(result,f1,f2,f3,f4,f5,f6,f7,f8,f9,
+ fA,fB,fC,fD,fE,fF,fG,fH,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, symbol 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)
+{
+#ifdef DEBUG_BLTIN
+ // If the function is an operator, print out the whole signature with the
+ // types, as operators are heavily overloaded. min and max are also heavily
+ // overloaded, so we check for them too. Many builtin functions have so
+ // many arguments that it is noise to print out their full signatures.
+ string s = name;
+ if (s.find("operator ", 0) == 0 || s == "min" || s == "max")
+ {
+ function *fun = functionFromFormals(result,f1,f2,f3,f4,f5,f6,f7,f8,f9,
+ fA,fB,fC,fD,fE,fF,fG,fH,fI);
+ ostringstream out;
+ fun->printVar(out, name);
+ REGISTER_BLTIN(f, out.str());
+ }
+ else {
+ REGISTER_BLTIN(f, name);
+ }
+#endif
+
+ access *a = new bltinAccess(f);
+ addFunc(ve,a,result,name,f1,f2,f3,f4,f5,f6,f7,f8,f9,
+ fA,fB,fC,fD,fE,fF,fG,fH,fI);
+}
+
+void addOpenFunc(venv &ve, bltin f, ty *result, symbol 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(name, ent);
+}
+
+
+// Add a rest function with zero or more default/explicit arguments.
+void addRestFunc(venv &ve, bltin f, ty *result, symbol 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(name, ent);
+}
+
+void addRealFunc0(venv &ve, bltin fcn, symbol name)
+{
+ addFunc(ve, fcn, primReal(), name);
+}
+
+template<double (*fcn)(double)>
+void addRealFunc(venv &ve, symbol name)
+{
+ addFunc(ve, realReal<fcn>, primReal(), name, formal(primReal(),SYM(x)));
+ addFunc(ve, arrayFunc<double,double,fcn>, realArray(), name,
+ formal(realArray(),SYM(a)));
+}
+
+#define addRealFunc(fcn, sym) addRealFunc<fcn>(ve, sym);
+
+void addRealFunc2(venv &ve, bltin fcn, symbol name)
+{
+ addFunc(ve,fcn,primReal(),name,formal(primReal(),SYM(a)),
+ formal(primReal(),SYM(b)));
+}
+
+template <double (*func)(double, int)>
+void realRealInt(vm::stack *s) {
+ Int n = pop<Int>(s);
+ double x = pop<double>(s);
+ s->push(func(x, intcast(n)));
+}
+
+template<double (*fcn)(double, int)>
+void addRealIntFunc(venv& ve, symbol name, symbol arg1,
+ symbol arg2) {
+ addFunc(ve, realRealInt<fcn>, primReal(), name, formal(primReal(), arg1),
+ formal(primInt(), arg2));
+}
+
+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<class T>
+void addVariable(venv &ve, T *ref, ty *t, symbol name,
+ record *module=settings::getSettingsModule()) {
+ access *a = new refAccess<T>(ref);
+ varEntry *ent = new varEntry(t, a, PUBLIC, module, 0, position());
+ ve.enter(name, ent);
+}
+
+template<class T>
+void addVariable(venv &ve, T value, ty *t, symbol 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(name, ent);
+}
+
+template<class T>
+void addConstant(venv &ve, T value, ty *t, symbol 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<Int>);
+ addExplicitCast(ve, primString(), primReal(), stringCast<double>);
+ addExplicitCast(ve, primString(), primPair(), stringCast<pair>);
+ addExplicitCast(ve, primString(), primTriple(), stringCast<triple>);
+ addExplicitCast(ve, primInt(), primString(), castString<Int>);
+ addExplicitCast(ve, primReal(), primString(), castString<double>);
+ addExplicitCast(ve, primPair(), primString(), castString<pair>);
+ addExplicitCast(ve, primTriple(), primString(), castString<triple>);
+
+ addExplicitCast(ve, primInt(), primReal(), castDoubleInt);
+
+ addCast(ve, primReal(), primInt(), cast<Int,double>);
+ addCast(ve, primPair(), primInt(), cast<Int,pair>);
+ addCast(ve, primPair(), primReal(), cast<double,pair>);
+
+ addCast(ve, primPath(), primPair(), cast<pair,path>);
+ 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<double,Int>);
+
+ addCast(ve, realArray(), IntArray(), arrayToArray<Int,double>);
+ addCast(ve, pairArray(), IntArray(), arrayToArray<Int,pair>);
+ addCast(ve, pairArray(), realArray(), arrayToArray<double,pair>);
+
+ addCast(ve, realArray2(), IntArray2(), array2ToArray2<Int,double>);
+ addCast(ve, pairArray2(), IntArray2(), array2ToArray2<Int,pair>);
+ addCast(ve, pairArray2(), realArray2(), array2ToArray2<double,pair>);
+}
+
+void addTupleOperators(venv &ve)
+{
+ addFunc(ve, realRealToPair, primPair(), SYM_TUPLE,
+ formal(primReal(), SYM(x)),
+ formal(primReal(), SYM(y)));
+ addFunc(ve, realRealRealToTriple, primTriple(), SYM_TUPLE,
+ formal(primReal(), SYM(x)),
+ formal(primReal(), SYM(y)),
+ formal(primReal(), SYM(z)));
+ addFunc(ve, real6ToTransform, primTransform(), SYM_TUPLE,
+ formal(primReal(), SYM(x)),
+ formal(primReal(), SYM(y)),
+ formal(primReal(), SYM(xx)),
+ formal(primReal(), SYM(xy)),
+ formal(primReal(), SYM(yx)),
+ formal(primReal(), SYM(yy)));
+}
+
+void addGuideOperators(venv &ve)
+{
+ // The guide operators .. and -- take an array of guides, and turn them
+ // into a single guide.
+ addRestFunc(ve, dotsGuide, primGuide(), SYM_DOTS, guideArray());
+ addRestFunc(ve, dashesGuide, primGuide(), SYM_DASHES, guideArray());
+}
+
+/* Avoid typing the same type three times. */
+void addSimpleOperator(venv &ve, bltin f, ty *t, symbol name)
+{
+ addFunc(ve,f,t,name,formal(t,SYM(a)),formal(t,SYM(b)));
+}
+void addBooleanOperator(venv &ve, bltin f, ty *t, symbol name)
+{
+ addFunc(ve,f,primBoolean(),name,formal(t,SYM(a)),formal(t,SYM(b)));
+}
+
+template<class T, template <class S> class op>
+void addArray2Array2Op(venv &ve, ty *t3, symbol name)
+{
+ addFunc(ve,array2Array2Op<T,op>,t3,name,formal(t3,SYM(a)),formal(t3,SYM(b)));
+}
+
+template<class T, template <class S> class op>
+void addOpArray2(venv &ve, ty *t1, symbol name, ty *t3)
+{
+ addFunc(ve,opArray2<T,T,op>,t3,name,formal(t1,SYM(a)),formal(t3,SYM(b)));
+}
+
+template<class T, template <class S> class op>
+void addArray2Op(venv &ve, ty *t1, symbol name, ty *t3)
+{
+ addFunc(ve,array2Op<T,T,op>,t3,name,formal(t3,SYM(a)),formal(t1,SYM(b)));
+}
+
+template<class T, template <class S> class op>
+void addOps(venv &ve, ty *t1, symbol name, ty *t2)
+{
+ addSimpleOperator(ve,binaryOp<T,op>,t1,name);
+ addFunc(ve,opArray<T,T,op>,t2,name,formal(t1,SYM(a)),formal(t2,SYM(b)));
+ addFunc(ve,arrayOp<T,T,op>,t2,name,formal(t2,SYM(a)),formal(t1,SYM(b)));
+ addSimpleOperator(ve,arrayArrayOp<T,op>,t2,name);
+}
+
+template<class T, template <class S> class op>
+void addBooleanOps(venv &ve, ty *t1, symbol name, ty *t2)
+{
+ addBooleanOperator(ve,binaryOp<T,op>,t1,name);
+ addFunc(ve,opArray<T,T,op>,
+ booleanArray(),name,formal(t1,SYM(a)),formal(t2,SYM(b)));
+ addFunc(ve,arrayOp<T,T,op>,
+ booleanArray(),name,formal(t2,SYM(a)),formal(t1,SYM(b)));
+ addFunc(ve,arrayArrayOp<T,op>,booleanArray(),name,formal(t2,SYM(a)),
+ formal(t2,SYM(b)));
+}
+
+void addWrite(venv &ve, bltin f, ty *t1, ty *t2)
+{
+ addRestFunc(ve,f,primVoid(),SYM(write),t2,
+ formal(primFile(),SYM(file),true),
+ formal(primString(),SYM(s),true),
+ formal(t1,SYM(x)),formal(voidFileFunction(),SYM(suffix),true));
+}
+
+template<class T>
+void addUnorderedOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4)
+{
+ addBooleanOps<T,equals>(ve,t1,SYM_EQ,t2);
+ addBooleanOps<T,notequals>(ve,t1,SYM_NEQ,t2);
+
+ addFunc(ve, run::array2Equals<T>, primBoolean(), SYM_EQ, formal(t3, SYM(a)),
+ formal(t3, SYM(b)));
+ addFunc(ve, run::array2NotEquals<T>, primBoolean(),
+ SYM_NEQ, formal(t3, SYM(a)),
+ formal(t3, SYM(b)));
+
+ addCast(ve,t1,primFile(),read<T>);
+ addCast(ve,t2,primFile(),readArray1<T>);
+ addCast(ve,t3,primFile(),readArray2<T>);
+ addCast(ve,t4,primFile(),readArray3<T>);
+
+ addWrite(ve,write<T>,t1,t2);
+ addRestFunc(ve,writeArray<T>,primVoid(),SYM(write),t3,
+ formal(primFile(),SYM(file),true),
+ formal(primString(),SYM(s),true),
+ formal(t2,SYM(a),false,true));
+ addFunc(ve,writeArray2<T>,primVoid(),SYM(write),
+ formal(primFile(),SYM(file),true),t3);
+ addFunc(ve,writeArray3<T>,primVoid(),SYM(write),
+ formal(primFile(),SYM(file),true),t4);
+}
+
+inline double abs(pair z) {
+ return z.length();
+}
+
+inline double abs(triple v) {
+ return v.length();
+}
+
+inline pair conjugate(pair z) {
+ return conj(z);
+}
+
+template<class T>
+inline T negate(T x) {
+ return -x;
+}
+
+template<class T, template <class S> class op>
+void addBinOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4, symbol name)
+{
+ addFunc(ve,binopArray<T,op>,t1,name,formal(t2,SYM(a)));
+ addFunc(ve,binopArray2<T,op>,t1,name,formal(t3,SYM(a)));
+ addFunc(ve,binopArray3<T,op>,t1,name,formal(t4,SYM(a)));
+}
+
+template<class T>
+void addOrderedOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4)
+{
+ addBooleanOps<T,less>(ve,t1,SYM_LT,t2);
+ addBooleanOps<T,lessequals>(ve,t1,SYM_LE,t2);
+ addBooleanOps<T,greaterequals>(ve,t1,SYM_GE,t2);
+ addBooleanOps<T,greater>(ve,t1,SYM_GT,t2);
+
+ addOps<T,run::min>(ve,t1,SYM(min),t2);
+ addOps<T,run::max>(ve,t1,SYM(max),t2);
+ addBinOps<T,run::min>(ve,t1,t2,t3,t4,SYM(min));
+ addBinOps<T,run::max>(ve,t1,t2,t3,t4,SYM(max));
+
+ addFunc(ve,sortArray<T>,t2,SYM(sort),formal(t2,SYM(a)));
+ addFunc(ve,sortArray2<T>,t3,SYM(sort),formal(t3,SYM(a)));
+
+ addFunc(ve,searchArray<T>,primInt(),SYM(search),formal(t2,SYM(a)),
+ formal(t1,SYM(key)));
+}
+
+template<class T>
+void addBasicOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4, bool integer=false,
+ bool Explicit=false)
+{
+ addOps<T,plus>(ve,t1,SYM_PLUS,t2);
+ addOps<T,minus>(ve,t1,SYM_MINUS,t2);
+ addFunc(ve,initialized,primBoolean(),SYM(initialized),formal(t1,SYM(a)));
+
+ addArray2Array2Op<T,plus>(ve,t3,SYM_PLUS);
+ addArray2Array2Op<T,minus>(ve,t3,SYM_MINUS);
+
+ addFunc(ve,&id,t1,SYM_PLUS,formal(t1,SYM(a)));
+ addFunc(ve,&id,t2,SYM_PLUS,formal(t2,SYM(a)));
+ addFunc(ve,Negate<T>,t1,SYM_MINUS,formal(t1,SYM(a)));
+ addFunc(ve,arrayFunc<T,T,negate>,t2,SYM_MINUS,formal(t2,SYM(a)));
+ addFunc(ve,arrayFunc2<T,T,negate>,t3,SYM_MINUS,formal(t3,SYM(a)));
+ if(!integer) addFunc(ve,interp<T>,t1,SYM(interp),
+ formal(t1,SYM(a),false,Explicit),
+ formal(t1,SYM(b),false,Explicit),
+ formal(primReal(),SYM(t)));
+
+ addFunc(ve,sumArray<T>,t1,SYM(sum),formal(t2,SYM(a)));
+ addUnorderedOps<T>(ve,t1,t2,t3,t4);
+}
+
+template<class T>
+void addOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4, bool integer=false,
+ bool Explicit=false)
+{
+ addBasicOps<T>(ve,t1,t2,t3,t4,integer,Explicit);
+
+ addOps<T,times>(ve,t1,SYM_TIMES,t2);
+ addOpArray2<T,times>(ve,t1,SYM_TIMES,t3);
+ addArray2Op<T,times>(ve,t1,SYM_TIMES,t3);
+
+ if(!integer) {
+ addOps<T,run::divide>(ve,t1,SYM_DIVIDE,t2);
+ addArray2Op<T,run::divide>(ve,t1,SYM_DIVIDE,t3);
+ }
+
+ addOps<T,power>(ve,t1,SYM_CARET,t2);
+}
+
+
+// Adds standard functions for a newly added array type.
+void addArrayOps(venv &ve, types::array *t)
+{
+ ty *ct = t->celltype;
+
+ // Check for the alias function to see if these operation have already been
+ // added, if they have, don't add them again.
+ static types::function aliasType(primBoolean(), primVoid(), primVoid());
+ aliasType.sig.formals[0].t = t;
+ aliasType.sig.formals[1].t = t;
+
+ if (ve.lookByType(SYM(alias), &aliasType))
+ return;
+
+ addFunc(ve, run::arrayAlias,
+ primBoolean(), SYM(alias), formal(t, SYM(a)), formal(t, SYM(b)));
+
+ size_t depth=(size_t) t->depth();
+
+ // Define an array constructor. This needs to know the depth of the array,
+ // which may not be known at runtime. Therefore, the depth, which is known
+ // here at compile-time, is pushed on the stack beforehand by use of a
+ // thunk.
+ callable *copyValueFunc = new thunk(new vm::bfunc(run::copyArrayValue),(Int) depth-1);
+ addFunc(ve, new callableAccess(copyValueFunc),
+ t, SYM(array), formal(primInt(), SYM(n)),
+ formal(ct, SYM(value)),
+ formal(primInt(), SYM(depth), true));
+
+ callable *copyFunc = new thunk(new vm::bfunc(run::copyArray),(Int) depth);
+ addFunc(ve, new callableAccess(copyFunc),
+ t, SYM(copy), formal(t, SYM(a)), formal(primInt(), SYM(depth), true));
+
+ addFunc(ve, run::arrayFunction,
+ t, SYM(map), formal(new function(ct, ct), SYM(f)), formal(t, SYM(a)));
+
+ addFunc(ve, run::arraySequence,
+ t, SYM(sequence), formal(new function(ct, primInt()), SYM(f)),
+ formal(primInt(), SYM(n)));
+
+ addFunc(ve, run::arraySort,
+ t, SYM(sort), formal(t, SYM(a)),
+ formal(new function(primBoolean(), ct, ct), SYM(less)),
+ formal(primBoolean(), SYM(stable), true));
+
+ switch (depth) {
+ case 1:
+ addRestFunc(ve, run::arrayConcat, t, SYM(concat), new types::array(t));
+ addFunc(ve, run::arraySearch,
+ primInt(), SYM(search), formal(t, SYM(a)), formal(ct, SYM(key)),
+ formal(new function(primBoolean(), ct, ct), SYM(less)));
+ break;
+ case 2:
+ addFunc(ve, run::array2Transpose, t, SYM(transpose), formal(t, SYM(a)));
+ break;
+ case 3:
+ addFunc(ve, run::array3Transpose, t, SYM(transpose), formal(t, SYM(a)),
+ formal(IntArray(),SYM(perm)));
+ break;
+ default:
+ break;
+ }
+}
+
+void addRecordOps(venv &ve, record *r)
+{
+ addFunc(ve, run::boolMemEq, primBoolean(), SYM(alias), formal(r, SYM(a)),
+ formal(r, SYM(b)));
+ addFunc(ve, run::boolMemEq, primBoolean(), SYM_EQ, formal(r, SYM(a)),
+ formal(r, SYM(b)));
+ addFunc(ve, run::boolMemNeq, primBoolean(), SYM_NEQ, formal(r, SYM(a)),
+ formal(r, SYM(b)));
+}
+
+void addFunctionOps(venv &ve, function *f)
+{
+ // No function ops.
+}
+
+
+void addOperators(venv &ve)
+{
+ addSimpleOperator(ve,binaryOp<string,plus>,primString(),SYM_PLUS);
+
+ addBooleanOps<bool,And>(ve,primBoolean(),SYM_AMPERSAND,booleanArray());
+ addBooleanOps<bool,Or>(ve,primBoolean(),SYM_BAR,booleanArray());
+ addBooleanOps<bool,Xor>(ve,primBoolean(),SYM_CARET,booleanArray());
+
+ addUnorderedOps<bool>(ve,primBoolean(),booleanArray(),booleanArray2(),
+ booleanArray3());
+ addOps<Int>(ve,primInt(),IntArray(),IntArray2(),IntArray3(),true);
+ addOps<double>(ve,primReal(),realArray(),realArray2(),realArray3());
+ addOps<pair>(ve,primPair(),pairArray(),pairArray2(),pairArray3(),false,true);
+ addBasicOps<triple>(ve,primTriple(),tripleArray(),tripleArray2(),
+ tripleArray3());
+ addFunc(ve,opArray<double,triple,times>,tripleArray(),SYM_TIMES,
+ formal(primReal(),SYM(a)),formal(tripleArray(),SYM(b)));
+ addFunc(ve,opArray2<double,triple,timesR>,tripleArray2(),SYM_TIMES,
+ formal(primReal(),SYM(a)),formal(tripleArray2(),SYM(b)));
+ addFunc(ve,arrayOp<triple,double,timesR>,tripleArray(),SYM_TIMES,
+ formal(tripleArray(),SYM(a)),formal(primReal(),SYM(b)));
+ addFunc(ve,array2Op<triple,double,timesR>,tripleArray2(),SYM_TIMES,
+ formal(tripleArray2(),SYM(a)),formal(primReal(),SYM(b)));
+ addFunc(ve,arrayOp<triple,double,divide>,tripleArray(),SYM_DIVIDE,
+ formal(tripleArray(),SYM(a)),formal(primReal(),SYM(b)));
+
+ addUnorderedOps<string>(ve,primString(),stringArray(),stringArray2(),
+ stringArray3());
+
+ addSimpleOperator(ve,binaryOp<pair,minbound>,primPair(),SYM(minbound));
+ addSimpleOperator(ve,binaryOp<pair,maxbound>,primPair(),SYM(maxbound));
+ addSimpleOperator(ve,binaryOp<triple,minbound>,primTriple(),SYM(minbound));
+ addSimpleOperator(ve,binaryOp<triple,maxbound>,primTriple(),SYM(maxbound));
+ addBinOps<pair,minbound>(ve,primPair(),pairArray(),pairArray2(),pairArray3(),
+ SYM(minbound));
+ addBinOps<pair,maxbound>(ve,primPair(),pairArray(),pairArray2(),pairArray3(),
+ SYM(maxbound));
+ addBinOps<triple,minbound>(ve,primTriple(),tripleArray(),tripleArray2(),
+ tripleArray3(),SYM(minbound));
+ addBinOps<triple,maxbound>(ve,primTriple(),tripleArray(),tripleArray2(),
+ tripleArray3(),SYM(maxbound));
+
+ addFunc(ve,arrayFunc<double,pair,abs>,realArray(),SYM(abs),
+ formal(pairArray(),SYM(a)));
+ addFunc(ve,arrayFunc<double,triple,abs>,realArray(),SYM(abs),
+ formal(tripleArray(),SYM(a)));
+
+ addFunc(ve,arrayFunc<pair,pair,conjugate>,pairArray(),SYM(conj),
+ formal(pairArray(),SYM(a)));
+ addFunc(ve,arrayFunc2<pair,pair,conjugate>,pairArray2(),SYM(conj),
+ formal(pairArray2(),SYM(a)));
+
+ addFunc(ve,binaryOp<Int,divide>,primReal(),SYM_DIVIDE,
+ formal(primInt(),SYM(a)),formal(primInt(),SYM(b)));
+ addFunc(ve,arrayOp<Int,Int,divide>,realArray(),SYM_DIVIDE,
+ formal(IntArray(),SYM(a)),formal(primInt(),SYM(b)));
+ addFunc(ve,opArray<Int,Int,divide>,realArray(),SYM_DIVIDE,
+ formal(primInt(),SYM(a)),formal(IntArray(),SYM(b)));
+ addFunc(ve,arrayArrayOp<Int,divide>,realArray(),SYM_DIVIDE,
+ formal(IntArray(),SYM(a)),formal(IntArray(),SYM(b)));
+
+ addOrderedOps<Int>(ve,primInt(),IntArray(),IntArray2(),IntArray3());
+ addOrderedOps<double>(ve,primReal(),realArray(),realArray2(),realArray3());
+ addOrderedOps<string>(ve,primString(),stringArray(),stringArray2(),
+ stringArray3());
+
+ addOps<Int,mod>(ve,primInt(),SYM_MOD,IntArray());
+ addOps<Int,quotient>(ve,primInt(),SYM_QUOTIENT,IntArray());
+ addOps<double,mod>(ve,primReal(),SYM_MOD,realArray());
+
+ addRestFunc(ve,diagonal<Int>,IntArray2(),SYM(diagonal),IntArray());
+ addRestFunc(ve,diagonal<double>,realArray2(),SYM(diagonal),realArray());
+ addRestFunc(ve,diagonal<pair>,pairArray2(),SYM(diagonal),pairArray());
+}
+
+dummyRecord *createDummyRecord(venv &ve, symbol name)
+{
+ dummyRecord *r=new dummyRecord(name);
+ vm::frame *f = make_dummyframe(name);
+ 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<vm::array *>(Stack);
+ size_t numArgs=checkArray(a);
+ for (size_t k=0; k<numArgs; ++k)
+ cout << k << ": " << (*a)[k];
+
+ Stack->push<Int>((Int)numArgs);
+}
+#endif
+
+// A function accessible in asy code print the bytecode of a function.
+void printBytecode(stack *Stack)
+{
+ // As arbitrary addresses can be sent to printBytecode, it should not be run
+ // in safe mode.
+ if (settings::safe) {
+ cerr << "use -nosafe flag to enable printBytecode" << endl;
+ return;
+ }
+
+ vm::array *a=vm::pop<vm::array *>(Stack);
+ size_t numArgs=checkArray(a);
+ if (numArgs != 1)
+ cerr << "printBytecode takes one argument" << endl;
+
+ // TODO: Add a reliable test for the object being a func.
+ callable *c = a->read<callable *>(0);
+ if (func *f = dynamic_cast<func *>(c))
+ print(cout, f->body->code);
+ else
+ cout << "callable is not a standard function";
+}
+
+
+
+
+// NOTE: We should move all of these into a "builtin" module.
+void base_venv(venv &ve)
+{
+ // Register the name of arrayDeleteHelper for debugging in "asy -s" mode.
+ // This is done automatically for other function, but because
+ // arrayDeleteHelper is not defined in the usual way, it must be done
+ // explicitly, and here is as good a place as any.
+ REGISTER_BLTIN(arrayDeleteHelper, "arrayDeleteHelper");
+
+ addInitializers(ve);
+ addCasts(ve);
+ addOperators(ve);
+ addTupleOperators(ve);
+ addGuideOperators(ve);
+
+ addRealFunc(sin,SYM(sin));
+ addRealFunc(cos,SYM(cos));
+ addRealFunc(tan,SYM(tan));
+ addRealFunc(asin,SYM(asin));
+ addRealFunc(acos,SYM(acos));
+ addRealFunc(atan,SYM(atan));
+ addRealFunc(exp,SYM(exp));
+ addRealFunc(log,SYM(log));
+ addRealFunc(log10,SYM(log10));
+ addRealFunc(sinh,SYM(sinh));
+ addRealFunc(cosh,SYM(cosh));
+ addRealFunc(tanh,SYM(tanh));
+ addRealFunc(asinh,SYM(asinh));
+ addRealFunc(acosh,SYM(acosh));
+ addRealFunc(atanh,SYM(atanh));
+ addRealFunc(sqrt,SYM(sqrt));
+ addRealFunc(cbrt,SYM(cbrt));
+ addRealFunc(fabs,SYM(fabs));
+ addRealFunc<fabs>(ve,SYM(abs));
+ addRealFunc(expm1,SYM(expm1));
+ addRealFunc(log1p,SYM(log1p));
+ addRealIntFunc<ldexp>(ve, SYM(ldexp), SYM(x), SYM(e));
+
+ addRealFunc(pow10,SYM(pow10));
+ addRealFunc(identity,SYM(identity));
+
+#ifdef STRUCTEXAMPLE
+ dummyRecord *fun=createDummyRecord(ve, SYM(test));
+ addFunc(fun->e.ve,realReal<sin>,primReal(),SYM(f),formal(primReal(),SYM(x)));
+ addVariable<Int>(fun->e.ve,1,primInt(),SYM(x));
+#endif
+
+ addFunc(ve,writestring,primVoid(),SYM(write),
+ formal(primFile(),SYM(file),true),
+ formal(primString(),SYM(s)),
+ formal(voidFileFunction(),SYM(suffix),true));
+
+ addWrite(ve,write<transform>,primTransform(),transformArray());
+ addWrite(ve,write<guide *>,primGuide(),guideArray());
+ addWrite(ve,write<pen>,primPen(),penArray());
+ addFunc(ve,arrayArrayOp<pen,equals>,booleanArray(),SYM_EQ,
+ formal(penArray(),SYM(a)),formal(penArray(),SYM(b)));
+ addFunc(ve,arrayArrayOp<pen,notequals>,booleanArray(),SYM_NEQ,
+ formal(penArray(),SYM(a)),formal(penArray(),SYM(b)));
+
+ addFunc(ve,arrayFunction,realArray(),SYM(map),
+ formal(realPairFunction(),SYM(f)),
+ formal(pairArray(),SYM(a)));
+ addFunc(ve,arrayFunction,IntArray(),SYM(map),
+ formal(IntRealFunction(),SYM(f)),
+ formal(realArray(),SYM(a)));
+
+ addConstant<Int>(ve, Int_MAX, primInt(), SYM(intMax));
+ addConstant<Int>(ve, Int_MIN, primInt(), SYM(intMin));
+ addConstant<double>(ve, HUGE_VAL, primReal(), SYM(inf));
+ addConstant<double>(ve, run::infinity, primReal(), SYM(infinity));
+ addConstant<double>(ve, nan(""), primReal(), SYM(nan));
+ addConstant<double>(ve, DBL_MAX, primReal(), SYM(realMax));
+ addConstant<double>(ve, DBL_MIN, primReal(), SYM(realMin));
+ addConstant<double>(ve, DBL_EPSILON, primReal(), SYM(realEpsilon));
+ addConstant<Int>(ve, DBL_DIG, primInt(), SYM(realDigits));
+ addConstant<Int>(ve, RANDOM_MAX, primInt(), SYM(randMax));
+ addConstant<double>(ve, PI, primReal(), SYM(pi));
+ addConstant<string>(ve, string(REVISION),primString(),SYM(VERSION));
+
+ addVariable<pen>(ve, &processData().currentpen, primPen(), SYM(currentpen));
+
+#ifdef OPENFUNCEXAMPLE
+ addOpenFunc(ve, openFunc, primInt(), SYM(openFunc));
+#endif
+
+ addOpenFunc(ve, printBytecode, primVoid(), SYM(printBytecode));
+
+ 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);
+
+#ifdef HAVE_LIBGSL
+ gen_rungsl_venv(ve);
+#endif
+}
+
+} //namespace trans
+
+namespace run {
+
+double infinity=cbrt(DBL_MAX); // Reduced for tension atleast infinity
+
+void arrayDeleteHelper(stack *Stack)
+{
+ array *a=pop<array *>(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<Int>(itj);
+ } else {
+ i=get<Int>(iti);
+ j=jdefault ? i : get<Int>(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);
+}
+
+// Used by coder to optimize conditional jumps.
+const bltin intLess = binaryOp<Int,less>;
+const bltin intGreater = binaryOp<Int,greater>;
+
+}