diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-01-12 12:53:04 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-01-12 12:53:04 -0800 |
commit | 7ac8feeff10abfd76f712f8f32406dd30ba1c73e (patch) | |
tree | 020352ac442c96bc402d71ef3c21bd82a82ca52a | |
parent | bdb6161bf0cf7b8658845783d526204ad4bee638 (diff) | |
download | mu-7ac8feeff10abfd76f712f8f32406dd30ba1c73e.tar.gz |
2557 - type-check most ingredients ahead of time
-rw-r--r-- | 020run.cc | 1 | ||||
-rw-r--r-- | 035call_ingredient.cc | 3 | ||||
-rw-r--r-- | 052tangle.cc | 6 | ||||
-rw-r--r-- | 056recipe_header.cc | 85 | ||||
-rw-r--r-- | 057static_dispatch.cc | 39 |
5 files changed, 86 insertions, 48 deletions
diff --git a/020run.cc b/020run.cc index a3948dd1..587e9f88 100644 --- a/020run.cc +++ b/020run.cc @@ -325,6 +325,7 @@ void run(string form) { vector<recipe_ordinal> tmp = load(form); transform_all(); if (tmp.empty()) return; + if (trace_count("error") > 0) return; run(tmp.front()); } diff --git a/035call_ingredient.cc b/035call_ingredient.cc index 7036fa06..f079f0c5 100644 --- a/035call_ingredient.cc +++ b/035call_ingredient.cc @@ -77,9 +77,8 @@ case NEXT_INGREDIENT: { products.resize(2); // pad the first product with sufficient zeros to match its type long long int size = size_of(current_instruction().products.at(0)); - for (long long int i = 0; i < size; ++i) { + for (long long int i = 0; i < size; ++i) products.at(0).push_back(0); - } products.at(1).push_back(0); } break; diff --git a/052tangle.cc b/052tangle.cc index efbbbead..3a55f451 100644 --- a/052tangle.cc +++ b/052tangle.cc @@ -182,12 +182,6 @@ before +label1 [ 2:number <- copy 0 ] +error: can't tangle before label +label1 -+mem: storing 0 in location 1 -+mem: storing 0 in location 4 -# label1 --mem: storing 0 in location 2 -# nothing else -$mem: 2 :(scenario tangle_keeps_labels_separate) recipe main [ diff --git a/056recipe_header.cc b/056recipe_header.cc index dae4cd22..a438054c 100644 --- a/056recipe_header.cc +++ b/056recipe_header.cc @@ -138,16 +138,97 @@ if (result.has_header) { :(before "End Rewrite Instruction(curr, recipe result)") if (curr.name == "load-ingredients") { curr.clear(); - recipe_ordinal op = get(Recipe_ordinal, "next-ingredient"); + recipe_ordinal op = get(Recipe_ordinal, "next-ingredient-without-typechecking"); for (long long int i = 0; i < SIZE(result.ingredients); ++i) { curr.operation = op; - curr.name = "next-ingredient"; + curr.name = "next-ingredient-without-typechecking"; curr.products.push_back(result.ingredients.at(i)); result.steps.push_back(curr); curr.clear(); } } +//: internal version of next-ingredient; don't call this directly +:(before "End Primitive Recipe Declarations") +NEXT_INGREDIENT_WITHOUT_TYPECHECKING, +:(before "End Primitive Recipe Numbers") +put(Recipe_ordinal, "next-ingredient-without-typechecking", NEXT_INGREDIENT_WITHOUT_TYPECHECKING); +:(before "End Primitive Recipe Checks") +case NEXT_INGREDIENT_WITHOUT_TYPECHECKING: { + break; +} +:(before "End Primitive Recipe Implementations") +case NEXT_INGREDIENT_WITHOUT_TYPECHECKING: { + assert(!Current_routine->calls.empty()); + if (current_call().next_ingredient_to_process < SIZE(current_call().ingredient_atoms)) { + products.push_back( + current_call().ingredient_atoms.at(current_call().next_ingredient_to_process)); + assert(SIZE(products) == 1); products.resize(2); // push a new vector + products.at(1).push_back(1); + ++current_call().next_ingredient_to_process; + } + else { + raise_error << maybe(current_recipe_name()) << "no ingredient to save in " << current_instruction().products.at(0).original_string << '\n' << end(); + products.resize(2); + products.at(0).push_back(0); + products.at(1).push_back(0); + } + break; +} + +//:: Check all calls against headers. + +:(scenario show_clear_error_on_bad_call) +% Hide_errors = true; +recipe main [ + 1:number <- foo 34 +] +recipe foo x:boolean -> y:number [ + local-scope + load-ingredients + reply 35 +] ++error: main: ingredient 0 has the wrong type at '1:number <- foo 34' + +:(scenario show_clear_error_on_bad_call_2) +% Hide_errors = true; +recipe main [ + 1:boolean <- foo 34 +] +recipe foo x:number -> y:number [ + local-scope + load-ingredients + reply x +] ++error: main: product 0 has the wrong type at '1:boolean <- foo 34' + +:(after "Transform.push_back(check_instruction)") +Transform.push_back(check_calls_against_header); // idempotent +:(code) +void check_calls_against_header(const recipe_ordinal r) { + trace(9991, "transform") << "--- type-check calls inside recipe " << get(Recipe, r).name << end(); + const recipe& caller = get(Recipe, r); + for (long long int i = 0; i < SIZE(caller.steps); ++i) { + const instruction& inst = caller.steps.at(i); + if (inst.operation < MAX_PRIMITIVE_RECIPES) continue; + const recipe& callee = get(Recipe, inst.operation); + if (!callee.has_header) continue; + for (long int i = 0; i < smaller(SIZE(inst.ingredients), SIZE(callee.ingredients)); ++i) { + if (!types_coercible(callee.ingredients.at(i), inst.ingredients.at(i))) + raise_error << maybe(caller.name) << "ingredient " << i << " has the wrong type at '" << inst.to_string() << "'\n" << end(); + } + for (long int i = 0; i < smaller(SIZE(inst.products), SIZE(callee.products)); ++i) { + if (is_dummy(inst.products.at(i))) continue; + if (!types_coercible(callee.products.at(i), inst.products.at(i))) + raise_error << maybe(caller.name) << "product " << i << " has the wrong type at '" << inst.to_string() << "'\n" << end(); + } + } +} + +inline long long int smaller(long long int a, long long int b) { + return a < b ? a : b; +} + //:: Check types going in and out of all recipes with headers. :(scenarios transform) diff --git a/057static_dispatch.cc b/057static_dispatch.cc index ed656f0c..2b48af10 100644 --- a/057static_dispatch.cc +++ b/057static_dispatch.cc @@ -359,7 +359,7 @@ recipe foo x:number -> y:number [ load-ingredients reply 34 ] -+error: foo: wrong type for ingredient x:number ++error: main: ingredient 0 has the wrong type at '1:number/raw <- foo x' -mem: storing 34 in location 1 :(scenario static_dispatch_dispatches_literal_to_boolean_before_character) @@ -413,43 +413,6 @@ recipe foo x:number -> y:number [ # number variant is preferred +mem: storing 35 in location 1 -//: after we make all attempts to dispatch, any unhandled cases will end up at -//: some wrong variant and trigger an error while trying to load-ingredients - -:(scenario static_dispatch_shows_clear_error_on_missing_variant) -% Hide_errors = true; -recipe main [ - 1:number <- foo 34 -] -recipe foo x:boolean -> y:number [ - local-scope - load-ingredients - reply 35 -] -+error: foo: wrong type for ingredient x:boolean -+error: (we're inside recipe foo x:boolean -> y:number) -+error: (we're trying to call '1:number <- foo 34' inside recipe main) - -:(before "End next-ingredient Type Mismatch Error") -raise_error << " (we're inside " << header_label(current_call().running_recipe) << ")\n" << end(); -raise_error << " (we're trying to call '" << to_instruction(*++Current_routine->calls.begin()).to_string() << "' inside " << header_label((++Current_routine->calls.begin())->running_recipe) << ")\n" << end(); - -:(scenario static_dispatch_shows_clear_error_on_missing_variant_2) -% Hide_errors = true; -recipe main [ - 1:boolean <- foo 34 -] -recipe foo x:number -> y:number [ - local-scope - load-ingredients - reply x -] -+error: foo: reply ingredient x can't be saved in 1:boolean -+error: (we just returned from recipe foo x:number -> y:number) - -:(before "End reply Type Mismatch Error") -raise_error << " (we just returned from " << header_label(caller_instruction.operation) << ")\n" << end(); - :(code) string header_label(recipe_ordinal r) { const recipe& caller = get(Recipe, r); |