1 /*****
2  * builtin.cc
3  * Tom Prince 2004/08/25
4  *
5  * Initialize builtins.
6  *****/
7 
8 #include <cmath>
9 
10 #include "builtin.h"
11 #include "entry.h"
12 
13 #include "runtime.h"
14 #include "runpicture.h"
15 #include "runlabel.h"
16 #include "runhistory.h"
17 #include "runarray.h"
18 #include "runfile.h"
19 #include "runsystem.h"
20 #include "runstring.h"
21 #include "runpair.h"
22 #include "runtriple.h"
23 #include "runpath.h"
24 #include "runpath3d.h"
25 #include "runmath.h"
26 
27 #include "types.h"
28 
29 #include "castop.h"
30 #include "mathop.h"
31 #include "arrayop.h"
32 #include "vm.h"
33 
34 #include "coder.h"
35 #include "exp.h"
36 #include "refaccess.h"
37 #include "settings.h"
38 
39 #include "opsymbols.h"
40 
41 #ifndef NOSYM
42 #include "builtin.symbols.h"
43 #endif
44 
45 namespace vm {
46   // Defined in stack.cc
47   extern vm::frame *make_dummyframe(string name);
48 }
49 
50 using namespace types;
51 using namespace camp;
52 using namespace vm;
53 
54 namespace trans {
55 using camp::transform;
56 using camp::pair;
57 using vm::bltin;
58 using run::divide;
59 using run::less;
60 using run::greater;
61 using run::plus;
62 using run::minus;
63 
64 using namespace run;
65 
66 void gen_runtime_venv(venv &ve);
67 void gen_runbacktrace_venv(venv &ve);
68 void gen_runpicture_venv(venv &ve);
69 void gen_runlabel_venv(venv &ve);
70 void gen_runhistory_venv(venv &ve);
71 void gen_runarray_venv(venv &ve);
72 void gen_runfile_venv(venv &ve);
73 void gen_runsystem_venv(venv &ve);
74 void gen_runstring_venv(venv &ve);
75 void gen_runpair_venv(venv &ve);
76 void gen_runtriple_venv(venv &ve);
77 void gen_runpath_venv(venv &ve);
78 void gen_runpath3d_venv(venv &ve);
79 void gen_runmath_venv(venv &ve);
80 void gen_rungsl_venv(venv &ve);
81 
addType(tenv & te,symbol name,ty * t)82 void addType(tenv &te, symbol name, ty *t)
83 {
84   te.enter(name, new tyEntry(t,0,0,position()));
85 }
86 
87 // The base environments for built-in types and functions
base_tenv(tenv & te)88 void base_tenv(tenv &te)
89 {
90 #define PRIMITIVE(name,Name,asyName) \
91         addType(te, symbol::trans(#asyName), prim##Name());
92 #include "primitives.h"
93 #undef PRIMITIVE
94 }
95 
96 const formal noformal(0);
97 
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)98 function *functionFromFormals(ty *result,
99              formal f1=noformal, formal f2=noformal, formal f3=noformal,
100              formal f4=noformal, formal f5=noformal, formal f6=noformal,
101              formal f7=noformal, formal f8=noformal, formal f9=noformal,
102              formal fA=noformal, formal fB=noformal, formal fC=noformal,
103              formal fD=noformal, formal fE=noformal, formal fF=noformal,
104              formal fG=noformal, formal fH=noformal, formal fI=noformal)
105 {
106   function *fun = new function(result);
107 
108   if (f1.t) fun->add(f1);
109   if (f2.t) fun->add(f2);
110   if (f3.t) fun->add(f3);
111   if (f4.t) fun->add(f4);
112   if (f5.t) fun->add(f5);
113   if (f6.t) fun->add(f6);
114   if (f7.t) fun->add(f7);
115   if (f8.t) fun->add(f8);
116   if (f9.t) fun->add(f9);
117   if (fA.t) fun->add(fA);
118   if (fB.t) fun->add(fB);
119   if (fC.t) fun->add(fC);
120   if (fD.t) fun->add(fD);
121   if (fE.t) fun->add(fE);
122   if (fF.t) fun->add(fF);
123   if (fG.t) fun->add(fG);
124   if (fH.t) fun->add(fH);
125   if (fI.t) fun->add(fI);
126 
127   return fun;
128 }
129 
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)130 void addFunc(venv &ve, access *a, ty *result, symbol id,
131              formal f1=noformal, formal f2=noformal, formal f3=noformal,
132              formal f4=noformal, formal f5=noformal, formal f6=noformal,
133              formal f7=noformal, formal f8=noformal, formal f9=noformal,
134              formal fA=noformal, formal fB=noformal, formal fC=noformal,
135              formal fD=noformal, formal fE=noformal, formal fF=noformal,
136              formal fG=noformal, formal fH=noformal, formal fI=noformal)
137 {
138   function *fun = functionFromFormals(result,f1,f2,f3,f4,f5,f6,f7,f8,f9,
139       fA,fB,fC,fD,fE,fF,fG,fH,fI);
140 
141   // NOTE: If the function is a field, we should encode the defining record in
142   // the entry
143   varEntry *ent = new varEntry(fun, a, 0, position());
144 
145   ve.enter(id, ent);
146 }
147 
148 // Add a function with one or more default arguments.
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)149 void addFunc(venv &ve, bltin f, ty *result, symbol name,
150              formal f1, formal f2, formal f3, formal f4, formal f5, formal f6,
151              formal f7, formal f8, formal f9, formal fA, formal fB, formal fC,
152              formal fD, formal fE, formal fF, formal fG, formal fH, formal fI)
153 {
154 #ifdef DEBUG_BLTIN
155   // If the function is an operator, print out the whole signature with the
156   // types, as operators are heavily overloaded.  min and max are also heavily
157   // overloaded, so we check for them too.  Many builtin functions have so
158   // many arguments that it is noise to print out their full signatures.
159   string s = name;
160   if (s.find("operator ", 0) == 0 || s == "min" || s == "max")
161   {
162     function *fun = functionFromFormals(result,f1,f2,f3,f4,f5,f6,f7,f8,f9,
163         fA,fB,fC,fD,fE,fF,fG,fH,fI);
164     ostringstream out;
165     fun->printVar(out, name);
166     REGISTER_BLTIN(f, out.str());
167   }
168   else {
169     REGISTER_BLTIN(f, name);
170   }
171 #endif
172 
173   access *a = new bltinAccess(f);
174   addFunc(ve,a,result,name,f1,f2,f3,f4,f5,f6,f7,f8,f9,
175       fA,fB,fC,fD,fE,fF,fG,fH,fI);
176 }
177 
addOpenFunc(venv & ve,bltin f,ty * result,symbol name)178 void addOpenFunc(venv &ve, bltin f, ty *result, symbol name)
179 {
180   function *fun = new function(result, signature::OPEN);
181 
182   REGISTER_BLTIN(f, name);
183   access *a= new bltinAccess(f);
184 
185   varEntry *ent = new varEntry(fun, a, 0, position());
186 
187   ve.enter(name, ent);
188 }
189 
190 
191 // Add a rest function with zero or more default/explicit arguments.
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)192 void addRestFunc(venv &ve, bltin f, ty *result, symbol name, formal frest,
193                  formal f1=noformal, formal f2=noformal, formal f3=noformal,
194                  formal f4=noformal, formal f5=noformal, formal f6=noformal,
195                  formal f7=noformal, formal f8=noformal, formal f9=noformal)
196 {
197   REGISTER_BLTIN(f, name);
198   access *a = new bltinAccess(f);
199   function *fun = new function(result);
200 
201   if (f1.t) fun->add(f1);
202   if (f2.t) fun->add(f2);
203   if (f3.t) fun->add(f3);
204   if (f4.t) fun->add(f4);
205   if (f5.t) fun->add(f5);
206   if (f6.t) fun->add(f6);
207   if (f7.t) fun->add(f7);
208   if (f8.t) fun->add(f8);
209   if (f9.t) fun->add(f9);
210 
211   if (frest.t) fun->addRest(frest);
212 
213   varEntry *ent = new varEntry(fun, a, 0, position());
214 
215   ve.enter(name, ent);
216 }
217 
addRealFunc0(venv & ve,bltin fcn,symbol name)218 void addRealFunc0(venv &ve, bltin fcn, symbol name)
219 {
220   addFunc(ve, fcn, primReal(), name);
221 }
222 
223 template<double (*fcn)(double)>
addRealFunc(venv & ve,symbol name)224 void addRealFunc(venv &ve, symbol name)
225 {
226   addFunc(ve, realReal<fcn>, primReal(), name, formal(primReal(),SYM(x)));
227   addFunc(ve, arrayFunc<double,double,fcn>, realArray(), name,
228           formal(realArray(),SYM(a)));
229 }
230 
231 #define addRealFunc(fcn, sym) addRealFunc<fcn>(ve, sym);
232 
addRealFunc2(venv & ve,bltin fcn,symbol name)233 void addRealFunc2(venv &ve, bltin fcn, symbol name)
234 {
235   addFunc(ve,fcn,primReal(),name,formal(primReal(),SYM(a)),
236           formal(primReal(),SYM(b)));
237 }
238 
239 template <double (*func)(double, int)>
realRealInt(vm::stack * s)240 void realRealInt(vm::stack *s) {
241   Int n = pop<Int>(s);
242   double x = pop<double>(s);
243   s->push(func(x, intcast(n)));
244 }
245 
246 template<double (*fcn)(double, int)>
addRealIntFunc(venv & ve,symbol name,symbol arg1,symbol arg2)247 void addRealIntFunc(venv& ve, symbol name, symbol arg1,
248                     symbol arg2) {
249   addFunc(ve, realRealInt<fcn>, primReal(), name, formal(primReal(), arg1),
250           formal(primInt(), arg2));
251 }
252 
addInitializer(venv & ve,ty * t,access * a)253 void addInitializer(venv &ve, ty *t, access *a)
254 {
255   addFunc(ve, a, t, symbol::initsym);
256 }
257 
addInitializer(venv & ve,ty * t,bltin f)258 void addInitializer(venv &ve, ty *t, bltin f)
259 {
260 #ifdef DEBUG_BLTIN
261   ostringstream s;
262   s << "initializer for " << *t;
263   REGISTER_BLTIN(f, s.str());
264 #endif
265   access *a = new bltinAccess(f);
266   addInitializer(ve, t, a);
267 }
268 
269 // Specifies that source may be cast to target, but only if an explicit
270 // cast expression is used.
addExplicitCast(venv & ve,ty * target,ty * source,access * a)271 void addExplicitCast(venv &ve, ty *target, ty *source, access *a) {
272   addFunc(ve, a, target, symbol::ecastsym, source);
273 }
274 
275 // Specifies that source may be implicitly cast to target by the
276 // function or instruction stores at a.
addCast(venv & ve,ty * target,ty * source,access * a)277 void addCast(venv &ve, ty *target, ty *source, access *a) {
278   //addExplicitCast(target,source,a);
279   addFunc(ve, a, target, symbol::castsym, source);
280 }
281 
addExplicitCast(venv & ve,ty * target,ty * source,bltin f)282 void addExplicitCast(venv &ve, ty *target, ty *source, bltin f) {
283 #ifdef DEBUG_BLTIN
284   ostringstream s;
285   s << "explicit cast from " << *source << " to " << *target;
286   REGISTER_BLTIN(f, s.str());
287 #endif
288   addExplicitCast(ve, target, source, new bltinAccess(f));
289 }
290 
addCast(venv & ve,ty * target,ty * source,bltin f)291 void addCast(venv &ve, ty *target, ty *source, bltin f) {
292 #ifdef DEBUG_BLTIN
293   ostringstream s;
294   s << "cast from " << *source << " to " << *target;
295   REGISTER_BLTIN(f, s.str());
296 #endif
297   addCast(ve, target, source, new bltinAccess(f));
298 }
299 
300 template<class T>
addVariable(venv & ve,T * ref,ty * t,symbol name,record * module=settings::getSettingsModule ())301 void addVariable(venv &ve, T *ref, ty *t, symbol name,
302                  record *module=settings::getSettingsModule()) {
303   access *a = new refAccess<T>(ref);
304   varEntry *ent = new varEntry(t, a, PUBLIC, module, 0, position());
305   ve.enter(name, ent);
306 }
307 
308 template<class T>
addVariable(venv & ve,T value,ty * t,symbol name,record * module=settings::getSettingsModule (),permission perm=PUBLIC)309 void addVariable(venv &ve, T value, ty *t, symbol name,
310                  record *module=settings::getSettingsModule(),
311                  permission perm=PUBLIC) {
312   item* ref=new item;
313   *ref=value;
314   access *a = new itemRefAccess(ref);
315   varEntry *ent = new varEntry(t, a, perm, module, 0, position());
316   ve.enter(name, ent);
317 }
318 
319 template<class T>
addConstant(venv & ve,T value,ty * t,symbol name,record * module=settings::getSettingsModule ())320 void addConstant(venv &ve, T value, ty *t, symbol name,
321                  record *module=settings::getSettingsModule()) {
322   addVariable(ve,value,t,name,module,RESTRICTED);
323 }
324 
325 // The identity access, i.e. no instructions are encoded for a cast or
326 // operation, and no functions are called.
327 identAccess id;
328 
IntRealFunction()329 function *IntRealFunction()
330 {
331   return new function(primInt(),primReal());
332 }
333 
realPairFunction()334 function *realPairFunction()
335 {
336   return new function(primReal(),primPair());
337 }
338 
voidFileFunction()339 function *voidFileFunction()
340 {
341   return new function(primVoid(),primFile());
342 }
343 
addInitializers(venv & ve)344 void addInitializers(venv &ve)
345 {
346   addInitializer(ve, primBoolean(), boolFalse);
347   addInitializer(ve, primInt(), IntZero);
348   addInitializer(ve, primReal(), realZero);
349 
350   addInitializer(ve, primString(), emptyString);
351   addInitializer(ve, primPair(), pairZero);
352   addInitializer(ve, primTriple(), tripleZero);
353   addInitializer(ve, primTransform(), transformIdentity);
354   addInitializer(ve, primGuide(), nullGuide);
355   addInitializer(ve, primPath(), nullPath);
356   addInitializer(ve, primPath3(), nullPath3);
357   addInitializer(ve, primPen(), newPen);
358   addInitializer(ve, primPicture(), newPicture);
359   addInitializer(ve, primFile(), nullFile);
360 }
361 
addCasts(venv & ve)362 void addCasts(venv &ve)
363 {
364   addExplicitCast(ve, primString(), primInt(), stringCast<Int>);
365   addExplicitCast(ve, primString(), primReal(), stringCast<double>);
366   addExplicitCast(ve, primString(), primPair(), stringCast<pair>);
367   addExplicitCast(ve, primString(), primTriple(), stringCast<triple>);
368   addExplicitCast(ve, primInt(), primString(), castString<Int>);
369   addExplicitCast(ve, primReal(), primString(), castString<double>);
370   addExplicitCast(ve, primPair(), primString(), castString<pair>);
371   addExplicitCast(ve, primTriple(), primString(), castString<triple>);
372 
373   addExplicitCast(ve, primInt(), primReal(), castDoubleInt);
374 
375   addCast(ve, primReal(), primInt(), cast<Int,double>);
376   addCast(ve, primPair(), primInt(), cast<Int,pair>);
377   addCast(ve, primPair(), primReal(), cast<double,pair>);
378 
379   addCast(ve, primPath(), primPair(), cast<pair,path>);
380   addCast(ve, primGuide(), primPair(), pairToGuide);
381   addCast(ve, primGuide(), primPath(), pathToGuide);
382   addCast(ve, primPath(), primGuide(), guideToPath);
383 
384   addCast(ve, primFile(), primNull(), nullFile);
385 
386   // Vectorized casts.
387   addExplicitCast(ve, IntArray(), realArray(), arrayToArray<double,Int>);
388 
389   addCast(ve, realArray(), IntArray(), arrayToArray<Int,double>);
390   addCast(ve, pairArray(), IntArray(), arrayToArray<Int,pair>);
391   addCast(ve, pairArray(), realArray(), arrayToArray<double,pair>);
392 
393   addCast(ve, realArray2(), IntArray2(), array2ToArray2<Int,double>);
394   addCast(ve, pairArray2(), IntArray2(), array2ToArray2<Int,pair>);
395   addCast(ve, pairArray2(), realArray2(), array2ToArray2<double,pair>);
396 }
397 
addTupleOperators(venv & ve)398 void addTupleOperators(venv &ve)
399 {
400   addFunc(ve, realRealToPair, primPair(), SYM_TUPLE,
401           formal(primReal(), SYM(x)),
402           formal(primReal(), SYM(y)));
403   addFunc(ve, realRealRealToTriple, primTriple(), SYM_TUPLE,
404           formal(primReal(), SYM(x)),
405           formal(primReal(), SYM(y)),
406           formal(primReal(), SYM(z)));
407   addFunc(ve, real6ToTransform, primTransform(), SYM_TUPLE,
408           formal(primReal(), SYM(x)),
409           formal(primReal(), SYM(y)),
410           formal(primReal(), SYM(xx)),
411           formal(primReal(), SYM(xy)),
412           formal(primReal(), SYM(yx)),
413           formal(primReal(), SYM(yy)));
414 }
415 
addGuideOperators(venv & ve)416 void addGuideOperators(venv &ve)
417 {
418   // The guide operators .. and -- take an array of guides, and turn them
419   // into a single guide.
420   addRestFunc(ve, dotsGuide, primGuide(), SYM_DOTS, guideArray());
421   addRestFunc(ve, dashesGuide, primGuide(), SYM_DASHES, guideArray());
422 }
423 
424 /* Avoid typing the same type three times. */
addSimpleOperator(venv & ve,bltin f,ty * t,symbol name)425 void addSimpleOperator(venv &ve, bltin f, ty *t, symbol name)
426 {
427   addFunc(ve,f,t,name,formal(t,SYM(a)),formal(t,SYM(b)));
428 }
addBooleanOperator(venv & ve,bltin f,ty * t,symbol name)429 void addBooleanOperator(venv &ve, bltin f, ty *t, symbol name)
430 {
431   addFunc(ve,f,primBoolean(),name,formal(t,SYM(a)),formal(t,SYM(b)));
432 }
433 
434 template<class T, template <class S> class op>
addArray2Array2Op(venv & ve,ty * t3,symbol name)435 void addArray2Array2Op(venv &ve, ty *t3, symbol name)
436 {
437   addFunc(ve,array2Array2Op<T,op>,t3,name,formal(t3,SYM(a)),formal(t3,SYM(b)));
438 }
439 
440 template<class T, template <class S> class op>
addOpArray2(venv & ve,ty * t1,symbol name,ty * t3)441 void addOpArray2(venv &ve, ty *t1, symbol name, ty *t3)
442 {
443   addFunc(ve,opArray2<T,T,op>,t3,name,formal(t1,SYM(a)),formal(t3,SYM(b)));
444 }
445 
446 template<class T, template <class S> class op>
addArray2Op(venv & ve,ty * t1,symbol name,ty * t3)447 void addArray2Op(venv &ve, ty *t1, symbol name, ty *t3)
448 {
449   addFunc(ve,array2Op<T,T,op>,t3,name,formal(t3,SYM(a)),formal(t1,SYM(b)));
450 }
451 
452 template<class T, template <class S> class op>
addOps(venv & ve,ty * t1,symbol name,ty * t2)453 void addOps(venv &ve, ty *t1, symbol name, ty *t2)
454 {
455   addSimpleOperator(ve,binaryOp<T,op>,t1,name);
456   addFunc(ve,opArray<T,T,op>,t2,name,formal(t1,SYM(a)),formal(t2,SYM(b)));
457   addFunc(ve,arrayOp<T,T,op>,t2,name,formal(t2,SYM(a)),formal(t1,SYM(b)));
458   addSimpleOperator(ve,arrayArrayOp<T,op>,t2,name);
459 }
460 
461 template<class T, template <class S> class op>
addBooleanOps(venv & ve,ty * t1,symbol name,ty * t2)462 void addBooleanOps(venv &ve, ty *t1, symbol name, ty *t2)
463 {
464   addBooleanOperator(ve,binaryOp<T,op>,t1,name);
465   addFunc(ve,opArray<T,T,op>,
466       booleanArray(),name,formal(t1,SYM(a)),formal(t2,SYM(b)));
467   addFunc(ve,arrayOp<T,T,op>,
468       booleanArray(),name,formal(t2,SYM(a)),formal(t1,SYM(b)));
469   addFunc(ve,arrayArrayOp<T,op>,booleanArray(),name,formal(t2,SYM(a)),
470           formal(t2,SYM(b)));
471 }
472 
addWrite(venv & ve,bltin f,ty * t1,ty * t2)473 void addWrite(venv &ve, bltin f, ty *t1, ty *t2)
474 {
475   addRestFunc(ve,f,primVoid(),SYM(write),t2,
476               formal(primFile(),SYM(file),true),
477               formal(primString(),SYM(s),true),
478               formal(t1,SYM(x)),formal(voidFileFunction(),SYM(suffix),true));
479 }
480 
481 template<class T>
addUnorderedOps(venv & ve,ty * t1,ty * t2,ty * t3,ty * t4)482 void addUnorderedOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4)
483 {
484   addBooleanOps<T,equals>(ve,t1,SYM_EQ,t2);
485   addBooleanOps<T,notequals>(ve,t1,SYM_NEQ,t2);
486 
487   addFunc(ve, run::array2Equals<T>, primBoolean(), SYM_EQ, formal(t3, SYM(a)),
488           formal(t3, SYM(b)));
489   addFunc(ve, run::array2NotEquals<T>, primBoolean(),
490           SYM_NEQ, formal(t3, SYM(a)),
491           formal(t3, SYM(b)));
492 
493   addCast(ve,t1,primFile(),read<T>);
494   addCast(ve,t2,primFile(),readArray<T>);
495   addCast(ve,t3,primFile(),readArray<T>);
496   addCast(ve,t4,primFile(),readArray<T>);
497 
498   addWrite(ve,write<T>,t1,t2);
499   addRestFunc(ve,writeArray<T>,primVoid(),SYM(write),t3,
500               formal(primFile(),SYM(file),true),
501               formal(primString(),SYM(s),true),
502               formal(t2,SYM(a),false,true));
503   addFunc(ve,writeArray2<T>,primVoid(),SYM(write),
504           formal(primFile(),SYM(file),true),t3);
505   addFunc(ve,writeArray3<T>,primVoid(),SYM(write),
506           formal(primFile(),SYM(file),true),t4);
507 }
508 
abs(pair z)509 inline double abs(pair z) {
510   return z.length();
511 }
512 
abs(triple v)513 inline double abs(triple v) {
514   return v.length();
515 }
516 
conjugate(pair z)517 inline pair conjugate(pair z) {
518   return conj(z);
519 }
520 
521 template<class T>
negate(T x)522 inline T negate(T x) {
523   return -x;
524 }
525 
526 template<class T, template <class S> class op>
addBinOps(venv & ve,ty * t1,ty * t2,ty * t3,ty * t4,symbol name)527 void addBinOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4, symbol name)
528 {
529   addFunc(ve,binopArray<T,op>,t1,name,formal(t2,SYM(a)));
530   addFunc(ve,binopArray2<T,op>,t1,name,formal(t3,SYM(a)));
531   addFunc(ve,binopArray3<T,op>,t1,name,formal(t4,SYM(a)));
532 }
533 
534 template<class T>
addOrderedOps(venv & ve,ty * t1,ty * t2,ty * t3,ty * t4)535 void addOrderedOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4)
536 {
537   addBooleanOps<T,less>(ve,t1,SYM_LT,t2);
538   addBooleanOps<T,lessequals>(ve,t1,SYM_LE,t2);
539   addBooleanOps<T,greaterequals>(ve,t1,SYM_GE,t2);
540   addBooleanOps<T,greater>(ve,t1,SYM_GT,t2);
541 
542   addOps<T,run::min>(ve,t1,SYM(min),t2);
543   addOps<T,run::max>(ve,t1,SYM(max),t2);
544   addBinOps<T,run::min>(ve,t1,t2,t3,t4,SYM(min));
545   addBinOps<T,run::max>(ve,t1,t2,t3,t4,SYM(max));
546 
547   addFunc(ve,sortArray<T>,t2,SYM(sort),formal(t2,SYM(a)));
548   addFunc(ve,sortArray2<T>,t3,SYM(sort),formal(t3,SYM(a)));
549 
550   addFunc(ve,searchArray<T>,primInt(),SYM(search),formal(t2,SYM(a)),
551           formal(t1,SYM(key)));
552 }
553 
554 template<class T>
addBasicOps(venv & ve,ty * t1,ty * t2,ty * t3,ty * t4,bool integer=false,bool Explicit=false)555 void addBasicOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4, bool integer=false,
556                  bool Explicit=false)
557 {
558   addOps<T,plus>(ve,t1,SYM_PLUS,t2);
559   addOps<T,minus>(ve,t1,SYM_MINUS,t2);
560 
561   addArray2Array2Op<T,plus>(ve,t3,SYM_PLUS);
562   addArray2Array2Op<T,minus>(ve,t3,SYM_MINUS);
563 
564   addFunc(ve,&id,t1,SYM_PLUS,formal(t1,SYM(a)));
565   addFunc(ve,&id,t2,SYM_PLUS,formal(t2,SYM(a)));
566   addFunc(ve,Negate<T>,t1,SYM_MINUS,formal(t1,SYM(a)));
567   addFunc(ve,arrayFunc<T,T,negate>,t2,SYM_MINUS,formal(t2,SYM(a)));
568   addFunc(ve,arrayFunc2<T,T,negate>,t3,SYM_MINUS,formal(t3,SYM(a)));
569   if(!integer) addFunc(ve,interp<T>,t1,SYM(interp),
570                        formal(t1,SYM(a),false,Explicit),
571                        formal(t1,SYM(b),false,Explicit),
572                        formal(primReal(),SYM(t)));
573 
574   addFunc(ve,sumArray<T>,t1,SYM(sum),formal(t2,SYM(a)));
575   addUnorderedOps<T>(ve,t1,t2,t3,t4);
576 }
577 
578 template<class T>
addOps(venv & ve,ty * t1,ty * t2,ty * t3,ty * t4,bool integer=false,bool Explicit=false)579 void addOps(venv &ve, ty *t1, ty *t2, ty *t3, ty *t4, bool integer=false,
580             bool Explicit=false)
581 {
582   addBasicOps<T>(ve,t1,t2,t3,t4,integer,Explicit);
583 
584   addOps<T,times>(ve,t1,SYM_TIMES,t2);
585   addOpArray2<T,times>(ve,t1,SYM_TIMES,t3);
586   addArray2Op<T,times>(ve,t1,SYM_TIMES,t3);
587 
588   if(!integer) {
589     addOps<T,run::divide>(ve,t1,SYM_DIVIDE,t2);
590     addArray2Op<T,run::divide>(ve,t1,SYM_DIVIDE,t3);
591   }
592 
593   addOps<T,power>(ve,t1,SYM_CARET,t2);
594 }
595 
596 
597 // Adds standard functions for a newly added array type.
addArrayOps(venv & ve,types::array * t)598 void addArrayOps(venv &ve, types::array *t)
599 {
600   ty *ct = t->celltype;
601 
602   // Check for the alias function to see if these operation have already been
603   // added, if they have, don't add them again.
604   static types::function aliasType(primBoolean(), primVoid(), primVoid());
605   aliasType.sig.formals[0].t = t;
606   aliasType.sig.formals[1].t = t;
607 
608   if (ve.lookByType(SYM(alias), &aliasType))
609     return;
610 
611   addFunc(ve, run::arrayAlias,
612           primBoolean(), SYM(alias), formal(t, SYM(a)), formal(t, SYM(b)));
613 
614   size_t depth=(size_t) t->depth();
615 
616   // Define an array constructor.  This needs to know the depth of the array,
617   // which may not be known at runtime.  Therefore, the depth, which is known
618   // here at compile-time, is pushed on the stack beforehand by use of a
619   // thunk.
620   callable *copyValueFunc = new thunk(new vm::bfunc(run::copyArrayValue),(Int) depth-1);
621   addFunc(ve, new callableAccess(copyValueFunc),
622           t, SYM(array), formal(primInt(), SYM(n)),
623           formal(ct, SYM(value)),
624           formal(primInt(), SYM(depth), true));
625 
626   callable *copyFunc = new thunk(new vm::bfunc(run::copyArray),(Int) depth);
627   addFunc(ve, new callableAccess(copyFunc),
628           t, SYM(copy), formal(t, SYM(a)), formal(primInt(), SYM(depth), true));
629 
630   addFunc(ve, run::arrayFunction,
631           t, SYM(map), formal(new function(ct, ct), SYM(f)), formal(t, SYM(a)));
632 
633   addFunc(ve, run::arraySequence,
634           t, SYM(sequence), formal(new function(ct, primInt()), SYM(f)),
635           formal(primInt(), SYM(n)));
636 
637   addFunc(ve, run::arraySort,
638           t, SYM(sort), formal(t, SYM(a)),
639           formal(new function(primBoolean(), ct, ct), SYM(less)));
640 
641   switch (depth) {
642     case 1:
643       addRestFunc(ve, run::arrayConcat, t, SYM(concat), new types::array(t));
644       addFunc(ve, run::arraySearch,
645               primInt(), SYM(search), formal(t, SYM(a)), formal(ct, SYM(key)),
646               formal(new function(primBoolean(), ct, ct), SYM(less)));
647       break;
648     case 2:
649       addFunc(ve, run::array2Transpose, t, SYM(transpose), formal(t, SYM(a)));
650       break;
651     case 3:
652       addFunc(ve, run::array3Transpose, t, SYM(transpose), formal(t, SYM(a)),
653               formal(IntArray(),SYM(perm)));
654       break;
655     default:
656       break;
657   }
658 }
659 
addRecordOps(venv & ve,record * r)660 void addRecordOps(venv &ve, record *r)
661 {
662   addFunc(ve, run::boolMemEq, primBoolean(), SYM(alias), formal(r, SYM(a)),
663           formal(r, SYM(b)));
664   addFunc(ve, run::boolMemEq, primBoolean(), SYM_EQ, formal(r, SYM(a)),
665           formal(r, SYM(b)));
666   addFunc(ve, run::boolMemNeq, primBoolean(), SYM_NEQ, formal(r, SYM(a)),
667           formal(r, SYM(b)));
668 }
669 
addFunctionOps(venv & ve,function * f)670 void addFunctionOps(venv &ve, function *f)
671 {
672   // No function ops.
673 }
674 
675 
addOperators(venv & ve)676 void addOperators(venv &ve)
677 {
678   addSimpleOperator(ve,binaryOp<string,plus>,primString(),SYM_PLUS);
679 
680   addBooleanOps<bool,And>(ve,primBoolean(),SYM_AMPERSAND,booleanArray());
681   addBooleanOps<bool,Or>(ve,primBoolean(),SYM_BAR,booleanArray());
682   addBooleanOps<bool,Xor>(ve,primBoolean(),SYM_CARET,booleanArray());
683 
684   addUnorderedOps<bool>(ve,primBoolean(),booleanArray(),booleanArray2(),
685                         booleanArray3());
686   addOps<Int>(ve,primInt(),IntArray(),IntArray2(),IntArray3(),true);
687   addOps<double>(ve,primReal(),realArray(),realArray2(),realArray3());
688   addOps<pair>(ve,primPair(),pairArray(),pairArray2(),pairArray3(),false,true);
689   addBasicOps<triple>(ve,primTriple(),tripleArray(),tripleArray2(),
690                       tripleArray3());
691   addFunc(ve,opArray<double,triple,times>,tripleArray(),SYM_TIMES,
692           formal(primReal(),SYM(a)),formal(tripleArray(),SYM(b)));
693   addFunc(ve,opArray2<double,triple,timesR>,tripleArray2(),SYM_TIMES,
694           formal(primReal(),SYM(a)),formal(tripleArray2(),SYM(b)));
695   addFunc(ve,arrayOp<triple,double,timesR>,tripleArray(),SYM_TIMES,
696           formal(tripleArray(),SYM(a)),formal(primReal(),SYM(b)));
697   addFunc(ve,array2Op<triple,double,timesR>,tripleArray2(),SYM_TIMES,
698           formal(tripleArray2(),SYM(a)),formal(primReal(),SYM(b)));
699   addFunc(ve,arrayOp<triple,double,divide>,tripleArray(),SYM_DIVIDE,
700           formal(tripleArray(),SYM(a)),formal(primReal(),SYM(b)));
701 
702   addUnorderedOps<string>(ve,primString(),stringArray(),stringArray2(),
703                           stringArray3());
704 
705   addSimpleOperator(ve,binaryOp<pair,minbound>,primPair(),SYM(minbound));
706   addSimpleOperator(ve,binaryOp<pair,maxbound>,primPair(),SYM(maxbound));
707   addSimpleOperator(ve,binaryOp<triple,minbound>,primTriple(),SYM(minbound));
708   addSimpleOperator(ve,binaryOp<triple,maxbound>,primTriple(),SYM(maxbound));
709   addBinOps<pair,minbound>(ve,primPair(),pairArray(),pairArray2(),pairArray3(),
710                            SYM(minbound));
711   addBinOps<pair,maxbound>(ve,primPair(),pairArray(),pairArray2(),pairArray3(),
712                            SYM(maxbound));
713   addBinOps<triple,minbound>(ve,primTriple(),tripleArray(),tripleArray2(),
714                              tripleArray3(),SYM(minbound));
715   addBinOps<triple,maxbound>(ve,primTriple(),tripleArray(),tripleArray2(),
716                              tripleArray3(),SYM(maxbound));
717 
718   addFunc(ve,arrayFunc<double,pair,abs>,realArray(),SYM(abs),
719           formal(pairArray(),SYM(a)));
720   addFunc(ve,arrayFunc<double,triple,abs>,realArray(),SYM(abs),
721           formal(tripleArray(),SYM(a)));
722 
723   addFunc(ve,arrayFunc<pair,pair,conjugate>,pairArray(),SYM(conj),
724           formal(pairArray(),SYM(a)));
725   addFunc(ve,arrayFunc2<pair,pair,conjugate>,pairArray2(),SYM(conj),
726           formal(pairArray2(),SYM(a)));
727 
728   addFunc(ve,binaryOp<Int,divide>,primReal(),SYM_DIVIDE,
729           formal(primInt(),SYM(a)),formal(primInt(),SYM(b)));
730   addFunc(ve,arrayOp<Int,Int,divide>,realArray(),SYM_DIVIDE,
731           formal(IntArray(),SYM(a)),formal(primInt(),SYM(b)));
732   addFunc(ve,opArray<Int,Int,divide>,realArray(),SYM_DIVIDE,
733           formal(primInt(),SYM(a)),formal(IntArray(),SYM(b)));
734   addFunc(ve,arrayArrayOp<Int,divide>,realArray(),SYM_DIVIDE,
735           formal(IntArray(),SYM(a)),formal(IntArray(),SYM(b)));
736 
737   addOrderedOps<Int>(ve,primInt(),IntArray(),IntArray2(),IntArray3());
738   addOrderedOps<double>(ve,primReal(),realArray(),realArray2(),realArray3());
739   addOrderedOps<string>(ve,primString(),stringArray(),stringArray2(),
740                         stringArray3());
741 
742   addOps<Int,mod>(ve,primInt(),SYM_MOD,IntArray());
743   addOps<double,mod>(ve,primReal(),SYM_MOD,realArray());
744 
745   addRestFunc(ve,diagonal<Int>,IntArray2(),SYM(diagonal),IntArray());
746   addRestFunc(ve,diagonal<double>,realArray2(),SYM(diagonal),realArray());
747   addRestFunc(ve,diagonal<pair>,pairArray2(),SYM(diagonal),pairArray());
748 }
749 
createDummyRecord(venv & ve,symbol name)750 dummyRecord *createDummyRecord(venv &ve, symbol name)
751 {
752   dummyRecord *r=new dummyRecord(name);
753   vm::frame *f = make_dummyframe(name);
754   addConstant(ve, f, r, name);
755   addRecordOps(ve, r);
756   return r;
757 }
758 
identity(double x)759 double identity(double x) {return x;}
pow10(double x)760 double pow10(double x) {return run::pow(10.0,x);}
761 
762 // An example of an open function.
763 #ifdef OPENFUNCEXAMPLE
openFunc(stack * Stack)764 void openFunc(stack *Stack)
765 {
766   vm::array *a=vm::pop<vm::array *>(Stack);
767   size_t numArgs=checkArray(a);
768   for (size_t k=0; k<numArgs; ++k)
769     cout << k << ": " << (*a)[k];
770 
771   Stack->push<Int>((Int)numArgs);
772 }
773 #endif
774 
775 // A function accessible in asy code print the bytecode of a function.
printBytecode(stack * Stack)776 void printBytecode(stack *Stack)
777 {
778   // As arbitrary addresses can be sent to printBytecode, it should not be run
779   // in safe mode.
780   if (settings::safe) {
781     cerr << "use -nosafe flag to enable printBytecode" << endl;
782     return;
783   }
784 
785   vm::array *a=vm::pop<vm::array *>(Stack);
786   size_t numArgs=checkArray(a);
787   if (numArgs != 1)
788     cerr << "printBytecode takes one argument" << endl;
789 
790   // TODO: Add a reliable test for the object being a func.
791   callable *c = a->read<callable *>(0);
792   if (func *f = dynamic_cast<func *>(c))
793     print(cout, f->body->code);
794   else
795     cout << "callable is not a standard function";
796 }
797 
798 
799 
800 
801 // NOTE: We should move all of these into a "builtin" module.
base_venv(venv & ve)802 void base_venv(venv &ve)
803 {
804   // Register the name of arrayDeleteHelper for debugging in "asy -s" mode.
805   // This is done automatically for other function, but because
806   // arrayDeleteHelper is not defined in the usual way, it must be done
807   // explicitly, and here is as good a place as any.
808   REGISTER_BLTIN(arrayDeleteHelper, "arrayDeleteHelper");
809 
810   addInitializers(ve);
811   addCasts(ve);
812   addOperators(ve);
813   addTupleOperators(ve);
814   addGuideOperators(ve);
815 
816   addRealFunc(sin,SYM(sin));
817   addRealFunc(cos,SYM(cos));
818   addRealFunc(tan,SYM(tan));
819   addRealFunc(asin,SYM(asin));
820   addRealFunc(acos,SYM(acos));
821   addRealFunc(atan,SYM(atan));
822   addRealFunc(exp,SYM(exp));
823   addRealFunc(log,SYM(log));
824   addRealFunc(log10,SYM(log10));
825   addRealFunc(sinh,SYM(sinh));
826   addRealFunc(cosh,SYM(cosh));
827   addRealFunc(tanh,SYM(tanh));
828   addRealFunc(asinh,SYM(asinh));
829   addRealFunc(acosh,SYM(acosh));
830   addRealFunc(atanh,SYM(atanh));
831   addRealFunc(sqrt,SYM(sqrt));
832   addRealFunc(cbrt,SYM(cbrt));
833   addRealFunc(fabs,SYM(fabs));
834   addRealFunc<fabs>(ve,SYM(abs));
835   addRealFunc(expm1,SYM(expm1));
836   addRealFunc(log1p,SYM(log1p));
837   addRealIntFunc<ldexp>(ve, SYM(ldexp), SYM(x), SYM(e));
838 
839   addRealFunc(pow10,SYM(pow10));
840   addRealFunc(identity,SYM(identity));
841 
842 #ifdef STRUCTEXAMPLE
843   dummyRecord *fun=createDummyRecord(ve, SYM(test));
844   addFunc(fun->e.ve,realReal<sin>,primReal(),SYM(f),formal(primReal(),SYM(x)));
845   addVariable<Int>(fun->e.ve,1,primInt(),SYM(x));
846 #endif
847 
848   addFunc(ve,writestring,primVoid(),SYM(write),
849           formal(primFile(),SYM(file),true),
850           formal(primString(),SYM(s)),
851           formal(voidFileFunction(),SYM(suffix),true));
852 
853   addWrite(ve,write<transform>,primTransform(),transformArray());
854   addWrite(ve,write<guide *>,primGuide(),guideArray());
855   addWrite(ve,write<pen>,primPen(),penArray());
856   addFunc(ve,arrayArrayOp<pen,equals>,booleanArray(),SYM_EQ,
857           formal(penArray(),SYM(a)),formal(penArray(),SYM(b)));
858   addFunc(ve,arrayArrayOp<pen,notequals>,booleanArray(),SYM_NEQ,
859           formal(penArray(),SYM(a)),formal(penArray(),SYM(b)));
860 
861   addFunc(ve,arrayFunction,realArray(),SYM(map),
862           formal(realPairFunction(),SYM(f)),
863           formal(pairArray(),SYM(a)));
864   addFunc(ve,arrayFunction,IntArray(),SYM(map),
865           formal(IntRealFunction(),SYM(f)),
866           formal(realArray(),SYM(a)));
867 
868   addConstant<Int>(ve, Int_MAX, primInt(), SYM(intMax));
869   addConstant<Int>(ve, Int_MIN, primInt(), SYM(intMin));
870   addConstant<double>(ve, HUGE_VAL, primReal(), SYM(inf));
871   addConstant<double>(ve, run::infinity, primReal(), SYM(infinity));
872   addConstant<double>(ve, DBL_MAX, primReal(), SYM(realMax));
873   addConstant<double>(ve, DBL_MIN, primReal(), SYM(realMin));
874   addConstant<double>(ve, DBL_EPSILON, primReal(), SYM(realEpsilon));
875   addConstant<Int>(ve, DBL_DIG, primInt(), SYM(realDigits));
876   addConstant<Int>(ve, RANDOM_MAX, primInt(), SYM(randMax));
877   addConstant<double>(ve, PI, primReal(), SYM(pi));
878   addConstant<string>(ve, string(settings::VERSION)+string(SVN_REVISION),
879                       primString(),SYM(VERSION));
880 
881   addVariable<pen>(ve, &processData().currentpen, primPen(), SYM(currentpen));
882 
883 #ifdef OPENFUNCEXAMPLE
884   addOpenFunc(ve, openFunc, primInt(), SYM(openFunc));
885 #endif
886 
887   addOpenFunc(ve, printBytecode, primVoid(), SYM(printBytecode));
888 
889   gen_runtime_venv(ve);
890   gen_runbacktrace_venv(ve);
891   gen_runpicture_venv(ve);
892   gen_runlabel_venv(ve);
893   gen_runhistory_venv(ve);
894   gen_runarray_venv(ve);
895   gen_runfile_venv(ve);
896   gen_runsystem_venv(ve);
897   gen_runstring_venv(ve);
898   gen_runpair_venv(ve);
899   gen_runtriple_venv(ve);
900   gen_runpath_venv(ve);
901   gen_runpath3d_venv(ve);
902   gen_runmath_venv(ve);
903 
904 #ifdef HAVE_LIBGSL
905   gen_rungsl_venv(ve);
906 #endif
907 }
908 
909 } //namespace trans
910 
911 namespace run {
912 
913 double infinity=cbrt(DBL_MAX); // Reduced for tension atleast infinity
914 
arrayDeleteHelper(stack * Stack)915 void arrayDeleteHelper(stack *Stack)
916 {
917   array *a=pop<array *>(Stack);
918   item itj=pop(Stack);
919   bool jdefault=isdefault(itj);
920   item iti=pop(Stack);
921   Int i,j;
922   if(isdefault(iti)) {
923     if(jdefault) {
924     (*a).clear();
925     return;
926     } else i=j=get<Int>(itj);
927   } else {
928     i=get<Int>(iti);
929     j=jdefault ? i : get<Int>(itj);
930   }
931 
932   size_t asize=checkArray(a);
933   if(a->cyclic() && asize > 0) {
934     if(j-i+1 >= (Int) asize) {
935       (*a).clear();
936       return;
937     }
938     i=imod(i,asize);
939     j=imod(j,asize);
940     if(j >= i)
941       (*a).erase((*a).begin()+i,(*a).begin()+j+1);
942     else {
943       (*a).erase((*a).begin()+i,(*a).end());
944       (*a).erase((*a).begin(),(*a).begin()+j+1);
945     }
946     return;
947   }
948 
949   if(i < 0 || i >= (Int) asize || i > j || j >= (Int) asize) {
950     ostringstream buf;
951     buf << "delete called on array of length " << (Int) asize
952         << " with out-of-bounds index range [" << i << "," << j << "]";
953     error(buf);
954   }
955 
956   (*a).erase((*a).begin()+i,(*a).begin()+j+1);
957 }
958 
959 // Used by coder to optimize conditional jumps.
960 const bltin intLess = binaryOp<Int,less>;
961 const bltin intGreater = binaryOp<Int,greater>;
962 
963 }
964