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
);
100 cpy
->data
.b
.lhs
= psi_num_exp_copy(exp
->data
.b
.lhs
);
101 cpy
->data
.b
.rhs
= psi_num_exp_copy(exp
->data
.b
.rhs
);
109 cpy
->token
= psi_token_copy(exp
->token
);
115 void psi_num_exp_free(struct psi_num_exp
**c_ptr
)
118 struct psi_num_exp
*c
= *c_ptr
;
124 psi_number_free(&c
->data
.n
);
129 psi_num_exp_free(&c
->data
.u
);
134 case PSI_T_AMPERSAND
:
142 psi_num_exp_free(&c
->data
.b
.lhs
);
143 psi_num_exp_free(&c
->data
.b
.rhs
);
158 static inline wint_t psi_num_exp_op_tok(token_t op
)
172 case PSI_T_AMPERSAND
:
198 void psi_num_exp_dump(int fd
, struct psi_num_exp
*exp
)
202 psi_number_dump(fd
, exp
->data
.n
);
207 dprintf(fd
, "%lc", psi_num_exp_op_tok(exp
->op
));
208 psi_num_exp_dump(fd
, exp
->data
.u
);
213 psi_num_exp_dump(fd
, exp
->data
.u
);
219 case PSI_T_AMPERSAND
:
226 psi_num_exp_dump(fd
, exp
->data
.b
.lhs
);
227 dprintf(fd
, " %lc ", psi_num_exp_op_tok(exp
->op
));
228 psi_num_exp_dump(fd
, exp
->data
.b
.rhs
);
237 bool psi_num_exp_validate(struct psi_data
*data
, struct psi_num_exp
*exp
,
238 struct psi_impl
*impl
, struct psi_decl
*cb_decl
, struct psi_let_exp
*current_let
,
239 struct psi_set_exp
*current_set
, struct psi_decl_enum
*current_enum
)
244 exp
->calc
= psi_calc_not
;
247 exp
->calc
= psi_calc_bin_not
;
254 exp
->calc
= psi_calc_bin_or
;
257 exp
->calc
= psi_calc_bin_xor
;
259 case PSI_T_AMPERSAND
:
260 exp
->calc
= psi_calc_bin_and
;
263 exp
->calc
= psi_calc_bin_lshift
;
266 exp
->calc
= psi_calc_bin_rshift
;
269 exp
->calc
= psi_calc_add
;
272 exp
->calc
= psi_calc_sub
;
275 exp
->calc
= psi_calc_mul
;
278 exp
->calc
= psi_calc_div
;
281 exp
->calc
= psi_calc_mod
;
284 data
->error(data
, exp
->token
, PSI_WARNING
,
285 "Unknown numeric operator (%d)", exp
->op
);
292 return psi_number_validate(data
, exp
->data
.n
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
297 return psi_num_exp_validate(data
, exp
->data
.u
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
302 case PSI_T_AMPERSAND
:
310 return psi_num_exp_validate(data
, exp
->data
.b
.lhs
, impl
, cb_decl
, current_let
, current_set
, current_enum
)
311 && psi_num_exp_validate(data
, exp
->data
.b
.rhs
, impl
, cb_decl
, current_let
, current_set
, current_enum
);
319 static inline void psi_impl_val_dump(token_t t
, impl_val
*res
,
320 struct psi_call_frame
*frame
)
325 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi8
, res
->i8
);
329 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi16
, res
->i16
);
333 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi32
, res
->i32
);
337 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi64
, res
->i64
);
340 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIfval
, res
->fval
);
343 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIdval
, res
->dval
);
349 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
351 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", " = ");
352 psi_impl_val_dump(t
, res
, frame
);
353 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
356 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
357 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
)
359 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
370 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
);
371 output
= psi_plist_add(output
, &entry
);
375 entry
.type
= exp
->op
;
376 input
= psi_plist_add(input
, &entry
);
377 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
);
378 while (psi_plist_pop(input
, &entry
)) {
379 if (entry
.type
== PSI_T_LPAREN
) {
382 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %lc", psi_num_exp_op_tok(entry
.type
));
383 output
= psi_plist_add(output
, &entry
);
389 while (psi_plist_top(input
, &entry
)) {
390 /* bail out if exp->op >= entry.type */
391 if (psi_num_exp_op_cmp(exp
->op
, entry
.type
) != 1) {
394 psi_plist_pop(input
, NULL
);
395 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %lc", psi_num_exp_op_tok(entry
.type
));
396 output
= psi_plist_add(output
, &entry
);
398 entry
.type
= exp
->op
;
399 entry
.data
.calc
= exp
->calc
;
400 input
= psi_plist_add(input
, &entry
);
401 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
);
405 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
);
406 while (psi_plist_top(input
, &entry
)) {
407 /* bail out if exp->op > entry.type */
408 if (psi_num_exp_op_cmp(exp
->op
, entry
.type
) == -1) {
411 psi_plist_pop(input
, NULL
);
412 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %lc", psi_num_exp_op_tok(entry
.type
));
413 output
= psi_plist_add(output
, &entry
);
415 entry
.type
= exp
->op
;
416 entry
.data
.calc
= exp
->calc
;
417 input
= psi_plist_add(input
, &entry
);
418 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
);
422 *output_ptr
= output
;
426 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
427 struct psi_call_frame
*frame
)
429 struct psi_plist
*output
, *input
;
438 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
439 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
441 psi_num_exp_reduce(exp
, &output
, &input
, frame
);
443 while (psi_plist_pop(input
, &entry
)) {
444 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %lc", psi_num_exp_op_tok(entry
.type
));
445 output
= psi_plist_add(output
, &entry
);
447 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
449 while (psi_plist_shift(output
, &entry
)) {
450 switch (entry
.type
) {
452 input
= psi_plist_add(input
, &entry
);
457 psi_plist_pop(input
, &rhs
);
458 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %lc", psi_num_exp_op_tok(entry
.type
));
459 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
461 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
462 input
= psi_plist_add(input
, &entry
);
463 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
468 case PSI_T_AMPERSAND
:
476 psi_plist_pop(input
, &rhs
);
477 psi_plist_pop(input
, &lhs
);
479 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
480 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %lc", psi_num_exp_op_tok(entry
.type
));
481 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
483 entry
.type
= entry
.data
.calc(
484 lhs
.type
, &lhs
.data
.value
,
485 rhs
.type
, &rhs
.data
.value
,
487 input
= psi_plist_add(input
, &entry
);
488 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
492 if (!psi_plist_count(output
)) {
497 *res
= entry
.data
.value
;