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