commit - 8e0ef4cbb0ed60a2e1ee46aa071d23c82bce4657
commit + da4de0c14b6791a1ba6f8e1dfb08f6d146882331
blob - d48ec96d91eb7b46b4867dbb2d012d15234c1fc9
blob + c05a341d1b5e223431a9baa834770897fcb445cb
--- script.c
+++ script.c
}
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("<unknown value>");
+ fprintf(f, "<unknown value>");
break;
}
}
+void
+pp_val(struct value *val)
+{
+ ppf_val(stdout, val);
+}
+
int
val_trueish(struct value *a)
{
}
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
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
#ifndef SCRIPT_H
#define SCRIPT_H
+#include "compat.h"
+
+#include <stdio.h>
+
#include "kamid.h"
enum {
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 *);