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