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
);
509 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
511 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", " = ");
512 psi_impl_val_dump(t
, res
, frame
);
513 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
516 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
517 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
, HashTable
*defs
)
519 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
525 struct psi_decl_type
*cast
;
531 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
, defs
);
532 output
= psi_plist_add(output
, &entry
);
536 entry
.type
= exp
->op
;
537 input
= psi_plist_add(input
, &entry
);
538 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
539 while (psi_plist_pop(input
, &entry
)) {
540 if (entry
.type
== PSI_T_LPAREN
) {
543 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
544 output
= psi_plist_add(output
, &entry
);
549 while (psi_plist_top(input
, &entry
)) {
550 /* bail out if exp->op >= entry.type */
551 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
554 psi_plist_pop(input
, NULL
);
555 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
556 output
= psi_plist_add(output
, &entry
);
558 entry
.type
= exp
->op
;
559 entry
.data
.cast
= exp
->data
.c
.typ
;
560 input
= psi_plist_add(input
, &entry
);
561 psi_num_exp_reduce(exp
->data
.c
.num
, &output
, &input
, frame
, defs
);
566 while (psi_plist_top(input
, &entry
)) {
567 /* bail out if exp->op >= entry.type */
568 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
571 psi_plist_pop(input
, NULL
);
572 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
573 output
= psi_plist_add(output
, &entry
);
575 entry
.type
= exp
->op
;
576 entry
.data
.calc
= exp
->calc
;
577 input
= psi_plist_add(input
, &entry
);
578 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
583 impl_val cond_val
= {0};
584 token_t cond_typ
= psi_num_exp_exec(exp
->data
.t
.cond
, &cond_val
, frame
, defs
);
586 psi_calc_bool_not(cond_typ
, &cond_val
, 0, NULL
, &cond_val
);
588 psi_num_exp_reduce(exp
->data
.t
.falsy
, &output
, &input
, frame
, defs
);
590 psi_num_exp_reduce(exp
->data
.t
.truthy
, &output
, &input
, frame
, defs
);
596 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
, defs
);
597 while (psi_plist_top(input
, &entry
)) {
598 /* bail out if exp->op > entry.type */
599 if (psi_calc_oper(exp
->op
, entry
.type
) == -1) {
602 psi_plist_pop(input
, NULL
);
603 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
604 output
= psi_plist_add(output
, &entry
);
606 entry
.type
= exp
->op
;
607 entry
.data
.calc
= exp
->calc
;
608 input
= psi_plist_add(input
, &entry
);
609 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
, defs
);
613 *output_ptr
= output
;
617 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
618 struct psi_call_frame
*frame
, HashTable
*defs
)
620 struct psi_plist
*output
, *input
;
626 struct psi_decl_type
*cast
;
630 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
631 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
633 psi_num_exp_reduce(exp
, &output
, &input
, frame
, defs
);
635 while (psi_plist_pop(input
, &entry
)) {
636 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
637 output
= psi_plist_add(output
, &entry
);
639 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
641 while (psi_plist_shift(output
, &entry
)) {
642 switch (entry
.type
) {
644 input
= psi_plist_add(input
, &entry
);
648 psi_plist_pop(input
, &rhs
);
649 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
650 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
652 entry
.type
= psi_decl_type_get_real(entry
.data
.cast
)->type
;
653 psi_calc_cast(rhs
.type
, &rhs
.data
.value
, entry
.type
, &entry
.data
.value
);
654 input
= psi_plist_add(input
, &entry
);
655 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
660 psi_plist_pop(input
, &rhs
);
661 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
662 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
664 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
665 input
= psi_plist_add(input
, &entry
);
666 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
681 case PSI_T_AMPERSAND
:
689 psi_plist_pop(input
, &rhs
);
690 psi_plist_pop(input
, &lhs
);
692 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
693 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
694 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
696 entry
.type
= entry
.data
.calc(
697 lhs
.type
, &lhs
.data
.value
,
698 rhs
.type
, &rhs
.data
.value
,
700 input
= psi_plist_add(input
, &entry
);
701 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
705 if (!psi_plist_count(output
)) {
710 psi_plist_free(output
);
711 psi_plist_free(input
);
713 *res
= entry
.data
.value
;