diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-01-30 12:03:16 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-01-30 12:03:16 -0800 |
commit | 1cfcb62fa11e2f57fb982500c7df810826988dfc (patch) | |
tree | 1f330bc2fc87765438f318e934890848035b1285 /057static_dispatch.cc | |
parent | 2ac236e2bc7b6c392142b296b9f6353ee6d9662e (diff) | |
download | mu-1cfcb62fa11e2f57fb982500c7df810826988dfc.tar.gz |
2617 - better error messages
When we stash a value, mu does several levels of work for us: a) First it inserts instructions above the stash to convert the value to text using to-text-line. b) to-text-line calls to-text. Both are shape-shifting, so multiple levels of specialization happen. To give a good error message, we track the 'stack' of current specializations at the time of the error, and also check if the offending instruction at the top-most level looks like it was inserted while rewriting stash instructions. Manual example (since booleans can't be stashed at the moment): x:boolean <- copy 1/true stash x
Diffstat (limited to '057static_dispatch.cc')
-rw-r--r-- | 057static_dispatch.cc | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/057static_dispatch.cc b/057static_dispatch.cc index 368804e7..fc860a99 100644 --- a/057static_dispatch.cc +++ b/057static_dispatch.cc @@ -140,6 +140,15 @@ for (long long int i = 0; i < SIZE(caller.products); ++i) { :(after "Transform.push_back(transform_names)") Transform.push_back(resolve_ambiguous_calls); // idempotent +//: In a later layer we'll introduce recursion in resolve_ambiguous_calls, by +//: having it generate code for shape-shifting recipes and then transform such +//: code. This data structure will help error messages be more useful. +//: +//: We're punning the 'call' data structure just because it has slots for +//: calling recipe and calling instruction. +:(before "End Globals") +list<call> resolve_stack; + :(code) void resolve_ambiguous_calls(recipe_ordinal r) { recipe& caller_recipe = get(Recipe, r); @@ -149,7 +158,12 @@ void resolve_ambiguous_calls(recipe_ordinal r) { instruction& inst = caller_recipe.steps.at(index); if (inst.is_label) continue; if (get_or_insert(Recipe_variants, inst.name).empty()) continue; + resolve_stack.push_front(call(r)); + resolve_stack.front().running_step_index = index; replace_best_variant(inst, caller_recipe); + assert(resolve_stack.front().running_recipe == r); + assert(resolve_stack.front().running_step_index == index); + resolve_stack.pop_front(); } } @@ -172,7 +186,38 @@ void replace_best_variant(instruction& inst, const recipe& caller_recipe) { // End Instruction Dispatch(inst, best_score) if (best_score == -1 && get(Recipe_ordinal, inst.name) >= MAX_PRIMITIVE_RECIPES) { raise_error << maybe(caller_recipe.name) << "failed to find a matching call for '" << inst.to_string() << "'\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); + if (specializer_recipe.name != "interactive") + raise_error << " (from '" << specializer_inst.to_string() << "' in " << specializer_recipe.name << ")\n" << end(); + else + raise_error << " (from '" << specializer_inst.to_string() << "')\n" << end(); + // One special-case to help with the rewrite_stash transform. (cross-layer) + if (specializer_inst.products.at(0).name.find("stash_") == 0) { + instruction stash_inst; + if (next_stash(*p, &stash_inst)) { + if (specializer_recipe.name != "interactive") + raise_error << " (part of '" << stash_inst.original_string << "' in " << specializer_recipe.name << ")\n" << end(); + else + raise_error << " (part of '" << stash_inst.original_string << "')\n" << end(); + } + } + } + } +} + +bool next_stash(const call& c, instruction* stash_inst) { + const recipe& specializer_recipe = get(Recipe, c.running_recipe); + long long int index = c.running_step_index; + for (++index; index < SIZE(specializer_recipe.steps); ++index) { + const instruction& inst = specializer_recipe.steps.at(index); + if (inst.name == "stash") { + *stash_inst = inst; + return true; + } } + return false; } long long int variant_score(const instruction& inst, recipe_ordinal variant) { |