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