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