1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
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.
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 *******************************************************************************/
26 #include "php_psi_stdinc.h"
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
)
39 struct psi_num_exp
*exp
= calloc(1, sizeof(*exp
));
42 exp
->data
.t
.cond
= cond
;
43 exp
->data
.t
.truthy
= truthy
;
44 exp
->data
.t
.falsy
= falsy
;
49 struct psi_num_exp
*psi_num_exp_init_binary(token_t op
,
50 struct psi_num_exp
*lhs
, struct psi_num_exp
*rhs
)
52 struct psi_num_exp
*exp
= calloc(1, sizeof(*exp
));
55 exp
->data
.b
.lhs
= lhs
;
56 exp
->data
.b
.rhs
= rhs
;
61 struct psi_num_exp
*psi_num_exp_init_unary(token_t op
,
62 struct psi_num_exp
*u
)
64 struct psi_num_exp
*exp
= calloc(1, sizeof(*exp
));
72 struct psi_num_exp
*psi_num_exp_init_num(struct psi_number
*n
)
74 struct psi_num_exp
*exp
= calloc(1, sizeof(*exp
));
76 exp
->op
= PSI_T_NUMBER
;
82 struct psi_num_exp
*psi_num_exp_init_cast(struct psi_decl_type
*typ
,
83 struct psi_num_exp
*num
)
85 struct psi_num_exp
*exp
= calloc(1, sizeof(*exp
));
88 exp
->data
.c
.typ
= typ
;
89 exp
->data
.c
.num
= num
;
94 struct psi_num_exp
*psi_num_exp_copy(struct psi_num_exp
*exp
)
96 struct psi_num_exp
*cpy
;
102 cpy
= malloc(sizeof(*cpy
));
107 cpy
->data
.n
= psi_number_copy(exp
->data
.n
);
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
);
118 cpy
->data
.u
= psi_num_exp_copy(exp
->data
.u
);
133 case PSI_T_AMPERSAND
:
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
);
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
);
156 cpy
->token
= psi_token_copy(exp
->token
);
162 void psi_num_exp_free(struct psi_num_exp
**c_ptr
)
165 struct psi_num_exp
*c
= *c_ptr
;
171 psi_number_free(&c
->data
.n
);
175 psi_decl_type_free(&c
->data
.c
.typ
);
176 psi_num_exp_free(&c
->data
.c
.num
);
182 psi_num_exp_free(&c
->data
.u
);
197 case PSI_T_AMPERSAND
:
205 psi_num_exp_free(&c
->data
.b
.lhs
);
206 psi_num_exp_free(&c
->data
.b
.rhs
);
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
);
227 static inline const char *psi_num_exp_op_tok(token_t op
)
243 case PSI_T_AMPERSAND
:
290 struct psi_plist
*psi_num_exp_tokens(struct psi_num_exp
*exp
,
291 struct psi_plist
*list
)
293 struct psi_token
*ntoken
;
295 list
= psi_plist_init((psi_plist_dtor
) psi_token_free
);
300 list
= psi_number_tokens(exp
->data
.n
, list
);
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
);
316 ntoken
= psi_token_copy(exp
->token
);
317 list
= psi_plist_add(list
, &ntoken
);
318 list
= psi_num_exp_tokens(exp
->data
.u
, list
);
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
);
332 if (!exp
->data
.b
.rhs
) {
338 case PSI_T_AMPERSAND
:
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
);
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
);
379 void psi_num_exp_dump(int fd
, struct psi_num_exp
*exp
)
383 psi_number_dump(fd
, exp
->data
.n
);
388 psi_decl_type_dump(1, exp
->data
.c
.typ
, 0);
395 dprintf(fd
, "%s", psi_num_exp_op_tok(exp
->op
));
396 psi_num_exp_dump(fd
, exp
->data
.u
);
401 psi_num_exp_dump(fd
, exp
->data
.u
);
407 if (!exp
->data
.b
.rhs
) {
413 case PSI_T_AMPERSAND
:
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
);
434 psi_num_exp_dump(fd
, exp
->data
.t
.cond
);
436 psi_num_exp_dump(fd
, exp
->data
.t
.truthy
);
438 psi_num_exp_dump(fd
, exp
->data
.t
.falsy
);
447 bool psi_num_exp_validate(struct psi_data
*data
, struct psi_num_exp
*exp
,
448 struct psi_validate_scope
*scope
)
450 if (exp
->op
&& exp
->op
!= PSI_T_NUMBER
) {
453 exp
->calc
= psi_calc_bool_not
;
456 exp
->calc
= psi_calc_bin_not
;
460 exp
->calc
= psi_calc_bool_or
;
463 exp
->calc
= psi_calc_bool_and
;
466 exp
->calc
= psi_calc_cmp_eq
;
469 exp
->calc
= psi_calc_cmp_ne
;
472 exp
->calc
= psi_calc_cmp_le
;
475 exp
->calc
= psi_calc_cmp_ge
;
478 exp
->calc
= psi_calc_cmp_lt
;
481 exp
->calc
= psi_calc_cmp_gt
;
490 exp
->calc
= psi_calc_bin_or
;
493 exp
->calc
= psi_calc_bin_xor
;
495 case PSI_T_AMPERSAND
:
496 exp
->calc
= psi_calc_bin_and
;
499 exp
->calc
= psi_calc_bin_lshift
;
502 exp
->calc
= psi_calc_bin_rshift
;
505 if (exp
->data
.b
.rhs
) {
506 exp
->calc
= psi_calc_add
;
510 if (exp
->data
.b
.rhs
) {
511 exp
->calc
= psi_calc_sub
;
513 exp
->calc
= psi_calc_minus
;
517 exp
->calc
= psi_calc_mul
;
520 exp
->calc
= psi_calc_div
;
523 exp
->calc
= psi_calc_mod
;
526 data
->error(data
, exp
->token
, PSI_WARNING
,
527 "Unknown numeric operator (%d)", exp
->op
);
534 return psi_number_validate(data
, exp
->data
.n
, scope
);
537 return psi_num_exp_validate(data
, exp
->data
.c
.num
, scope
)
538 && psi_decl_type_validate(data
, exp
->data
.c
.typ
, NULL
, scope
);
545 return psi_num_exp_validate(data
, exp
->data
.u
, scope
);
550 if (!exp
->data
.b
.rhs
) {
556 case PSI_T_AMPERSAND
:
572 return psi_num_exp_validate(data
, exp
->data
.b
.lhs
, scope
)
573 && psi_num_exp_validate(data
, exp
->data
.b
.rhs
, scope
);
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
);
587 static inline void psi_impl_val_dump(token_t t
, impl_val
*res
,
588 struct psi_call_frame
*frame
)
593 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi8
, res
->i8
);
597 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi16
, res
->i16
);
601 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi32
, res
->i32
);
605 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi64
, res
->i64
);
608 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIfval
, res
->fval
);
611 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIdval
, res
->dval
);
614 case PSI_T_LONG_DOUBLE
:
615 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIldval
, res
->ldval
);
623 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
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");
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
)
633 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
639 struct psi_decl_type
*cast
;
645 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
, defs
, exp
);
646 output
= psi_plist_add(output
, &entry
);
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
) {
657 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
658 output
= psi_plist_add(output
, &entry
);
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) {
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
);
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
);
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) {
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
);
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
);
697 impl_val cond_val
= {0};
698 token_t cond_typ
= psi_num_exp_exec(exp
->data
.t
.cond
, &cond_val
, frame
, defs
);
700 psi_calc_bool_not(cond_typ
, &cond_val
, 0, NULL
, &cond_val
);
702 psi_num_exp_reduce(exp
->data
.t
.falsy
, &output
, &input
, frame
, defs
);
704 psi_num_exp_reduce(exp
->data
.t
.truthy
, &output
, &input
, frame
, defs
);
712 if (!exp
->data
.b
.rhs
) {
713 entry
.type
= psi_num_exp_exec(exp
->data
.b
.lhs
, &entry
.data
.value
, frame
, defs
);
716 entry
.type
= exp
->calc(entry
.type
, &entry
.data
.value
, 0, NULL
, &entry
.data
.value
);
718 output
= psi_plist_add(output
, &entry
);
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) {
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
);
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
);
740 *output_ptr
= output
;
744 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
745 struct psi_call_frame
*frame
, HashTable
*defs
)
747 struct psi_plist
*output
, *input
;
753 struct psi_decl_type
*cast
;
757 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
758 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
760 psi_num_exp_reduce(exp
, &output
, &input
, frame
, defs
);
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
);
766 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
768 while (psi_plist_shift(output
, &entry
)) {
769 switch (entry
.type
) {
771 input
= psi_plist_add(input
, &entry
);
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
);
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
);
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
);
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
);
808 case PSI_T_AMPERSAND
:
816 psi_plist_pop(input
, &rhs
);
817 psi_plist_pop(input
, &lhs
);
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
);
823 entry
.type
= entry
.data
.calc(
824 lhs
.type
, &lhs
.data
.value
,
825 rhs
.type
, &rhs
.data
.value
,
827 input
= psi_plist_add(input
, &entry
);
828 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
832 if (!psi_plist_count(output
)) {
837 psi_plist_free(output
);
838 psi_plist_free(input
);
840 *res
= entry
.data
.value
;