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"
36 struct psi_num_exp
*psi_num_exp_init_binary(token_t op
,
37 struct psi_num_exp
*lhs
, struct psi_num_exp
*rhs
)
39 struct psi_num_exp
*exp
= calloc(1, sizeof(*exp
));
42 exp
->data
.b
.lhs
= lhs
;
43 exp
->data
.b
.rhs
= rhs
;
48 struct psi_num_exp
*psi_num_exp_init_unary(token_t op
,
49 struct psi_num_exp
*u
)
51 struct psi_num_exp
*exp
= calloc(1, sizeof(*exp
));
59 struct psi_num_exp
*psi_num_exp_init_num(struct psi_number
*n
)
61 struct psi_num_exp
*exp
= calloc(1, sizeof(*exp
));
63 exp
->op
= PSI_T_NUMBER
;
69 struct psi_num_exp
*psi_num_exp_init_cast(struct psi_decl_type
*typ
,
70 struct psi_num_exp
*num
)
72 struct psi_num_exp
*exp
= calloc(1, sizeof(*exp
));
75 exp
->data
.c
.typ
= typ
;
76 exp
->data
.c
.num
= num
;
81 struct psi_num_exp
*psi_num_exp_copy(struct psi_num_exp
*exp
)
83 struct psi_num_exp
*cpy
;
89 cpy
= malloc(sizeof(*cpy
));
94 cpy
->data
.n
= psi_number_copy(exp
->data
.n
);
98 cpy
->data
.c
.typ
= psi_decl_type_copy(exp
->data
.c
.typ
);
99 cpy
->data
.c
.num
= psi_num_exp_copy(exp
->data
.c
.num
);
105 cpy
->data
.u
= psi_num_exp_copy(exp
->data
.u
);
120 case PSI_T_AMPERSAND
:
128 cpy
->data
.b
.lhs
= psi_num_exp_copy(exp
->data
.b
.lhs
);
129 cpy
->data
.b
.rhs
= psi_num_exp_copy(exp
->data
.b
.rhs
);
137 cpy
->token
= psi_token_copy(exp
->token
);
143 void psi_num_exp_free(struct psi_num_exp
**c_ptr
)
146 struct psi_num_exp
*c
= *c_ptr
;
152 psi_number_free(&c
->data
.n
);
156 psi_decl_type_free(&c
->data
.c
.typ
);
157 psi_num_exp_free(&c
->data
.c
.num
);
163 psi_num_exp_free(&c
->data
.u
);
178 case PSI_T_AMPERSAND
:
186 psi_num_exp_free(&c
->data
.b
.lhs
);
187 psi_num_exp_free(&c
->data
.b
.rhs
);
202 static inline const char *psi_num_exp_op_tok(token_t op
)
218 case PSI_T_AMPERSAND
:
262 void psi_num_exp_dump(int fd
, struct psi_num_exp
*exp
)
266 psi_number_dump(fd
, exp
->data
.n
);
271 dprintf(fd
, "%s", psi_num_exp_op_tok(exp
->op
));
272 psi_num_exp_dump(fd
, exp
->data
.u
);
277 psi_num_exp_dump(fd
, exp
->data
.u
);
294 case PSI_T_AMPERSAND
:
301 psi_num_exp_dump(fd
, exp
->data
.b
.lhs
);
302 dprintf(fd
, " %s ", psi_num_exp_op_tok(exp
->op
));
303 psi_num_exp_dump(fd
, exp
->data
.b
.rhs
);
312 bool psi_num_exp_validate(struct psi_data
*data
, struct psi_num_exp
*exp
,
313 struct psi_impl
*impl
, struct psi_decl
*cb_decl
, struct psi_let_exp
*current_let
,
314 struct psi_set_exp
*current_set
, struct psi_decl_enum
*current_enum
)
316 if (exp
->op
&& exp
->op
!= PSI_T_NUMBER
) {
319 exp
->calc
= psi_calc_bool_not
;
322 exp
->calc
= psi_calc_bin_not
;
326 exp
->calc
= psi_calc_bool_or
;
329 exp
->calc
= psi_calc_bool_and
;
332 exp
->calc
= psi_calc_cmp_eq
;
335 exp
->calc
= psi_calc_cmp_ne
;
338 exp
->calc
= psi_calc_cmp_le
;
341 exp
->calc
= psi_calc_cmp_ge
;
344 exp
->calc
= psi_calc_cmp_lt
;
347 exp
->calc
= psi_calc_cmp_gt
;
355 exp
->calc
= psi_calc_bin_or
;
358 exp
->calc
= psi_calc_bin_xor
;
360 case PSI_T_AMPERSAND
:
361 exp
->calc
= psi_calc_bin_and
;
364 exp
->calc
= psi_calc_bin_lshift
;
367 exp
->calc
= psi_calc_bin_rshift
;
370 exp
->calc
= psi_calc_add
;
373 exp
->calc
= psi_calc_sub
;
376 exp
->calc
= psi_calc_mul
;
379 exp
->calc
= psi_calc_div
;
382 exp
->calc
= psi_calc_mod
;
385 data
->error(data
, exp
->token
, PSI_WARNING
,
386 "Unknown numeric operator (%d)", exp
->op
);
393 return psi_number_validate(data
, exp
->data
.n
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
396 return psi_num_exp_validate(data
, exp
->data
.c
.num
, impl
, cb_decl
, current_let
, current_set
, current_enum
)
397 && psi_decl_type_validate(data
, exp
->data
.c
.typ
, NULL
);
403 return psi_num_exp_validate(data
, exp
->data
.u
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
418 case PSI_T_AMPERSAND
:
426 return psi_num_exp_validate(data
, exp
->data
.b
.lhs
, impl
, cb_decl
, current_let
, current_set
, current_enum
)
427 && psi_num_exp_validate(data
, exp
->data
.b
.rhs
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
435 static inline void psi_impl_val_dump(token_t t
, impl_val
*res
,
436 struct psi_call_frame
*frame
)
441 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi8
, res
->i8
);
445 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi16
, res
->i16
);
449 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi32
, res
->i32
);
453 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi64
, res
->i64
);
456 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIfval
, res
->fval
);
459 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIdval
, res
->dval
);
466 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
468 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", " = ");
469 psi_impl_val_dump(t
, res
, frame
);
470 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
473 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
474 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
, HashTable
*defs
)
476 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
482 struct psi_decl_type
*cast
;
488 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
, defs
);
489 output
= psi_plist_add(output
, &entry
);
493 entry
.type
= exp
->op
;
494 input
= psi_plist_add(input
, &entry
);
495 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
496 while (psi_plist_pop(input
, &entry
)) {
497 if (entry
.type
== PSI_T_LPAREN
) {
500 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
501 output
= psi_plist_add(output
, &entry
);
506 while (psi_plist_top(input
, &entry
)) {
507 /* bail out if exp->op >= entry.type */
508 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
511 psi_plist_pop(input
, NULL
);
512 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
513 output
= psi_plist_add(output
, &entry
);
515 entry
.type
= exp
->op
;
516 entry
.data
.cast
= exp
->data
.c
.typ
;
517 input
= psi_plist_add(input
, &entry
);
518 psi_num_exp_reduce(exp
->data
.c
.num
, &output
, &input
, frame
, defs
);
523 while (psi_plist_top(input
, &entry
)) {
524 /* bail out if exp->op >= entry.type */
525 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
528 psi_plist_pop(input
, NULL
);
529 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
530 output
= psi_plist_add(output
, &entry
);
532 entry
.type
= exp
->op
;
533 entry
.data
.calc
= exp
->calc
;
534 input
= psi_plist_add(input
, &entry
);
535 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
539 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
, defs
);
540 while (psi_plist_top(input
, &entry
)) {
541 /* bail out if exp->op > entry.type */
542 if (psi_calc_oper(exp
->op
, entry
.type
) == -1) {
545 psi_plist_pop(input
, NULL
);
546 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
547 output
= psi_plist_add(output
, &entry
);
549 entry
.type
= exp
->op
;
550 entry
.data
.calc
= exp
->calc
;
551 input
= psi_plist_add(input
, &entry
);
552 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
, defs
);
556 *output_ptr
= output
;
560 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
561 struct psi_call_frame
*frame
, HashTable
*defs
)
563 struct psi_plist
*output
, *input
;
569 struct psi_decl_type
*cast
;
573 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
574 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
576 psi_num_exp_reduce(exp
, &output
, &input
, frame
, defs
);
578 while (psi_plist_pop(input
, &entry
)) {
579 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
580 output
= psi_plist_add(output
, &entry
);
582 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
584 while (psi_plist_shift(output
, &entry
)) {
585 switch (entry
.type
) {
587 input
= psi_plist_add(input
, &entry
);
591 psi_plist_pop(input
, &rhs
);
592 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
593 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
595 entry
.type
= psi_decl_type_get_real(entry
.data
.cast
)->type
;
596 psi_calc_cast(rhs
.type
, &rhs
.data
.value
, entry
.type
, &entry
.data
.value
);
597 input
= psi_plist_add(input
, &entry
);
598 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
603 psi_plist_pop(input
, &rhs
);
604 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
605 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
607 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
608 input
= psi_plist_add(input
, &entry
);
609 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
624 case PSI_T_AMPERSAND
:
632 psi_plist_pop(input
, &rhs
);
633 psi_plist_pop(input
, &lhs
);
635 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
636 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
637 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
639 entry
.type
= entry
.data
.calc(
640 lhs
.type
, &lhs
.data
.value
,
641 rhs
.type
, &rhs
.data
.value
,
643 input
= psi_plist_add(input
, &entry
);
644 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
648 if (!psi_plist_count(output
)) {
653 psi_plist_free(output
);
654 psi_plist_free(input
);
656 *res
= entry
.data
.value
;