commit da4de0c14b6791a1ba6f8e1dfb08f6d146882331 from: Omar Polo date: Wed Aug 04 13:14:40 2021 UTC implement casts commit - 8e0ef4cbb0ed60a2e1ee46aa071d23c82bce4657 commit + da4de0c14b6791a1ba6f8e1dfb08f6d146882331 blob - d48ec96d91eb7b46b4867dbb2d012d15234c1fc9 blob + c05a341d1b5e223431a9baa834770897fcb445cb --- script.c +++ script.c @@ -205,27 +205,33 @@ op_cast(struct op *expr, int totype) } void -pp_val(struct value *val) +ppf_val(FILE *f, struct value *val) { switch (val->type) { case V_SYM: - printf("%s", val->v.str); + fprintf(f, "%s", val->v.str); break; case V_STR: - printf("\"%s\"", val->v.str); + fprintf(f, "\"%s\"", val->v.str); break; case V_NUM: case V_U8: case V_U16: case V_U32: - printf("%"PRIu64, val->v.num); + fprintf(f, "%"PRIu64, val->v.num); break; default: - printf(""); + fprintf(f, ""); break; } } +void +pp_val(struct value *val) +{ + ppf_val(stdout, val); +} + int val_trueish(struct value *a) { @@ -257,6 +263,61 @@ val_eq(struct value *a, struct value *b) } return 0; +} + +static inline const char * +pp_totype(int totype) +{ + /* + * Not all of these are valid cast type thought, including + * every possibility only to aid debugging. + */ + switch (totype) { + case V_STR: return "str"; + case V_SYM: return "sym"; + case V_NUM: return "num"; + case V_QID: return "qid"; + case V_U8: return "u8"; + case V_U16: return "u16"; + case V_U32: return "u32"; + default: return "unknown"; + } +} + +int +val_cast(struct value *a, int totype) +{ + uint64_t v; + +#define NUMCAST(v, totype, max) do { \ + if (v >= max) { \ + fprintf(stderr, "Can't cast %"PRIu64 \ + " to %s\n", v, pp_totype(totype)); \ + return EVAL_ERR; \ + } \ + a->type = totype; \ + return EVAL_OK; \ + } while (0) + + if (!val_isnum(a)) { + fprintf(stderr, "Can't cast "); + ppf_val(stderr, a); + fprintf(stderr, " to type %s\n", pp_totype(totype)); + return EVAL_ERR; + } + + v = a->v.num; + switch (totype) { + case V_U8: NUMCAST(v, totype, UINT8_MAX); + case V_U16: NUMCAST(v, totype, UINT16_MAX); + case V_U32: NUMCAST(v, totype, UINT32_MAX); + default: + fprintf(stderr, "Can't cast %"PRIu64" to %s\n", + v, pp_totype(totype)); + return EVAL_ERR; + } + +#undef NUMCAST } void @@ -399,7 +460,12 @@ eval(struct op *op) break; case OP_CAST: - printf("TODO: cast value\n"); + if ((ret = eval(op->v.cast.expr)) != EVAL_OK) + return ret; + popv(&a); + if ((ret = val_cast(&a, op->v.cast.totype)) != EVAL_OK) + return ret; + pushv(&a); break; case OP_CMP_EQ: blob - 1f73f4a1853cc476c39d610cd266fdea399f93a7 blob + 7ffb5c8f3b19f814fd697398a1862a7feaff2bfc --- script.h +++ script.h @@ -17,6 +17,10 @@ #ifndef SCRIPT_H #define SCRIPT_H +#include "compat.h" + +#include + #include "kamid.h" enum { @@ -127,9 +131,11 @@ struct op *op_lit_num(uint64_t); struct op *op_cmp_eq(struct op *, struct op *); struct op *op_cast(struct op *, int); +void ppf_val(FILE *, struct value *); void pp_val(struct value *); int val_trueish(struct value *); int val_eq(struct value *, struct value *); +int val_cast(struct value *, int); void pp_op(struct op *); void pp_block(struct op *); int eval(struct op *);