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