about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-04-13 11:00:08 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-04-13 11:00:08 -0700
commitad05221de91b9ec058de36319c617e7ac771e950 (patch)
treefbb537bdac02151d16ebce8591952e47093ccd48
parent85b2f61b7727989c9291cff324b861d495ce315d (diff)
downloadmu-ad05221de91b9ec058de36319c617e7ac771e950.tar.gz
3818 - better error messages on type mismatch
Thanks Ella Couch for suggesting this approach.
-rw-r--r--054static_dispatch.cc51
1 files changed, 50 insertions, 1 deletions
diff --git a/054static_dispatch.cc b/054static_dispatch.cc
index 6e2638ef..fe072d56 100644
--- a/054static_dispatch.cc
+++ b/054static_dispatch.cc
@@ -194,7 +194,20 @@ string best_variant(instruction& inst, const recipe& caller_recipe) {
 
   // error messages
   if (get(Recipe_ordinal, inst.name) >= MAX_PRIMITIVE_RECIPES) {  // we currently don't check types for primitive variants
-    raise << maybe(caller_recipe.name) << "failed to find a matching call for '" << inst.original_string << "'\n" << end();
+    if (SIZE(variants) == 1) {
+      raise << maybe(caller_recipe.name) << "instruction '" << inst.original_string << "' does not match '" << header_label(get(Recipe, variants.at(0))) << "'\n" << end();
+      raise << "  instruction expands to '" << to_string(inst) << "'\n" << end();
+    }
+    else {
+      raise << maybe(caller_recipe.name) << "failed to find a matching call for '" << inst.original_string << "'\n" << end();
+      raise << "  which expands to:\n" << end();
+      raise << "    " << to_string(inst) << '\n' << end();
+      raise << "  available variants are:\n" << end();
+      for (int i = 0;  i < SIZE(variants);  ++i) {
+        const recipe& curr = get(Recipe, variants.at(i));
+        raise << "    " << header_label(curr) << '\n' << end();
+      }
+    }
     for (list<call>::iterator p = /*skip*/++Resolve_stack.begin();  p != Resolve_stack.end();  ++p) {
       const recipe& specializer_recipe = get(Recipe, p->running_recipe);
       const instruction& specializer_inst = specializer_recipe.steps.at(p->running_step_index);
@@ -621,5 +634,41 @@ def! foo a:text -> result:num [
 ]
 +mem: storing 35 in location 1
 
+:(scenario ignore_static_dispatch_in_type_errors_without_overloading)
+% Hide_errors = true;
+def main [
+  local-scope
+  x:&:num <- copy 0
+  foo x
+]
+def foo x:&:char [
+  local-scope
+  load-ingredients
+]
++error: main: instruction 'foo x' does not match 'recipe foo {x: ("address" "character")}'
++error:   instruction expands to 'foo {x: ("address" "number")}'
+
+:(scenario show_available_variants_in_dispatch_errors)
+% Hide_errors = true;
+def main [
+  local-scope
+  x:&:num <- copy 0
+  foo x
+]
+def foo x:&:char [
+  local-scope
+  load-ingredients
+]
+def foo x:&:bool [
+  local-scope
+  load-ingredients
+]
++error: main: failed to find a matching call for 'foo x'
++error:   which expands to:
++error:     foo {x: ("address" "number")}
++error:   available variants are:
++error:     recipe foo {x: ("address" "character")}
++error:     recipe foo_2 {x: ("address" "boolean")}
+
 :(before "End Includes")
 using std::abs;