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