From 9115c03949bc2470285e5d695abc48daae8cf6f0 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 27 Dec 2008 16:59:53 +0100 Subject: [PATCH] Simplify type coercion in condition evaluation Change nstr_mkselval() to generate values with promoted types only, and replace nstr_coerce_val() by new and simpler nstr_optype() in nstr_comp(). Replace the only remaining use of nstr_coerce_val() in surv() by nstr_promote(), and remove nstr_coerce_val(). This loses one half of the unimplemented sketch of coercions to NSC_STRING. Drop the other half from nstr_exec_val(). --- include/nsc.h | 5 +- src/lib/commands/surv.c | 2 +- src/lib/common/nstreval.c | 7 +-- src/lib/subs/nstr.c | 112 ++++++++++---------------------------- 4 files changed, 36 insertions(+), 90 deletions(-) diff --git a/include/nsc.h b/include/nsc.h index 11c01ea6..536f33f1 100644 --- a/include/nsc.h +++ b/include/nsc.h @@ -48,7 +48,7 @@ enum nsc_type { /* promoted types */ NSC_LONG, /* long */ NSC_DOUBLE, /* double */ - NSC_STRING, /* char *, zero-terminated string */ + NSC_STRING, /* character string */ /* unpromoted types */ NSC_CHAR, /* signed char */ NSC_UCHAR, /* unsigned char */ @@ -61,7 +61,7 @@ enum nsc_type { may need hiding */ NSC_TIME, /* time_t */ NSC_FLOAT, /* float */ - NSC_STRINGY, /* char[], may be zero-terminated */ + NSC_STRINGY, /* char[] */ /* aliases, must match typedefs */ NSC_NATID = NSC_UCHAR /* nation id */ }; @@ -287,7 +287,6 @@ extern struct symbol sector_navigation[]; /* src/lib/subs/nstr.c */ extern int nstr_comp(struct nscstr *np, int len, int type, char *str); extern char *nstr_comp_val(char *, struct valstr*, int); -extern int nstr_coerce_val(struct valstr *, enum nsc_type, char *); extern int nstr_exec(struct nscstr *, int, void *); /* src/lib/common/nstreval.c */ extern struct valstr *nstr_mksymval(struct valstr *, struct castr *, int); diff --git a/src/lib/commands/surv.c b/src/lib/commands/surv.c index 8a5da038..6eda99fc 100644 --- a/src/lib/commands/surv.c +++ b/src/lib/commands/surv.c @@ -71,7 +71,7 @@ surv(void) ptr = nstr_comp_val(ptr, &val, EF_SECTOR); if (!ptr) return RET_SYN; - if (val.val_cat != NSC_OFF || nstr_coerce_val(&val, NSC_LONG, NULL) < 0) { + if (val.val_cat != NSC_OFF || nstr_promote(val.val_type) != NSC_LONG) { pr("Can't survey this\n"); return RET_SYN; } diff --git a/src/lib/common/nstreval.c b/src/lib/common/nstreval.c index 770df45f..dd9addc8 100644 --- a/src/lib/common/nstreval.c +++ b/src/lib/common/nstreval.c @@ -66,8 +66,7 @@ nstr_mksymval(struct valstr *val, struct castr *ca, int idx) * PTR points to a context object of the type that was used to compile * the value. * Unless WANT is NSC_NOTYPE, coerce the value to promoted value type - * WANT. VAL must be coercible. That's the case if a previous - * nstr_coerce_val(VAL, WANT, STR) succeeded. + * WANT. VAL must be coercible. */ struct valstr * nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want) @@ -186,6 +185,7 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want) valtype = NSC_NOTYPE; } + /* coerce */ if (valtype == want) ; else if (want == NSC_DOUBLE) { @@ -193,8 +193,7 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want) valtype = want; val->val_as.dbl = val->val_as.lng; } - } else if (want == NSC_STRING) - CANT_REACH(); /* FIXME implement */ + } if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) { /* make up an error value */ diff --git a/src/lib/subs/nstr.c b/src/lib/subs/nstr.c index ec625c6f..f5ab1972 100644 --- a/src/lib/subs/nstr.c +++ b/src/lib/subs/nstr.c @@ -46,9 +46,10 @@ static char *nstr_parse_val(char *, struct valstr *); static int nstr_match_ca(struct valstr *, struct castr *); static int nstr_match_val(struct valstr *, struct castr *, int); static int nstr_string_ok(struct castr *ca, int idx); +static struct valstr *nstr_resolve_id(struct valstr *, struct castr *, int, int); static struct valstr *nstr_resolve_sel(struct valstr *, struct castr *); static struct valstr *nstr_mkselval(struct valstr *, int, struct castr *); -static struct valstr *nstr_resolve_id(struct valstr *, struct castr *, int, int); +static int nstr_optype(enum nsc_type, enum nsc_type); /* * Compile conditions into array NP[LEN]. @@ -68,7 +69,6 @@ nstr_comp(struct nscstr *np, int len, int type, char *str) struct nscstr dummy; int lft_caidx, rgt_caidx; int lft_val, rgt_val; - int lft_type, rgt_type; cond = str; for (i = 0; ; ++i, ++np) { @@ -125,7 +125,7 @@ nstr_comp(struct nscstr *np, int len, int type, char *str) } else { /* * Neither side works as selector value; any identifiers - * must name selectors. + * must name selectors or strings. */ if (!nstr_resolve_id(&np->lft, ca, lft_caidx, nstr_string_ok(ca, rgt_caidx))) @@ -135,29 +135,13 @@ nstr_comp(struct nscstr *np, int len, int type, char *str) return -1; } - /* find operator type, coerce operands */ - lft_type = nstr_promote(np->lft.val_type); - rgt_type = nstr_promote(np->rgt.val_type); - np->optype = NSC_NOTYPE; - if (lft_type == NSC_STRING) { - if (!nstr_coerce_val(&np->rgt, NSC_STRING, str)) - np->optype = NSC_STRING; - } else if (rgt_type == NSC_STRING) { - if (!nstr_coerce_val(&np->lft, NSC_STRING, str)) - np->optype = NSC_STRING; - } else if (lft_type == NSC_DOUBLE) { - if (!nstr_coerce_val(&np->rgt, NSC_DOUBLE, str)) - np->optype = NSC_DOUBLE; - } else if (rgt_type == NSC_DOUBLE) { - if (!nstr_coerce_val(&np->lft, NSC_DOUBLE, str)) - np->optype = NSC_DOUBLE; - } else { - if (!nstr_coerce_val(&np->lft, NSC_LONG, str) - && !nstr_coerce_val(&np->rgt, NSC_LONG, str)) - np->optype = NSC_LONG; - } - if (np->optype == NSC_NOTYPE) + /* find operator type */ + np->optype = nstr_optype(np->lft.val_type, np->rgt.val_type); + if (np->optype == NSC_NOTYPE) { + pr("%.*s -- condition operand type mismatch\n", + (int)(tail-cond), cond); return -1; + } /* another condition? */ if (*tail == 0) @@ -436,19 +420,37 @@ nstr_resolve_sel(struct valstr *val, struct castr *ca) static struct valstr * nstr_mkselval(struct valstr *val, int selval, struct castr *ca) { - if (CANT_HAPPEN(nstr_promote(ca->ca_type) != NSC_LONG - || ca->ca_table == EF_BAD)) { + enum nsc_type type = nstr_promote(ca->ca_type); + + if (CANT_HAPPEN(type != NSC_LONG || ca->ca_table == EF_BAD)) { val->val_type = NSC_NOTYPE; val->val_cat = NSC_NOCAT; return val; } - val->val_type = ca->ca_type; + val->val_type = type; val->val_cat = NSC_VAL; val->val_as.lng = selval; return val; } +/* + * Return operator type for operand types LFT, RGT. + */ +static int +nstr_optype(enum nsc_type lft, enum nsc_type rgt) +{ + lft = nstr_promote(lft); + rgt = nstr_promote(rgt); + if (lft == rgt) + return lft; + if (lft == NSC_DOUBLE && rgt == NSC_LONG) + return NSC_DOUBLE; + if (rgt == NSC_DOUBLE && lft == NSC_LONG) + return NSC_DOUBLE; + return NSC_NOTYPE; +} + /* * Compile a value in STR into VAL. * Return a pointer to the first character after the value on success, @@ -466,57 +468,3 @@ nstr_comp_val(char *str, struct valstr *val, int type) return NULL; return tail; } - -static int -cond_type_mismatch(char *str) -{ - if (str) - pr("%s -- condition operand type mismatch\n", str); - return -1; -} - -/* - * Coerce VAL to promoted value type TO. - * Return 0 on success, -1 on error. - * If VAL is evaluated, convert it, else only check. - * STR is the condition text to be used for error messages. Suppress - * messages if it is a null pointer. - */ -int -nstr_coerce_val(struct valstr *val, enum nsc_type to, char *str) -{ - /* FIXME get rid of promotion? */ - enum nsc_type from = nstr_promote(val->val_type); - - if (from == NSC_NOTYPE) - return 0; - - if (from != to) { - switch (to) { - case NSC_STRING: - return cond_type_mismatch(str); /* FIXME implement */ - case NSC_DOUBLE: - if (from == NSC_LONG) { - if (val->val_cat == NSC_VAL) - val->val_as.dbl = val->val_as.lng; - } else - return cond_type_mismatch(str); - break; - case NSC_LONG: - return cond_type_mismatch(str); - default: - CANT_REACH(); - to = from; - } - } - - if (val->val_cat == NSC_VAL) { - /* unimplemented conversions; don't currently occur here */ - CANT_HAPPEN(val->val_type == NSC_XCOORD - || val->val_type == NSC_YCOORD - || val->val_type == NSC_HIDDEN); - val->val_type = to; - } - - return 0; -}