7d168c1a9782569cf80512ab397eaf712f5c4850
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"
40 struct psi_num_exp
*psi_num_exp_init_ternary(token_t op
,
41 struct psi_num_exp
*cond
, struct psi_num_exp
*truthy
,
42 struct psi_num_exp
*falsy
)
44 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
47 exp
->data
.t
.cond
= cond
;
48 exp
->data
.t
.truthy
= truthy
;
49 exp
->data
.t
.falsy
= falsy
;
54 struct psi_num_exp
*psi_num_exp_init_binary(token_t op
,
55 struct psi_num_exp
*lhs
, struct psi_num_exp
*rhs
)
57 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
60 exp
->data
.b
.lhs
= lhs
;
61 exp
->data
.b
.rhs
= rhs
;
66 struct psi_num_exp
*psi_num_exp_init_unary(token_t op
,
67 struct psi_num_exp
*u
)
69 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
77 struct psi_num_exp
*psi_num_exp_init_num(struct psi_number
*n
)
79 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
81 exp
->op
= PSI_T_NUMBER
;
87 struct psi_num_exp
*psi_num_exp_init_cast(struct psi_decl_type
*typ
,
88 struct psi_num_exp
*num
)
90 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
93 exp
->data
.c
.typ
= typ
;
94 exp
->data
.c
.num
= num
;
99 struct psi_num_exp
*psi_num_exp_copy(struct psi_num_exp
*exp
)
101 struct psi_num_exp
*cpy
;
107 cpy
= pemalloc(sizeof(*cpy
), 1);
112 cpy
->data
.n
= psi_number_copy(exp
->data
.n
);
116 cpy
->data
.c
.typ
= psi_decl_type_copy(exp
->data
.c
.typ
);
117 cpy
->data
.c
.num
= psi_num_exp_copy(exp
->data
.c
.num
);
123 cpy
->data
.u
= psi_num_exp_copy(exp
->data
.u
);
138 case PSI_T_AMPERSAND
:
146 cpy
->data
.b
.lhs
= psi_num_exp_copy(exp
->data
.b
.lhs
);
147 cpy
->data
.b
.rhs
= psi_num_exp_copy(exp
->data
.b
.rhs
);
151 cpy
->data
.t
.cond
= psi_num_exp_copy(exp
->data
.t
.cond
);
152 cpy
->data
.t
.truthy
= psi_num_exp_copy(exp
->data
.t
.truthy
);
153 cpy
->data
.t
.falsy
= psi_num_exp_copy(exp
->data
.t
.falsy
);
161 cpy
->token
= psi_token_copy(exp
->token
);
167 void psi_num_exp_copy_ctor(struct psi_num_exp
**exp_ptr
)
169 *exp_ptr
= psi_num_exp_copy(*exp_ptr
);
172 void psi_num_exp_free(struct psi_num_exp
**c_ptr
)
175 struct psi_num_exp
*c
= *c_ptr
;
181 psi_number_free(&c
->data
.n
);
185 psi_decl_type_free(&c
->data
.c
.typ
);
186 psi_num_exp_free(&c
->data
.c
.num
);
192 psi_num_exp_free(&c
->data
.u
);
207 case PSI_T_AMPERSAND
:
215 psi_num_exp_free(&c
->data
.b
.lhs
);
216 psi_num_exp_free(&c
->data
.b
.rhs
);
220 psi_num_exp_free(&c
->data
.t
.cond
);
221 psi_num_exp_free(&c
->data
.t
.truthy
);
222 psi_num_exp_free(&c
->data
.t
.falsy
);
229 psi_token_free(&c
->token
);
235 static inline const char *psi_num_exp_op_tok(token_t op
)
251 case PSI_T_AMPERSAND
:
298 struct psi_plist
*psi_num_exp_tokens(struct psi_num_exp
*exp
,
299 struct psi_plist
*list
)
301 struct psi_token
*ntoken
;
304 list
= psi_plist_init((psi_plist_dtor
) psi_token_free
);
309 list
= psi_number_tokens(exp
->data
.n
, list
);
313 ntoken
= exp
->data
.c
.typ
->token
;
314 ntoken
= psi_token_init(PSI_T_LPAREN
, "(", 1, ntoken
->col
-1, ntoken
->line
, ntoken
->file
);
315 list
= psi_plist_add(list
, &ntoken
);
316 ntoken
= psi_token_copy(exp
->data
.c
.typ
->token
);
317 list
= psi_plist_add(list
, &ntoken
);
318 ntoken
= psi_token_init(PSI_T_RPAREN
, ")", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
319 list
= psi_plist_add(list
, &ntoken
);
325 ntoken
= psi_token_copy(exp
->token
);
326 list
= psi_plist_add(list
, &ntoken
);
327 list
= psi_num_exp_tokens(exp
->data
.u
, list
);
331 ntoken
= psi_token_copy(exp
->token
);
332 list
= psi_plist_add(list
, &ntoken
);
333 list
= psi_num_exp_tokens(exp
->data
.u
, list
);
334 psi_plist_top(list
, &ntoken
);
335 ntoken
= psi_token_init(PSI_T_RPAREN
, ")", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
336 list
= psi_plist_add(list
, &ntoken
);
341 if (!exp
->data
.b
.rhs
) {
347 case PSI_T_AMPERSAND
:
363 list
= psi_num_exp_tokens(exp
->data
.b
.lhs
, list
);
364 ntoken
= psi_token_copy(exp
->token
);
365 list
= psi_plist_add(list
, &ntoken
);
366 list
= psi_num_exp_tokens(exp
->data
.b
.rhs
, list
);
370 list
= psi_num_exp_tokens(exp
->data
.t
.cond
, list
);
371 ntoken
= psi_token_copy(exp
->token
);
372 list
= psi_plist_add(list
, &ntoken
);
373 list
= psi_num_exp_tokens(exp
->data
.t
.truthy
, list
);
374 psi_plist_top(list
, &ntoken
);
375 ntoken
= psi_token_init(PSI_T_COLON
, ":", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
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 if (!psi_number_validate(data
, exp
->data
.n
, scope
)) {
545 struct psi_dump dump
= {{.hn
= &str
},
546 .fun
= (psi_dump_cb
) psi_smart_str_printf
};
548 psi_num_exp_dump(&dump
, exp
);
550 data
->error(data
, exp
->token
, PSI_WARNING
,
551 "Invalid numeric expression: '%s'",
558 return psi_num_exp_validate(data
, exp
->data
.c
.num
, scope
)
559 && psi_decl_type_validate(data
, exp
->data
.c
.typ
, NULL
, scope
);
566 return psi_num_exp_validate(data
, exp
->data
.u
, scope
);
571 if (!exp
->data
.b
.rhs
) {
577 case PSI_T_AMPERSAND
:
593 return psi_num_exp_validate(data
, exp
->data
.b
.lhs
, scope
)
594 && psi_num_exp_validate(data
, exp
->data
.b
.rhs
, scope
);
597 return psi_num_exp_validate(data
, exp
->data
.t
.cond
, scope
)
598 && psi_num_exp_validate(data
, exp
->data
.t
.truthy
, scope
)
599 && psi_num_exp_validate(data
, exp
->data
.t
.falsy
, scope
);
608 static inline void psi_impl_val_dump(token_t t
, impl_val
*res
,
609 struct psi_call_frame
*frame
)
614 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi8
, res
->i8
);
618 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi16
, res
->i16
);
622 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi32
, res
->i32
);
626 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi64
, res
->i64
);
629 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIfval
, res
->fval
);
632 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIdval
, res
->dval
);
635 case PSI_T_LONG_DOUBLE
:
636 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIldval
, res
->ldval
);
644 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
646 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", " = ");
647 psi_impl_val_dump(t
, res
, frame
);
648 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
651 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
652 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
, struct psi_cpp
*cpp
)
654 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
660 struct psi_decl_type
*cast
;
666 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
, cpp
, exp
);
667 output
= psi_plist_add(output
, &entry
);
671 entry
.type
= exp
->op
;
672 input
= psi_plist_add(input
, &entry
);
673 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, cpp
);
674 while (psi_plist_pop(input
, &entry
)) {
675 if (entry
.type
== PSI_T_LPAREN
) {
678 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
679 output
= psi_plist_add(output
, &entry
);
684 while (psi_plist_top(input
, &entry
)) {
685 /* bail out if exp->op >= entry.type */
686 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
689 psi_plist_pop(input
, NULL
);
690 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
691 output
= psi_plist_add(output
, &entry
);
693 entry
.type
= exp
->op
;
694 entry
.data
.cast
= exp
->data
.c
.typ
;
695 input
= psi_plist_add(input
, &entry
);
696 psi_num_exp_reduce(exp
->data
.c
.num
, &output
, &input
, frame
, cpp
);
701 while (psi_plist_top(input
, &entry
)) {
702 /* bail out if exp->op >= entry.type */
703 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
706 psi_plist_pop(input
, NULL
);
707 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
708 output
= psi_plist_add(output
, &entry
);
710 entry
.type
= exp
->op
;
711 entry
.data
.calc
= exp
->calc
;
712 input
= psi_plist_add(input
, &entry
);
713 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, cpp
);
718 impl_val cond_val
= {0};
719 token_t cond_typ
= psi_num_exp_exec(exp
->data
.t
.cond
, &cond_val
, frame
, cpp
);
721 psi_calc_bool_not(cond_typ
, &cond_val
, 0, NULL
, &cond_val
);
723 psi_num_exp_reduce(exp
->data
.t
.falsy
, &output
, &input
, frame
, cpp
);
725 psi_num_exp_reduce(exp
->data
.t
.truthy
, &output
, &input
, frame
, cpp
);
733 if (!exp
->data
.b
.rhs
) {
734 entry
.type
= psi_num_exp_exec(exp
->data
.b
.lhs
, &entry
.data
.value
, frame
, cpp
);
737 entry
.type
= exp
->calc(entry
.type
, &entry
.data
.value
, 0, NULL
, &entry
.data
.value
);
739 output
= psi_plist_add(output
, &entry
);
744 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
, cpp
);
745 while (psi_plist_top(input
, &entry
)) {
746 /* bail out if exp->op > entry.type */
747 if (psi_calc_oper(exp
->op
, entry
.type
) == -1) {
750 psi_plist_pop(input
, NULL
);
751 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
752 output
= psi_plist_add(output
, &entry
);
754 entry
.type
= exp
->op
;
755 entry
.data
.calc
= exp
->calc
;
756 input
= psi_plist_add(input
, &entry
);
757 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
, cpp
);
761 *output_ptr
= output
;
765 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
766 struct psi_call_frame
*frame
, struct psi_cpp
*cpp
)
768 struct psi_plist
*output
, *input
;
774 struct psi_decl_type
*cast
;
778 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
779 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
781 psi_num_exp_reduce(exp
, &output
, &input
, frame
, cpp
);
783 while (psi_plist_pop(input
, &entry
)) {
784 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
785 output
= psi_plist_add(output
, &entry
);
787 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
789 while (psi_plist_shift(output
, &entry
)) {
790 switch (entry
.type
) {
792 input
= psi_plist_add(input
, &entry
);
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
= psi_decl_type_get_real(entry
.data
.cast
)->type
;
801 psi_calc_cast(rhs
.type
, &rhs
.data
.value
, entry
.type
, &entry
.data
.value
);
802 input
= psi_plist_add(input
, &entry
);
803 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
808 psi_plist_pop(input
, &rhs
);
809 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
810 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
812 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
813 input
= psi_plist_add(input
, &entry
);
814 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
829 case PSI_T_AMPERSAND
:
837 psi_plist_pop(input
, &rhs
);
838 psi_plist_pop(input
, &lhs
);
840 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
841 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
842 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
844 entry
.type
= entry
.data
.calc(
845 lhs
.type
, &lhs
.data
.value
,
846 rhs
.type
, &rhs
.data
.value
,
848 input
= psi_plist_add(input
, &entry
);
849 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
853 if (!psi_plist_count(output
)) {
858 psi_plist_free(output
);
859 psi_plist_free(input
);
861 *res
= entry
.data
.value
;