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
);
219 psi_token_free(&c
->token
);
225 static inline const char *psi_num_exp_op_tok(token_t op
)
241 case PSI_T_AMPERSAND
:
288 struct psi_plist
*psi_num_exp_tokens(struct psi_num_exp
*exp
,
289 struct psi_plist
*list
)
291 struct psi_token
*ntoken
;
293 list
= psi_plist_init((psi_plist_dtor
) psi_token_free
);
298 list
= psi_number_tokens(exp
->data
.n
, list
);
302 ntoken
= exp
->data
.c
.typ
->token
;
303 ntoken
= psi_token_init(PSI_T_LPAREN
, "(", 1, ntoken
->col
-1, ntoken
->line
, ntoken
->file
);
304 list
= psi_plist_add(list
, &ntoken
);
305 ntoken
= psi_token_copy(exp
->data
.c
.typ
->token
);
306 list
= psi_plist_add(list
, &ntoken
);
307 ntoken
= psi_token_init(PSI_T_RPAREN
, ")", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
308 list
= psi_plist_add(list
, &ntoken
);
314 ntoken
= psi_token_copy(exp
->token
);
315 list
= psi_plist_add(list
, &ntoken
);
316 list
= psi_num_exp_tokens(exp
->data
.u
, list
);
320 ntoken
= psi_token_copy(exp
->token
);
321 list
= psi_plist_add(list
, &ntoken
);
322 list
= psi_num_exp_tokens(exp
->data
.u
, list
);
323 psi_plist_top(list
, &ntoken
);
324 ntoken
= psi_token_init(PSI_T_RPAREN
, ")", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
325 list
= psi_plist_add(list
, &ntoken
);
330 if (!exp
->data
.b
.rhs
) {
336 case PSI_T_AMPERSAND
:
352 list
= psi_num_exp_tokens(exp
->data
.b
.lhs
, list
);
353 ntoken
= psi_token_copy(exp
->token
);
354 list
= psi_plist_add(list
, &ntoken
);
355 list
= psi_num_exp_tokens(exp
->data
.b
.rhs
, list
);
359 list
= psi_num_exp_tokens(exp
->data
.t
.cond
, list
);
360 ntoken
= psi_token_copy(exp
->token
);
361 list
= psi_plist_add(list
, &ntoken
);
362 list
= psi_num_exp_tokens(exp
->data
.t
.truthy
, list
);
363 psi_plist_top(list
, &ntoken
);
364 ntoken
= psi_token_init(PSI_T_COLON
, ":", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
365 list
= psi_plist_add(list
, &ntoken
);
366 list
= psi_plist_add(list
, &ntoken
);
367 list
= psi_num_exp_tokens(exp
->data
.t
.falsy
, list
);
377 void psi_num_exp_dump(int fd
, struct psi_num_exp
*exp
)
381 psi_number_dump(fd
, exp
->data
.n
);
386 psi_decl_type_dump(1, exp
->data
.c
.typ
, 0);
393 dprintf(fd
, "%s", psi_num_exp_op_tok(exp
->op
));
394 psi_num_exp_dump(fd
, exp
->data
.u
);
399 psi_num_exp_dump(fd
, exp
->data
.u
);
405 if (!exp
->data
.b
.rhs
) {
411 case PSI_T_AMPERSAND
:
426 psi_num_exp_dump(fd
, exp
->data
.b
.lhs
);
427 dprintf(fd
, " %s ", psi_num_exp_op_tok(exp
->op
));
428 psi_num_exp_dump(fd
, exp
->data
.b
.rhs
);
432 psi_num_exp_dump(fd
, exp
->data
.t
.cond
);
434 psi_num_exp_dump(fd
, exp
->data
.t
.truthy
);
436 psi_num_exp_dump(fd
, exp
->data
.t
.falsy
);
445 bool psi_num_exp_validate(struct psi_data
*data
, struct psi_num_exp
*exp
,
446 struct psi_validate_scope
*scope
)
448 if (exp
->op
&& exp
->op
!= PSI_T_NUMBER
) {
451 exp
->calc
= psi_calc_bool_not
;
454 exp
->calc
= psi_calc_bin_not
;
458 exp
->calc
= psi_calc_bool_or
;
461 exp
->calc
= psi_calc_bool_and
;
464 exp
->calc
= psi_calc_cmp_eq
;
467 exp
->calc
= psi_calc_cmp_ne
;
470 exp
->calc
= psi_calc_cmp_le
;
473 exp
->calc
= psi_calc_cmp_ge
;
476 exp
->calc
= psi_calc_cmp_lt
;
479 exp
->calc
= psi_calc_cmp_gt
;
488 exp
->calc
= psi_calc_bin_or
;
491 exp
->calc
= psi_calc_bin_xor
;
493 case PSI_T_AMPERSAND
:
494 exp
->calc
= psi_calc_bin_and
;
497 exp
->calc
= psi_calc_bin_lshift
;
500 exp
->calc
= psi_calc_bin_rshift
;
503 if (exp
->data
.b
.rhs
) {
504 exp
->calc
= psi_calc_add
;
508 if (exp
->data
.b
.rhs
) {
509 exp
->calc
= psi_calc_sub
;
511 exp
->calc
= psi_calc_minus
;
515 exp
->calc
= psi_calc_mul
;
518 exp
->calc
= psi_calc_div
;
521 exp
->calc
= psi_calc_mod
;
524 data
->error(data
, exp
->token
, PSI_WARNING
,
525 "Unknown numeric operator (%d)", exp
->op
);
532 return psi_number_validate(data
, exp
->data
.n
, scope
);
535 return psi_num_exp_validate(data
, exp
->data
.c
.num
, scope
)
536 && psi_decl_type_validate(data
, exp
->data
.c
.typ
, NULL
, scope
);
543 return psi_num_exp_validate(data
, exp
->data
.u
, scope
);
548 if (!exp
->data
.b
.rhs
) {
554 case PSI_T_AMPERSAND
:
570 return psi_num_exp_validate(data
, exp
->data
.b
.lhs
, scope
)
571 && psi_num_exp_validate(data
, exp
->data
.b
.rhs
, scope
);
574 return psi_num_exp_validate(data
, exp
->data
.t
.cond
, scope
)
575 && psi_num_exp_validate(data
, exp
->data
.t
.truthy
, scope
)
576 && psi_num_exp_validate(data
, exp
->data
.t
.falsy
, scope
);
585 static inline void psi_impl_val_dump(token_t t
, impl_val
*res
,
586 struct psi_call_frame
*frame
)
591 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi8
, res
->i8
);
595 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi16
, res
->i16
);
599 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi32
, res
->i32
);
603 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi64
, res
->i64
);
606 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIfval
, res
->fval
);
609 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIdval
, res
->dval
);
612 case PSI_T_LONG_DOUBLE
:
613 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIldval
, res
->ldval
);
621 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
623 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", " = ");
624 psi_impl_val_dump(t
, res
, frame
);
625 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
628 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
629 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
, HashTable
*defs
)
631 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
637 struct psi_decl_type
*cast
;
643 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
, defs
, exp
);
644 output
= psi_plist_add(output
, &entry
);
648 entry
.type
= exp
->op
;
649 input
= psi_plist_add(input
, &entry
);
650 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
651 while (psi_plist_pop(input
, &entry
)) {
652 if (entry
.type
== PSI_T_LPAREN
) {
655 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
656 output
= psi_plist_add(output
, &entry
);
661 while (psi_plist_top(input
, &entry
)) {
662 /* bail out if exp->op >= entry.type */
663 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
666 psi_plist_pop(input
, NULL
);
667 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
668 output
= psi_plist_add(output
, &entry
);
670 entry
.type
= exp
->op
;
671 entry
.data
.cast
= exp
->data
.c
.typ
;
672 input
= psi_plist_add(input
, &entry
);
673 psi_num_exp_reduce(exp
->data
.c
.num
, &output
, &input
, frame
, defs
);
678 while (psi_plist_top(input
, &entry
)) {
679 /* bail out if exp->op >= entry.type */
680 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
683 psi_plist_pop(input
, NULL
);
684 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
685 output
= psi_plist_add(output
, &entry
);
687 entry
.type
= exp
->op
;
688 entry
.data
.calc
= exp
->calc
;
689 input
= psi_plist_add(input
, &entry
);
690 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
695 impl_val cond_val
= {0};
696 token_t cond_typ
= psi_num_exp_exec(exp
->data
.t
.cond
, &cond_val
, frame
, defs
);
698 psi_calc_bool_not(cond_typ
, &cond_val
, 0, NULL
, &cond_val
);
700 psi_num_exp_reduce(exp
->data
.t
.falsy
, &output
, &input
, frame
, defs
);
702 psi_num_exp_reduce(exp
->data
.t
.truthy
, &output
, &input
, frame
, defs
);
710 if (!exp
->data
.b
.rhs
) {
711 entry
.type
= psi_num_exp_exec(exp
->data
.b
.lhs
, &entry
.data
.value
, frame
, defs
);
714 entry
.type
= exp
->calc(entry
.type
, &entry
.data
.value
, 0, NULL
, &entry
.data
.value
);
716 output
= psi_plist_add(output
, &entry
);
721 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
, defs
);
722 while (psi_plist_top(input
, &entry
)) {
723 /* bail out if exp->op > entry.type */
724 if (psi_calc_oper(exp
->op
, entry
.type
) == -1) {
727 psi_plist_pop(input
, NULL
);
728 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
729 output
= psi_plist_add(output
, &entry
);
731 entry
.type
= exp
->op
;
732 entry
.data
.calc
= exp
->calc
;
733 input
= psi_plist_add(input
, &entry
);
734 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
, defs
);
738 *output_ptr
= output
;
742 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
743 struct psi_call_frame
*frame
, HashTable
*defs
)
745 struct psi_plist
*output
, *input
;
751 struct psi_decl_type
*cast
;
755 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
756 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
758 psi_num_exp_reduce(exp
, &output
, &input
, frame
, defs
);
760 while (psi_plist_pop(input
, &entry
)) {
761 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
762 output
= psi_plist_add(output
, &entry
);
764 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
766 while (psi_plist_shift(output
, &entry
)) {
767 switch (entry
.type
) {
769 input
= psi_plist_add(input
, &entry
);
773 psi_plist_pop(input
, &rhs
);
774 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
775 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
777 entry
.type
= psi_decl_type_get_real(entry
.data
.cast
)->type
;
778 psi_calc_cast(rhs
.type
, &rhs
.data
.value
, entry
.type
, &entry
.data
.value
);
779 input
= psi_plist_add(input
, &entry
);
780 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
785 psi_plist_pop(input
, &rhs
);
786 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
787 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
789 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
790 input
= psi_plist_add(input
, &entry
);
791 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
806 case PSI_T_AMPERSAND
:
814 psi_plist_pop(input
, &rhs
);
815 psi_plist_pop(input
, &lhs
);
817 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
818 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
819 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
821 entry
.type
= entry
.data
.calc(
822 lhs
.type
, &lhs
.data
.value
,
823 rhs
.type
, &rhs
.data
.value
,
825 input
= psi_plist_add(input
, &entry
);
826 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
830 if (!psi_plist_count(output
)) {
835 psi_plist_free(output
);
836 psi_plist_free(input
);
838 *res
= entry
.data
.value
;