fix float formats; fix sime defval edge cases
[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 psi_num_exp_dump(dump, exp->data.c.num);
395 break;
396
397 case PSI_T_NOT:
398 case PSI_T_TILDE:
399 unary:
400 PSI_DUMP(dump, "%s", psi_num_exp_op_tok(exp->op));
401 psi_num_exp_dump(dump, exp->data.u);
402 break;
403
404 case PSI_T_LPAREN:
405 PSI_DUMP(dump, "(");
406 psi_num_exp_dump(dump, exp->data.u);
407 PSI_DUMP(dump, ")");
408 break;
409
410 case PSI_T_PLUS:
411 case PSI_T_MINUS:
412 if (!exp->data.b.rhs) {
413 goto unary;
414 }
415 /* no break */
416 case PSI_T_PIPE:
417 case PSI_T_CARET:
418 case PSI_T_AMPERSAND:
419 case PSI_T_LSHIFT:
420 case PSI_T_RSHIFT:
421 case PSI_T_ASTERISK:
422 case PSI_T_SLASH:
423
424 case PSI_T_OR:
425 case PSI_T_AND:
426
427 case PSI_T_CMP_EQ:
428 case PSI_T_CMP_NE:
429 case PSI_T_CMP_LE:
430 case PSI_T_CMP_GE:
431 case PSI_T_RCHEVR:
432 case PSI_T_LCHEVR:
433 psi_num_exp_dump(dump, exp->data.b.lhs);
434 PSI_DUMP(dump, " %s ", psi_num_exp_op_tok(exp->op));
435 psi_num_exp_dump(dump, exp->data.b.rhs);
436 break;
437
438 case PSI_T_IIF:
439 psi_num_exp_dump(dump, exp->data.t.cond);
440 PSI_DUMP(dump, " ? ");
441 psi_num_exp_dump(dump, exp->data.t.truthy);
442 PSI_DUMP(dump, " : ");
443 psi_num_exp_dump(dump, exp->data.t.falsy);
444 break;
445
446 default:
447 assert(0);
448 }
449
450 }
451
452 bool psi_num_exp_validate(struct psi_data *data, struct psi_num_exp *exp,
453 struct psi_validate_scope *scope)
454 {
455 if (exp->op && exp->op != PSI_T_NUMBER) {
456 switch (exp->op) {
457 case PSI_T_NOT:
458 exp->calc = psi_calc_bool_not;
459 break;
460 case PSI_T_TILDE:
461 exp->calc = psi_calc_bin_not;
462 break;
463
464 case PSI_T_OR:
465 exp->calc = psi_calc_bool_or;
466 break;
467 case PSI_T_AND:
468 exp->calc = psi_calc_bool_and;
469 break;
470 case PSI_T_CMP_EQ:
471 exp->calc = psi_calc_cmp_eq;
472 break;
473 case PSI_T_CMP_NE:
474 exp->calc = psi_calc_cmp_ne;
475 break;
476 case PSI_T_CMP_LE:
477 exp->calc = psi_calc_cmp_le;
478 break;
479 case PSI_T_CMP_GE:
480 exp->calc = psi_calc_cmp_ge;
481 break;
482 case PSI_T_LCHEVR:
483 exp->calc = psi_calc_cmp_lt;
484 break;
485 case PSI_T_RCHEVR:
486 exp->calc = psi_calc_cmp_gt;
487 break;
488
489 case PSI_T_CAST:
490 case PSI_T_LPAREN:
491 case PSI_T_IIF:
492 break;
493
494 case PSI_T_PIPE:
495 exp->calc = psi_calc_bin_or;
496 break;
497 case PSI_T_CARET:
498 exp->calc = psi_calc_bin_xor;
499 break;
500 case PSI_T_AMPERSAND:
501 exp->calc = psi_calc_bin_and;
502 break;
503 case PSI_T_LSHIFT:
504 exp->calc = psi_calc_bin_lshift;
505 break;
506 case PSI_T_RSHIFT:
507 exp->calc = psi_calc_bin_rshift;
508 break;
509 case PSI_T_PLUS:
510 if (exp->data.b.rhs) {
511 exp->calc = psi_calc_add;
512 }
513 break;
514 case PSI_T_MINUS:
515 if (exp->data.b.rhs) {
516 exp->calc = psi_calc_sub;
517 } else {
518 exp->calc = psi_calc_minus;
519 }
520 break;
521 case PSI_T_ASTERISK:
522 exp->calc = psi_calc_mul;
523 break;
524 case PSI_T_SLASH:
525 exp->calc = psi_calc_div;
526 break;
527 case PSI_T_MODULO:
528 exp->calc = psi_calc_mod;
529 break;
530 default:
531 data->error(data, exp->token, PSI_WARNING,
532 "Unknown numeric operator (%d)", exp->op);
533 return false;
534 }
535 }
536
537 switch (exp->op) {
538 case PSI_T_NUMBER:
539 return psi_number_validate(data, exp->data.n, scope);
540
541 case PSI_T_CAST:
542 return psi_num_exp_validate(data, exp->data.c.num, scope)
543 && psi_decl_type_validate(data, exp->data.c.typ, NULL, scope);
544 break;
545
546 case PSI_T_NOT:
547 case PSI_T_TILDE:
548 case PSI_T_LPAREN:
549 unary:
550 return psi_num_exp_validate(data, exp->data.u, scope);
551 break;
552
553 case PSI_T_PLUS:
554 case PSI_T_MINUS:
555 if (!exp->data.b.rhs) {
556 goto unary;
557 }
558 /* no break */
559 case PSI_T_PIPE:
560 case PSI_T_CARET:
561 case PSI_T_AMPERSAND:
562 case PSI_T_LSHIFT:
563 case PSI_T_RSHIFT:
564 case PSI_T_ASTERISK:
565 case PSI_T_SLASH:
566 case PSI_T_MODULO:
567
568 case PSI_T_OR:
569 case PSI_T_AND:
570
571 case PSI_T_CMP_EQ:
572 case PSI_T_CMP_NE:
573 case PSI_T_CMP_LE:
574 case PSI_T_CMP_GE:
575 case PSI_T_RCHEVR:
576 case PSI_T_LCHEVR:
577 return psi_num_exp_validate(data, exp->data.b.lhs, scope)
578 && psi_num_exp_validate(data, exp->data.b.rhs, scope);
579
580 case PSI_T_IIF:
581 return psi_num_exp_validate(data, exp->data.t.cond, scope)
582 && psi_num_exp_validate(data, exp->data.t.truthy, scope)
583 && psi_num_exp_validate(data, exp->data.t.falsy, scope);
584
585 default:
586 assert(0);
587 }
588
589 return false;
590 }
591
592 static inline void psi_impl_val_dump(token_t t, impl_val *res,
593 struct psi_call_frame *frame)
594 {
595 switch (t) {
596 case PSI_T_INT8:
597 case PSI_T_UINT8:
598 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
599 break;
600 case PSI_T_INT16:
601 case PSI_T_UINT16:
602 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
603 break;
604 case PSI_T_INT32:
605 case PSI_T_UINT32:
606 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
607 break;
608 case PSI_T_INT64:
609 case PSI_T_UINT64:
610 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
611 break;
612 case PSI_T_FLOAT:
613 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
614 break;
615 case PSI_T_DOUBLE:
616 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
617 break;
618 #if HAVE_LONG_DOUBLE
619 case PSI_T_LONG_DOUBLE:
620 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
621 break;
622 #endif
623 default:
624 assert(0);
625 }
626 }
627
628 static inline void psi_num_exp_verify_result(token_t t, impl_val *res, struct psi_call_frame *frame)
629 {
630 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", " = ");
631 psi_impl_val_dump(t, res, frame);
632 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
633 }
634
635 static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **output_ptr,
636 struct psi_plist **input_ptr, struct psi_call_frame *frame, struct psi_cpp *cpp)
637 {
638 struct psi_plist *output = *output_ptr, *input = *input_ptr;
639 struct element {
640 token_t type;
641 union {
642 impl_val value;
643 psi_calc calc;
644 struct psi_decl_type *cast;
645 } data;
646 } entry;
647
648 switch (exp->op) {
649 case PSI_T_NUMBER:
650 entry.type = psi_number_eval(exp->data.n, &entry.data.value, frame, cpp, exp);
651 output = psi_plist_add(output, &entry);
652 break;
653
654 case PSI_T_LPAREN:
655 entry.type = exp->op;
656 input = psi_plist_add(input, &entry);
657 psi_num_exp_reduce(exp->data.u, &output, &input, frame, cpp);
658 while (psi_plist_pop(input, &entry)) {
659 if (entry.type == PSI_T_LPAREN) {
660 break;
661 }
662 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
663 output = psi_plist_add(output, &entry);
664 }
665 break;
666
667 case PSI_T_CAST:
668 while (psi_plist_top(input, &entry)) {
669 /* bail out if exp->op >= entry.type */
670 if (psi_calc_oper(exp->op, entry.type) != 1) {
671 break;
672 }
673 psi_plist_pop(input, NULL);
674 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
675 output = psi_plist_add(output, &entry);
676 }
677 entry.type = exp->op;
678 entry.data.cast = exp->data.c.typ;
679 input = psi_plist_add(input, &entry);
680 psi_num_exp_reduce(exp->data.c.num, &output, &input, frame, cpp);
681 break;
682
683 case PSI_T_NOT:
684 case PSI_T_TILDE:
685 while (psi_plist_top(input, &entry)) {
686 /* bail out if exp->op >= entry.type */
687 if (psi_calc_oper(exp->op, entry.type) != 1) {
688 break;
689 }
690 psi_plist_pop(input, NULL);
691 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
692 output = psi_plist_add(output, &entry);
693 }
694 entry.type = exp->op;
695 entry.data.calc = exp->calc;
696 input = psi_plist_add(input, &entry);
697 psi_num_exp_reduce(exp->data.u, &output, &input, frame, cpp);
698 break;
699
700 case PSI_T_IIF:
701 {
702 impl_val cond_val = {0};
703 token_t cond_typ = psi_num_exp_exec(exp->data.t.cond, &cond_val, frame, cpp);
704
705 psi_calc_bool_not(cond_typ, &cond_val, 0, NULL, &cond_val);
706 if (cond_val.u8) {
707 psi_num_exp_reduce(exp->data.t.falsy, &output, &input, frame, cpp);
708 } else {
709 psi_num_exp_reduce(exp->data.t.truthy, &output, &input, frame, cpp);
710 }
711 }
712 break;
713
714 case PSI_T_MINUS:
715 case PSI_T_PLUS:
716 /* unary */
717 if (!exp->data.b.rhs) {
718 entry.type = psi_num_exp_exec(exp->data.b.lhs, &entry.data.value, frame, cpp);
719
720 if (exp->calc) {
721 entry.type = exp->calc(entry.type, &entry.data.value, 0, NULL, &entry.data.value);
722 }
723 output = psi_plist_add(output, &entry);
724 break;
725 }
726 /* no break */
727 default:
728 psi_num_exp_reduce(exp->data.b.lhs, &output, &input, frame, cpp);
729 while (psi_plist_top(input, &entry)) {
730 /* bail out if exp->op > entry.type */
731 if (psi_calc_oper(exp->op, entry.type) == -1) {
732 break;
733 }
734 psi_plist_pop(input, NULL);
735 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
736 output = psi_plist_add(output, &entry);
737 }
738 entry.type = exp->op;
739 entry.data.calc = exp->calc;
740 input = psi_plist_add(input, &entry);
741 psi_num_exp_reduce(exp->data.b.rhs, &output, &input, frame, cpp);
742 break;
743 }
744
745 *output_ptr = output;
746 *input_ptr = input;
747 }
748
749 token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
750 struct psi_call_frame *frame, struct psi_cpp *cpp)
751 {
752 struct psi_plist *output, *input;
753 struct element {
754 token_t type;
755 union {
756 impl_val value;
757 psi_calc calc;
758 struct psi_decl_type *cast;
759 } data;
760 } entry, lhs, rhs;
761
762 output = psi_plist_init_ex(sizeof(entry), NULL);
763 input = psi_plist_init_ex(sizeof(entry), NULL);
764
765 psi_num_exp_reduce(exp, &output, &input, frame, cpp);
766
767 while (psi_plist_pop(input, &entry)) {
768 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
769 output = psi_plist_add(output, &entry);
770 }
771 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
772
773 while (psi_plist_shift(output, &entry)) {
774 switch (entry.type) {
775 default:
776 input = psi_plist_add(input, &entry);
777 break;
778
779 case PSI_T_CAST:
780 psi_plist_pop(input, &rhs);
781 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
782 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
783
784 entry.type = psi_decl_type_get_real(entry.data.cast)->type;
785 psi_calc_cast(rhs.type, &rhs.data.value, entry.type, &entry.data.value);
786 input = psi_plist_add(input, &entry);
787 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
788 break;
789
790 case PSI_T_NOT:
791 case PSI_T_TILDE:
792 psi_plist_pop(input, &rhs);
793 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
794 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
795
796 entry.type = entry.data.calc(rhs.type, &rhs.data.value, 0, NULL, &entry.data.value);
797 input = psi_plist_add(input, &entry);
798 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
799 break;
800
801 case PSI_T_OR:
802 case PSI_T_AND:
803
804 case PSI_T_CMP_EQ:
805 case PSI_T_CMP_NE:
806 case PSI_T_CMP_LE:
807 case PSI_T_CMP_GE:
808 case PSI_T_RCHEVR:
809 case PSI_T_LCHEVR:
810
811 case PSI_T_PIPE:
812 case PSI_T_CARET:
813 case PSI_T_AMPERSAND:
814 case PSI_T_LSHIFT:
815 case PSI_T_RSHIFT:
816 case PSI_T_MINUS:
817 case PSI_T_PLUS:
818 case PSI_T_ASTERISK:
819 case PSI_T_SLASH:
820 case PSI_T_MODULO:
821 psi_plist_pop(input, &rhs);
822 psi_plist_pop(input, &lhs);
823
824 psi_impl_val_dump(lhs.type, &lhs.data.value, frame);
825 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
826 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
827
828 entry.type = entry.data.calc(
829 lhs.type, &lhs.data.value,
830 rhs.type, &rhs.data.value,
831 &entry.data.value);
832 input = psi_plist_add(input, &entry);
833 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
834 break;
835 }
836
837 if (!psi_plist_count(output)) {
838 break;
839 }
840 }
841
842 psi_plist_free(output);
843 psi_plist_free(input);
844
845 *res = entry.data.value;
846 return entry.type;
847 }
848