validation
[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 void psi_num_exp_dump(int fd, struct psi_num_exp *exp)
291 {
292 switch (exp->op) {
293 case PSI_T_NUMBER:
294 psi_number_dump(fd, exp->data.n);
295 break;
296
297 case PSI_T_NOT:
298 case PSI_T_TILDE:
299 dprintf(fd, "%s", psi_num_exp_op_tok(exp->op));
300 psi_num_exp_dump(fd, exp->data.u);
301 break;
302
303 case PSI_T_LPAREN:
304 dprintf(fd, "(");
305 psi_num_exp_dump(fd, exp->data.u);
306 dprintf(fd, ")");
307 break;
308
309
310 case PSI_T_OR:
311 case PSI_T_AND:
312
313 case PSI_T_CMP_EQ:
314 case PSI_T_CMP_NE:
315 case PSI_T_CMP_LE:
316 case PSI_T_CMP_GE:
317 case PSI_T_RCHEVR:
318 case PSI_T_LCHEVR:
319
320 case PSI_T_PIPE:
321 case PSI_T_CARET:
322 case PSI_T_AMPERSAND:
323 case PSI_T_LSHIFT:
324 case PSI_T_RSHIFT:
325 case PSI_T_PLUS:
326 case PSI_T_MINUS:
327 case PSI_T_ASTERISK:
328 case PSI_T_SLASH:
329 psi_num_exp_dump(fd, exp->data.b.lhs);
330 dprintf(fd, " %s ", psi_num_exp_op_tok(exp->op));
331 psi_num_exp_dump(fd, exp->data.b.rhs);
332 break;
333
334 case PSI_T_IIF:
335 psi_num_exp_dump(fd, exp->data.t.cond);
336 dprintf(fd, " ? ");
337 psi_num_exp_dump(fd, exp->data.t.truthy);
338 dprintf(fd, " : ");
339 psi_num_exp_dump(fd, exp->data.t.falsy);
340 break;
341
342 default:
343 assert(0);
344 }
345
346 }
347
348 bool psi_num_exp_validate(struct psi_data *data, struct psi_num_exp *exp,
349 struct psi_impl *impl, struct psi_decl *cb_decl, struct psi_let_exp *current_let,
350 struct psi_set_exp *current_set, struct psi_decl_enum *current_enum)
351 {
352 if (exp->op && exp->op != PSI_T_NUMBER) {
353 switch (exp->op) {
354 case PSI_T_NOT:
355 exp->calc = psi_calc_bool_not;
356 break;
357 case PSI_T_TILDE:
358 exp->calc = psi_calc_bin_not;
359 break;
360
361 case PSI_T_OR:
362 exp->calc = psi_calc_bool_or;
363 break;
364 case PSI_T_AND:
365 exp->calc = psi_calc_bool_and;
366 break;
367 case PSI_T_CMP_EQ:
368 exp->calc = psi_calc_cmp_eq;
369 break;
370 case PSI_T_CMP_NE:
371 exp->calc = psi_calc_cmp_ne;
372 break;
373 case PSI_T_CMP_LE:
374 exp->calc = psi_calc_cmp_le;
375 break;
376 case PSI_T_CMP_GE:
377 exp->calc = psi_calc_cmp_ge;
378 break;
379 case PSI_T_LCHEVR:
380 exp->calc = psi_calc_cmp_lt;
381 break;
382 case PSI_T_RCHEVR:
383 exp->calc = psi_calc_cmp_gt;
384 break;
385
386 case PSI_T_CAST:
387 case PSI_T_LPAREN:
388 case PSI_T_IIF:
389 break;
390
391 case PSI_T_PIPE:
392 exp->calc = psi_calc_bin_or;
393 break;
394 case PSI_T_CARET:
395 exp->calc = psi_calc_bin_xor;
396 break;
397 case PSI_T_AMPERSAND:
398 exp->calc = psi_calc_bin_and;
399 break;
400 case PSI_T_LSHIFT:
401 exp->calc = psi_calc_bin_lshift;
402 break;
403 case PSI_T_RSHIFT:
404 exp->calc = psi_calc_bin_rshift;
405 break;
406 case PSI_T_PLUS:
407 exp->calc = psi_calc_add;
408 break;
409 case PSI_T_MINUS:
410 exp->calc = psi_calc_sub;
411 break;
412 case PSI_T_ASTERISK:
413 exp->calc = psi_calc_mul;
414 break;
415 case PSI_T_SLASH:
416 exp->calc = psi_calc_div;
417 break;
418 case PSI_T_MODULO:
419 exp->calc = psi_calc_mod;
420 break;
421 default:
422 data->error(data, exp->token, PSI_WARNING,
423 "Unknown numeric operator (%d)", exp->op);
424 return false;
425 }
426 }
427
428 switch (exp->op) {
429 case PSI_T_NUMBER:
430 return psi_number_validate(data, exp->data.n, impl, cb_decl, current_let, current_set, current_enum);
431
432 case PSI_T_CAST:
433 return psi_num_exp_validate(data, exp->data.c.num, impl, cb_decl, current_let, current_set, current_enum)
434 && psi_decl_type_validate(data, exp->data.c.typ, 0, NULL);
435 break;
436
437 case PSI_T_NOT:
438 case PSI_T_TILDE:
439 case PSI_T_LPAREN:
440 return psi_num_exp_validate(data, exp->data.u, impl, cb_decl, current_let, current_set, current_enum);
441 break;
442
443 case PSI_T_OR:
444 case PSI_T_AND:
445
446 case PSI_T_CMP_EQ:
447 case PSI_T_CMP_NE:
448 case PSI_T_CMP_LE:
449 case PSI_T_CMP_GE:
450 case PSI_T_RCHEVR:
451 case PSI_T_LCHEVR:
452
453 case PSI_T_PIPE:
454 case PSI_T_CARET:
455 case PSI_T_AMPERSAND:
456 case PSI_T_LSHIFT:
457 case PSI_T_RSHIFT:
458 case PSI_T_PLUS:
459 case PSI_T_MINUS:
460 case PSI_T_ASTERISK:
461 case PSI_T_SLASH:
462 case PSI_T_MODULO:
463 return psi_num_exp_validate(data, exp->data.b.lhs, impl, cb_decl, current_let, current_set, current_enum)
464 && psi_num_exp_validate(data, exp->data.b.rhs, impl, cb_decl, current_let, current_set, current_enum);
465
466 case PSI_T_IIF:
467 return psi_num_exp_validate(data, exp->data.t.cond, impl, cb_decl, current_let, current_set, current_enum)
468 && psi_num_exp_validate(data, exp->data.t.truthy, impl, cb_decl, current_let, current_set, current_enum)
469 && psi_num_exp_validate(data, exp->data.t.falsy, impl, cb_decl, current_let, current_set, current_enum);
470
471 default:
472 assert(0);
473 }
474
475 return false;
476 }
477
478 static inline void psi_impl_val_dump(token_t t, impl_val *res,
479 struct psi_call_frame *frame)
480 {
481 switch (t) {
482 case PSI_T_INT8:
483 case PSI_T_UINT8:
484 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
485 break;
486 case PSI_T_INT16:
487 case PSI_T_UINT16:
488 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
489 break;
490 case PSI_T_INT32:
491 case PSI_T_UINT32:
492 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
493 break;
494 case PSI_T_INT64:
495 case PSI_T_UINT64:
496 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
497 break;
498 case PSI_T_FLOAT:
499 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
500 break;
501 case PSI_T_DOUBLE:
502 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
503 break;
504 default:
505 assert(0);
506 }
507 }
508
509 static inline void psi_num_exp_verify_result(token_t t, impl_val *res, struct psi_call_frame *frame)
510 {
511 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", " = ");
512 psi_impl_val_dump(t, res, frame);
513 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
514 }
515
516 static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **output_ptr,
517 struct psi_plist **input_ptr, struct psi_call_frame *frame, HashTable *defs)
518 {
519 struct psi_plist *output = *output_ptr, *input = *input_ptr;
520 struct element {
521 token_t type;
522 union {
523 impl_val value;
524 psi_calc calc;
525 struct psi_decl_type *cast;
526 } data;
527 } entry;
528
529 switch (exp->op) {
530 case PSI_T_NUMBER:
531 entry.type = psi_number_eval(exp->data.n, &entry.data.value, frame, defs);
532 output = psi_plist_add(output, &entry);
533 break;
534
535 case PSI_T_LPAREN:
536 entry.type = exp->op;
537 input = psi_plist_add(input, &entry);
538 psi_num_exp_reduce(exp->data.u, &output, &input, frame, defs);
539 while (psi_plist_pop(input, &entry)) {
540 if (entry.type == PSI_T_LPAREN) {
541 break;
542 }
543 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
544 output = psi_plist_add(output, &entry);
545 }
546 break;
547
548 case PSI_T_CAST:
549 while (psi_plist_top(input, &entry)) {
550 /* bail out if exp->op >= entry.type */
551 if (psi_calc_oper(exp->op, entry.type) != 1) {
552 break;
553 }
554 psi_plist_pop(input, NULL);
555 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
556 output = psi_plist_add(output, &entry);
557 }
558 entry.type = exp->op;
559 entry.data.cast = exp->data.c.typ;
560 input = psi_plist_add(input, &entry);
561 psi_num_exp_reduce(exp->data.c.num, &output, &input, frame, defs);
562 break;
563
564 case PSI_T_NOT:
565 case PSI_T_TILDE:
566 while (psi_plist_top(input, &entry)) {
567 /* bail out if exp->op >= entry.type */
568 if (psi_calc_oper(exp->op, entry.type) != 1) {
569 break;
570 }
571 psi_plist_pop(input, NULL);
572 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
573 output = psi_plist_add(output, &entry);
574 }
575 entry.type = exp->op;
576 entry.data.calc = exp->calc;
577 input = psi_plist_add(input, &entry);
578 psi_num_exp_reduce(exp->data.u, &output, &input, frame, defs);
579 break;
580
581 case PSI_T_IIF:
582 {
583 impl_val cond_val = {0};
584 token_t cond_typ = psi_num_exp_exec(exp->data.t.cond, &cond_val, frame, defs);
585
586 psi_calc_bool_not(cond_typ, &cond_val, 0, NULL, &cond_val);
587 if (cond_val.u8) {
588 psi_num_exp_reduce(exp->data.t.falsy, &output, &input, frame, defs);
589 } else {
590 psi_num_exp_reduce(exp->data.t.truthy, &output, &input, frame, defs);
591 }
592 }
593 break;
594
595 default:
596 psi_num_exp_reduce(exp->data.b.lhs, &output, &input, frame, defs);
597 while (psi_plist_top(input, &entry)) {
598 /* bail out if exp->op > entry.type */
599 if (psi_calc_oper(exp->op, entry.type) == -1) {
600 break;
601 }
602 psi_plist_pop(input, NULL);
603 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
604 output = psi_plist_add(output, &entry);
605 }
606 entry.type = exp->op;
607 entry.data.calc = exp->calc;
608 input = psi_plist_add(input, &entry);
609 psi_num_exp_reduce(exp->data.b.rhs, &output, &input, frame, defs);
610 break;
611 }
612
613 *output_ptr = output;
614 *input_ptr = input;
615 }
616
617 token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
618 struct psi_call_frame *frame, HashTable *defs)
619 {
620 struct psi_plist *output, *input;
621 struct element {
622 token_t type;
623 union {
624 impl_val value;
625 psi_calc calc;
626 struct psi_decl_type *cast;
627 } data;
628 } entry, lhs, rhs;
629
630 output = psi_plist_init_ex(sizeof(entry), NULL);
631 input = psi_plist_init_ex(sizeof(entry), NULL);
632
633 psi_num_exp_reduce(exp, &output, &input, frame, defs);
634
635 while (psi_plist_pop(input, &entry)) {
636 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
637 output = psi_plist_add(output, &entry);
638 }
639 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
640
641 while (psi_plist_shift(output, &entry)) {
642 switch (entry.type) {
643 default:
644 input = psi_plist_add(input, &entry);
645 break;
646
647 case PSI_T_CAST:
648 psi_plist_pop(input, &rhs);
649 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
650 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
651
652 entry.type = psi_decl_type_get_real(entry.data.cast)->type;
653 psi_calc_cast(rhs.type, &rhs.data.value, entry.type, &entry.data.value);
654 input = psi_plist_add(input, &entry);
655 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
656 break;
657
658 case PSI_T_NOT:
659 case PSI_T_TILDE:
660 psi_plist_pop(input, &rhs);
661 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
662 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
663
664 entry.type = entry.data.calc(rhs.type, &rhs.data.value, 0, NULL, &entry.data.value);
665 input = psi_plist_add(input, &entry);
666 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
667 break;
668
669 case PSI_T_OR:
670 case PSI_T_AND:
671
672 case PSI_T_CMP_EQ:
673 case PSI_T_CMP_NE:
674 case PSI_T_CMP_LE:
675 case PSI_T_CMP_GE:
676 case PSI_T_RCHEVR:
677 case PSI_T_LCHEVR:
678
679 case PSI_T_PIPE:
680 case PSI_T_CARET:
681 case PSI_T_AMPERSAND:
682 case PSI_T_LSHIFT:
683 case PSI_T_RSHIFT:
684 case PSI_T_MINUS:
685 case PSI_T_PLUS:
686 case PSI_T_ASTERISK:
687 case PSI_T_SLASH:
688 case PSI_T_MODULO:
689 psi_plist_pop(input, &rhs);
690 psi_plist_pop(input, &lhs);
691
692 psi_impl_val_dump(lhs.type, &lhs.data.value, frame);
693 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
694 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
695
696 entry.type = entry.data.calc(
697 lhs.type, &lhs.data.value,
698 rhs.type, &rhs.data.value,
699 &entry.data.value);
700 input = psi_plist_add(input, &entry);
701 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
702 break;
703 }
704
705 if (!psi_plist_count(output)) {
706 break;
707 }
708 }
709
710 psi_plist_free(output);
711 psi_plist_free(input);
712
713 *res = entry.data.value;
714 return entry.type;
715 }
716