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 *******************************************************************************/
29 # include "php_config.h"
39 struct psi_num_exp
*psi_num_exp_init_ternary(token_t op
,
40 struct psi_num_exp
*cond
, struct psi_num_exp
*truthy
,
41 struct psi_num_exp
*falsy
)
43 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
46 exp
->data
.t
.cond
= cond
;
47 exp
->data
.t
.truthy
= truthy
;
48 exp
->data
.t
.falsy
= falsy
;
53 struct psi_num_exp
*psi_num_exp_init_binary(token_t op
,
54 struct psi_num_exp
*lhs
, struct psi_num_exp
*rhs
)
56 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
59 exp
->data
.b
.lhs
= lhs
;
60 exp
->data
.b
.rhs
= rhs
;
65 struct psi_num_exp
*psi_num_exp_init_unary(token_t op
,
66 struct psi_num_exp
*u
)
68 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
76 struct psi_num_exp
*psi_num_exp_init_num(struct psi_number
*n
)
78 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
80 exp
->op
= PSI_T_NUMBER
;
86 struct psi_num_exp
*psi_num_exp_init_cast(struct psi_decl_type
*typ
,
87 struct psi_num_exp
*num
)
89 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
92 exp
->data
.c
.typ
= typ
;
93 exp
->data
.c
.num
= num
;
98 struct psi_num_exp
*psi_num_exp_copy(struct psi_num_exp
*exp
)
100 struct psi_num_exp
*cpy
;
106 cpy
= pemalloc(sizeof(*cpy
), 1);
111 cpy
->data
.n
= psi_number_copy(exp
->data
.n
);
115 cpy
->data
.c
.typ
= psi_decl_type_copy(exp
->data
.c
.typ
);
116 cpy
->data
.c
.num
= psi_num_exp_copy(exp
->data
.c
.num
);
122 cpy
->data
.u
= psi_num_exp_copy(exp
->data
.u
);
137 case PSI_T_AMPERSAND
:
145 cpy
->data
.b
.lhs
= psi_num_exp_copy(exp
->data
.b
.lhs
);
146 cpy
->data
.b
.rhs
= psi_num_exp_copy(exp
->data
.b
.rhs
);
150 cpy
->data
.t
.cond
= psi_num_exp_copy(exp
->data
.t
.cond
);
151 cpy
->data
.t
.truthy
= psi_num_exp_copy(exp
->data
.t
.truthy
);
152 cpy
->data
.t
.falsy
= psi_num_exp_copy(exp
->data
.t
.falsy
);
160 cpy
->token
= psi_token_copy(exp
->token
);
166 void psi_num_exp_copy_ctor(struct psi_num_exp
**exp_ptr
)
168 *exp_ptr
= psi_num_exp_copy(*exp_ptr
);
171 void psi_num_exp_free(struct psi_num_exp
**c_ptr
)
174 struct psi_num_exp
*c
= *c_ptr
;
180 psi_number_free(&c
->data
.n
);
184 psi_decl_type_free(&c
->data
.c
.typ
);
185 psi_num_exp_free(&c
->data
.c
.num
);
191 psi_num_exp_free(&c
->data
.u
);
206 case PSI_T_AMPERSAND
:
214 psi_num_exp_free(&c
->data
.b
.lhs
);
215 psi_num_exp_free(&c
->data
.b
.rhs
);
219 psi_num_exp_free(&c
->data
.t
.cond
);
220 psi_num_exp_free(&c
->data
.t
.truthy
);
221 psi_num_exp_free(&c
->data
.t
.falsy
);
228 psi_token_free(&c
->token
);
234 static inline const char *psi_num_exp_op_tok(token_t op
)
250 case PSI_T_AMPERSAND
:
297 struct psi_plist
*psi_num_exp_tokens(struct psi_num_exp
*exp
,
298 struct psi_plist
*list
)
300 struct psi_token
*ntoken
;
303 list
= psi_plist_init((psi_plist_dtor
) psi_token_free
);
308 list
= psi_number_tokens(exp
->data
.n
, list
);
312 ntoken
= exp
->data
.c
.typ
->token
;
313 ntoken
= psi_token_init(PSI_T_LPAREN
, "(", 1, ntoken
->col
-1, ntoken
->line
, ntoken
->file
);
314 list
= psi_plist_add(list
, &ntoken
);
315 ntoken
= psi_token_copy(exp
->data
.c
.typ
->token
);
316 list
= psi_plist_add(list
, &ntoken
);
317 ntoken
= psi_token_init(PSI_T_RPAREN
, ")", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
318 list
= psi_plist_add(list
, &ntoken
);
324 ntoken
= psi_token_copy(exp
->token
);
325 list
= psi_plist_add(list
, &ntoken
);
326 list
= psi_num_exp_tokens(exp
->data
.u
, list
);
330 ntoken
= psi_token_copy(exp
->token
);
331 list
= psi_plist_add(list
, &ntoken
);
332 list
= psi_num_exp_tokens(exp
->data
.u
, list
);
333 psi_plist_top(list
, &ntoken
);
334 ntoken
= psi_token_init(PSI_T_RPAREN
, ")", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
335 list
= psi_plist_add(list
, &ntoken
);
340 if (!exp
->data
.b
.rhs
) {
346 case PSI_T_AMPERSAND
:
362 list
= psi_num_exp_tokens(exp
->data
.b
.lhs
, list
);
363 ntoken
= psi_token_copy(exp
->token
);
364 list
= psi_plist_add(list
, &ntoken
);
365 list
= psi_num_exp_tokens(exp
->data
.b
.rhs
, list
);
369 list
= psi_num_exp_tokens(exp
->data
.t
.cond
, list
);
370 ntoken
= psi_token_copy(exp
->token
);
371 list
= psi_plist_add(list
, &ntoken
);
372 list
= psi_num_exp_tokens(exp
->data
.t
.truthy
, list
);
373 psi_plist_top(list
, &ntoken
);
374 ntoken
= psi_token_init(PSI_T_COLON
, ":", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
375 list
= psi_plist_add(list
, &ntoken
);
376 list
= psi_plist_add(list
, &ntoken
);
377 list
= psi_num_exp_tokens(exp
->data
.t
.falsy
, list
);
387 void psi_num_exp_dump(struct psi_dump
*dump
, struct psi_num_exp
*exp
)
391 psi_number_dump(dump
, exp
->data
.n
);
396 psi_decl_type_dump(dump
, exp
->data
.c
.typ
, 0);
398 psi_num_exp_dump(dump
, exp
->data
.c
.num
);
404 PSI_DUMP(dump
, "%s", psi_num_exp_op_tok(exp
->op
));
405 psi_num_exp_dump(dump
, exp
->data
.u
);
410 psi_num_exp_dump(dump
, exp
->data
.u
);
416 if (!exp
->data
.b
.rhs
) {
422 case PSI_T_AMPERSAND
:
437 psi_num_exp_dump(dump
, exp
->data
.b
.lhs
);
438 PSI_DUMP(dump
, " %s ", psi_num_exp_op_tok(exp
->op
));
439 psi_num_exp_dump(dump
, exp
->data
.b
.rhs
);
443 psi_num_exp_dump(dump
, exp
->data
.t
.cond
);
444 PSI_DUMP(dump
, " ? ");
445 psi_num_exp_dump(dump
, exp
->data
.t
.truthy
);
446 PSI_DUMP(dump
, " : ");
447 psi_num_exp_dump(dump
, exp
->data
.t
.falsy
);
456 bool psi_num_exp_validate(struct psi_data
*data
, struct psi_num_exp
*exp
,
457 struct psi_validate_scope
*scope
)
459 if (exp
->op
&& exp
->op
!= PSI_T_NUMBER
) {
462 exp
->calc
= psi_calc_bool_not
;
465 exp
->calc
= psi_calc_bin_not
;
469 exp
->calc
= psi_calc_bool_or
;
472 exp
->calc
= psi_calc_bool_and
;
475 exp
->calc
= psi_calc_cmp_eq
;
478 exp
->calc
= psi_calc_cmp_ne
;
481 exp
->calc
= psi_calc_cmp_le
;
484 exp
->calc
= psi_calc_cmp_ge
;
487 exp
->calc
= psi_calc_cmp_lt
;
490 exp
->calc
= psi_calc_cmp_gt
;
499 exp
->calc
= psi_calc_bin_or
;
502 exp
->calc
= psi_calc_bin_xor
;
504 case PSI_T_AMPERSAND
:
505 exp
->calc
= psi_calc_bin_and
;
508 exp
->calc
= psi_calc_bin_lshift
;
511 exp
->calc
= psi_calc_bin_rshift
;
514 if (exp
->data
.b
.rhs
) {
515 exp
->calc
= psi_calc_add
;
519 if (exp
->data
.b
.rhs
) {
520 exp
->calc
= psi_calc_sub
;
522 exp
->calc
= psi_calc_minus
;
526 exp
->calc
= psi_calc_mul
;
529 exp
->calc
= psi_calc_div
;
532 exp
->calc
= psi_calc_mod
;
535 data
->error(data
, exp
->token
, PSI_WARNING
,
536 "Unknown numeric operator (%d)", exp
->op
);
543 return psi_number_validate(data
, exp
->data
.n
, scope
);
546 return psi_num_exp_validate(data
, exp
->data
.c
.num
, scope
)
547 && psi_decl_type_validate(data
, exp
->data
.c
.typ
, NULL
, scope
);
554 return psi_num_exp_validate(data
, exp
->data
.u
, scope
);
559 if (!exp
->data
.b
.rhs
) {
565 case PSI_T_AMPERSAND
:
581 return psi_num_exp_validate(data
, exp
->data
.b
.lhs
, scope
)
582 && psi_num_exp_validate(data
, exp
->data
.b
.rhs
, scope
);
585 return psi_num_exp_validate(data
, exp
->data
.t
.cond
, scope
)
586 && psi_num_exp_validate(data
, exp
->data
.t
.truthy
, scope
)
587 && psi_num_exp_validate(data
, exp
->data
.t
.falsy
, scope
);
596 static inline void psi_impl_val_dump(token_t t
, impl_val
*res
,
597 struct psi_call_frame
*frame
)
602 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi8
, res
->i8
);
606 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi16
, res
->i16
);
610 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi32
, res
->i32
);
614 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi64
, res
->i64
);
617 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIfval
, res
->fval
);
620 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIdval
, res
->dval
);
623 case PSI_T_LONG_DOUBLE
:
624 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIldval
, res
->ldval
);
632 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
634 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", " = ");
635 psi_impl_val_dump(t
, res
, frame
);
636 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
639 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
640 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
, struct psi_cpp
*cpp
)
642 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
648 struct psi_decl_type
*cast
;
654 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
, cpp
, exp
);
655 output
= psi_plist_add(output
, &entry
);
659 entry
.type
= exp
->op
;
660 input
= psi_plist_add(input
, &entry
);
661 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, cpp
);
662 while (psi_plist_pop(input
, &entry
)) {
663 if (entry
.type
== PSI_T_LPAREN
) {
666 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
667 output
= psi_plist_add(output
, &entry
);
672 while (psi_plist_top(input
, &entry
)) {
673 /* bail out if exp->op >= entry.type */
674 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
677 psi_plist_pop(input
, NULL
);
678 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
679 output
= psi_plist_add(output
, &entry
);
681 entry
.type
= exp
->op
;
682 entry
.data
.cast
= exp
->data
.c
.typ
;
683 input
= psi_plist_add(input
, &entry
);
684 psi_num_exp_reduce(exp
->data
.c
.num
, &output
, &input
, frame
, cpp
);
689 while (psi_plist_top(input
, &entry
)) {
690 /* bail out if exp->op >= entry.type */
691 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
694 psi_plist_pop(input
, NULL
);
695 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
696 output
= psi_plist_add(output
, &entry
);
698 entry
.type
= exp
->op
;
699 entry
.data
.calc
= exp
->calc
;
700 input
= psi_plist_add(input
, &entry
);
701 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, cpp
);
706 impl_val cond_val
= {0};
707 token_t cond_typ
= psi_num_exp_exec(exp
->data
.t
.cond
, &cond_val
, frame
, cpp
);
709 psi_calc_bool_not(cond_typ
, &cond_val
, 0, NULL
, &cond_val
);
711 psi_num_exp_reduce(exp
->data
.t
.falsy
, &output
, &input
, frame
, cpp
);
713 psi_num_exp_reduce(exp
->data
.t
.truthy
, &output
, &input
, frame
, cpp
);
721 if (!exp
->data
.b
.rhs
) {
722 entry
.type
= psi_num_exp_exec(exp
->data
.b
.lhs
, &entry
.data
.value
, frame
, cpp
);
725 entry
.type
= exp
->calc(entry
.type
, &entry
.data
.value
, 0, NULL
, &entry
.data
.value
);
727 output
= psi_plist_add(output
, &entry
);
732 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
, cpp
);
733 while (psi_plist_top(input
, &entry
)) {
734 /* bail out if exp->op > entry.type */
735 if (psi_calc_oper(exp
->op
, entry
.type
) == -1) {
738 psi_plist_pop(input
, NULL
);
739 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
740 output
= psi_plist_add(output
, &entry
);
742 entry
.type
= exp
->op
;
743 entry
.data
.calc
= exp
->calc
;
744 input
= psi_plist_add(input
, &entry
);
745 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
, cpp
);
749 *output_ptr
= output
;
753 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
754 struct psi_call_frame
*frame
, struct psi_cpp
*cpp
)
756 struct psi_plist
*output
, *input
;
762 struct psi_decl_type
*cast
;
766 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
767 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
769 psi_num_exp_reduce(exp
, &output
, &input
, frame
, cpp
);
771 while (psi_plist_pop(input
, &entry
)) {
772 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
773 output
= psi_plist_add(output
, &entry
);
775 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
777 while (psi_plist_shift(output
, &entry
)) {
778 switch (entry
.type
) {
780 input
= psi_plist_add(input
, &entry
);
784 psi_plist_pop(input
, &rhs
);
785 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
786 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
788 entry
.type
= psi_decl_type_get_real(entry
.data
.cast
)->type
;
789 psi_calc_cast(rhs
.type
, &rhs
.data
.value
, entry
.type
, &entry
.data
.value
);
790 input
= psi_plist_add(input
, &entry
);
791 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
796 psi_plist_pop(input
, &rhs
);
797 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
798 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
800 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
801 input
= psi_plist_add(input
, &entry
);
802 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
817 case PSI_T_AMPERSAND
:
825 psi_plist_pop(input
, &rhs
);
826 psi_plist_pop(input
, &lhs
);
828 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
829 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
830 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
832 entry
.type
= entry
.data
.calc(
833 lhs
.type
, &lhs
.data
.value
,
834 rhs
.type
, &rhs
.data
.value
,
836 input
= psi_plist_add(input
, &entry
);
837 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
841 if (!psi_plist_count(output
)) {
846 psi_plist_free(output
);
847 psi_plist_free(input
);
849 *res
= entry
.data
.value
;