about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-04-18 18:04:50 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-04-18 18:04:50 -0700
commitf8b0b04da1d63dfb442fa547a82f98f1be14b446 (patch)
tree4f6c24ec8996ab7878caff8bcc90c392826c88e3
parent04683e4ecec9bc26f0930a548fc2173d89f686c4 (diff)
downloadmu-f8b0b04da1d63dfb442fa547a82f98f1be14b446.tar.gz
3833
Loosen type-checking slightly to accomodate type abbreviations.
-rw-r--r--021check_instruction.cc17
-rw-r--r--053recipe_header.cc8
-rw-r--r--061text.mu6
3 files changed, 28 insertions, 3 deletions
diff --git a/021check_instruction.cc b/021check_instruction.cc
index 90f24926..35b3eea0 100644
--- a/021check_instruction.cc
+++ b/021check_instruction.cc
@@ -146,7 +146,12 @@ bool types_strictly_match(const type_tree* to, const type_tree* from) {
     if (from->value == -1) return from->name == to->name;
     return from->value == to->value;
   }
-  return types_strictly_match(to->left, from->left) && types_strictly_match(to->right, from->right);
+  if (types_strictly_match(to->left, from->left) && types_strictly_match(to->right, from->right))
+    return true;
+  // fallback: (x) == x
+  if (to->right == NULL && types_strictly_match(to->left, from)) return true;
+  if (from->right == NULL && types_strictly_match(to, from->left)) return true;
+  return false;
 }
 
 void test_unknown_type_does_not_match_unknown_type() {
@@ -161,6 +166,16 @@ void test_unknown_type_matches_itself() {
   CHECK(types_strictly_match(a, b));
 }
 
+void test_type_abbreviations_match_raw_types() {
+  put(Type_abbreviations, "text", new_type_tree("address:array:character"));
+  // a has type (address buffer (address array character))
+  reagent a("a:address:buffer:text");
+  expand_type_abbreviations(a.type);
+  // b has type (address buffer address array character)
+  reagent b("b:address:buffer:address:array:character");
+  CHECK(types_strictly_match(a, b));
+}
+
 //: helpers
 
 bool is_unsafe(const reagent& r) {
diff --git a/053recipe_header.cc b/053recipe_header.cc
index 0f9aa4fc..d9495f46 100644
--- a/053recipe_header.cc
+++ b/053recipe_header.cc
@@ -296,14 +296,18 @@ void check_calls_against_header(const recipe_ordinal r) {
     if (!callee.has_header) continue;
     for (long int i = 0;  i < min(SIZE(inst.ingredients), SIZE(callee.ingredients));  ++i) {
       // ingredients coerced from call to callee
-      if (!types_coercible(callee.ingredients.at(i), inst.ingredients.at(i)))
+      if (!types_coercible(callee.ingredients.at(i), inst.ingredients.at(i))) {
         raise << maybe(caller.name) << "ingredient " << i << " has the wrong type at '" << inst.original_string << "'\n" << end();
+        raise << "  ['" << to_string(callee.ingredients.at(i).type) << "' vs '" << to_string(inst.ingredients.at(i).type) << "']\n" << end();
+      }
     }
     for (long int i = 0;  i < min(SIZE(inst.products), SIZE(callee.products));  ++i) {
       if (is_dummy(inst.products.at(i))) continue;
       // products coerced from callee to call
-      if (!types_coercible(inst.products.at(i), callee.products.at(i)))
+      if (!types_coercible(inst.products.at(i), callee.products.at(i))) {
         raise << maybe(caller.name) << "product " << i << " has the wrong type at '" << inst.original_string << "'\n" << end();
+        raise << "  ['" << to_string(inst.products.at(i).type) << "' vs '" << to_string(callee.products.at(i).type) << "']\n" << end();
+      }
     }
   }
 }
diff --git a/061text.mu b/061text.mu
index 96e6b644..db198d01 100644
--- a/061text.mu
+++ b/061text.mu
@@ -344,6 +344,12 @@ scenario buffer-append-handles-backspace [
   ]
 ]
 
+scenario append-to-buffer-of-non-characters [
+  local-scope
+  x:&:buffer:text <- new-buffer 1/capacity
+  # no errors
+]
+
 def buffer-to-array in:&:buffer:_elem -> result:&:@:_elem [
   local-scope
   load-ingredients