]> git.pond.sub.org Git - empserver/commitdiff
Simplify type coercion in condition evaluation
authorMarkus Armbruster <armbru@pond.sub.org>
Sat, 27 Dec 2008 15:59:53 +0000 (16:59 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Sat, 27 Dec 2008 15:59:53 +0000 (16:59 +0100)
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
src/lib/commands/surv.c
src/lib/common/nstreval.c
src/lib/subs/nstr.c

index 11c01ea65cf41d53124199a194038fab82c7a5c1..536f33f1c778b5f7033b766418dbfce73189bdda 100644 (file)
@@ -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);
index 8a5da0385dd09e641f459fc6b156f5366054c3c8..6eda99fc474bc1dea12e8d957419e64059868e7b 100644 (file)
@@ -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;
     }
index 770df45fdecf20f8b18c1ebb3531868e79ac6b78..dd9addc8e655d58fbb329e08018900b6657d34c5 100644 (file)
@@ -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 */
index ec625c6fd2632644381ca26adc53b8bf20936312..f5ab19726cc228a9dd72a633663059a91ae5005d 100644 (file)
@@ -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;
-}