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_not
;
296 exp
->calc
= psi_calc_bin_not
;
300 exp
->calc
= psi_calc_or
;
303 exp
->calc
= psi_calc_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 inline int psi_num_exp_op_cmp(token_t op1
, token_t op2
)
443 if (PSI_T_LPAREN
== op2
) {
445 } else if (PSI_T_LPAREN
== op1
) {
447 } else if (op1
== op2
) {
455 return psi_token_oper_cmp(op1
, op2
);
458 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
459 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
)
461 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
472 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
);
473 output
= psi_plist_add(output
, &entry
);
477 entry
.type
= exp
->op
;
478 input
= psi_plist_add(input
, &entry
);
479 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
);
480 while (psi_plist_pop(input
, &entry
)) {
481 if (entry
.type
== PSI_T_LPAREN
) {
484 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
485 output
= psi_plist_add(output
, &entry
);
491 while (psi_plist_top(input
, &entry
)) {
492 /* bail out if exp->op >= entry.type */
493 if (psi_num_exp_op_cmp(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
.u
, &output
, &input
, frame
);
507 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
);
508 while (psi_plist_top(input
, &entry
)) {
509 /* bail out if exp->op > entry.type */
510 if (psi_num_exp_op_cmp(exp
->op
, entry
.type
) == -1) {
513 psi_plist_pop(input
, NULL
);
514 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
515 output
= psi_plist_add(output
, &entry
);
517 entry
.type
= exp
->op
;
518 entry
.data
.calc
= exp
->calc
;
519 input
= psi_plist_add(input
, &entry
);
520 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
);
524 *output_ptr
= output
;
528 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
529 struct psi_call_frame
*frame
)
531 struct psi_plist
*output
, *input
;
540 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
541 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
543 psi_num_exp_reduce(exp
, &output
, &input
, frame
);
545 while (psi_plist_pop(input
, &entry
)) {
546 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
547 output
= psi_plist_add(output
, &entry
);
549 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
551 while (psi_plist_shift(output
, &entry
)) {
552 switch (entry
.type
) {
554 input
= psi_plist_add(input
, &entry
);
559 psi_plist_pop(input
, &rhs
);
560 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
561 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
563 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
564 input
= psi_plist_add(input
, &entry
);
565 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
580 case PSI_T_AMPERSAND
:
588 psi_plist_pop(input
, &rhs
);
589 psi_plist_pop(input
, &lhs
);
591 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
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
= entry
.data
.calc(
596 lhs
.type
, &lhs
.data
.value
,
597 rhs
.type
, &rhs
.data
.value
,
599 input
= psi_plist_add(input
, &entry
);
600 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
604 if (!psi_plist_count(output
)) {
609 psi_plist_free(output
);
610 psi_plist_free(input
);
612 *res
= entry
.data
.value
;