fix gdbinit; postprocessing macros
[m6w6/ext-psi] / src / types / num_exp.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #include "php_psi_stdinc.h"
27
28 #include <assert.h>
29
30 #include "data.h"
31 #include "context.h"
32 #include "call.h"
33 #include "calc.h"
34
35 struct psi_num_exp *psi_num_exp_init_ternary(token_t op,
36 struct psi_num_exp *cond, struct psi_num_exp *truthy,
37 struct psi_num_exp *falsy)
38 {
39 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
40
41 exp->op = op;
42 exp->data.t.cond = cond;
43 exp->data.t.truthy = truthy;
44 exp->data.t.falsy = falsy;
45
46 return exp;
47 }
48
49 struct psi_num_exp *psi_num_exp_init_binary(token_t op,
50 struct psi_num_exp *lhs, struct psi_num_exp *rhs)
51 {
52 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
53
54 exp->op = op;
55 exp->data.b.lhs = lhs;
56 exp->data.b.rhs = rhs;
57
58 return exp;
59 }
60
61 struct psi_num_exp *psi_num_exp_init_unary(token_t op,
62 struct psi_num_exp *u)
63 {
64 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
65
66 exp->op = op;
67 exp->data.u = u;
68
69 return exp;
70 }
71
72 struct psi_num_exp *psi_num_exp_init_num(struct psi_number *n)
73 {
74 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
75
76 exp->op = PSI_T_NUMBER;
77 exp->data.n = n;
78
79 return exp;
80 }
81
82 struct psi_num_exp *psi_num_exp_init_cast(struct psi_decl_type *typ,
83 struct psi_num_exp *num)
84 {
85 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
86
87 exp->op = PSI_T_CAST;
88 exp->data.c.typ = typ;
89 exp->data.c.num = num;
90
91 return exp;
92 }
93
94 struct psi_num_exp *psi_num_exp_copy(struct psi_num_exp *exp)
95 {
96 struct psi_num_exp *cpy;
97
98 if (!exp) {
99 return NULL;
100 }
101
102 cpy = pemalloc(sizeof(*cpy), 1);
103 *cpy = *exp;
104
105 switch (exp->op) {
106 case PSI_T_NUMBER:
107 cpy->data.n = psi_number_copy(exp->data.n);
108 break;
109
110 case PSI_T_CAST:
111 cpy->data.c.typ = psi_decl_type_copy(exp->data.c.typ);
112 cpy->data.c.num = psi_num_exp_copy(exp->data.c.num);
113 break;
114
115 case PSI_T_NOT:
116 case PSI_T_TILDE:
117 case PSI_T_LPAREN:
118 cpy->data.u = psi_num_exp_copy(exp->data.u);
119 break;
120
121 case PSI_T_OR:
122 case PSI_T_AND:
123
124 case PSI_T_CMP_EQ:
125 case PSI_T_CMP_NE:
126 case PSI_T_CMP_LE:
127 case PSI_T_CMP_GE:
128 case PSI_T_RCHEVR:
129 case PSI_T_LCHEVR:
130
131 case PSI_T_PIPE:
132 case PSI_T_CARET:
133 case PSI_T_AMPERSAND:
134 case PSI_T_LSHIFT:
135 case PSI_T_RSHIFT:
136 case PSI_T_PLUS:
137 case PSI_T_MINUS:
138 case PSI_T_ASTERISK:
139 case PSI_T_SLASH:
140 case PSI_T_MODULO:
141 cpy->data.b.lhs = psi_num_exp_copy(exp->data.b.lhs);
142 cpy->data.b.rhs = psi_num_exp_copy(exp->data.b.rhs);
143 break;
144
145 case PSI_T_IIF:
146 cpy->data.t.cond = psi_num_exp_copy(exp->data.t.cond);
147 cpy->data.t.truthy = psi_num_exp_copy(exp->data.t.truthy);
148 cpy->data.t.falsy = psi_num_exp_copy(exp->data.t.falsy);
149 break;
150
151 default:
152 assert(0);
153 }
154
155 if (exp->token) {
156 cpy->token = psi_token_copy(exp->token);
157 }
158
159 return cpy;
160 }
161
162 void psi_num_exp_copy_ctor(struct psi_num_exp **exp_ptr)
163 {
164 *exp_ptr = psi_num_exp_copy(*exp_ptr);
165 }
166
167 void psi_num_exp_free(struct psi_num_exp **c_ptr)
168 {
169 if (*c_ptr) {
170 struct psi_num_exp *c = *c_ptr;
171
172 *c_ptr = NULL;
173
174 switch (c->op) {
175 case PSI_T_NUMBER:
176 psi_number_free(&c->data.n);
177 break;
178
179 case PSI_T_CAST:
180 psi_decl_type_free(&c->data.c.typ);
181 psi_num_exp_free(&c->data.c.num);
182 break;
183
184 case PSI_T_NOT:
185 case PSI_T_TILDE:
186 case PSI_T_LPAREN:
187 psi_num_exp_free(&c->data.u);
188 break;
189
190 case PSI_T_OR:
191 case PSI_T_AND:
192
193 case PSI_T_CMP_EQ:
194 case PSI_T_CMP_NE:
195 case PSI_T_CMP_LE:
196 case PSI_T_CMP_GE:
197 case PSI_T_RCHEVR:
198 case PSI_T_LCHEVR:
199
200 case PSI_T_PIPE:
201 case PSI_T_CARET:
202 case PSI_T_AMPERSAND:
203 case PSI_T_LSHIFT:
204 case PSI_T_RSHIFT:
205 case PSI_T_PLUS:
206 case PSI_T_MINUS:
207 case PSI_T_ASTERISK:
208 case PSI_T_SLASH:
209 case PSI_T_MODULO:
210 psi_num_exp_free(&c->data.b.lhs);
211 psi_num_exp_free(&c->data.b.rhs);
212 break;
213
214 case PSI_T_IIF:
215 psi_num_exp_free(&c->data.t.cond);
216 psi_num_exp_free(&c->data.t.truthy);
217 psi_num_exp_free(&c->data.t.falsy);
218 break;
219
220 default:
221 assert(0);
222 }
223
224 psi_token_free(&c->token);
225
226 free(c);
227 }
228 }
229
230 static inline const char *psi_num_exp_op_tok(token_t op)
231 {
232 switch (op) {
233 case PSI_T_NOT:
234 return "!";
235 case PSI_T_TILDE:
236 return "~";
237 case PSI_T_LPAREN:
238 return "(";
239 case PSI_T_CAST:
240 return "(cast)";
241
242 case PSI_T_PIPE:
243 return "|";
244 case PSI_T_CARET:
245 return "^";
246 case PSI_T_AMPERSAND:
247 return "&";
248
249 case PSI_T_LSHIFT:
250 return "<<";
251 case PSI_T_RSHIFT:
252 return ">>";
253
254 case PSI_T_PLUS:
255 return "+";
256 case PSI_T_MINUS:
257 return "-";
258
259 case PSI_T_ASTERISK:
260 return "*";
261 case PSI_T_SLASH:
262 return "/";
263 case PSI_T_MODULO:
264 return "%";
265
266 case PSI_T_OR:
267 return "||";
268 case PSI_T_AND:
269 return "&&";
270
271 case PSI_T_CMP_EQ:
272 return "==";
273 case PSI_T_CMP_NE:
274 return "!=";
275 case PSI_T_CMP_LE:
276 return "<=";
277 case PSI_T_CMP_GE:
278 return ">=";
279 case PSI_T_RCHEVR:
280 return ">";
281 case PSI_T_LCHEVR:
282 return "<";
283
284 case PSI_T_IIF:
285 return "?";
286
287 default:
288 assert(0);
289 }
290 return 0;
291 }
292
293 struct psi_plist *psi_num_exp_tokens(struct psi_num_exp *exp,
294 struct psi_plist *list)
295 {
296 struct psi_token *ntoken;
297
298 if (!list) {
299 list = psi_plist_init((psi_plist_dtor) psi_token_free);
300 }
301
302 switch (exp->op) {
303 case PSI_T_NUMBER:
304 list = psi_number_tokens(exp->data.n, list);
305 break;
306
307 case PSI_T_CAST:
308 ntoken = exp->data.c.typ->token;
309 ntoken = psi_token_init(PSI_T_LPAREN, "(", 1, ntoken->col-1, ntoken->line, ntoken->file);
310 list = psi_plist_add(list, &ntoken);
311 ntoken = psi_token_copy(exp->data.c.typ->token);
312 list = psi_plist_add(list, &ntoken);
313 ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
314 list = psi_plist_add(list, &ntoken);
315 break;
316
317 case PSI_T_NOT:
318 case PSI_T_TILDE:
319 unary:
320 ntoken = psi_token_copy(exp->token);
321 list = psi_plist_add(list, &ntoken);
322 list = psi_num_exp_tokens(exp->data.u, list);
323 break;
324
325 case PSI_T_LPAREN:
326 ntoken = psi_token_copy(exp->token);
327 list = psi_plist_add(list, &ntoken);
328 list = psi_num_exp_tokens(exp->data.u, list);
329 psi_plist_top(list, &ntoken);
330 ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
331 list = psi_plist_add(list, &ntoken);
332 break;
333
334 case PSI_T_PLUS:
335 case PSI_T_MINUS:
336 if (!exp->data.b.rhs) {
337 goto unary;
338 }
339 /* no break */
340 case PSI_T_PIPE:
341 case PSI_T_CARET:
342 case PSI_T_AMPERSAND:
343 case PSI_T_LSHIFT:
344 case PSI_T_RSHIFT:
345 case PSI_T_ASTERISK:
346 case PSI_T_SLASH:
347
348 case PSI_T_OR:
349 case PSI_T_AND:
350
351 case PSI_T_CMP_EQ:
352 case PSI_T_CMP_NE:
353 case PSI_T_CMP_LE:
354 case PSI_T_CMP_GE:
355 case PSI_T_RCHEVR:
356 case PSI_T_LCHEVR:
357
358 list = psi_num_exp_tokens(exp->data.b.lhs, list);
359 ntoken = psi_token_copy(exp->token);
360 list = psi_plist_add(list, &ntoken);
361 list = psi_num_exp_tokens(exp->data.b.rhs, list);
362 break;
363
364 case PSI_T_IIF:
365 list = psi_num_exp_tokens(exp->data.t.cond, list);
366 ntoken = psi_token_copy(exp->token);
367 list = psi_plist_add(list, &ntoken);
368 list = psi_num_exp_tokens(exp->data.t.truthy, list);
369 psi_plist_top(list, &ntoken);
370 ntoken = psi_token_init(PSI_T_COLON, ":", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
371 list = psi_plist_add(list, &ntoken);
372 list = psi_plist_add(list, &ntoken);
373 list = psi_num_exp_tokens(exp->data.t.falsy, list);
374 break;
375
376 default:
377 assert(0);
378 }
379
380 return list;
381 }
382
383 void psi_num_exp_dump(struct psi_dump *dump, struct psi_num_exp *exp)
384 {
385 switch (exp->op) {
386 case PSI_T_NUMBER:
387 psi_number_dump(dump, exp->data.n);
388 break;
389
390 case PSI_T_CAST:
391 PSI_DUMP(dump, "(");
392 psi_decl_type_dump(dump, exp->data.c.typ, 0);
393 PSI_DUMP(dump, ")");
394 break;
395
396 case PSI_T_NOT:
397 case PSI_T_TILDE:
398 unary:
399 PSI_DUMP(dump, "%s", psi_num_exp_op_tok(exp->op));
400 psi_num_exp_dump(dump, exp->data.u);
401 break;
402
403 case PSI_T_LPAREN:
404 PSI_DUMP(dump, "(");
405 psi_num_exp_dump(dump, exp->data.u);
406 PSI_DUMP(dump, ")");
407 break;
408
409 case PSI_T_PLUS:
410 case PSI_T_MINUS:
411 if (!exp->data.b.rhs) {
412 goto unary;
413 }
414 /* no break */
415 case PSI_T_PIPE:
416 case PSI_T_CARET:
417 case PSI_T_AMPERSAND:
418 case PSI_T_LSHIFT:
419 case PSI_T_RSHIFT:
420 case PSI_T_ASTERISK:
421 case PSI_T_SLASH:
422
423 case PSI_T_OR:
424 case PSI_T_AND:
425
426 case PSI_T_CMP_EQ:
427 case PSI_T_CMP_NE:
428 case PSI_T_CMP_LE:
429 case PSI_T_CMP_GE:
430 case PSI_T_RCHEVR:
431 case PSI_T_LCHEVR:
432 psi_num_exp_dump(dump, exp->data.b.lhs);
433 PSI_DUMP(dump, " %s ", psi_num_exp_op_tok(exp->op));
434 psi_num_exp_dump(dump, exp->data.b.rhs);
435 break;
436
437 case PSI_T_IIF:
438 psi_num_exp_dump(dump, exp->data.t.cond);
439 PSI_DUMP(dump, " ? ");
440 psi_num_exp_dump(dump, exp->data.t.truthy);
441 PSI_DUMP(dump, " : ");
442 psi_num_exp_dump(dump, exp->data.t.falsy);
443 break;
444
445 default:
446 assert(0);
447 }
448
449 }
450
451 bool psi_num_exp_validate(struct psi_data *data, struct psi_num_exp *exp,
452 struct psi_validate_scope *scope)
453 {
454 if (exp->op && exp->op != PSI_T_NUMBER) {
455 switch (exp->op) {
456 case PSI_T_NOT:
457 exp->calc = psi_calc_bool_not;
458 break;
459 case PSI_T_TILDE:
460 exp->calc = psi_calc_bin_not;
461 break;
462
463 case PSI_T_OR:
464 exp->calc = psi_calc_bool_or;
465 break;
466 case PSI_T_AND:
467 exp->calc = psi_calc_bool_and;
468 break;
469 case PSI_T_CMP_EQ:
470 exp->calc = psi_calc_cmp_eq;
471 break;
472 case PSI_T_CMP_NE:
473 exp->calc = psi_calc_cmp_ne;
474 break;
475 case PSI_T_CMP_LE:
476 exp->calc = psi_calc_cmp_le;
477 break;
478 case PSI_T_CMP_GE:
479 exp->calc = psi_calc_cmp_ge;
480 break;
481 case PSI_T_LCHEVR:
482 exp->calc = psi_calc_cmp_lt;
483 break;
484 case PSI_T_RCHEVR:
485 exp->calc = psi_calc_cmp_gt;
486 break;
487
488 case PSI_T_CAST:
489 case PSI_T_LPAREN:
490 case PSI_T_IIF:
491 break;
492
493 case PSI_T_PIPE:
494 exp->calc = psi_calc_bin_or;
495 break;
496 case PSI_T_CARET:
497 exp->calc = psi_calc_bin_xor;
498 break;
499 case PSI_T_AMPERSAND:
500 exp->calc = psi_calc_bin_and;
501 break;
502 case PSI_T_LSHIFT:
503 exp->calc = psi_calc_bin_lshift;
504 break;
505 case PSI_T_RSHIFT:
506 exp->calc = psi_calc_bin_rshift;
507 break;
508 case PSI_T_PLUS:
509 if (exp->data.b.rhs) {
510 exp->calc = psi_calc_add;
511 }
512 break;
513 case PSI_T_MINUS:
514 if (exp->data.b.rhs) {
515 exp->calc = psi_calc_sub;
516 } else {
517 exp->calc = psi_calc_minus;
518 }
519 break;
520 case PSI_T_ASTERISK:
521 exp->calc = psi_calc_mul;
522 break;
523 case PSI_T_SLASH:
524 exp->calc = psi_calc_div;
525 break;
526 case PSI_T_MODULO:
527 exp->calc = psi_calc_mod;
528 break;
529 default:
530 data->error(data, exp->token, PSI_WARNING,
531 "Unknown numeric operator (%d)", exp->op);
532 return false;
533 }
534 }
535
536 switch (exp->op) {
537 case PSI_T_NUMBER:
538 return psi_number_validate(data, exp->data.n, scope);
539
540 case PSI_T_CAST:
541 return psi_num_exp_validate(data, exp->data.c.num, scope)
542 && psi_decl_type_validate(data, exp->data.c.typ, NULL, scope);
543 break;
544
545 case PSI_T_NOT:
546 case PSI_T_TILDE:
547 case PSI_T_LPAREN:
548 unary:
549 return psi_num_exp_validate(data, exp->data.u, scope);
550 break;
551
552 case PSI_T_PLUS:
553 case PSI_T_MINUS:
554 if (!exp->data.b.rhs) {
555 goto unary;
556 }
557 /* no break */
558 case PSI_T_PIPE:
559 case PSI_T_CARET:
560 case PSI_T_AMPERSAND:
561 case PSI_T_LSHIFT:
562 case PSI_T_RSHIFT:
563 case PSI_T_ASTERISK:
564 case PSI_T_SLASH:
565 case PSI_T_MODULO:
566
567 case PSI_T_OR:
568 case PSI_T_AND:
569
570 case PSI_T_CMP_EQ:
571 case PSI_T_CMP_NE:
572 case PSI_T_CMP_LE:
573 case PSI_T_CMP_GE:
574 case PSI_T_RCHEVR:
575 case PSI_T_LCHEVR:
576 return psi_num_exp_validate(data, exp->data.b.lhs, scope)
577 && psi_num_exp_validate(data, exp->data.b.rhs, scope);
578
579 case PSI_T_IIF:
580 return psi_num_exp_validate(data, exp->data.t.cond, scope)
581 && psi_num_exp_validate(data, exp->data.t.truthy, scope)
582 && psi_num_exp_validate(data, exp->data.t.falsy, scope);
583
584 default:
585 assert(0);
586 }
587
588 return false;
589 }
590
591 static inline void psi_impl_val_dump(token_t t, impl_val *res,
592 struct psi_call_frame *frame)
593 {
594 switch (t) {
595 case PSI_T_INT8:
596 case PSI_T_UINT8:
597 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
598 break;
599 case PSI_T_INT16:
600 case PSI_T_UINT16:
601 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
602 break;
603 case PSI_T_INT32:
604 case PSI_T_UINT32:
605 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
606 break;
607 case PSI_T_INT64:
608 case PSI_T_UINT64:
609 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
610 break;
611 case PSI_T_FLOAT:
612 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
613 break;
614 case PSI_T_DOUBLE:
615 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
616 break;
617 #if HAVE_LONG_DOUBLE
618 case PSI_T_LONG_DOUBLE:
619 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
620 break;
621 #endif
622 default:
623 assert(0);
624 }
625 }
626
627 static inline void psi_num_exp_verify_result(token_t t, impl_val *res, struct psi_call_frame *frame)
628 {
629 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", " = ");
630 psi_impl_val_dump(t, res, frame);
631 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
632 }
633
634 static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **output_ptr,
635 struct psi_plist **input_ptr, struct psi_call_frame *frame, struct psi_cpp *cpp)
636 {
637 struct psi_plist *output = *output_ptr, *input = *input_ptr;
638 struct element {
639 token_t type;
640 union {
641 impl_val value;
642 psi_calc calc;
643 struct psi_decl_type *cast;
644 } data;
645 } entry;
646
647 switch (exp->op) {
648 case PSI_T_NUMBER:
649 entry.type = psi_number_eval(exp->data.n, &entry.data.value, frame, cpp, exp);
650 output = psi_plist_add(output, &entry);
651 break;
652
653 case PSI_T_LPAREN:
654 entry.type = exp->op;
655 input = psi_plist_add(input, &entry);
656 psi_num_exp_reduce(exp->data.u, &output, &input, frame, cpp);
657 while (psi_plist_pop(input, &entry)) {
658 if (entry.type == PSI_T_LPAREN) {
659 break;
660 }
661 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
662 output = psi_plist_add(output, &entry);
663 }
664 break;
665
666 case PSI_T_CAST:
667 while (psi_plist_top(input, &entry)) {
668 /* bail out if exp->op >= entry.type */
669 if (psi_calc_oper(exp->op, entry.type) != 1) {
670 break;
671 }
672 psi_plist_pop(input, NULL);
673 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
674 output = psi_plist_add(output, &entry);
675 }
676 entry.type = exp->op;
677 entry.data.cast = exp->data.c.typ;
678 input = psi_plist_add(input, &entry);
679 psi_num_exp_reduce(exp->data.c.num, &output, &input, frame, cpp);
680 break;
681
682 case PSI_T_NOT:
683 case PSI_T_TILDE:
684 while (psi_plist_top(input, &entry)) {
685 /* bail out if exp->op >= entry.type */
686 if (psi_calc_oper(exp->op, entry.type) != 1) {
687 break;
688 }
689 psi_plist_pop(input, NULL);
690 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
691 output = psi_plist_add(output, &entry);
692 }
693 entry.type = exp->op;
694 entry.data.calc = exp->calc;
695 input = psi_plist_add(input, &entry);
696 psi_num_exp_reduce(exp->data.u, &output, &input, frame, cpp);
697 break;
698
699 case PSI_T_IIF:
700 {
701 impl_val cond_val = {0};
702 token_t cond_typ = psi_num_exp_exec(exp->data.t.cond, &cond_val, frame, cpp);
703
704 psi_calc_bool_not(cond_typ, &cond_val, 0, NULL, &cond_val);
705 if (cond_val.u8) {
706 psi_num_exp_reduce(exp->data.t.falsy, &output, &input, frame, cpp);
707 } else {
708 psi_num_exp_reduce(exp->data.t.truthy, &output, &input, frame, cpp);
709 }
710 }
711 break;
712
713 case PSI_T_MINUS:
714 case PSI_T_PLUS:
715 /* unary */
716 if (!exp->data.b.rhs) {
717 entry.type = psi_num_exp_exec(exp->data.b.lhs, &entry.data.value, frame, cpp);
718
719 if (exp->calc) {
720 entry.type = exp->calc(entry.type, &entry.data.value, 0, NULL, &entry.data.value);
721 }
722 output = psi_plist_add(output, &entry);
723 break;
724 }
725 /* no break */
726 default:
727 psi_num_exp_reduce(exp->data.b.lhs, &output, &input, frame, cpp);
728 while (psi_plist_top(input, &entry)) {
729 /* bail out if exp->op > entry.type */
730 if (psi_calc_oper(exp->op, entry.type) == -1) {
731 break;
732 }
733 psi_plist_pop(input, NULL);
734 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
735 output = psi_plist_add(output, &entry);
736 }
737 entry.type = exp->op;
738 entry.data.calc = exp->calc;
739 input = psi_plist_add(input, &entry);
740 psi_num_exp_reduce(exp->data.b.rhs, &output, &input, frame, cpp);
741 break;
742 }
743
744 *output_ptr = output;
745 *input_ptr = input;
746 }
747
748 token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
749 struct psi_call_frame *frame, struct psi_cpp *cpp)
750 {
751 struct psi_plist *output, *input;
752 struct element {
753 token_t type;
754 union {
755 impl_val value;
756 psi_calc calc;
757 struct psi_decl_type *cast;
758 } data;
759 } entry, lhs, rhs;
760
761 output = psi_plist_init_ex(sizeof(entry), NULL);
762 input = psi_plist_init_ex(sizeof(entry), NULL);
763
764 psi_num_exp_reduce(exp, &output, &input, frame, cpp);
765
766 while (psi_plist_pop(input, &entry)) {
767 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
768 output = psi_plist_add(output, &entry);
769 }
770 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
771
772 while (psi_plist_shift(output, &entry)) {
773 switch (entry.type) {
774 default:
775 input = psi_plist_add(input, &entry);
776 break;
777
778 case PSI_T_CAST:
779 psi_plist_pop(input, &rhs);
780 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
781 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
782
783 entry.type = psi_decl_type_get_real(entry.data.cast)->type;
784 psi_calc_cast(rhs.type, &rhs.data.value, entry.type, &entry.data.value);
785 input = psi_plist_add(input, &entry);
786 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
787 break;
788
789 case PSI_T_NOT:
790 case PSI_T_TILDE:
791 psi_plist_pop(input, &rhs);
792 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
793 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
794
795 entry.type = entry.data.calc(rhs.type, &rhs.data.value, 0, NULL, &entry.data.value);
796 input = psi_plist_add(input, &entry);
797 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
798 break;
799
800 case PSI_T_OR:
801 case PSI_T_AND:
802
803 case PSI_T_CMP_EQ:
804 case PSI_T_CMP_NE:
805 case PSI_T_CMP_LE:
806 case PSI_T_CMP_GE:
807 case PSI_T_RCHEVR:
808 case PSI_T_LCHEVR:
809
810 case PSI_T_PIPE:
811 case PSI_T_CARET:
812 case PSI_T_AMPERSAND:
813 case PSI_T_LSHIFT:
814 case PSI_T_RSHIFT:
815 case PSI_T_MINUS:
816 case PSI_T_PLUS:
817 case PSI_T_ASTERISK:
818 case PSI_T_SLASH:
819 case PSI_T_MODULO:
820 psi_plist_pop(input, &rhs);
821 psi_plist_pop(input, &lhs);
822
823 psi_impl_val_dump(lhs.type, &lhs.data.value, frame);
824 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
825 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
826
827 entry.type = entry.data.calc(
828 lhs.type, &lhs.data.value,
829 rhs.type, &rhs.data.value,
830 &entry.data.value);
831 input = psi_plist_add(input, &entry);
832 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
833 break;
834 }
835
836 if (!psi_plist_count(output)) {
837 break;
838 }
839 }
840
841 psi_plist_free(output);
842 psi_plist_free(input);
843
844 *res = entry.data.value;
845 return entry.type;
846 }
847