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 void psi_num_exp_dump(int fd
, struct psi_num_exp
*exp
)
294 psi_number_dump(fd
, exp
->data
.n
);
299 dprintf(fd
, "%s", psi_num_exp_op_tok(exp
->op
));
300 psi_num_exp_dump(fd
, exp
->data
.u
);
305 psi_num_exp_dump(fd
, exp
->data
.u
);
322 case PSI_T_AMPERSAND
:
329 psi_num_exp_dump(fd
, exp
->data
.b
.lhs
);
330 dprintf(fd
, " %s ", psi_num_exp_op_tok(exp
->op
));
331 psi_num_exp_dump(fd
, exp
->data
.b
.rhs
);
335 psi_num_exp_dump(fd
, exp
->data
.t
.cond
);
337 psi_num_exp_dump(fd
, exp
->data
.t
.truthy
);
339 psi_num_exp_dump(fd
, exp
->data
.t
.falsy
);
348 bool psi_num_exp_validate(struct psi_data
*data
, struct psi_num_exp
*exp
,
349 struct psi_impl
*impl
, struct psi_decl
*cb_decl
, struct psi_let_exp
*current_let
,
350 struct psi_set_exp
*current_set
, struct psi_decl_enum
*current_enum
)
352 if (exp
->op
&& exp
->op
!= PSI_T_NUMBER
) {
355 exp
->calc
= psi_calc_bool_not
;
358 exp
->calc
= psi_calc_bin_not
;
362 exp
->calc
= psi_calc_bool_or
;
365 exp
->calc
= psi_calc_bool_and
;
368 exp
->calc
= psi_calc_cmp_eq
;
371 exp
->calc
= psi_calc_cmp_ne
;
374 exp
->calc
= psi_calc_cmp_le
;
377 exp
->calc
= psi_calc_cmp_ge
;
380 exp
->calc
= psi_calc_cmp_lt
;
383 exp
->calc
= psi_calc_cmp_gt
;
392 exp
->calc
= psi_calc_bin_or
;
395 exp
->calc
= psi_calc_bin_xor
;
397 case PSI_T_AMPERSAND
:
398 exp
->calc
= psi_calc_bin_and
;
401 exp
->calc
= psi_calc_bin_lshift
;
404 exp
->calc
= psi_calc_bin_rshift
;
407 exp
->calc
= psi_calc_add
;
410 exp
->calc
= psi_calc_sub
;
413 exp
->calc
= psi_calc_mul
;
416 exp
->calc
= psi_calc_div
;
419 exp
->calc
= psi_calc_mod
;
422 data
->error(data
, exp
->token
, PSI_WARNING
,
423 "Unknown numeric operator (%d)", exp
->op
);
430 return psi_number_validate(data
, exp
->data
.n
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
433 return psi_num_exp_validate(data
, exp
->data
.c
.num
, impl
, cb_decl
, current_let
, current_set
, current_enum
)
434 && psi_decl_type_validate(data
, exp
->data
.c
.typ
, 0, NULL
);
440 return psi_num_exp_validate(data
, exp
->data
.u
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
455 case PSI_T_AMPERSAND
:
463 return psi_num_exp_validate(data
, exp
->data
.b
.lhs
, impl
, cb_decl
, current_let
, current_set
, current_enum
)
464 && psi_num_exp_validate(data
, exp
->data
.b
.rhs
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
467 return psi_num_exp_validate(data
, exp
->data
.t
.cond
, impl
, cb_decl
, current_let
, current_set
, current_enum
)
468 && psi_num_exp_validate(data
, exp
->data
.t
.truthy
, impl
, cb_decl
, current_let
, current_set
, current_enum
)
469 && psi_num_exp_validate(data
, exp
->data
.t
.falsy
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
478 static inline void psi_impl_val_dump(token_t t
, impl_val
*res
,
479 struct psi_call_frame
*frame
)
484 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi8
, res
->i8
);
488 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi16
, res
->i16
);
492 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi32
, res
->i32
);
496 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi64
, res
->i64
);
499 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIfval
, res
->fval
);
502 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIdval
, res
->dval
);
505 case PSI_T_LONG_DOUBLE
:
506 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIldval
, res
->ldval
);
514 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
516 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", " = ");
517 psi_impl_val_dump(t
, res
, frame
);
518 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
521 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
522 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
, HashTable
*defs
)
524 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
530 struct psi_decl_type
*cast
;
536 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
, defs
);
537 output
= psi_plist_add(output
, &entry
);
541 entry
.type
= exp
->op
;
542 input
= psi_plist_add(input
, &entry
);
543 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
544 while (psi_plist_pop(input
, &entry
)) {
545 if (entry
.type
== PSI_T_LPAREN
) {
548 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
549 output
= psi_plist_add(output
, &entry
);
554 while (psi_plist_top(input
, &entry
)) {
555 /* bail out if exp->op >= entry.type */
556 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
559 psi_plist_pop(input
, NULL
);
560 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
561 output
= psi_plist_add(output
, &entry
);
563 entry
.type
= exp
->op
;
564 entry
.data
.cast
= exp
->data
.c
.typ
;
565 input
= psi_plist_add(input
, &entry
);
566 psi_num_exp_reduce(exp
->data
.c
.num
, &output
, &input
, frame
, defs
);
571 while (psi_plist_top(input
, &entry
)) {
572 /* bail out if exp->op >= entry.type */
573 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
576 psi_plist_pop(input
, NULL
);
577 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
578 output
= psi_plist_add(output
, &entry
);
580 entry
.type
= exp
->op
;
581 entry
.data
.calc
= exp
->calc
;
582 input
= psi_plist_add(input
, &entry
);
583 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
588 impl_val cond_val
= {0};
589 token_t cond_typ
= psi_num_exp_exec(exp
->data
.t
.cond
, &cond_val
, frame
, defs
);
591 psi_calc_bool_not(cond_typ
, &cond_val
, 0, NULL
, &cond_val
);
593 psi_num_exp_reduce(exp
->data
.t
.falsy
, &output
, &input
, frame
, defs
);
595 psi_num_exp_reduce(exp
->data
.t
.truthy
, &output
, &input
, frame
, defs
);
601 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
, defs
);
602 while (psi_plist_top(input
, &entry
)) {
603 /* bail out if exp->op > entry.type */
604 if (psi_calc_oper(exp
->op
, entry
.type
) == -1) {
607 psi_plist_pop(input
, NULL
);
608 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
609 output
= psi_plist_add(output
, &entry
);
611 entry
.type
= exp
->op
;
612 entry
.data
.calc
= exp
->calc
;
613 input
= psi_plist_add(input
, &entry
);
614 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
, defs
);
618 *output_ptr
= output
;
622 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
623 struct psi_call_frame
*frame
, HashTable
*defs
)
625 struct psi_plist
*output
, *input
;
631 struct psi_decl_type
*cast
;
635 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
636 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
638 psi_num_exp_reduce(exp
, &output
, &input
, frame
, defs
);
640 while (psi_plist_pop(input
, &entry
)) {
641 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
642 output
= psi_plist_add(output
, &entry
);
644 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
646 while (psi_plist_shift(output
, &entry
)) {
647 switch (entry
.type
) {
649 input
= psi_plist_add(input
, &entry
);
653 psi_plist_pop(input
, &rhs
);
654 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
655 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
657 entry
.type
= psi_decl_type_get_real(entry
.data
.cast
)->type
;
658 psi_calc_cast(rhs
.type
, &rhs
.data
.value
, entry
.type
, &entry
.data
.value
);
659 input
= psi_plist_add(input
, &entry
);
660 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
665 psi_plist_pop(input
, &rhs
);
666 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
667 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
669 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
670 input
= psi_plist_add(input
, &entry
);
671 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
686 case PSI_T_AMPERSAND
:
694 psi_plist_pop(input
, &rhs
);
695 psi_plist_pop(input
, &lhs
);
697 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
698 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
699 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
701 entry
.type
= entry
.data
.calc(
702 lhs
.type
, &lhs
.data
.value
,
703 rhs
.type
, &rhs
.data
.value
,
705 input
= psi_plist_add(input
, &entry
);
706 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
710 if (!psi_plist_count(output
)) {
715 psi_plist_free(output
);
716 psi_plist_free(input
);
718 *res
= entry
.data
.value
;