1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V.
7 */
8
9/*
10 * (authors) M. Kersten
11 *
12 * MAL builder
13 * The MAL builder library containst the primitives to simplify construction
14 * of programs by compilers. It has grown out of the MonetDB/SQL code generator.
15 * The strings being passed as arguments are copied in the process.
16 *
17 */
18#include "monetdb_config.h"
19#include "mal_builder.h"
20#include "mal_function.h"
21#include "mal_namespace.h"
22
23InstrPtr
24newAssignment(MalBlkPtr mb)
25{
26 InstrPtr q = newInstruction(mb,NULL,NULL);
27
28 if ( q == NULL)
29 return NULL;
30 if ((getArg(q,0)= newTmpVariable(mb,TYPE_any)) < 0 || mb->errors != MAL_SUCCEED) {
31 freeInstruction(q);
32 return NULL;
33 }
34 pushInstruction(mb, q);
35 return q;
36}
37
38InstrPtr
39newStmt(MalBlkPtr mb, const char *module, const char *name)
40{
41 InstrPtr q;
42 str mName = putName(module), nName = putName(name);
43
44 if(mName == NULL || nName == NULL) {
45 return NULL;
46 }
47 q = newInstruction(mb, mName, nName);
48 if ( q == NULL)
49 return NULL;
50 setDestVar(q, newTmpVariable(mb, TYPE_any));
51 if (getDestVar(q) < 0 || mb->errors != MAL_SUCCEED) {
52 freeInstruction(q);
53 return NULL;
54 }
55 pushInstruction(mb, q);
56 return q;
57}
58
59InstrPtr
60newStmtArgs(MalBlkPtr mb, const char *module, const char *name, int args)
61{
62 InstrPtr q;
63 str mName = putName(module), nName = putName(name);
64
65 if(mName == NULL || nName == NULL) {
66 return NULL;
67 }
68 q = newInstructionArgs(mb, mName, nName, args);
69 if ( q == NULL)
70 return NULL;
71 setDestVar(q, newTmpVariable(mb, TYPE_any));
72 if (getDestVar(q) < 0 || mb->errors != MAL_SUCCEED) {
73 freeInstruction(q);
74 return NULL;
75 }
76 pushInstruction(mb, q);
77 return q;
78}
79
80InstrPtr
81newReturnStmt(MalBlkPtr mb)
82{
83 InstrPtr q = newInstruction(mb, NULL, NULL);
84
85 if ( q == NULL)
86 return NULL;
87 if ((getArg(q,0)= newTmpVariable(mb,TYPE_any)) < 0 || mb->errors != MAL_SUCCEED) {
88 freeInstruction(q);
89 return NULL;
90 }
91 q->barrier= RETURNsymbol;
92 pushInstruction(mb, q);
93 return q;
94}
95
96InstrPtr
97newFcnCall(MalBlkPtr mb, char *mod, char *fcn)
98{
99 InstrPtr q = newAssignment(mb);
100 str fcnName, modName;
101
102 if ( q == NULL || mod == NULL || fcn == NULL)
103 return NULL;
104 modName = putName(mod);
105 fcnName = putName(fcn);
106 if(modName == NULL || fcnName == NULL) {
107 freeInstruction(q);
108 return NULL;
109 }
110 setModuleId(q, modName);
111 setFunctionId(q, fcnName);
112 return q;
113}
114
115InstrPtr
116newComment(MalBlkPtr mb, const char *val)
117{
118 InstrPtr q = newInstruction(mb, NULL, NULL);
119 ValRecord cst;
120
121 if (q == NULL)
122 return NULL;
123 q->token = REMsymbol;
124 q->barrier = 0;
125 cst.vtype= TYPE_str;
126 if ((cst.val.sval= GDKstrdup(val)) == NULL) {
127 freeInstruction(q);
128 return NULL;
129 }
130 cst.len = strlen(cst.val.sval);
131 getArg(q,0) = defConstant(mb,TYPE_str,&cst);
132 clrVarConstant(mb,getArg(q,0));
133 setVarDisabled(mb,getArg(q,0));
134 if (mb->errors != MAL_SUCCEED) {
135 freeInstruction(q);
136 return NULL;
137 }
138 pushInstruction(mb, q);
139 return q;
140}
141
142InstrPtr
143newCatchStmt(MalBlkPtr mb, str nme)
144{
145 InstrPtr q = newAssignment(mb);
146 int i= findVariable(mb,nme);
147
148 if ( q == NULL)
149 return NULL;
150 q->barrier = CATCHsymbol;
151 if ( i< 0) {
152 if ((getArg(q,0)= newVariable(mb, nme, strlen(nme),TYPE_str)) < 0 || mb->errors != MAL_SUCCEED) {
153 freeInstruction(q);
154 return NULL;
155 }
156 setVarUDFtype(mb,getArg(q,0));
157 } else getArg(q,0) = i;
158 return q;
159}
160
161InstrPtr
162newRaiseStmt(MalBlkPtr mb, str nme)
163{
164 InstrPtr q = newAssignment(mb);
165 int i= findVariable(mb,nme);
166
167 if ( q == NULL)
168 return NULL;
169 q->barrier = RAISEsymbol;
170 if ( i< 0) {
171 if ((getArg(q,0)= newVariable(mb, nme, strlen(nme),TYPE_str)) < 0 || mb->errors != MAL_SUCCEED) {
172 freeInstruction(q);
173 return NULL;
174 }
175 } else
176 getArg(q,0) = i;
177 return q;
178}
179
180InstrPtr
181newExitStmt(MalBlkPtr mb, str nme)
182{
183 InstrPtr q = newAssignment(mb);
184 int i= findVariable(mb,nme);
185
186 if ( q == NULL)
187 return NULL;
188 q->barrier = EXITsymbol;
189 if ( i< 0) {
190 if ((getArg(q,0)= newVariable(mb, nme,strlen(nme),TYPE_str)) < 0 || mb->errors != MAL_SUCCEED) {
191 freeInstruction(q);
192 return NULL;
193 }
194 } else
195 getArg(q,0) = i;
196 return q;
197}
198
199InstrPtr
200pushEndInstruction(MalBlkPtr mb)
201{
202 InstrPtr q;
203
204 q = newInstruction(mb,NULL, NULL);
205 if ( q == NULL)
206 return NULL;
207 q->token = ENDsymbol;
208 q->barrier = 0;
209 q->argc = 0;
210 q->retc = 0;
211 q->argv[0] = 0;
212 pushInstruction(mb, q);
213 return q;
214}
215
216int
217getIntConstant(MalBlkPtr mb, int val)
218{
219 int _t;
220 ValRecord cst;
221
222 cst.vtype= TYPE_int;
223 cst.val.ival= val;
224 cst.len = 0;
225 _t= fndConstant(mb, &cst, mb->vtop);
226 if( _t < 0)
227 _t = defConstant(mb, TYPE_int,&cst);
228 return _t;
229}
230
231InstrPtr
232pushInt(MalBlkPtr mb, InstrPtr q, int val)
233{
234 int _t;
235 ValRecord cst;
236
237 if (q == NULL)
238 return NULL;
239 cst.vtype= TYPE_int;
240 cst.val.ival= val;
241 cst.len = 0;
242 _t = defConstant(mb, TYPE_int,&cst);
243 return pushArgument(mb, q, _t);
244}
245
246int
247getBteConstant(MalBlkPtr mb, bte val)
248{
249 int _t;
250 ValRecord cst;
251
252 cst.vtype= TYPE_bte;
253 cst.val.btval= val;
254 cst.len = 0;
255 _t= fndConstant(mb, &cst, mb->vtop);
256 if( _t < 0)
257 _t = defConstant(mb, TYPE_bte, &cst);
258 return _t;
259}
260
261InstrPtr
262pushBte(MalBlkPtr mb, InstrPtr q, bte val)
263{
264 int _t;
265 ValRecord cst;
266
267 if (q == NULL)
268 return NULL;
269 cst.vtype= TYPE_bte;
270 cst.val.btval= val;
271 cst.len = 0;
272 _t = defConstant(mb, TYPE_bte,&cst);
273 return pushArgument(mb, q, _t);
274}
275
276int
277getOidConstant(MalBlkPtr mb, oid val)
278{
279 int _t;
280 ValRecord cst;
281
282 cst.vtype= TYPE_oid;
283 cst.val.oval= val;
284 cst.len = 0;
285 _t= fndConstant(mb, &cst, mb->vtop);
286 if( _t < 0)
287 _t = defConstant(mb, TYPE_oid, &cst);
288 return _t;
289}
290
291InstrPtr
292pushOid(MalBlkPtr mb, InstrPtr q, oid val)
293{
294 int _t;
295 ValRecord cst;
296
297 if (q == NULL)
298 return NULL;
299 cst.vtype= TYPE_oid;
300 cst.val.oval= val;
301 cst.len = 0;
302 _t = defConstant(mb,TYPE_oid,&cst);
303 return pushArgument(mb, q, _t);
304}
305
306InstrPtr
307pushVoid(MalBlkPtr mb, InstrPtr q)
308{
309 int _t;
310 ValRecord cst;
311
312 if (q == NULL)
313 return NULL;
314 cst.vtype= TYPE_void;
315 cst.val.oval= oid_nil;
316 cst.len = 0;
317 _t = defConstant(mb,TYPE_void,&cst);
318 return pushArgument(mb, q, _t);
319}
320
321int
322getLngConstant(MalBlkPtr mb, lng val)
323{
324 int _t;
325 ValRecord cst;
326
327 cst.vtype= TYPE_lng;
328 cst.val.lval= val;
329 cst.len = 0;
330 _t= fndConstant(mb, &cst, mb->vtop);
331 if( _t < 0)
332 _t = defConstant(mb, TYPE_lng, &cst);
333 return _t;
334}
335
336InstrPtr
337pushLng(MalBlkPtr mb, InstrPtr q, lng val)
338{
339 int _t;
340 ValRecord cst;
341
342 if (q == NULL)
343 return NULL;
344 cst.vtype= TYPE_lng;
345 cst.val.lval= val;
346 cst.len = 0;
347 _t = defConstant(mb,TYPE_lng,&cst);
348 return pushArgument(mb, q, _t);
349}
350
351int
352getShtConstant(MalBlkPtr mb, sht val)
353{
354 int _t;
355 ValRecord cst;
356
357 cst.vtype= TYPE_sht;
358 cst.val.shval= val;
359 cst.len = 0;
360 _t= fndConstant(mb, &cst, mb->vtop);
361 if( _t < 0)
362 _t = defConstant(mb, TYPE_sht, &cst);
363 return _t;
364}
365
366InstrPtr
367pushSht(MalBlkPtr mb, InstrPtr q, sht val)
368{
369 int _t;
370 ValRecord cst;
371
372 if ( q == NULL)
373 return NULL;
374 cst.vtype= TYPE_sht;
375 cst.val.shval= val;
376 cst.len = 0;
377 _t = defConstant(mb,TYPE_sht,&cst);
378 return pushArgument(mb, q, _t);
379}
380
381#ifdef HAVE_HGE
382int
383getHgeConstant(MalBlkPtr mb, hge val)
384{
385 int _t;
386 ValRecord cst;
387
388 cst.vtype= TYPE_oid;
389 cst.val.hval= val;
390 cst.len = 0;
391 _t= fndConstant(mb, &cst, mb->vtop);
392 if( _t < 0)
393 _t = defConstant(mb, TYPE_hge, &cst);
394 return _t;
395}
396
397InstrPtr
398pushHge(MalBlkPtr mb, InstrPtr q, hge val)
399{
400 int _t;
401 ValRecord cst;
402
403 if ( q == NULL)
404 return NULL;
405 cst.vtype= TYPE_hge;
406 cst.val.hval= val;
407 cst.len = 0;
408 _t = defConstant(mb,TYPE_hge,&cst);
409 return pushArgument(mb, q, _t);
410}
411#endif
412
413int
414getDblConstant(MalBlkPtr mb, dbl val)
415{
416 int _t;
417 ValRecord cst;
418
419 cst.vtype= TYPE_dbl;
420 cst.val.dval= val;
421 cst.len = 0;
422 _t= fndConstant(mb, &cst, mb->vtop);
423 if( _t < 0)
424 _t = defConstant(mb, TYPE_dbl, &cst);
425 return _t;
426}
427
428InstrPtr
429pushDbl(MalBlkPtr mb, InstrPtr q, dbl val)
430{
431 int _t;
432 ValRecord cst;
433
434 if (q == NULL)
435 return NULL;
436 cst.vtype= TYPE_dbl;
437 cst.val.dval= val;
438 cst.len = 0;
439 _t = defConstant(mb,TYPE_dbl,&cst);
440 return pushArgument(mb, q, _t);
441}
442
443int
444getFltConstant(MalBlkPtr mb, flt val)
445{
446 int _t;
447 ValRecord cst;
448
449 cst.vtype= TYPE_flt;
450 cst.val.fval= val;
451 cst.len = 0;
452 _t= fndConstant(mb, &cst, mb->vtop);
453 if( _t < 0)
454 _t = defConstant(mb, TYPE_flt, &cst);
455 return _t;
456}
457
458InstrPtr
459pushFlt(MalBlkPtr mb, InstrPtr q, flt val)
460{
461 int _t;
462 ValRecord cst;
463
464 if (q == NULL)
465 return NULL;
466 cst.vtype= TYPE_flt;
467 cst.val.fval= val;
468 cst.len = 0;
469 _t = defConstant(mb,TYPE_flt,&cst);
470 return pushArgument(mb, q, _t);
471}
472
473int
474getStrConstant(MalBlkPtr mb, str val)
475{
476 int _t;
477 ValRecord cst;
478
479 cst.vtype = TYPE_str;
480 cst.val.sval = val;
481 cst.len = strlen(val);
482 _t= fndConstant(mb, &cst, mb->vtop);
483 if( _t < 0) {
484 if ((cst.val.sval= GDKstrdup(val)) == NULL)
485 return -1;
486 _t = defConstant(mb, TYPE_str, &cst);
487 }
488 return _t;
489}
490
491InstrPtr
492pushStr(MalBlkPtr mb, InstrPtr q, const char *Val)
493{
494 int _t;
495 ValRecord cst;
496
497 if (q == NULL)
498 return NULL;
499 cst.vtype= TYPE_str;
500 if ((cst.val.sval= GDKstrdup(Val)) == NULL) {
501 freeInstruction(q);
502 return NULL;
503 }
504 cst.len = strlen(cst.val.sval);
505 _t = defConstant(mb,TYPE_str,&cst);
506 return pushArgument(mb, q, _t);
507}
508
509int
510getBitConstant(MalBlkPtr mb, bit val)
511{
512 int _t;
513 ValRecord cst;
514
515 cst.vtype= TYPE_bit;
516 cst.val.btval= val;
517 cst.len = 0;
518 _t= fndConstant(mb, &cst, mb->vtop);
519 if( _t < 0)
520 _t = defConstant(mb, TYPE_bit, &cst);
521 return _t;
522}
523
524InstrPtr
525pushBit(MalBlkPtr mb, InstrPtr q, bit val)
526{
527 int _t;
528 ValRecord cst;
529
530 if (q == NULL)
531 return NULL;
532 cst.vtype= TYPE_bit;
533 cst.val.btval= val;
534 cst.len = 0;
535 _t = defConstant(mb,TYPE_bit,&cst);
536
537 return pushArgument(mb, q, _t);
538}
539
540InstrPtr
541pushNil(MalBlkPtr mb, InstrPtr q, int tpe)
542{
543 int _t;
544 ValRecord cst;
545
546 if (q == NULL)
547 return NULL;
548 cst.len = 0;
549 if( !isaBatType(tpe) && tpe != TYPE_bat ) {
550 assert(tpe < MAXATOMS); /* in particular, tpe!=TYPE_any */
551 if (!tpe) {
552 cst.vtype=TYPE_void;
553 cst.val.oval= oid_nil;
554 } else if (ATOMextern(tpe)) {
555 ptr p = ATOMnil(tpe);
556 if( p == NULL){
557 freeInstruction(q);
558 return NULL;
559 }
560 VALset(&cst, tpe, p);
561 } else {
562 if (VALinit(&cst, tpe, ATOMnilptr(tpe)) == NULL) {
563 freeInstruction(q);
564 return NULL;
565 }
566 }
567 _t = defConstant(mb,tpe,&cst);
568 } else {
569 cst.vtype = TYPE_bat;
570 cst.val.bval = bat_nil;
571 _t = defConstant(mb,TYPE_bat,&cst);
572 getVarType(mb,_t) = tpe;
573 }
574 q= pushArgument(mb, q, _t);
575 setVarUDFtype(mb,getArg(q,q->argc-1)); /* needed */
576 return q;
577}
578
579InstrPtr
580pushNilType(MalBlkPtr mb, InstrPtr q, char *tpe)
581{
582 int _t,idx;
583 ValRecord cst;
584 str msg;
585
586 if (q == NULL)
587 return NULL;
588 idx= getAtomIndex(tpe, strlen(tpe), TYPE_any);
589 if( idx < 0 || idx >= GDKatomcnt || idx >= MAXATOMS)
590 return NULL;
591 cst.vtype=TYPE_void;
592 cst.val.oval= oid_nil;
593 cst.len = 0;
594 msg = convertConstant(idx, &cst);
595 if (msg != MAL_SUCCEED) {
596 freeException(msg);
597 return NULL;
598 }
599 _t = defConstant(mb,idx,&cst);
600 setVarUDFtype(mb,_t);
601
602 return pushArgument(mb, q, _t);
603}
604InstrPtr
605pushType(MalBlkPtr mb, InstrPtr q, int tpe)
606{
607 int _t;
608 ValRecord cst;
609 str msg;
610
611 if (q == NULL)
612 return NULL;
613 cst.vtype=TYPE_void;
614 cst.val.oval= oid_nil;
615 cst.len = 0;
616 msg = convertConstant(tpe, &cst);
617 if (msg != MAL_SUCCEED) {
618 freeException(msg);
619 return NULL;
620 }
621 _t = defConstant(mb,tpe,&cst);
622 setVarUDFtype(mb,_t);
623
624 return pushArgument(mb, q, _t);
625}
626
627InstrPtr
628pushZero(MalBlkPtr mb, InstrPtr q, int tpe)
629{
630 int _t;
631 ValRecord cst;
632 str msg;
633
634 if (q == NULL)
635 return NULL;
636 cst.vtype=TYPE_int;
637 cst.val.ival= 0;
638 cst.len = 0;
639 msg = convertConstant(tpe, &cst);
640 if (msg != MAL_SUCCEED) {
641 freeException(msg);
642 return NULL;
643 }
644 _t = defConstant(mb,tpe,&cst);
645
646 return pushArgument(mb, q, _t);
647}
648
649InstrPtr
650pushEmptyBAT(MalBlkPtr mb, InstrPtr q, int tpe)
651{
652 if (q == NULL)
653 return NULL;
654 getModuleId(q) = getName("bat");
655 getFunctionId(q) = getName("new");
656
657 q = pushArgument(mb, q, newTypeVariable(mb,TYPE_void));
658 q = pushArgument(mb, q, newTypeVariable(mb,getBatType(tpe)));
659 q = pushZero(mb,q,TYPE_lng);
660 return q;
661}
662
663InstrPtr
664pushValue(MalBlkPtr mb, InstrPtr q, ValPtr vr)
665{
666 int _t;
667 ValRecord cst;
668
669 if (q == NULL)
670 return NULL;
671 if (VALcopy(&cst, vr) == NULL) {
672 freeInstruction(q);
673 return NULL;
674 }
675 _t = defConstant(mb,cst.vtype,&cst);
676 return pushArgument(mb, q, _t);
677}
678