Ver código fonte

ncd: modules: arithmetic: Don't fail immediately on arithmetic errors, expose their occurrence.

Ambroz Bizjak 11 anos atrás
pai
commit
2352511d46
2 arquivos alterados com 50 adições e 25 exclusões
  1. 32 25
      ncd/modules/arithmetic.c
  2. 18 0
      ncd/tests/arithmetic.ncd

+ 32 - 25
ncd/modules/arithmetic.c

@@ -60,7 +60,11 @@
  *   If any of these restrictions is violated, an error is triggered.
  * 
  * Variables:
- *   (empty) - the result of the operation as a string representing a decimal number
+ *   is_error - whether there was an arithmetic error with the operation (true/false).
+ *   (empty) - the result of the operation as a string representing a decimal number.
+ *             If an attempt is made to access this variable after an arithmetic error,
+ *             the variable resolution will fail, and an error will be logged including
+ *             information about the particular arithemtic error.
  */
 
 #include <stdio.h>
@@ -84,10 +88,11 @@ typedef int (*boolean_compute_func) (uintmax_t n1, uintmax_t n2);
 
 struct number_instance {
     NCDModuleInst *i;
+    char const *error;
     uintmax_t value;
 };
 
-typedef int (*number_compute_func) (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out);
+typedef char const * (*number_compute_func) (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out);
 
 static int compute_lesser (uintmax_t n1, uintmax_t n2)
 {
@@ -119,54 +124,49 @@ static int compute_different (uintmax_t n1, uintmax_t n2)
     return n1 != n2;
 }
 
-static int compute_add (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
+static char const * compute_add (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
 {
     if (n1 > UINTMAX_MAX - n2) {
-        ModuleLog(i, BLOG_ERROR, "addition overflow");
-        return 0;
+        return "addition overflow";
     }
     *out = n1 + n2;
-    return 1;
+    return NULL;
 }
 
-static int compute_subtract (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
+static char const * compute_subtract (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
 {
     if (n1 < n2) {
-        ModuleLog(i, BLOG_ERROR, "subtraction underflow");
-        return 0;
+        return "subtraction underflow";
     }
     *out = n1 - n2;
-    return 1;
+    return NULL;
 }
 
-static int compute_multiply (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
+static char const * compute_multiply (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
 {
     if (n2 != 0 && n1 > UINTMAX_MAX / n2) {
-        ModuleLog(i, BLOG_ERROR, "multiplication overflow");
-        return 0;
+        return "multiplication overflow";
     }
     *out = n1 * n2;
-    return 1;
+    return NULL;
 }
 
-static int compute_divide (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
+static char const * compute_divide (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
 {
     if (n2 == 0) {
-        ModuleLog(i, BLOG_ERROR, "division quotient is zero");
-        return 0;
+        return "division quotient is zero";
     }
     *out = n1 / n2;
-    return 1;
+    return NULL;
 }
 
-static int compute_modulo (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
+static char const * compute_modulo (NCDModuleInst *i, uintmax_t n1, uintmax_t n2, uintmax_t *out)
 {
     if (n2 == 0) {
-        ModuleLog(i, BLOG_ERROR, "modulo modulus is zero");
-        return 0;
+        return "modulo modulus is zero";
     }
     *out = n1 % n2;
-    return 1;
+    return NULL;
 }
 
 static void new_boolean_templ (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params, boolean_compute_func cfunc)
@@ -238,9 +238,7 @@ static void new_number_templ (void *vo, NCDModuleInst *i, const struct NCDModule
         goto fail0;
     }
     
-    if (!cfunc(i, n1, n2, &o->value)) {
-        goto fail0;
-    }
+    o->error = cfunc(i, n1, n2, &o->value);
     
     NCDModuleInst_Backend_Up(i);
     return;
@@ -253,7 +251,16 @@ static int number_func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem,
 {
     struct number_instance *o = vo;
     
+    if (name == NCD_STRING_IS_ERROR) {
+        *out = ncd_make_boolean(mem, !!o->error, o->i->params->iparams->string_index);
+        return 1;
+    }
+    
     if (name == NCD_STRING_EMPTY) {
+        if (o->error) {
+            ModuleLog(o->i, BLOG_ERROR, "%s", o->error);
+            return 0;
+        }
         *out = ncd_make_uintmax(mem, o->value);
         return 1;
     }

+ 18 - 0
ncd/tests/arithmetic.ncd

@@ -65,5 +65,23 @@ process main {
     strcmp(r, "1") a;
     assert(a);
 
+    num_add("18446744073709551615", "1") r;
+    assert(r.is_error);
+
+    num_subtract("0", "1") r;
+    assert(r.is_error);
+
+    num_multiply("9223372036854775808", "2") r;
+    assert(r.is_error);
+
+    num_divide("4", "0") r;
+    assert(r.is_error);
+    
+    num_modulo("4", "0") r;
+    assert(r.is_error);
+    
+    num_add("1", "1") r;
+    assert_false(r.is_error);
+
     exit("0");
 }