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().
This commit is contained in:
parent
d2fba584e8
commit
9115c03949
4 changed files with 36 additions and 90 deletions
|
@ -48,7 +48,7 @@ enum nsc_type {
|
||||||
/* promoted types */
|
/* promoted types */
|
||||||
NSC_LONG, /* long */
|
NSC_LONG, /* long */
|
||||||
NSC_DOUBLE, /* double */
|
NSC_DOUBLE, /* double */
|
||||||
NSC_STRING, /* char *, zero-terminated string */
|
NSC_STRING, /* character string */
|
||||||
/* unpromoted types */
|
/* unpromoted types */
|
||||||
NSC_CHAR, /* signed char */
|
NSC_CHAR, /* signed char */
|
||||||
NSC_UCHAR, /* unsigned char */
|
NSC_UCHAR, /* unsigned char */
|
||||||
|
@ -61,7 +61,7 @@ enum nsc_type {
|
||||||
may need hiding */
|
may need hiding */
|
||||||
NSC_TIME, /* time_t */
|
NSC_TIME, /* time_t */
|
||||||
NSC_FLOAT, /* float */
|
NSC_FLOAT, /* float */
|
||||||
NSC_STRINGY, /* char[], may be zero-terminated */
|
NSC_STRINGY, /* char[] */
|
||||||
/* aliases, must match typedefs */
|
/* aliases, must match typedefs */
|
||||||
NSC_NATID = NSC_UCHAR /* nation id */
|
NSC_NATID = NSC_UCHAR /* nation id */
|
||||||
};
|
};
|
||||||
|
@ -287,7 +287,6 @@ extern struct symbol sector_navigation[];
|
||||||
/* src/lib/subs/nstr.c */
|
/* src/lib/subs/nstr.c */
|
||||||
extern int nstr_comp(struct nscstr *np, int len, int type, char *str);
|
extern int nstr_comp(struct nscstr *np, int len, int type, char *str);
|
||||||
extern char *nstr_comp_val(char *, struct valstr*, int);
|
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 *);
|
extern int nstr_exec(struct nscstr *, int, void *);
|
||||||
/* src/lib/common/nstreval.c */
|
/* src/lib/common/nstreval.c */
|
||||||
extern struct valstr *nstr_mksymval(struct valstr *, struct castr *, int);
|
extern struct valstr *nstr_mksymval(struct valstr *, struct castr *, int);
|
||||||
|
|
|
@ -71,7 +71,7 @@ surv(void)
|
||||||
ptr = nstr_comp_val(ptr, &val, EF_SECTOR);
|
ptr = nstr_comp_val(ptr, &val, EF_SECTOR);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return RET_SYN;
|
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");
|
pr("Can't survey this\n");
|
||||||
return RET_SYN;
|
return RET_SYN;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* PTR points to a context object of the type that was used to compile
|
||||||
* the value.
|
* the value.
|
||||||
* Unless WANT is NSC_NOTYPE, coerce the value to promoted value type
|
* Unless WANT is NSC_NOTYPE, coerce the value to promoted value type
|
||||||
* WANT. VAL must be coercible. That's the case if a previous
|
* WANT. VAL must be coercible.
|
||||||
* nstr_coerce_val(VAL, WANT, STR) succeeded.
|
|
||||||
*/
|
*/
|
||||||
struct valstr *
|
struct valstr *
|
||||||
nstr_exec_val(struct valstr *val, natid cnum, void *ptr, enum nsc_type want)
|
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;
|
valtype = NSC_NOTYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* coerce */
|
||||||
if (valtype == want)
|
if (valtype == want)
|
||||||
;
|
;
|
||||||
else if (want == NSC_DOUBLE) {
|
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;
|
valtype = want;
|
||||||
val->val_as.dbl = val->val_as.lng;
|
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)) {
|
if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) {
|
||||||
/* make up an error value */
|
/* make up an error value */
|
||||||
|
|
|
@ -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_ca(struct valstr *, struct castr *);
|
||||||
static int nstr_match_val(struct valstr *, struct castr *, int);
|
static int nstr_match_val(struct valstr *, struct castr *, int);
|
||||||
static int nstr_string_ok(struct castr *ca, int idx);
|
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_resolve_sel(struct valstr *, struct castr *);
|
||||||
static struct valstr *nstr_mkselval(struct valstr *, int, 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].
|
* Compile conditions into array NP[LEN].
|
||||||
|
@ -68,7 +69,6 @@ nstr_comp(struct nscstr *np, int len, int type, char *str)
|
||||||
struct nscstr dummy;
|
struct nscstr dummy;
|
||||||
int lft_caidx, rgt_caidx;
|
int lft_caidx, rgt_caidx;
|
||||||
int lft_val, rgt_val;
|
int lft_val, rgt_val;
|
||||||
int lft_type, rgt_type;
|
|
||||||
|
|
||||||
cond = str;
|
cond = str;
|
||||||
for (i = 0; ; ++i, ++np) {
|
for (i = 0; ; ++i, ++np) {
|
||||||
|
@ -125,7 +125,7 @@ nstr_comp(struct nscstr *np, int len, int type, char *str)
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Neither side works as selector value; any identifiers
|
* 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,
|
if (!nstr_resolve_id(&np->lft, ca, lft_caidx,
|
||||||
nstr_string_ok(ca, rgt_caidx)))
|
nstr_string_ok(ca, rgt_caidx)))
|
||||||
|
@ -135,29 +135,13 @@ nstr_comp(struct nscstr *np, int len, int type, char *str)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find operator type, coerce operands */
|
/* find operator type */
|
||||||
lft_type = nstr_promote(np->lft.val_type);
|
np->optype = nstr_optype(np->lft.val_type, np->rgt.val_type);
|
||||||
rgt_type = nstr_promote(np->rgt.val_type);
|
if (np->optype == NSC_NOTYPE) {
|
||||||
np->optype = NSC_NOTYPE;
|
pr("%.*s -- condition operand type mismatch\n",
|
||||||
if (lft_type == NSC_STRING) {
|
(int)(tail-cond), cond);
|
||||||
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)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* another condition? */
|
/* another condition? */
|
||||||
if (*tail == 0)
|
if (*tail == 0)
|
||||||
|
@ -436,19 +420,37 @@ nstr_resolve_sel(struct valstr *val, struct castr *ca)
|
||||||
static struct valstr *
|
static struct valstr *
|
||||||
nstr_mkselval(struct valstr *val, int selval, struct castr *ca)
|
nstr_mkselval(struct valstr *val, int selval, struct castr *ca)
|
||||||
{
|
{
|
||||||
if (CANT_HAPPEN(nstr_promote(ca->ca_type) != NSC_LONG
|
enum nsc_type type = nstr_promote(ca->ca_type);
|
||||||
|| ca->ca_table == EF_BAD)) {
|
|
||||||
|
if (CANT_HAPPEN(type != NSC_LONG || ca->ca_table == EF_BAD)) {
|
||||||
val->val_type = NSC_NOTYPE;
|
val->val_type = NSC_NOTYPE;
|
||||||
val->val_cat = NSC_NOCAT;
|
val->val_cat = NSC_NOCAT;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
val->val_type = ca->ca_type;
|
val->val_type = type;
|
||||||
val->val_cat = NSC_VAL;
|
val->val_cat = NSC_VAL;
|
||||||
val->val_as.lng = selval;
|
val->val_as.lng = selval;
|
||||||
return val;
|
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.
|
* Compile a value in STR into VAL.
|
||||||
* Return a pointer to the first character after the value on success,
|
* 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 NULL;
|
||||||
return tail;
|
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;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue