944b876a4176ad6b38106bc57d033119d1882779
[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
39 struct psi_num_exp *psi_num_exp_init_ternary(token_t op,
40 struct psi_num_exp *cond, struct psi_num_exp *truthy,
41 struct psi_num_exp *falsy)
42 {
43 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
44
45 exp->op = op;
46 exp->data.t.cond = cond;
47 exp->data.t.truthy = truthy;
48 exp->data.t.falsy = falsy;
49
50 return exp;
51 }
52
53 struct psi_num_exp *psi_num_exp_init_binary(token_t op,
54 struct psi_num_exp *lhs, struct psi_num_exp *rhs)
55 {
56 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
57
58 exp->op = op;
59 exp->data.b.lhs = lhs;
60 exp->data.b.rhs = rhs;
61
62 return exp;
63 }
64
65 struct psi_num_exp *psi_num_exp_init_unary(token_t op,
66 struct psi_num_exp *u)
67 {
68 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
69
70 exp->op = op;
71 exp->data.u = u;
72
73 return exp;
74 }
75
76 struct psi_num_exp *psi_num_exp_init_num(struct psi_number *n)
77 {
78 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
79
80 exp->op = PSI_T_NUMBER;
81 exp->data.n = n;
82
83 return exp;
84 }
85
86 struct psi_num_exp *psi_num_exp_init_cast(struct psi_decl_type *typ,
87 struct psi_num_exp *num)
88 {
89 struct psi_num_exp *exp = pecalloc(1, sizeof(*exp), 1);
90
91 exp->op = PSI_T_CAST;
92 exp->data.c.typ = typ;
93 exp->data.c.num = num;
94
95 return exp;
96 }
97
98 struct psi_num_exp *psi_num_exp_copy(struct psi_num_exp *exp)
99 {
100 struct psi_num_exp *cpy;
101
102 if (!exp) {
103 return NULL;
104 }
105
106 cpy = pemalloc(sizeof(*cpy), 1);
107 *cpy = *exp;
108
109 switch (exp->op) {
110 case PSI_T_NUMBER:
111 cpy->data.n = psi_number_copy(exp->data.n);
112 break;
113
114 case PSI_T_CAST:
115 cpy->data.c.typ = psi_decl_type_copy(exp->data.c.typ);
116 cpy->data.c.num = psi_num_exp_copy(exp->data.c.num);
117 break;
118
119 case PSI_T_NOT:
120 case PSI_T_TILDE:
121 case PSI_T_LPAREN:
122 cpy->data.u = psi_num_exp_copy(exp->data.u);
123 break;
124
125 case PSI_T_OR:
126 case PSI_T_AND:
127
128 case PSI_T_CMP_EQ:
129 case PSI_T_CMP_NE:
130 case PSI_T_CMP_LE:
131 case PSI_T_CMP_GE:
132 case PSI_T_RCHEVR:
133 case PSI_T_LCHEVR:
134
135 case PSI_T_PIPE:
136 case PSI_T_CARET:
137 case PSI_T_AMPERSAND:
138 case PSI_T_LSHIFT:
139 case PSI_T_RSHIFT:
140 case PSI_T_PLUS:
141 case PSI_T_MINUS:
142 case PSI_T_ASTERISK:
143 case PSI_T_SLASH:
144 case PSI_T_MODULO:
145 cpy->data.b.lhs = psi_num_exp_copy(exp->data.b.lhs);
146 cpy->data.b.rhs = psi_num_exp_copy(exp->data.b.rhs);
147 break;
148
149 case PSI_T_IIF:
150 cpy->data.t.cond = psi_num_exp_copy(exp->data.t.cond);
151 cpy->data.t.truthy = psi_num_exp_copy(exp->data.t.truthy);
152 cpy->data.t.falsy = psi_num_exp_copy(exp->data.t.falsy);
153 break;
154
155 default:
156 assert(0);
157 }
158
159 if (exp->token) {
160 cpy->token = psi_token_copy(exp->token);
161 }
162
163 return cpy;
164 }
165
166 void psi_num_exp_copy_ctor(struct psi_num_exp **exp_ptr)
167 {
168 *exp_ptr = psi_num_exp_copy(*exp_ptr);
169 }
170
171 void psi_num_exp_free(struct psi_num_exp **c_ptr)
172 {
173 if (*c_ptr) {
174 struct psi_num_exp *c = *c_ptr;
175
176 *c_ptr = NULL;
177
178 switch (c->op) {
179 case PSI_T_NUMBER:
180 psi_number_free(&c->data.n);
181 break;
182
183 case PSI_T_CAST:
184 psi_decl_type_free(&c->data.c.typ);
185 psi_num_exp_free(&c->data.c.num);
186 break;
187
188 case PSI_T_NOT:
189 case PSI_T_TILDE:
190 case PSI_T_LPAREN:
191 psi_num_exp_free(&c->data.u);
192 break;
193
194 case PSI_T_OR:
195 case PSI_T_AND:
196
197 case PSI_T_CMP_EQ:
198 case PSI_T_CMP_NE:
199 case PSI_T_CMP_LE:
200 case PSI_T_CMP_GE:
201 case PSI_T_RCHEVR:
202 case PSI_T_LCHEVR:
203
204 case PSI_T_PIPE:
205 case PSI_T_CARET:
206 case PSI_T_AMPERSAND:
207 case PSI_T_LSHIFT:
208 case PSI_T_RSHIFT:
209 case PSI_T_PLUS:
210 case PSI_T_MINUS:
211 case PSI_T_ASTERISK:
212 case PSI_T_SLASH:
213 case PSI_T_MODULO:
214 psi_num_exp_free(&c->data.b.lhs);
215 psi_num_exp_free(&c->data.b.rhs);
216 break;
217
218 case PSI_T_IIF:
219 psi_num_exp_free(&c->data.t.cond);
220 psi_num_exp_free(&c->data.t.truthy);
221 psi_num_exp_free(&c->data.t.falsy);
222 break;
223
224 default:
225 assert(0);
226 }
227
228 psi_token_free(&c->token);
229
230 free(c);
231 }
232 }
233
234 static inline const char *psi_num_exp_op_tok(token_t op)
235 {
236 switch (op) {
237 case PSI_T_NOT:
238 return "!";
239 case PSI_T_TILDE:
240 return "~";
241 case PSI_T_LPAREN:
242 return "(";
243 case PSI_T_CAST:
244 return "(cast)";
245
246 case PSI_T_PIPE:
247 return "|";
248 case PSI_T_CARET:
249 return "^";
250 case PSI_T_AMPERSAND:
251 return "&";
252
253 case PSI_T_LSHIFT:
254 return "<<";
255 case PSI_T_RSHIFT:
256 return ">>";
257
258 case PSI_T_PLUS:
259 return "+";
260 case PSI_T_MINUS:
261 return "-";
262
263 case PSI_T_ASTERISK:
264 return "*";
265 case PSI_T_SLASH:
266 return "/";
267 case PSI_T_MODULO:
268 return "%";
269
270 case PSI_T_OR:
271 return "||";
272 case PSI_T_AND:
273 return "&&";
274
275 case PSI_T_CMP_EQ:
276 return "==";
277 case PSI_T_CMP_NE:
278 return "!=";
279 case PSI_T_CMP_LE:
280 return "<=";
281 case PSI_T_CMP_GE:
282 return ">=";
283 case PSI_T_RCHEVR:
284 return ">";
285 case PSI_T_LCHEVR:
286 return "<";
287
288 case PSI_T_IIF:
289 return "?";
290
291 default:
292 assert(0);
293 }
294 return 0;
295 }
296
297 struct psi_plist *psi_num_exp_tokens(struct psi_num_exp *exp,
298 struct psi_plist *list)
299 {
300 struct psi_token *ntoken;
301
302 if (!list) {
303 list = psi_plist_init((psi_plist_dtor) psi_token_free);
304 }
305
306 switch (exp->op) {
307 case PSI_T_NUMBER:
308 list = psi_number_tokens(exp->data.n, list);
309 break;
310
311 case PSI_T_CAST:
312 ntoken = exp->data.c.typ->token;
313 ntoken = psi_token_init(PSI_T_LPAREN, "(", 1, ntoken->col-1, ntoken->line, ntoken->file);
314 list = psi_plist_add(list, &ntoken);
315 ntoken = psi_token_copy(exp->data.c.typ->token);
316 list = psi_plist_add(list, &ntoken);
317 ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
318 list = psi_plist_add(list, &ntoken);
319 break;
320
321 case PSI_T_NOT:
322 case PSI_T_TILDE:
323 unary:
324 ntoken = psi_token_copy(exp->token);
325 list = psi_plist_add(list, &ntoken);
326 list = psi_num_exp_tokens(exp->data.u, list);
327 break;
328
329 case PSI_T_LPAREN:
330 ntoken = psi_token_copy(exp->token);
331 list = psi_plist_add(list, &ntoken);
332 list = psi_num_exp_tokens(exp->data.u, list);
333 psi_plist_top(list, &ntoken);
334 ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
335 list = psi_plist_add(list, &ntoken);
336 break;
337
338 case PSI_T_PLUS:
339 case PSI_T_MINUS:
340 if (!exp->data.b.rhs) {
341 goto unary;
342 }
343 /* no break */
344 case PSI_T_PIPE:
345 case PSI_T_CARET:
346 case PSI_T_AMPERSAND:
347 case PSI_T_LSHIFT:
348 case PSI_T_RSHIFT:
349 case PSI_T_ASTERISK:
350 case PSI_T_SLASH:
351
352 case PSI_T_OR:
353 case PSI_T_AND:
354
355 case PSI_T_CMP_EQ:
356 case PSI_T_CMP_NE:
357 case PSI_T_CMP_LE:
358 case PSI_T_CMP_GE:
359 case PSI_T_RCHEVR:
360 case PSI_T_LCHEVR:
361
362 list = psi_num_exp_tokens(exp->data.b.lhs, list);
363 ntoken = psi_token_copy(exp->token);
364 list = psi_plist_add(list, &ntoken);
365 list = psi_num_exp_tokens(exp->data.b.rhs, list);
366 break;
367
368 case PSI_T_IIF:
369 list = psi_num_exp_tokens(exp->data.t.cond, list);
370 ntoken = psi_token_copy(exp->token);
371 list = psi_plist_add(list, &ntoken);
372 list = psi_num_exp_tokens(exp->data.t.truthy, list);
373 psi_plist_top(list, &ntoken);
374 ntoken = psi_token_init(PSI_T_COLON, ":", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
375 list = psi_plist_add(list, &ntoken);
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 return psi_number_validate(data, exp->data.n, scope);
544
545 case PSI_T_CAST:
546 return psi_num_exp_validate(data, exp->data.c.num, scope)
547 && psi_decl_type_validate(data, exp->data.c.typ, NULL, scope);
548 break;
549
550 case PSI_T_NOT:
551 case PSI_T_TILDE:
552 case PSI_T_LPAREN:
553 unary:
554 return psi_num_exp_validate(data, exp->data.u, scope);
555 break;
556
557 case PSI_T_PLUS:
558 case PSI_T_MINUS:
559 if (!exp->data.b.rhs) {
560 goto unary;
561 }
562 /* no break */
563 case PSI_T_PIPE:
564 case PSI_T_CARET:
565 case PSI_T_AMPERSAND:
566 case PSI_T_LSHIFT:
567 case PSI_T_RSHIFT:
568 case PSI_T_ASTERISK:
569 case PSI_T_SLASH:
570 case PSI_T_MODULO:
571
572 case PSI_T_OR:
573 case PSI_T_AND:
574
575 case PSI_T_CMP_EQ:
576 case PSI_T_CMP_NE:
577 case PSI_T_CMP_LE:
578 case PSI_T_CMP_GE:
579 case PSI_T_RCHEVR:
580 case PSI_T_LCHEVR:
581 return psi_num_exp_validate(data, exp->data.b.lhs, scope)
582 && psi_num_exp_validate(data, exp->data.b.rhs, scope);
583
584 case PSI_T_IIF:
585 return psi_num_exp_validate(data, exp->data.t.cond, scope)
586 && psi_num_exp_validate(data, exp->data.t.truthy, scope)
587 && psi_num_exp_validate(data, exp->data.t.falsy, scope);
588
589 default:
590 assert(0);
591 }
592
593 return false;
594 }
595
596 static inline void psi_impl_val_dump(token_t t, impl_val *res,
597 struct psi_call_frame *frame)
598 {
599 switch (t) {
600 case PSI_T_INT8:
601 case PSI_T_UINT8:
602 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
603 break;
604 case PSI_T_INT16:
605 case PSI_T_UINT16:
606 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
607 break;
608 case PSI_T_INT32:
609 case PSI_T_UINT32:
610 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
611 break;
612 case PSI_T_INT64:
613 case PSI_T_UINT64:
614 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
615 break;
616 case PSI_T_FLOAT:
617 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
618 break;
619 case PSI_T_DOUBLE:
620 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
621 break;
622 #if HAVE_LONG_DOUBLE
623 case PSI_T_LONG_DOUBLE:
624 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval);
625 break;
626 #endif
627 default:
628 assert(0);
629 }
630 }
631
632 static inline void psi_num_exp_verify_result(token_t t, impl_val *res, struct psi_call_frame *frame)
633 {
634 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", " = ");
635 psi_impl_val_dump(t, res, frame);
636 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
637 }
638
639 static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **output_ptr,
640 struct psi_plist **input_ptr, struct psi_call_frame *frame, struct psi_cpp *cpp)
641 {
642 struct psi_plist *output = *output_ptr, *input = *input_ptr;
643 struct element {
644 token_t type;
645 union {
646 impl_val value;
647 psi_calc calc;
648 struct psi_decl_type *cast;
649 } data;
650 } entry;
651
652 switch (exp->op) {
653 case PSI_T_NUMBER:
654 entry.type = psi_number_eval(exp->data.n, &entry.data.value, frame, cpp, exp);
655 output = psi_plist_add(output, &entry);
656 break;
657
658 case PSI_T_LPAREN:
659 entry.type = exp->op;
660 input = psi_plist_add(input, &entry);
661 psi_num_exp_reduce(exp->data.u, &output, &input, frame, cpp);
662 while (psi_plist_pop(input, &entry)) {
663 if (entry.type == PSI_T_LPAREN) {
664 break;
665 }
666 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
667 output = psi_plist_add(output, &entry);
668 }
669 break;
670
671 case PSI_T_CAST:
672 while (psi_plist_top(input, &entry)) {
673 /* bail out if exp->op >= entry.type */
674 if (psi_calc_oper(exp->op, entry.type) != 1) {
675 break;
676 }
677 psi_plist_pop(input, NULL);
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 entry.type = exp->op;
682 entry.data.cast = exp->data.c.typ;
683 input = psi_plist_add(input, &entry);
684 psi_num_exp_reduce(exp->data.c.num, &output, &input, frame, cpp);
685 break;
686
687 case PSI_T_NOT:
688 case PSI_T_TILDE:
689 while (psi_plist_top(input, &entry)) {
690 /* bail out if exp->op >= entry.type */
691 if (psi_calc_oper(exp->op, entry.type) != 1) {
692 break;
693 }
694 psi_plist_pop(input, NULL);
695 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
696 output = psi_plist_add(output, &entry);
697 }
698 entry.type = exp->op;
699 entry.data.calc = exp->calc;
700 input = psi_plist_add(input, &entry);
701 psi_num_exp_reduce(exp->data.u, &output, &input, frame, cpp);
702 break;
703
704 case PSI_T_IIF:
705 {
706 impl_val cond_val = {0};
707 token_t cond_typ = psi_num_exp_exec(exp->data.t.cond, &cond_val, frame, cpp);
708
709 psi_calc_bool_not(cond_typ, &cond_val, 0, NULL, &cond_val);
710 if (cond_val.u8) {
711 psi_num_exp_reduce(exp->data.t.falsy, &output, &input, frame, cpp);
712 } else {
713 psi_num_exp_reduce(exp->data.t.truthy, &output, &input, frame, cpp);
714 }
715 }
716 break;
717
718 case PSI_T_MINUS:
719 case PSI_T_PLUS:
720 /* unary */
721 if (!exp->data.b.rhs) {
722 entry.type = psi_num_exp_exec(exp->data.b.lhs, &entry.data.value, frame, cpp);
723
724 if (exp->calc) {
725 entry.type = exp->calc(entry.type, &entry.data.value, 0, NULL, &entry.data.value);
726 }
727 output = psi_plist_add(output, &entry);
728 break;
729 }
730 /* no break */
731 default:
732 psi_num_exp_reduce(exp->data.b.lhs, &output, &input, frame, cpp);
733 while (psi_plist_top(input, &entry)) {
734 /* bail out if exp->op > entry.type */
735 if (psi_calc_oper(exp->op, entry.type) == -1) {
736 break;
737 }
738 psi_plist_pop(input, NULL);
739 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
740 output = psi_plist_add(output, &entry);
741 }
742 entry.type = exp->op;
743 entry.data.calc = exp->calc;
744 input = psi_plist_add(input, &entry);
745 psi_num_exp_reduce(exp->data.b.rhs, &output, &input, frame, cpp);
746 break;
747 }
748
749 *output_ptr = output;
750 *input_ptr = input;
751 }
752
753 token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
754 struct psi_call_frame *frame, struct psi_cpp *cpp)
755 {
756 struct psi_plist *output, *input;
757 struct element {
758 token_t type;
759 union {
760 impl_val value;
761 psi_calc calc;
762 struct psi_decl_type *cast;
763 } data;
764 } entry, lhs, rhs;
765
766 output = psi_plist_init_ex(sizeof(entry), NULL);
767 input = psi_plist_init_ex(sizeof(entry), NULL);
768
769 psi_num_exp_reduce(exp, &output, &input, frame, cpp);
770
771 while (psi_plist_pop(input, &entry)) {
772 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
773 output = psi_plist_add(output, &entry);
774 }
775 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
776
777 while (psi_plist_shift(output, &entry)) {
778 switch (entry.type) {
779 default:
780 input = psi_plist_add(input, &entry);
781 break;
782
783 case PSI_T_CAST:
784 psi_plist_pop(input, &rhs);
785 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
786 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
787
788 entry.type = psi_decl_type_get_real(entry.data.cast)->type;
789 psi_calc_cast(rhs.type, &rhs.data.value, entry.type, &entry.data.value);
790 input = psi_plist_add(input, &entry);
791 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
792 break;
793
794 case PSI_T_NOT:
795 case PSI_T_TILDE:
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 = entry.data.calc(rhs.type, &rhs.data.value, 0, NULL, &entry.data.value);
801 input = psi_plist_add(input, &entry);
802 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
803 break;
804
805 case PSI_T_OR:
806 case PSI_T_AND:
807
808 case PSI_T_CMP_EQ:
809 case PSI_T_CMP_NE:
810 case PSI_T_CMP_LE:
811 case PSI_T_CMP_GE:
812 case PSI_T_RCHEVR:
813 case PSI_T_LCHEVR:
814
815 case PSI_T_PIPE:
816 case PSI_T_CARET:
817 case PSI_T_AMPERSAND:
818 case PSI_T_LSHIFT:
819 case PSI_T_RSHIFT:
820 case PSI_T_MINUS:
821 case PSI_T_PLUS:
822 case PSI_T_ASTERISK:
823 case PSI_T_SLASH:
824 case PSI_T_MODULO:
825 psi_plist_pop(input, &rhs);
826 psi_plist_pop(input, &lhs);
827
828 psi_impl_val_dump(lhs.type, &lhs.data.value, frame);
829 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
830 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
831
832 entry.type = entry.data.calc(
833 lhs.type, &lhs.data.value,
834 rhs.type, &rhs.data.value,
835 &entry.data.value);
836 input = psi_plist_add(input, &entry);
837 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
838 break;
839 }
840
841 if (!psi_plist_count(output)) {
842 break;
843 }
844 }
845
846 psi_plist_free(output);
847 psi_plist_free(input);
848
849 *res = entry.data.value;
850 return entry.type;
851 }
852