X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Ftypes%2Fnumber.c;h=bc9d0a0faf6d23ae83e8e07ea69a2e93657b53fa;hp=c5f22d265eede95d680e3c74c0c6f563ec103c39;hb=ab7994dd2141b784e023b568230024571ec99517;hpb=42f44eb5bf4ecd36e26e051fada79d861d0f92d2 diff --git a/src/types/number.c b/src/types/number.c index c5f22d2..bc9d0a0 100644 --- a/src/types/number.c +++ b/src/types/number.c @@ -26,16 +26,22 @@ #include "php_psi_stdinc.h" #include +#include #include "data.h" #include "calc.h" #include "call.h" #include "parser.h" -struct psi_number *psi_number_init(token_t t, void *num) +#include "Zend/zend_constants.h" +#include "Zend/zend_operators.h" + + +struct psi_number *psi_number_init(token_t t, void *num, unsigned flags) { struct psi_number *exp = calloc(1, sizeof(*exp)); + exp->flags = flags; switch (exp->type = t) { case PSI_T_INT8: exp->data.ival.i8 = *(int8_t *) num; @@ -62,12 +68,18 @@ struct psi_number *psi_number_init(token_t t, void *num) exp->data.ival.u64 = *(uint64_t *) num; break; case PSI_T_FLOAT: - exp->data.ival.dval = *(float *) num; - exp->type = PSI_T_DOUBLE; + exp->data.ival.fval = *(float *) num; break; case PSI_T_DOUBLE: exp->data.ival.dval = *(double *) num; break; +#if HAVE_LONG_DOUBLE + case PSI_T_LONG_DOUBLE: + exp->data.ival.ldval = *(long double *) num; + break; +#endif + case PSI_T_NULL: + break; case PSI_T_QUOTED_CHAR: case PSI_T_NUMBER: case PSI_T_NSNAME: @@ -80,6 +92,9 @@ struct psi_number *psi_number_init(token_t t, void *num) case PSI_T_FUNCTION: exp->data.call = num; break; + case PSI_T_SIZEOF: + exp->data.dtyp = num; + break; default: assert(0); } @@ -105,9 +120,14 @@ struct psi_number *psi_number_copy(struct psi_number *exp) case PSI_T_UINT32: case PSI_T_INT64: case PSI_T_UINT64: + case PSI_T_FLOAT: case PSI_T_DOUBLE: +#if HAVE_LONG_DOUBLE + case PSI_T_LONG_DOUBLE: +#endif case PSI_T_ENUM: case PSI_T_CONST: + case PSI_T_NULL: break; case PSI_T_NUMBER: case PSI_T_NSNAME: @@ -121,6 +141,9 @@ struct psi_number *psi_number_copy(struct psi_number *exp) case PSI_T_FUNCTION: num->data.call = psi_cpp_macro_call_copy(num->data.call); break; + case PSI_T_SIZEOF: + num->data.dtyp = psi_decl_type_copy(num->data.dtyp); + break; default: assert(0); } @@ -145,9 +168,14 @@ void psi_number_free(struct psi_number **exp_ptr) case PSI_T_UINT32: case PSI_T_INT64: case PSI_T_UINT64: + case PSI_T_FLOAT: case PSI_T_DOUBLE: +#if HAVE_LONG_DOUBLE + case PSI_T_LONG_DOUBLE: +#endif case PSI_T_ENUM: case PSI_T_CONST: + case PSI_T_NULL: break; case PSI_T_FUNCTION: psi_cpp_macro_call_free(&exp->data.call); @@ -161,6 +189,9 @@ void psi_number_free(struct psi_number **exp_ptr) case PSI_T_NAME: psi_decl_var_free(&exp->data.dvar); break; + case PSI_T_SIZEOF: + psi_decl_type_free(&exp->data.dtyp); + break; default: assert(0); } @@ -168,6 +199,66 @@ void psi_number_free(struct psi_number **exp_ptr) } } +struct psi_plist *psi_number_tokens(struct psi_number *exp, + struct psi_plist *list) +{ + struct psi_token *ntoken; + if (!list) { + list = psi_plist_init((psi_plist_dtor) psi_token_free); + } + + switch (exp->type) { + case PSI_T_NAME: + /* decl_var */ + ntoken = psi_token_copy(exp->data.dvar->token); + + if (exp->data.dvar->pointer_level > 1 || !exp->data.dvar->array_size) { + struct psi_token *temp = ntoken; + unsigned pl = exp->data.dvar->pointer_level - !!exp->data.dvar->array_size; + + while (pl--) { + + ntoken = psi_token_init(PSI_T_POINTER, "*", 1, ntoken->col+ntoken->size, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + } + ntoken = temp; + } + + list = psi_plist_add(list, &ntoken); + + if (exp->data.dvar->array_size) { + char buf[0x20], *ptr; + + ntoken = psi_token_init(PSI_T_LBRACKET, "[", 1, ntoken->col+ntoken->size, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + ptr = zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], exp->data.dvar->array_size); + + ntoken = psi_token_init(PSI_T_NUMBER, ptr, strlen(ptr), ntoken->col+ntoken->size, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + } + break; + + case PSI_T_SIZEOF: + /* decl_type */ + ntoken = psi_token_copy(exp->token); + list = psi_plist_add(list, &ntoken); + ntoken = psi_token_init(PSI_T_LPAREN, "(", 1, ntoken->col+ntoken->size, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + ntoken = psi_token_copy(exp->data.dtyp->token); + list = psi_plist_add(list, &ntoken); + ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->size, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + break; + + default: + ntoken = psi_token_copy(exp->token); + list = psi_plist_add(list, &ntoken); + break; + } + + return list; +} + void psi_number_dump(int fd, struct psi_number *exp) { switch (exp->type) { @@ -195,8 +286,37 @@ void psi_number_dump(int fd, struct psi_number *exp) case PSI_T_UINT64: dprintf(fd, "%" PRIu64, exp->data.ival.u64); break; + case PSI_T_FLOAT: + if (isinf(exp->data.ival.dval)) { + dprintf(fd, "\\INF"); + } else if (isnan(exp->data.ival.dval)) { + dprintf(fd, "\\NAN"); + } else { + dprintf(fd, "%" PRIfval, exp->data.ival.dval); + } + break; case PSI_T_DOUBLE: - dprintf(fd, "%F", exp->data.ival.dval); + if (isinf(exp->data.ival.dval)) { + dprintf(fd, "\\INF"); + } else if (isnan(exp->data.ival.dval)) { + dprintf(fd, "\\NAN"); + } else { + dprintf(fd, "%" PRIdval, exp->data.ival.dval); + } + break; +#if HAVE_LONG_DOUBLE + case PSI_T_LONG_DOUBLE: + if (isinfl(exp->data.ival.ldval)) { + dprintf(fd, "\\INF"); + } else if (isnanl(exp->data.ival.ldval)) { + dprintf(fd, "\\NAN"); + } else { + dprintf(fd, "%" PRIldval, exp->data.ival.ldval); + } + break; +#endif + case PSI_T_NULL: + dprintf(fd, "NULL"); break; case PSI_T_NUMBER: case PSI_T_NSNAME: @@ -204,6 +324,9 @@ void psi_number_dump(int fd, struct psi_number *exp) case PSI_T_QUOTED_CHAR: dprintf(fd, "%s", exp->data.numb); break; + case PSI_T_FUNCTION: + psi_cpp_macro_call_dump(fd, exp->data.call); + break; case PSI_T_CONST: dprintf(fd, "%s", exp->data.cnst->name); break; @@ -213,39 +336,238 @@ void psi_number_dump(int fd, struct psi_number *exp) case PSI_T_NAME: psi_decl_var_dump(fd, exp->data.dvar); break; + case PSI_T_SIZEOF: + dprintf(fd, "sizeof("); + psi_decl_type_dump(fd, exp->data.dtyp, 0); + dprintf(fd, ")"); + break; default: assert(0); } } -static inline bool psi_number_validate_enum(struct psi_data *data, struct psi_number *exp, - struct psi_decl_enum *enm) +static inline bool psi_number_validate_enum(struct psi_data *data, + struct psi_number *exp, struct psi_validate_scope *scope) { - size_t i = 0; - struct psi_decl_enum_item *itm; + if (scope && scope->current_enum) { + size_t i = 0; + struct psi_decl_enum_item *itm; + struct psi_decl_enum *enm; - while (psi_plist_get(enm->items, i++, &itm)) { - if (!strcmp(itm->name, exp->data.dvar->name)) { - psi_decl_var_free(&exp->data.dvar); - exp->type = PSI_T_ENUM; - exp->data.enm = itm; - return psi_number_validate(data, exp, NULL, NULL, NULL, NULL, enm); + enm = scope->current_enum; + + switch (exp->type) { + case PSI_T_NAME: + while (psi_plist_get(enm->items, i++, &itm)) { + if (!strcmp(itm->name, exp->data.dvar->name)) { + psi_decl_var_free(&exp->data.dvar); + exp->type = PSI_T_ENUM; + exp->data.enm = itm; + return psi_number_validate(data, exp, scope); + } + } + break; + + case PSI_T_DEFINE: + while (psi_plist_get(enm->items, i++, &itm)) { + if (!strcmp(itm->name, exp->data.numb)) { + free(exp->data.numb); + exp->type = PSI_T_ENUM; + exp->data.enm = itm; + return psi_number_validate(data, exp, scope); + } + } + break; + + default: + assert(0); } } - return false; } +static inline token_t validate_char(char *numb, impl_val *res, unsigned *lvl) +{ + char *endptr; + token_t typ = PSI_T_INT8; + + res->i8 = numb[0]; + endptr = &numb[1]; + + switch(res->i8) { + case '\\': + res->i8 = numb[1]; + endptr = &numb[2]; + + switch(res->i8) { + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': + res->i8 = strtol(&numb[1], &endptr, 8); + break; + + case 'x': + res->i8 = strtol(&numb[2], &endptr, 16); + break; + + case 'a': + res->i8 = '\a'; + break; + case 'b': + res->i8 = '\b'; + break; + case 'f': + res->i8 = '\f'; + break; + case 'n': + res->i8 = '\n'; + break; + case 'r': + res->i8 = '\r'; + break; + case 't': + res->i8 = '\t'; + break; + case 'v': + res->i8 = '\v'; + break; + default: + break; + } + break; + default: + break; + } + + /* more to grok? */ + if (*endptr) { + impl_val tmp_val = {0}; + token_t tmp_typ = validate_char(endptr, &tmp_val, lvl); + + if (!tmp_typ) { + return 0; + } + + res->i32 = res->i8 << (8 * *lvl); + typ = psi_calc_add(PSI_T_INT32, res, tmp_typ, &tmp_val, res); + } + + ++(*lvl); + + return typ; +} +static inline bool psi_number_validate_char(struct psi_data *data, struct psi_number *exp) +{ + impl_val val = {0}; + unsigned lvl = 1; + token_t typ = validate_char(exp->data.numb, &val, &lvl); + + if (!typ) { + return false; + } + + free(exp->data.numb); + exp->type = typ; + exp->data.ival = val; + return true; +} + +static inline bool psi_number_validate_number(struct psi_data *data, struct psi_number *exp) +{ + impl_val tmp = {0}; + + if (exp->flags) { + switch (exp->flags & 0x0f) { + case PSI_NUMBER_INT: + switch (exp->flags & 0x0f00) { + case PSI_NUMBER_L: + default: + tmp.i64 = strtol(exp->data.numb, NULL, 0); + free(exp->data.numb); + exp->type = PSI_T_INT64; + exp->data.ival.i64 = tmp.i64; + break; + case PSI_NUMBER_LL: + tmp.i64 = strtoll(exp->data.numb, NULL, 0); + free(exp->data.numb); + exp->type = PSI_T_INT64; + exp->data.ival.i64 = tmp.i64; + break; + case PSI_NUMBER_U: + case PSI_NUMBER_UL: + tmp.u64 = strtoul(exp->data.numb, NULL, 0); + free(exp->data.numb); + exp->type = PSI_T_UINT64; + exp->data.ival.u64 = tmp.u64; + break; + case PSI_NUMBER_ULL: + tmp.u64 = strtoull(exp->data.numb, NULL, 0); + free(exp->data.numb); + exp->type = PSI_T_UINT64; + exp->data.ival.u64 = tmp.u64; + break; + } + return true; + + case PSI_NUMBER_FLT: + switch (exp->flags & 0x0ff00) { + case PSI_NUMBER_F: + case PSI_NUMBER_DF: + tmp.fval = strtof(exp->data.numb, NULL); + free(exp->data.numb); + exp->type = PSI_T_FLOAT; + exp->data.ival.fval = tmp.fval; + break; + case PSI_NUMBER_L: + case PSI_NUMBER_DL: +#if HAVE_LONG_DOUBLE + tmp.ldval = strtold(exp->data.numb, NULL); + free(exp->data.numb); + exp->type = PSI_T_LONG_DOUBLE; + exp->data.ival.ldval = tmp.ldval; + break; +#endif + case PSI_NUMBER_DD: + default: + tmp.dval = strtod(exp->data.numb, NULL); + free(exp->data.numb); + exp->type = PSI_T_DOUBLE; + exp->data.ival.dval = tmp.dval; + break; + } + return true; + default: + assert(0); + break; + } + } else { + switch (is_numeric_string(exp->data.numb, strlen(exp->data.numb), (zend_long *) &tmp, (double *) &tmp, 1)) { + case IS_LONG: + free(exp->data.numb); + exp->type = PSI_T_INT64; + exp->data.ival.i64 = tmp.zend.lval; + return true; + + case IS_DOUBLE: + free(exp->data.numb); + exp->type = PSI_T_DOUBLE; + exp->data.ival.dval = tmp.dval; + return true; + } + } + data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)"); + return false; + +} bool psi_number_validate(struct psi_data *data, struct psi_number *exp, - struct psi_impl *impl, struct psi_decl *cb_decl, struct psi_let_exp *current_let, - struct psi_set_exp *current_set, struct psi_decl_enum *current_enum) + struct psi_validate_scope *scope) { size_t i = 0; - impl_val tmp = {0}; struct psi_const *cnst; struct psi_decl_enum *enm; switch (exp->type) { + case PSI_T_NULL: + exp->type = PSI_T_UINT8; + /* no break */ case PSI_T_CONST: case PSI_T_INT8: case PSI_T_UINT8: @@ -255,29 +577,32 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp, case PSI_T_UINT32: case PSI_T_INT64: case PSI_T_UINT64: + case PSI_T_FLOAT: case PSI_T_DOUBLE: +#if HAVE_LONG_DOUBLE + case PSI_T_LONG_DOUBLE: +#endif case PSI_T_ENUM: - case PSI_T_DEFINE: - case PSI_T_FUNCTION: return true; case PSI_T_NAME: - if (current_enum && psi_number_validate_enum(data, exp, current_enum)) { + if (scope && scope->defs && zend_hash_str_exists(scope->defs, exp->data.dvar->name, strlen(exp->data.dvar->name))) { + return true; + } + if (scope && scope->current_enum && psi_number_validate_enum(data, exp, scope)) { return true; } while (psi_plist_get(data->enums, i++, &enm)) { - if (psi_number_validate_enum(data, exp, enm)) { + struct psi_validate_scope enum_scope = *scope; + enum_scope.current_enum = enm; + if (psi_number_validate_enum(data, exp, &enum_scope)) { return true; } } if (exp->data.dvar->arg) { return true; } - if (psi_decl_var_validate(data, exp->data.dvar, impl ? impl->decl : NULL, - current_let, current_set)) { - return true; - } - if (cb_decl && psi_decl_var_validate(data, exp->data.dvar, cb_decl, NULL, NULL)) { + if (psi_decl_var_validate(data, exp->data.dvar, scope)) { return true; } data->error(data, exp->token, PSI_WARNING, @@ -285,7 +610,77 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp, exp->data.dvar->name); return false; + case PSI_T_FUNCTION: + if (scope && scope->defs && zend_hash_str_exists(scope->defs, exp->data.numb, strlen(exp->data.numb))) { + return true; + } + return false; + + case PSI_T_DEFINE: + if (scope && scope->defs && zend_hash_str_exists(scope->defs, exp->data.numb, strlen(exp->data.numb))) { + if (!scope->macro || strcmp(scope->macro->token->text, exp->data.numb)) { + return true; + } + /* #define foo foo */ + } + while (psi_plist_get(data->enums, i++, &enm)) { + struct psi_validate_scope enum_scope = *scope; + enum_scope.current_enum = enm; + if (psi_number_validate_enum(data, exp, &enum_scope)) { + return true; + } + } + return false; + + case PSI_T_SIZEOF: + if (psi_decl_type_validate(data, exp->data.dtyp, NULL, scope)) { + struct psi_decl_type *dtyp = exp->data.dtyp; + + exp->type = PSI_T_UINT64; + exp->data.ival.u64 = psi_decl_type_get_size(dtyp, NULL); + psi_decl_type_free(&dtyp); + return true; + } else { + struct psi_decl_type *dtyp = exp->data.dtyp; + + data->error(data, exp->token, PSI_WARNING, + "Cannot compute sizeof(%s) (%u)", dtyp->name, dtyp->type); + + exp->type = PSI_T_UINT8; + exp->data.ival.u8 = 0; + psi_decl_type_free(&dtyp); + } + break; + case PSI_T_NSNAME: + { + zval *zc; + + if (*exp->data.numb == '\\') { + zc = zend_get_constant_str(exp->data.numb + 1, strlen(exp->data.numb) - 1); + } else { + zc = zend_get_constant_str(exp->data.numb, strlen(exp->data.numb)); + } + + if (zc) { + switch (Z_TYPE_P(zc)) { + case IS_LONG: + free(exp->data.numb); + exp->type = PSI_T_INT64; + exp->data.ival.i64 = Z_LVAL_P(zc); + return true; + + case IS_DOUBLE: + free(exp->data.numb); + exp->type = PSI_T_DOUBLE; + exp->data.ival.dval = Z_DVAL_P(zc); + return true; + + default: + assert(0); + } + } + } while (psi_plist_get(data->consts, i++, &cnst)) { if (!strcmp(cnst->name, exp->data.numb)) { free(exp->data.numb); @@ -300,95 +695,10 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp, return false; case PSI_T_NUMBER: - switch (is_numeric_string(exp->data.numb, strlen(exp->data.numb), (zend_long *) &tmp, (double *) &tmp, 1)) { - case IS_LONG: - free(exp->data.numb); - exp->type = PSI_T_INT64; - exp->data.ival.i64 = tmp.zend.lval; - return true; - - case IS_DOUBLE: - free(exp->data.numb); - exp->type = PSI_T_DOUBLE; - exp->data.ival.dval = tmp.dval; - return true; - } - data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)"); - return false; + return psi_number_validate_number(data, exp); case PSI_T_QUOTED_CHAR: - /* FIXME L */ - tmp.i8 = exp->data.numb[1 + (*exp->data.numb == 'L')]; - switch(tmp.i8) { - case '\\': - tmp.i8 = exp->data.numb[2 + (*exp->data.numb == 'L')]; - switch(tmp.i8) { - case 'x': - tmp.i8 = strtol(&exp->data.numb[3 + (*exp->data.numb == 'L')], &exp->data.numb[strlen(exp->data.numb)-1], 16); - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = tmp.i8; - return true; - case '\'': - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = '\''; - return true; - case 'a': - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = '\a'; - return true; - case 'b': - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = '\b'; - return true; - case 'f': - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = '\f'; - return true; - case 'n': - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = '\n'; - return true; - case 'r': - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = '\r'; - return true; - case 't': - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = '\t'; - return true; - case 'v': - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = '\v'; - return true; - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': - tmp.i8 = strtol(&exp->data.numb[2 + (*exp->data.numb == 'L')], &exp->data.numb[strlen(exp->data.numb)-1], 8); - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = tmp.i8; - return true; - default: - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = tmp.i8; - return true; - } - break; - default: - free(exp->data.numb); - exp->type = PSI_T_INT8; - exp->data.ival.i8 = tmp.i8; - return true; - } - break; + return psi_number_validate_char(data, exp); default: assert(0); @@ -397,8 +707,6 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp, return false; } -#include "Zend/zend_constants.h" - static inline token_t psi_number_eval_constant(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame) { @@ -414,7 +722,7 @@ static inline token_t psi_number_eval_constant(struct psi_number *exp, 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); + if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%u)", exp->data.cnst->type->type); return 0; } } @@ -426,32 +734,47 @@ static inline token_t psi_number_eval_decl_var(struct psi_number *exp, impl_val *ref; struct psi_call_frame_symbol *sym; struct psi_decl_type *real; + struct psi_decl_var *var; 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); + var = exp->data.dvar; + real = psi_decl_type_get_real(var->arg->type); + size = psi_decl_arg_get_size(var->arg); + sym = psi_call_frame_fetch_symbol(frame, var); + ref = deref_impl_val(sym->ptr, var); memcpy(res, ref, size); + if (var->arg->var->pointer_level > var->pointer_level) { + switch (SIZEOF_VOID_P) { + case 4: + return PSI_T_INT32; + case 8: + return PSI_T_INT64; + default: + assert(0); + } + } return real->type; } static inline token_t psi_number_eval_define(struct psi_number *exp, - impl_val *res, HashTable *defs) + impl_val *res, HashTable *defs, struct psi_num_exp *rec_guard) { - struct psi_cpp_macro_decl *macro = zend_hash_str_find_ptr(defs, exp->data.numb, strlen(exp->data.numb)); - - //WHATT? - fprintf(stderr, "number_eval_define: %s %s(%p)\n", - exp->token->text, macro ? macro->token->text : "", macro); + if (defs) { + struct psi_cpp_macro_decl *macro; + macro = zend_hash_str_find_ptr(defs, exp->data.numb, strlen(exp->data.numb)); + if (macro && macro->exp && macro->exp != rec_guard) { + return psi_num_exp_exec(macro->exp, res, NULL, defs); + } + } res->u8 = 0; return PSI_T_UINT8; } -token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame, HashTable *defs) +token_t psi_number_eval(struct psi_number *exp, impl_val *res, + struct psi_call_frame *frame, HashTable *defs, struct psi_num_exp *rec_guard) { switch (exp->type) { case PSI_T_INT8: @@ -487,16 +810,32 @@ token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_f if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64); return PSI_T_UINT64; + case PSI_T_FLOAT: + *res = exp->data.ival; + if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval); + return exp->type; + case PSI_T_DOUBLE: *res = exp->data.ival; if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval); return exp->type; +#if HAVE_LONG_DOUBLE + case PSI_T_LONG_DOUBLE: + *res = exp->data.ival; + if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIldval, res->ldval); + return exp->type; +#endif + 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_NUMBER: + res->i64 = atol(exp->data.numb); + return PSI_T_INT64; + case PSI_T_CONST: return psi_number_eval_constant(exp, res, frame); @@ -504,7 +843,7 @@ token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_f return psi_number_eval_decl_var(exp, res, frame); case PSI_T_DEFINE: - return psi_number_eval_define(exp, res, defs); + return psi_number_eval_define(exp, res, defs, rec_guard); case PSI_T_FUNCTION: res->u8 = 0;