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
));
68 struct psi_num_exp
*psi_num_exp_copy(struct psi_num_exp
*exp
)
70 struct psi_num_exp
*cpy
;
76 cpy
= malloc(sizeof(*cpy
));
81 cpy
->data
.n
= psi_number_copy(exp
->data
.n
);
87 cpy
->data
.u
= psi_num_exp_copy(exp
->data
.u
);
102 case PSI_T_AMPERSAND
:
110 cpy
->data
.b
.lhs
= psi_num_exp_copy(exp
->data
.b
.lhs
);
111 cpy
->data
.b
.rhs
= psi_num_exp_copy(exp
->data
.b
.rhs
);
119 cpy
->token
= psi_token_copy(exp
->token
);
125 void psi_num_exp_free(struct psi_num_exp
**c_ptr
)
128 struct psi_num_exp
*c
= *c_ptr
;
134 psi_number_free(&c
->data
.n
);
139 psi_num_exp_free(&c
->data
.u
);
154 case PSI_T_AMPERSAND
:
162 psi_num_exp_free(&c
->data
.b
.lhs
);
163 psi_num_exp_free(&c
->data
.b
.rhs
);
178 static inline const char *psi_num_exp_op_tok(token_t op
)
192 case PSI_T_AMPERSAND
:
236 void psi_num_exp_dump(int fd
, struct psi_num_exp
*exp
)
240 psi_number_dump(fd
, exp
->data
.n
);
245 dprintf(fd
, "%s", psi_num_exp_op_tok(exp
->op
));
246 psi_num_exp_dump(fd
, exp
->data
.u
);
251 psi_num_exp_dump(fd
, exp
->data
.u
);
268 case PSI_T_AMPERSAND
:
275 psi_num_exp_dump(fd
, exp
->data
.b
.lhs
);
276 dprintf(fd
, " %s ", psi_num_exp_op_tok(exp
->op
));
277 psi_num_exp_dump(fd
, exp
->data
.b
.rhs
);
286 bool psi_num_exp_validate(struct psi_data
*data
, struct psi_num_exp
*exp
,
287 struct psi_impl
*impl
, struct psi_decl
*cb_decl
, struct psi_let_exp
*current_let
,
288 struct psi_set_exp
*current_set
, struct psi_decl_enum
*current_enum
)
293 exp
->calc
= psi_calc_bool_not
;
296 exp
->calc
= psi_calc_bin_not
;
300 exp
->calc
= psi_calc_bool_or
;
303 exp
->calc
= psi_calc_bool_and
;
306 exp
->calc
= psi_calc_cmp_eq
;
309 exp
->calc
= psi_calc_cmp_ne
;
312 exp
->calc
= psi_calc_cmp_le
;
315 exp
->calc
= psi_calc_cmp_ge
;
318 exp
->calc
= psi_calc_cmp_lt
;
321 exp
->calc
= psi_calc_cmp_gt
;
328 exp
->calc
= psi_calc_bin_or
;
331 exp
->calc
= psi_calc_bin_xor
;
333 case PSI_T_AMPERSAND
:
334 exp
->calc
= psi_calc_bin_and
;
337 exp
->calc
= psi_calc_bin_lshift
;
340 exp
->calc
= psi_calc_bin_rshift
;
343 exp
->calc
= psi_calc_add
;
346 exp
->calc
= psi_calc_sub
;
349 exp
->calc
= psi_calc_mul
;
352 exp
->calc
= psi_calc_div
;
355 exp
->calc
= psi_calc_mod
;
358 data
->error(data
, exp
->token
, PSI_WARNING
,
359 "Unknown numeric operator (%d)", exp
->op
);
366 return psi_number_validate(data
, exp
->data
.n
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
371 return psi_num_exp_validate(data
, exp
->data
.u
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
386 case PSI_T_AMPERSAND
:
394 return psi_num_exp_validate(data
, exp
->data
.b
.lhs
, impl
, cb_decl
, current_let
, current_set
, current_enum
)
395 && psi_num_exp_validate(data
, exp
->data
.b
.rhs
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
403 static inline void psi_impl_val_dump(token_t t
, impl_val
*res
,
404 struct psi_call_frame
*frame
)
409 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi8
, res
->i8
);
413 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi16
, res
->i16
);
417 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi32
, res
->i32
);
421 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi64
, res
->i64
);
424 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIfval
, res
->fval
);
427 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIdval
, res
->dval
);
434 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
436 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", " = ");
437 psi_impl_val_dump(t
, res
, frame
);
438 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
441 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
442 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
, HashTable
*defs
)
444 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
455 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
, defs
);
456 output
= psi_plist_add(output
, &entry
);
460 entry
.type
= exp
->op
;
461 input
= psi_plist_add(input
, &entry
);
462 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
463 while (psi_plist_pop(input
, &entry
)) {
464 if (entry
.type
== PSI_T_LPAREN
) {
467 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
468 output
= psi_plist_add(output
, &entry
);
474 while (psi_plist_top(input
, &entry
)) {
475 /* bail out if exp->op >= entry.type */
476 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
479 psi_plist_pop(input
, NULL
);
480 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
481 output
= psi_plist_add(output
, &entry
);
483 entry
.type
= exp
->op
;
484 entry
.data
.calc
= exp
->calc
;
485 input
= psi_plist_add(input
, &entry
);
486 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, defs
);
490 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
, defs
);
491 while (psi_plist_top(input
, &entry
)) {
492 /* bail out if exp->op > entry.type */
493 if (psi_calc_oper(exp
->op
, entry
.type
) == -1) {
496 psi_plist_pop(input
, NULL
);
497 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
498 output
= psi_plist_add(output
, &entry
);
500 entry
.type
= exp
->op
;
501 entry
.data
.calc
= exp
->calc
;
502 input
= psi_plist_add(input
, &entry
);
503 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
, defs
);
507 *output_ptr
= output
;
511 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
512 struct psi_call_frame
*frame
, HashTable
*defs
)
514 struct psi_plist
*output
, *input
;
523 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
524 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
526 psi_num_exp_reduce(exp
, &output
, &input
, frame
, defs
);
528 while (psi_plist_pop(input
, &entry
)) {
529 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
530 output
= psi_plist_add(output
, &entry
);
532 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
534 while (psi_plist_shift(output
, &entry
)) {
535 switch (entry
.type
) {
537 input
= psi_plist_add(input
, &entry
);
542 psi_plist_pop(input
, &rhs
);
543 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
544 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
546 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
547 input
= psi_plist_add(input
, &entry
);
548 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
563 case PSI_T_AMPERSAND
:
571 psi_plist_pop(input
, &rhs
);
572 psi_plist_pop(input
, &lhs
);
574 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
575 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
576 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
578 entry
.type
= entry
.data
.calc(
579 lhs
.type
, &lhs
.data
.value
,
580 rhs
.type
, &rhs
.data
.value
,
582 input
= psi_plist_add(input
, &entry
);
583 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
587 if (!psi_plist_count(output
)) {
592 psi_plist_free(output
);
593 psi_plist_free(input
);
595 *res
= entry
.data
.value
;