bison
[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
36 struct psi_num_exp *psi_num_exp_init_binary(token_t op,
37 struct psi_num_exp *lhs, struct psi_num_exp *rhs)
38 {
39 struct psi_num_exp *exp = calloc(1, sizeof(*exp));
40
41 exp->op = op;
42 exp->data.b.lhs = lhs;
43 exp->data.b.rhs = rhs;
44
45 return exp;
46 }
47
48 struct psi_num_exp *psi_num_exp_init_unary(token_t op,
49 struct psi_num_exp *u)
50 {
51 struct psi_num_exp *exp = calloc(1, sizeof(*exp));
52
53 exp->op = op;
54 exp->data.u = u;
55
56 return exp;
57 }
58
59 struct psi_num_exp *psi_num_exp_init_num(struct psi_number *n)
60 {
61 struct psi_num_exp *exp = calloc(1, sizeof(*exp));
62
63 exp->op = PSI_T_NUMBER;
64 exp->data.n = n;
65
66 return exp;
67 }
68
69 struct psi_num_exp *psi_num_exp_init_cast(struct psi_decl_type *typ,
70 struct psi_num_exp *num)
71 {
72 struct psi_num_exp *exp = calloc(1, sizeof(*exp));
73
74 exp->op = PSI_T_CAST;
75 exp->data.c.typ = typ;
76 exp->data.c.num = num;
77
78 return exp;
79 }
80
81 struct psi_num_exp *psi_num_exp_copy(struct psi_num_exp *exp)
82 {
83 struct psi_num_exp *cpy;
84
85 if (!exp) {
86 return NULL;
87 }
88
89 cpy = malloc(sizeof(*cpy));
90 *cpy = *exp;
91
92 switch (exp->op) {
93 case PSI_T_NUMBER:
94 cpy->data.n = psi_number_copy(exp->data.n);
95 break;
96
97 case PSI_T_CAST:
98 cpy->data.c.typ = psi_decl_type_copy(exp->data.c.typ);
99 cpy->data.c.num = psi_num_exp_copy(exp->data.c.num);
100 break;
101
102 case PSI_T_NOT:
103 case PSI_T_TILDE:
104 case PSI_T_LPAREN:
105 cpy->data.u = psi_num_exp_copy(exp->data.u);
106 break;
107
108 case PSI_T_OR:
109 case PSI_T_AND:
110
111 case PSI_T_CMP_EQ:
112 case PSI_T_CMP_NE:
113 case PSI_T_CMP_LE:
114 case PSI_T_CMP_GE:
115 case PSI_T_RCHEVR:
116 case PSI_T_LCHEVR:
117
118 case PSI_T_PIPE:
119 case PSI_T_CARET:
120 case PSI_T_AMPERSAND:
121 case PSI_T_LSHIFT:
122 case PSI_T_RSHIFT:
123 case PSI_T_PLUS:
124 case PSI_T_MINUS:
125 case PSI_T_ASTERISK:
126 case PSI_T_SLASH:
127 case PSI_T_MODULO:
128 cpy->data.b.lhs = psi_num_exp_copy(exp->data.b.lhs);
129 cpy->data.b.rhs = psi_num_exp_copy(exp->data.b.rhs);
130 break;
131
132 default:
133 assert(0);
134 }
135
136 if (exp->token) {
137 cpy->token = psi_token_copy(exp->token);
138 }
139
140 return cpy;
141 }
142
143 void psi_num_exp_free(struct psi_num_exp **c_ptr)
144 {
145 if (*c_ptr) {
146 struct psi_num_exp *c = *c_ptr;
147
148 *c_ptr = NULL;
149
150 switch (c->op) {
151 case PSI_T_NUMBER:
152 psi_number_free(&c->data.n);
153 break;
154
155 case PSI_T_CAST:
156 psi_decl_type_free(&c->data.c.typ);
157 psi_num_exp_free(&c->data.c.num);
158 break;
159
160 case PSI_T_NOT:
161 case PSI_T_TILDE:
162 case PSI_T_LPAREN:
163 psi_num_exp_free(&c->data.u);
164 break;
165
166 case PSI_T_OR:
167 case PSI_T_AND:
168
169 case PSI_T_CMP_EQ:
170 case PSI_T_CMP_NE:
171 case PSI_T_CMP_LE:
172 case PSI_T_CMP_GE:
173 case PSI_T_RCHEVR:
174 case PSI_T_LCHEVR:
175
176 case PSI_T_PIPE:
177 case PSI_T_CARET:
178 case PSI_T_AMPERSAND:
179 case PSI_T_LSHIFT:
180 case PSI_T_RSHIFT:
181 case PSI_T_PLUS:
182 case PSI_T_MINUS:
183 case PSI_T_ASTERISK:
184 case PSI_T_SLASH:
185 case PSI_T_MODULO:
186 psi_num_exp_free(&c->data.b.lhs);
187 psi_num_exp_free(&c->data.b.rhs);
188 break;
189
190 default:
191 assert(0);
192 }
193
194 if (c->token) {
195 free(c->token);
196 }
197
198 free(c);
199 }
200 }
201
202 static inline const char *psi_num_exp_op_tok(token_t op)
203 {
204 switch (op) {
205 case PSI_T_NOT:
206 return "!";
207 case PSI_T_TILDE:
208 return "~";
209 case PSI_T_LPAREN:
210 return "(";
211 case PSI_T_CAST:
212 return "(cast)";
213
214 case PSI_T_PIPE:
215 return "|";
216 case PSI_T_CARET:
217 return "^";
218 case PSI_T_AMPERSAND:
219 return "&";
220
221 case PSI_T_LSHIFT:
222 return "<<";
223 case PSI_T_RSHIFT:
224 return ">>";
225
226 case PSI_T_PLUS:
227 return "+";
228 case PSI_T_MINUS:
229 return "-";
230
231 case PSI_T_ASTERISK:
232 return "*";
233 case PSI_T_SLASH:
234 return "/";
235 case PSI_T_MODULO:
236 return "%";
237
238 case PSI_T_OR:
239 return "||";
240 case PSI_T_AND:
241 return "&&";
242
243 case PSI_T_CMP_EQ:
244 return "==";
245 case PSI_T_CMP_NE:
246 return "!=";
247 case PSI_T_CMP_LE:
248 return "<=";
249 case PSI_T_CMP_GE:
250 return ">=";
251 case PSI_T_RCHEVR:
252 return ">";
253 case PSI_T_LCHEVR:
254 return "<";
255
256 default:
257 assert(0);
258 }
259 return 0;
260 }
261
262 void psi_num_exp_dump(int fd, struct psi_num_exp *exp)
263 {
264 switch (exp->op) {
265 case PSI_T_NUMBER:
266 psi_number_dump(fd, exp->data.n);
267 break;
268
269 case PSI_T_NOT:
270 case PSI_T_TILDE:
271 dprintf(fd, "%s", psi_num_exp_op_tok(exp->op));
272 psi_num_exp_dump(fd, exp->data.u);
273 break;
274
275 case PSI_T_LPAREN:
276 dprintf(fd, "(");
277 psi_num_exp_dump(fd, exp->data.u);
278 dprintf(fd, ")");
279 break;
280
281
282 case PSI_T_OR:
283 case PSI_T_AND:
284
285 case PSI_T_CMP_EQ:
286 case PSI_T_CMP_NE:
287 case PSI_T_CMP_LE:
288 case PSI_T_CMP_GE:
289 case PSI_T_RCHEVR:
290 case PSI_T_LCHEVR:
291
292 case PSI_T_PIPE:
293 case PSI_T_CARET:
294 case PSI_T_AMPERSAND:
295 case PSI_T_LSHIFT:
296 case PSI_T_RSHIFT:
297 case PSI_T_PLUS:
298 case PSI_T_MINUS:
299 case PSI_T_ASTERISK:
300 case PSI_T_SLASH:
301 psi_num_exp_dump(fd, exp->data.b.lhs);
302 dprintf(fd, " %s ", psi_num_exp_op_tok(exp->op));
303 psi_num_exp_dump(fd, exp->data.b.rhs);
304 break;
305
306 default:
307 assert(0);
308 }
309
310 }
311
312 bool psi_num_exp_validate(struct psi_data *data, struct psi_num_exp *exp,
313 struct psi_impl *impl, struct psi_decl *cb_decl, struct psi_let_exp *current_let,
314 struct psi_set_exp *current_set, struct psi_decl_enum *current_enum)
315 {
316 if (exp->op && exp->op != PSI_T_NUMBER) {
317 switch (exp->op) {
318 case PSI_T_NOT:
319 exp->calc = psi_calc_bool_not;
320 break;
321 case PSI_T_TILDE:
322 exp->calc = psi_calc_bin_not;
323 break;
324
325 case PSI_T_OR:
326 exp->calc = psi_calc_bool_or;
327 break;
328 case PSI_T_AND:
329 exp->calc = psi_calc_bool_and;
330 break;
331 case PSI_T_CMP_EQ:
332 exp->calc = psi_calc_cmp_eq;
333 break;
334 case PSI_T_CMP_NE:
335 exp->calc = psi_calc_cmp_ne;
336 break;
337 case PSI_T_CMP_LE:
338 exp->calc = psi_calc_cmp_le;
339 break;
340 case PSI_T_CMP_GE:
341 exp->calc = psi_calc_cmp_ge;
342 break;
343 case PSI_T_LCHEVR:
344 exp->calc = psi_calc_cmp_lt;
345 break;
346 case PSI_T_RCHEVR:
347 exp->calc = psi_calc_cmp_gt;
348 break;
349
350 case PSI_T_CAST:
351 case PSI_T_LPAREN:
352 break;
353
354 case PSI_T_PIPE:
355 exp->calc = psi_calc_bin_or;
356 break;
357 case PSI_T_CARET:
358 exp->calc = psi_calc_bin_xor;
359 break;
360 case PSI_T_AMPERSAND:
361 exp->calc = psi_calc_bin_and;
362 break;
363 case PSI_T_LSHIFT:
364 exp->calc = psi_calc_bin_lshift;
365 break;
366 case PSI_T_RSHIFT:
367 exp->calc = psi_calc_bin_rshift;
368 break;
369 case PSI_T_PLUS:
370 exp->calc = psi_calc_add;
371 break;
372 case PSI_T_MINUS:
373 exp->calc = psi_calc_sub;
374 break;
375 case PSI_T_ASTERISK:
376 exp->calc = psi_calc_mul;
377 break;
378 case PSI_T_SLASH:
379 exp->calc = psi_calc_div;
380 break;
381 case PSI_T_MODULO:
382 exp->calc = psi_calc_mod;
383 break;
384 default:
385 data->error(data, exp->token, PSI_WARNING,
386 "Unknown numeric operator (%d)", exp->op);
387 return false;
388 }
389 }
390
391 switch (exp->op) {
392 case PSI_T_NUMBER:
393 return psi_number_validate(data, exp->data.n, impl, cb_decl, current_let, current_set, current_enum);
394
395 case PSI_T_CAST:
396 return psi_num_exp_validate(data, exp->data.c.num, impl, cb_decl, current_let, current_set, current_enum)
397 && psi_decl_type_validate(data, exp->data.c.typ, NULL);
398 break;
399
400 case PSI_T_NOT:
401 case PSI_T_TILDE:
402 case PSI_T_LPAREN:
403 return psi_num_exp_validate(data, exp->data.u, impl, cb_decl, current_let, current_set, current_enum);
404 break;
405
406 case PSI_T_OR:
407 case PSI_T_AND:
408
409 case PSI_T_CMP_EQ:
410 case PSI_T_CMP_NE:
411 case PSI_T_CMP_LE:
412 case PSI_T_CMP_GE:
413 case PSI_T_RCHEVR:
414 case PSI_T_LCHEVR:
415
416 case PSI_T_PIPE:
417 case PSI_T_CARET:
418 case PSI_T_AMPERSAND:
419 case PSI_T_LSHIFT:
420 case PSI_T_RSHIFT:
421 case PSI_T_PLUS:
422 case PSI_T_MINUS:
423 case PSI_T_ASTERISK:
424 case PSI_T_SLASH:
425 case PSI_T_MODULO:
426 return psi_num_exp_validate(data, exp->data.b.lhs, impl, cb_decl, current_let, current_set, current_enum)
427 && psi_num_exp_validate(data, exp->data.b.rhs, impl, cb_decl, current_let, current_set, current_enum);
428 default:
429 assert(0);
430 }
431
432 return false;
433 }
434
435 static inline void psi_impl_val_dump(token_t t, impl_val *res,
436 struct psi_call_frame *frame)
437 {
438 switch (t) {
439 case PSI_T_INT8:
440 case PSI_T_UINT8:
441 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
442 break;
443 case PSI_T_INT16:
444 case PSI_T_UINT16:
445 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi16, res->i16);
446 break;
447 case PSI_T_INT32:
448 case PSI_T_UINT32:
449 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi32, res->i32);
450 break;
451 case PSI_T_INT64:
452 case PSI_T_UINT64:
453 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
454 break;
455 case PSI_T_FLOAT:
456 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
457 break;
458 case PSI_T_DOUBLE:
459 if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
460 break;
461 default:
462 assert(0);
463 }
464 }
465
466 static inline void psi_num_exp_verify_result(token_t t, impl_val *res, struct psi_call_frame *frame)
467 {
468 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", " = ");
469 psi_impl_val_dump(t, res, frame);
470 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
471 }
472
473 static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **output_ptr,
474 struct psi_plist **input_ptr, struct psi_call_frame *frame, HashTable *defs)
475 {
476 struct psi_plist *output = *output_ptr, *input = *input_ptr;
477 struct element {
478 token_t type;
479 union {
480 impl_val value;
481 psi_calc calc;
482 struct psi_decl_type *cast;
483 } data;
484 } entry;
485
486 switch (exp->op) {
487 case PSI_T_NUMBER:
488 entry.type = psi_number_eval(exp->data.n, &entry.data.value, frame, defs);
489 output = psi_plist_add(output, &entry);
490 break;
491
492 case PSI_T_LPAREN:
493 entry.type = exp->op;
494 input = psi_plist_add(input, &entry);
495 psi_num_exp_reduce(exp->data.u, &output, &input, frame, defs);
496 while (psi_plist_pop(input, &entry)) {
497 if (entry.type == PSI_T_LPAREN) {
498 break;
499 }
500 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
501 output = psi_plist_add(output, &entry);
502 }
503 break;
504
505 case PSI_T_CAST:
506 while (psi_plist_top(input, &entry)) {
507 /* bail out if exp->op >= entry.type */
508 if (psi_calc_oper(exp->op, entry.type) != 1) {
509 break;
510 }
511 psi_plist_pop(input, NULL);
512 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
513 output = psi_plist_add(output, &entry);
514 }
515 entry.type = exp->op;
516 entry.data.cast = exp->data.c.typ;
517 input = psi_plist_add(input, &entry);
518 psi_num_exp_reduce(exp->data.c.num, &output, &input, frame, defs);
519 break;
520
521 case PSI_T_NOT:
522 case PSI_T_TILDE:
523 while (psi_plist_top(input, &entry)) {
524 /* bail out if exp->op >= entry.type */
525 if (psi_calc_oper(exp->op, entry.type) != 1) {
526 break;
527 }
528 psi_plist_pop(input, NULL);
529 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
530 output = psi_plist_add(output, &entry);
531 }
532 entry.type = exp->op;
533 entry.data.calc = exp->calc;
534 input = psi_plist_add(input, &entry);
535 psi_num_exp_reduce(exp->data.u, &output, &input, frame, defs);
536 break;
537
538 default:
539 psi_num_exp_reduce(exp->data.b.lhs, &output, &input, frame, defs);
540 while (psi_plist_top(input, &entry)) {
541 /* bail out if exp->op > entry.type */
542 if (psi_calc_oper(exp->op, entry.type) == -1) {
543 break;
544 }
545 psi_plist_pop(input, NULL);
546 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
547 output = psi_plist_add(output, &entry);
548 }
549 entry.type = exp->op;
550 entry.data.calc = exp->calc;
551 input = psi_plist_add(input, &entry);
552 psi_num_exp_reduce(exp->data.b.rhs, &output, &input, frame, defs);
553 break;
554 }
555
556 *output_ptr = output;
557 *input_ptr = input;
558 }
559
560 token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
561 struct psi_call_frame *frame, HashTable *defs)
562 {
563 struct psi_plist *output, *input;
564 struct element {
565 token_t type;
566 union {
567 impl_val value;
568 psi_calc calc;
569 struct psi_decl_type *cast;
570 } data;
571 } entry, lhs, rhs;
572
573 output = psi_plist_init_ex(sizeof(entry), NULL);
574 input = psi_plist_init_ex(sizeof(entry), NULL);
575
576 psi_num_exp_reduce(exp, &output, &input, frame, defs);
577
578 while (psi_plist_pop(input, &entry)) {
579 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
580 output = psi_plist_add(output, &entry);
581 }
582 if (frame) PSI_DEBUG_PRINT(frame->context, "%s", "\n");
583
584 while (psi_plist_shift(output, &entry)) {
585 switch (entry.type) {
586 default:
587 input = psi_plist_add(input, &entry);
588 break;
589
590 case PSI_T_CAST:
591 psi_plist_pop(input, &rhs);
592 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
593 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
594
595 entry.type = psi_decl_type_get_real(entry.data.cast)->type;
596 psi_calc_cast(rhs.type, &rhs.data.value, entry.type, &entry.data.value);
597 input = psi_plist_add(input, &entry);
598 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
599 break;
600
601 case PSI_T_NOT:
602 case PSI_T_TILDE:
603 psi_plist_pop(input, &rhs);
604 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
605 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
606
607 entry.type = entry.data.calc(rhs.type, &rhs.data.value, 0, NULL, &entry.data.value);
608 input = psi_plist_add(input, &entry);
609 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
610 break;
611
612 case PSI_T_OR:
613 case PSI_T_AND:
614
615 case PSI_T_CMP_EQ:
616 case PSI_T_CMP_NE:
617 case PSI_T_CMP_LE:
618 case PSI_T_CMP_GE:
619 case PSI_T_RCHEVR:
620 case PSI_T_LCHEVR:
621
622 case PSI_T_PIPE:
623 case PSI_T_CARET:
624 case PSI_T_AMPERSAND:
625 case PSI_T_LSHIFT:
626 case PSI_T_RSHIFT:
627 case PSI_T_MINUS:
628 case PSI_T_PLUS:
629 case PSI_T_ASTERISK:
630 case PSI_T_SLASH:
631 case PSI_T_MODULO:
632 psi_plist_pop(input, &rhs);
633 psi_plist_pop(input, &lhs);
634
635 psi_impl_val_dump(lhs.type, &lhs.data.value, frame);
636 if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
637 psi_impl_val_dump(rhs.type, &rhs.data.value, frame);
638
639 entry.type = entry.data.calc(
640 lhs.type, &lhs.data.value,
641 rhs.type, &rhs.data.value,
642 &entry.data.value);
643 input = psi_plist_add(input, &entry);
644 psi_num_exp_verify_result(entry.type, &entry.data.value, frame);
645 break;
646 }
647
648 if (!psi_plist_count(output)) {
649 break;
650 }
651 }
652
653 psi_plist_free(output);
654 psi_plist_free(input);
655
656 *res = entry.data.value;
657 return entry.type;
658 }
659