X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Ftypes%2Fnum_exp.c;h=88db742eb6df4329e293b5c15c6886eb8694c740;hp=7d752a376469fbc30e591bb81ef40dd9e69fa392;hb=7df12c88a4e14611a2585d6e7c994c59e8d7485a;hpb=8c3b5c915ddf11e03e595d7db8917b2b4711a35b diff --git a/src/types/num_exp.c b/src/types/num_exp.c index 7d752a3..88db742 100644 --- a/src/types/num_exp.c +++ b/src/types/num_exp.c @@ -114,6 +114,33 @@ void psi_num_exp_free(struct psi_num_exp **exp_ptr) } } +static inline wint_t psi_num_exp_op_tok(token_t op) +{ + switch (op) { + case PSI_T_LSHIFT: + return L'«'; + case PSI_T_RSHIFT: + return L'»'; + case PSI_T_PLUS: + return L'+'; + case PSI_T_MINUS: + return L'-'; + case PSI_T_ASTERISK: + return L'*'; + case PSI_T_SLASH: + return L'/'; + case PSI_T_AMPERSAND: + return L'&'; + case PSI_T_CARET: + return L'^'; + case PSI_T_PIPE: + return L'|'; + default: + assert(0); + } + return 0; +} + void psi_num_exp_dump(int fd, struct psi_num_exp *exp) { while (exp) { @@ -142,25 +169,7 @@ void psi_num_exp_dump(int fd, struct psi_num_exp *exp) } if (exp->operand) { - char op; - - switch (exp->op) { - case PSI_T_PLUS: - op = '+'; - break; - case PSI_T_MINUS: - op = '-'; - break; - case PSI_T_ASTERISK: - op = '*'; - break; - case PSI_T_SLASH: - op = '/'; - break; - default: - assert(0); - } - dprintf(fd, " %c ", op); + dprintf(fd, " %c ", psi_num_exp_op_tok(exp->op)); } exp = exp->operand; @@ -196,6 +205,12 @@ bool psi_num_exp_validate(struct psi_data *data, struct psi_num_exp *exp, if (exp->operand) { switch (exp->op) { + case PSI_T_LSHIFT: + exp->calc = psi_calc_bin_lshift; + break; + case PSI_T_RSHIFT: + exp->calc = psi_calc_bin_rshift; + break; case PSI_T_PLUS: exp->calc = psi_calc_add; break; @@ -208,6 +223,15 @@ bool psi_num_exp_validate(struct psi_data *data, struct psi_num_exp *exp, case PSI_T_SLASH: exp->calc = psi_calc_div; break; + case PSI_T_AMPERSAND: + exp->calc = psi_calc_bin_and; + break; + case PSI_T_CARET: + exp->calc = psi_calc_bin_xor; + break; + case PSI_T_PIPE: + exp->calc = psi_calc_bin_or; + break; default: data->error(data, exp->token, PSI_WARNING, "Unknown numeric operator (%d)", exp->op); @@ -297,46 +321,63 @@ static inline token_t psi_num_exp_eval_constant(struct psi_num_exp *exp, case PSI_T_INT: res->i64 = zend_get_constant_str(exp->data.cnst->name, strlen(exp->data.cnst->name))->value.lval; + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIi64, res->i64); return PSI_T_INT64; case PSI_T_FLOAT: res->dval = zend_get_constant_str(exp->data.cnst->name, strlen(exp->data.cnst->name))->value.dval; + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIdval, res->dval); return PSI_T_DOUBLE; default: + if (frame) PSI_DEBUG_PRINT(frame->context, "?(t=%d)", exp->data.cnst->type->type); return 0; } } -static inline token_t psi_num_exp_eval_decl_var(struct psi_num_exp *exp, - impl_val *res, struct psi_call_frame *frame) +static inline void psi_num_exp_verify_result(token_t t, impl_val *res, struct psi_call_frame *frame) { - impl_val *ref; - struct psi_call_frame_symbol *sym; - struct psi_decl_type *real; - size_t size; - - real = psi_decl_type_get_real(exp->data.dvar->arg->type); - size = psi_decl_arg_get_size(exp->data.dvar->arg); - sym = psi_call_frame_fetch_symbol(frame, exp->data.dvar); - ref = deref_impl_val(sym->ptr, exp->data.dvar); - - memcpy(res, ref, size); - - switch (real->type) { + switch (t) { case PSI_T_INT8: case PSI_T_UINT8: + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIi8, res->i8); + break; case PSI_T_INT16: case PSI_T_UINT16: + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIi16, res->i16); + break; case PSI_T_INT32: case PSI_T_UINT32: + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIi32, res->i32); + break; case PSI_T_INT64: case PSI_T_UINT64: + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIi64, res->i64); + break; case PSI_T_FLOAT: + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIfval, res->fval); + break; case PSI_T_DOUBLE: + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIdval, res->dval); break; default: assert(0); } +} + +static inline token_t psi_num_exp_eval_decl_var(struct psi_num_exp *exp, + impl_val *res, struct psi_call_frame *frame) +{ + impl_val *ref; + struct psi_call_frame_symbol *sym; + struct psi_decl_type *real; + size_t size; + + real = psi_decl_type_get_real(exp->data.dvar->arg->type); + size = psi_decl_arg_get_size(exp->data.dvar->arg); + sym = psi_call_frame_fetch_symbol(frame, exp->data.dvar); + ref = deref_impl_val(sym->ptr, exp->data.dvar); + + memcpy(res, ref, size); return real->type; } @@ -346,12 +387,18 @@ static inline token_t psi_num_exp_eval(struct psi_num_exp *exp, impl_val *res, { switch (exp->type) { case PSI_T_INT64: + *res = exp->data.ival; + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIi64, res->i64); + return PSI_T_INT64; + case PSI_T_DOUBLE: *res = exp->data.ival; + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIdval, res->dval); return exp->type; case PSI_T_ENUM: res->i64 = exp->data.enm->val; + if (frame) PSI_DEBUG_PRINT(frame->context, "%" PRIi64, res->i64); return PSI_T_INT64; case PSI_T_CONST: @@ -368,20 +415,79 @@ static inline token_t psi_num_exp_eval(struct psi_num_exp *exp, impl_val *res, return 0; } +#include "context.h" + +static inline int psi_num_exp_op_cmp(token_t op1, token_t op2) +{ + assert(op1 >= PSI_T_LSHIFT && op2 <= PSI_T_PIPE); + assert(op2 >= PSI_T_LSHIFT && op2 <= PSI_T_PIPE); + + switch (op1) { + case PSI_T_LSHIFT: + case PSI_T_RSHIFT: + return op2 > PSI_T_RSHIFT; + + case PSI_T_PLUS: + case PSI_T_MINUS: + return op2 > PSI_T_MINUS ? 1 : (op2 < PSI_T_PLUS ? -1 : 0); + + case PSI_T_ASTERISK: + case PSI_T_SLASH: + return op2 > PSI_T_SLASH ? 1 : (op2 < PSI_T_ASTERISK ? -1 : 0); + + case PSI_T_AMPERSAND: + case PSI_T_CARET: + case PSI_T_PIPE: + return -1 * (op2 < PSI_T_AMPERSAND); + } + + return 0; +} + token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res, struct psi_call_frame *frame) { impl_val num = {0}; - token_t num_type = psi_num_exp_eval(exp, &num, frame); + token_t num_type; + + num_type = psi_num_exp_eval(exp, &num, frame); - /* FIXME operator precedence */ if (exp->operand) { - impl_val tmp = {0}; - token_t tmp_type = psi_num_exp_exec(exp->operand, &tmp, frame); + impl_val rhs; + token_t rhs_type, res_type; + + /* only if there's a following op, and we have a higher precedence */ + if (exp->operand->operand && + psi_num_exp_op_cmp(exp->op, exp->operand->op) < 0) { + impl_val tmp, lhs; + token_t tmp_type, lhs_type; - return exp->calc(num_type, &num, tmp_type, &tmp, res); + if (frame) PSI_DEBUG_PRINT(frame->context, " %lc ", psi_num_exp_op_tok(exp->op)); + + tmp_type = psi_num_exp_eval(exp->operand, &tmp, frame); + lhs_type = exp->calc(num_type, &num, tmp_type, &tmp, &lhs); + + if (frame) PSI_DEBUG_PRINT(frame->context, " %c ", '='); + psi_num_exp_verify_result(lhs_type, &lhs, frame); + if (frame) PSI_DEBUG_PRINT(frame->context, " %c", '\n'); + + rhs_type = psi_num_exp_exec(exp->operand->operand, &rhs, frame); + res_type = exp->operand->calc(lhs_type, &lhs, rhs_type, &rhs, res); + } else { + if (frame) PSI_DEBUG_PRINT(frame->context, " %lc ", psi_num_exp_op_tok(exp->op)); + + rhs_type = psi_num_exp_exec(exp->operand, &rhs, frame); + res_type = exp->calc(num_type, &num, rhs_type, &rhs, res); + } + + if (frame) PSI_DEBUG_PRINT(frame->context, " %c ", '='); + psi_num_exp_verify_result(res_type, res, frame); + if (frame) PSI_DEBUG_PRINT(frame->context, " %c", '\n'); + + return res_type; } *res = num; + return num_type; }