diff options
39 files changed, 507 insertions, 460 deletions
diff --git a/003trace.cc b/003trace.cc index e37b9f12..455ced85 100644 --- a/003trace.cc +++ b/003trace.cc @@ -81,8 +81,10 @@ // End Tracing // hack to ensure most code in this layer comes before anything else :(before "End Tracing") +bool Hide_errors = false; bool Hide_warnings = false; :(before "End Setup") +Hide_errors = false; Hide_warnings = false; :(before "End Types") @@ -132,7 +134,9 @@ struct trace_stream { string curr_contents = curr_stream->str(); if (curr_contents.empty()) return; past_lines.push_back(trace_line(curr_depth, trim(curr_label), curr_contents)); // preserve indent in contents - if (!Hide_warnings && curr_label == "warn") + if (!Hide_errors && curr_label == "error") + cerr << curr_label << ": " << curr_contents << '\n'; + else if (!Hide_warnings && curr_label == "warn") cerr << curr_label << ": " << curr_contents << '\n'; delete curr_stream; curr_stream = NULL; @@ -160,9 +164,10 @@ trace_stream* Trace_stream = NULL; // Top-level helper. IMPORTANT: can't nest. #define trace(...) !Trace_stream ? cerr /*print nothing*/ : Trace_stream->stream(__VA_ARGS__) -// Warnings should go straight to cerr by default since calls to trace() have +// Errors and warnings should go straight to cerr by default since calls to trace() have // some unfriendly constraints (they delay printing, they can't nest) #define raise ((!Trace_stream || !Hide_warnings) ? (tb_shutdown(),cerr) /*do print*/ : Trace_stream->stream("warn")) +#define raise_error ((!Trace_stream || !Hide_errors) ? (tb_shutdown(),cerr) /*do print*/ : Trace_stream->stream("error")) :(before "End Types") struct end {}; @@ -263,12 +268,12 @@ int trace_count(string label, string line) { return result; } -#define CHECK_TRACE_WARNS() CHECK(trace_count("warn") > 0) -#define CHECK_TRACE_DOESNT_WARN() \ - if (trace_count("warn") > 0) { \ +#define CHECK_TRACE_CONTAINS_ERROR() CHECK(trace_count("error") > 0) +#define CHECK_TRACE_DOESNT_CONTAIN_ERROR() \ + if (trace_count("error") > 0) { \ ++Num_failures; \ - cerr << "\nF - " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): unexpected warnings\n"; \ - DUMP("warn"); \ + cerr << "\nF - " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): unexpected errors\n"; \ + DUMP("error"); \ Passed = false; \ return; \ } diff --git a/003trace.test.cc b/003trace.test.cc index a16457a1..f34cbf88 100644 --- a/003trace.test.cc +++ b/003trace.test.cc @@ -59,11 +59,11 @@ void test_trace_count_ignores_trailing_whitespace() { // pending: DUMP tests // pending: readable_contents() adds newline if necessary. // pending: raise also prints to stderr. -// pending: raise doesn't print to stderr if Hide_warnings is set. -// pending: raise doesn't have to be saved if Hide_warnings is set, just printed. +// pending: raise doesn't print to stderr if Hide_errors is set. +// pending: raise doesn't have to be saved if Hide_errors is set, just printed. // pending: raise prints to stderr if Trace_stream is NULL. -// pending: raise prints to stderr if Trace_stream is NULL even if Hide_warnings is set. -// pending: raise << ... die() doesn't die if Hide_warnings is set. +// pending: raise prints to stderr if Trace_stream is NULL even if Hide_errors is set. +// pending: raise << ... die() doesn't die if Hide_errors is set. diff --git a/011load.cc b/011load.cc index a084ba6e..4b1b1929 100644 --- a/011load.cc +++ b/011load.cc @@ -34,7 +34,7 @@ vector<recipe_ordinal> load(istream& in) { } // End Command Handlers else { - raise << "unknown top-level command: " << command << '\n' << end(); + raise_error << "unknown top-level command: " << command << '\n' << end(); } } return result; @@ -43,7 +43,7 @@ vector<recipe_ordinal> load(istream& in) { long long int slurp_recipe(istream& in) { string recipe_name = next_word(in); if (recipe_name.empty()) - raise << "empty recipe name\n" << end(); + raise_error << "empty recipe name\n" << end(); if (Recipe_ordinal.find(recipe_name) == Recipe_ordinal.end()) { Recipe_ordinal[recipe_name] = Next_recipe_ordinal++; } @@ -63,7 +63,7 @@ recipe slurp_body(istream& in) { recipe result; skip_whitespace(in); if (in.get() != '[') - raise << "recipe body must begin with '['\n" << end(); + raise_error << "recipe body must begin with '['\n" << end(); skip_whitespace_and_comments(in); instruction curr; while (next_instruction(in, &curr)) { @@ -77,17 +77,17 @@ bool next_instruction(istream& in, instruction* curr) { in >> std::noskipws; curr->clear(); if (in.eof()) { - raise << "0: unbalanced '[' for recipe\n" << end(); + raise_error << "0: unbalanced '[' for recipe\n" << end(); return false; } skip_whitespace(in); if (in.eof()) { - raise << "1: unbalanced '[' for recipe\n" << end(); + raise_error << "1: unbalanced '[' for recipe\n" << end(); return false; } skip_whitespace_and_comments(in); if (in.eof()) { - raise << "2: unbalanced '[' for recipe\n" << end(); + raise_error << "2: unbalanced '[' for recipe\n" << end(); return false; } @@ -95,7 +95,7 @@ bool next_instruction(istream& in, instruction* curr) { while (in.peek() != '\n' && !in.eof()) { skip_whitespace(in); if (in.eof()) { - raise << "3: unbalanced '[' for recipe\n" << end(); + raise_error << "3: unbalanced '[' for recipe\n" << end(); return false; } string word = next_word(in); @@ -112,7 +112,7 @@ bool next_instruction(istream& in, instruction* curr) { curr->label = words.at(0); trace("parse") << "label: " << curr->label << end(); if (in.eof()) { - raise << "7: unbalanced '[' for recipe\n" << end(); + raise_error << "7: unbalanced '[' for recipe\n" << end(); return false; } return true; @@ -128,7 +128,7 @@ bool next_instruction(istream& in, instruction* curr) { } if (p == words.end()) { - raise << "instruction prematurely ended with '<-'\n" << end(); + raise_error << "instruction prematurely ended with '<-'\n" << end(); return false; } curr->name = *p; @@ -136,7 +136,7 @@ bool next_instruction(istream& in, instruction* curr) { Recipe_ordinal[*p] = Next_recipe_ordinal++; } if (Recipe_ordinal[*p] == 0) { - raise << "Recipe " << *p << " has number 0, which is reserved for IDLE.\n" << end(); + raise_error << "Recipe " << *p << " has number 0, which is reserved for IDLE.\n" << end(); return false; } curr->operation = Recipe_ordinal[*p]; ++p; @@ -154,7 +154,7 @@ bool next_instruction(istream& in, instruction* curr) { trace("parse") << " product: " << p->to_string() << end(); } if (in.eof()) { - raise << "9: unbalanced '[' for recipe\n" << end(); + raise_error << "9: unbalanced '[' for recipe\n" << end(); return false; } return true; diff --git a/013literal_string.cc b/013literal_string.cc index 7424a31d..98cc85e7 100644 --- a/013literal_string.cc +++ b/013literal_string.cc @@ -73,7 +73,7 @@ void slurp_quoted_comment_oblivious(istream& in, ostringstream& out) { if (brace_depth == 0) break; } if (in.eof() && brace_depth > 0) { - raise << "unbalanced '['\n" << end(); + raise_error << "unbalanced '['\n" << end(); out.clear(); } } @@ -100,7 +100,7 @@ void slurp_quoted_comment_aware(istream& in, ostringstream& out) { out << c; if (c == ']') return; } - raise << "unbalanced '['\n" << end(); + raise_error << "unbalanced '['\n" << end(); out.clear(); } diff --git a/020run.cc b/020run.cc index 329bcdb0..c08049a0 100644 --- a/020run.cc +++ b/020run.cc @@ -64,7 +64,7 @@ void run_current_routine() if (current_instruction().is_label) { ++current_step_index(); continue; } trace(Initial_callstack_depth+Callstack_depth, "run") << current_instruction().to_string() << end(); if (Memory[0] != 0) { - raise << "something wrote to location 0; this should never happen\n" << end(); + raise_error << "something wrote to location 0; this should never happen\n" << end(); Memory[0] = 0; } // Read all ingredients from memory. @@ -92,7 +92,7 @@ void run_current_routine() } } if (SIZE(products) < SIZE(current_instruction().products)) { - raise << SIZE(products) << " vs " << SIZE(current_instruction().products) << ": failed to write to all products! " << current_instruction().to_string() << '\n' << end(); + raise_error << SIZE(products) << " vs " << SIZE(current_instruction().products) << ": failed to write to all products! " << current_instruction().to_string() << '\n' << end(); } else { for (long long int i = 0; i < SIZE(current_instruction().products); ++i) { @@ -210,7 +210,7 @@ void load_permanently(string filename) { ifstream fin(filename.c_str()); fin.peek(); if (!fin) { - raise << "no such file " << filename << '\n' << end(); + raise_error << "no such file " << filename << '\n' << end(); return; } fin >> std::noskipws; @@ -267,7 +267,7 @@ void write_memory(reagent x, vector<double> data) { if (is_literal(x)) return; long long int base = x.value; if (size_mismatch(x, data)) { - raise << maybe(current_recipe_name()) << "size mismatch in storing to " << x.original_string << " (" << size_of(x.types) << " vs " << SIZE(data) << ") at '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "size mismatch in storing to " << x.original_string << " (" << size_of(x.types) << " vs " << SIZE(data) << ") at '" << current_instruction().to_string() << "'\n" << end(); return; } for (long long int offset = 0; offset < SIZE(data); ++offset) { @@ -304,7 +304,7 @@ bool is_literal(const reagent& r) { return SIZE(r.types) == 1 && r.types.at(0) == 0; } -// hook to suppress inserting recipe name into warnings +// hook to suppress inserting recipe name into errors and warnings (for later layers) string maybe(string s) { return s + ": "; } @@ -334,7 +334,7 @@ recipe main [ +run: _ <- copy 0 :(scenario write_to_0_disallowed) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 0:number <- copy 34 ] diff --git a/021check_instruction.cc b/021check_instruction.cc index bf238020..fcd861da 100644 --- a/021check_instruction.cc +++ b/021check_instruction.cc @@ -21,12 +21,12 @@ void check_instruction(const recipe_ordinal r) { // Primitive Recipe Checks case COPY: { if (SIZE(inst.products) != SIZE(inst.ingredients)) { - raise << "ingredients and products should match in '" << inst.to_string() << "'\n" << end(); + raise_error << "ingredients and products should match in '" << inst.to_string() << "'\n" << end(); break; } for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!types_match(inst.products.at(i), inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "can't copy " << inst.ingredients.at(i).original_string << " to " << inst.products.at(i).original_string << "; types don't match\n" << end(); + raise_error << maybe(Recipe[r].name) << "can't copy " << inst.ingredients.at(i).original_string << " to " << inst.products.at(i).original_string << "; types don't match\n" << end(); goto finish_checking_instruction; } } @@ -43,32 +43,32 @@ void check_instruction(const recipe_ordinal r) { } :(scenario copy_checks_reagent_count) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:number <- copy 34, 35 ] -+warn: ingredients and products should match in '1:number <- copy 34, 35' ++error: ingredients and products should match in '1:number <- copy 34, 35' :(scenario write_scalar_to_array_disallowed) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:array:number <- copy 34 ] -+warn: main: can't copy 34 to 1:array:number; types don't match ++error: main: can't copy 34 to 1:array:number; types don't match :(scenario write_scalar_to_array_disallowed_2) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:number, 2:array:number <- copy 34, 35 ] -+warn: main: can't copy 35 to 2:array:number; types don't match ++error: main: can't copy 35 to 2:array:number; types don't match :(scenario write_scalar_to_address_disallowed) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:address:number <- copy 34 ] -+warn: main: can't copy 34 to 1:address:number; types don't match ++error: main: can't copy 34 to 1:address:number; types don't match :(code) bool types_match(reagent lhs, reagent rhs) { diff --git a/022arithmetic.cc b/022arithmetic.cc index fbf3029a..16fab86c 100644 --- a/022arithmetic.cc +++ b/022arithmetic.cc @@ -9,16 +9,16 @@ case ADD: { // primary goal of these checks is to forbid address arithmetic for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_number(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'add' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'add' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } if (SIZE(inst.products) > 1) { - raise << maybe(Recipe[r].name) << "'add' yields exactly one product in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'add' yields exactly one product in '" << inst.to_string() << "'\n" << end(); break; } if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) { - raise << maybe(Recipe[r].name) << "'add' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'add' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end(); break; } break; @@ -55,18 +55,18 @@ recipe main [ +mem: storing 12 in location 1 :(scenario add_checks_type) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:number <- add 2:boolean, 1 ] -+warn: main: 'add' requires number ingredients, but got 2:boolean ++error: main: 'add' requires number ingredients, but got 2:boolean :(scenario add_checks_return_type) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:address:number <- add 2, 2 ] -+warn: main: 'add' should yield a number, but got 1:address:number ++error: main: 'add' should yield a number, but got 1:address:number :(before "End Primitive Recipe Declarations") SUBTRACT, @@ -75,22 +75,22 @@ Recipe_ordinal["subtract"] = SUBTRACT; :(before "End Primitive Recipe Checks") case SUBTRACT: { if (inst.ingredients.empty()) { - raise << maybe(Recipe[r].name) << "'subtract' has no ingredients\n" << end(); + raise_error << maybe(Recipe[r].name) << "'subtract' has no ingredients\n" << end(); break; } for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (is_raw(inst.ingredients.at(i))) continue; // permit address offset computations in tests if (!is_mu_number(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'subtract' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'subtract' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } if (SIZE(inst.products) > 1) { - raise << maybe(Recipe[r].name) << "'subtract' yields exactly one product in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'subtract' yields exactly one product in '" << inst.to_string() << "'\n" << end(); break; } if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) { - raise << maybe(Recipe[r].name) << "'subtract' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'subtract' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end(); break; } break; @@ -133,16 +133,16 @@ Recipe_ordinal["multiply"] = MULTIPLY; case MULTIPLY: { for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_number(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'add' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'multiply' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } if (SIZE(inst.products) > 1) { - raise << maybe(Recipe[r].name) << "'multiply' yields exactly one product in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'multiply' yields exactly one product in '" << inst.to_string() << "'\n" << end(); break; } if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) { - raise << maybe(Recipe[r].name) << "'multiply' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'multiply' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end(); break; } break; @@ -185,21 +185,21 @@ Recipe_ordinal["divide"] = DIVIDE; :(before "End Primitive Recipe Checks") case DIVIDE: { if (inst.ingredients.empty()) { - raise << maybe(Recipe[r].name) << "'divide' has no ingredients\n" << end(); + raise_error << maybe(Recipe[r].name) << "'divide' has no ingredients\n" << end(); break; } for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_number(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'divide' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'divide' requires number ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } if (SIZE(inst.products) > 1) { - raise << maybe(Recipe[r].name) << "'divide' yields exactly one product in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'divide' yields exactly one product in '" << inst.to_string() << "'\n" << end(); break; } if (!inst.products.empty() && !is_dummy(inst.products.at(0)) && !is_mu_number(inst.products.at(0))) { - raise << maybe(Recipe[r].name) << "'divide' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'divide' should yield a number, but got " << inst.products.at(0).original_string << '\n' << end(); break; } break; @@ -243,20 +243,20 @@ Recipe_ordinal["divide-with-remainder"] = DIVIDE_WITH_REMAINDER; :(before "End Primitive Recipe Checks") case DIVIDE_WITH_REMAINDER: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(current_recipe_name()) << "'divide-with-remainder' requires exactly two ingredients, but got '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "'divide-with-remainder' requires exactly two ingredients, but got '" << current_instruction().to_string() << "'\n" << end(); break; } if (!is_mu_number(inst.ingredients.at(0)) || !is_mu_number(inst.ingredients.at(1))) { - raise << maybe(current_recipe_name()) << "'divide-with-remainder' requires number ingredients, but got '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "'divide-with-remainder' requires number ingredients, but got '" << current_instruction().to_string() << "'\n" << end(); break; } if (SIZE(inst.products) > 2) { - raise << maybe(Recipe[r].name) << "'divide-with-remainder' yields two products in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'divide-with-remainder' yields two products in '" << inst.to_string() << "'\n" << end(); break; } for (long long int i = 0; i < SIZE(inst.products); ++i) { if (!is_dummy(inst.products.at(i)) && !is_mu_number(inst.products.at(i))) { - raise << maybe(Recipe[r].name) << "'divide-with-remainder' should yield a number, but got " << inst.products.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'divide-with-remainder' should yield a number, but got " << inst.products.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } @@ -268,7 +268,7 @@ case DIVIDE_WITH_REMAINDER: { long long int a = static_cast<long long int>(ingredients.at(0).at(0)); long long int b = static_cast<long long int>(ingredients.at(1).at(0)); if (b == 0) { - raise << maybe(current_recipe_name()) << "divide by zero in '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "divide by zero in '" << current_instruction().to_string() << "'\n" << end(); break; } long long int quotient = a / b; @@ -308,12 +308,12 @@ recipe main [ +mem: storing inf in location 1 :(scenario divide_by_zero_2) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:number <- divide-with-remainder 4, 0 ] # integer division can't return floating-point infinity -+warn: main: divide by zero in '1:number <- divide-with-remainder 4, 0' ++error: main: divide by zero in '1:number <- divide-with-remainder 4, 0' :(code) inline bool scalar(const vector<long long int>& x) { diff --git a/023boolean.cc b/023boolean.cc index 24752e72..49683455 100644 --- a/023boolean.cc +++ b/023boolean.cc @@ -8,7 +8,7 @@ Recipe_ordinal["and"] = AND; case AND: { for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_scalar(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'and' requires boolean ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'and' requires boolean ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } @@ -58,7 +58,7 @@ Recipe_ordinal["or"] = OR; case OR: { for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_scalar(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'and' requires boolean ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'and' requires boolean ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } @@ -107,12 +107,12 @@ Recipe_ordinal["not"] = NOT; :(before "End Primitive Recipe Checks") case NOT: { if (SIZE(inst.products) > SIZE(inst.ingredients)) { - raise << maybe(Recipe[r].name) << "'not' cannot have fewer ingredients than products in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'not' cannot have fewer ingredients than products in '" << inst.to_string() << "'\n" << end(); break; } for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_scalar(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'not' requires boolean ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'not' requires boolean ingredients, but got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } diff --git a/024jump.cc b/024jump.cc index b249535e..9e5c0838 100644 --- a/024jump.cc +++ b/024jump.cc @@ -16,11 +16,11 @@ Recipe_ordinal["jump"] = JUMP; :(before "End Primitive Recipe Checks") case JUMP: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'jump' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'jump' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'jump' should be a label or offset, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'jump' should be a label or offset, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -55,15 +55,15 @@ Recipe_ordinal["jump-if"] = JUMP_IF; :(before "End Primitive Recipe Checks") case JUMP_IF: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'jump-if' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'jump-if' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "'jump-if' requires a boolean for its first ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'jump-if' requires a boolean for its first ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(1))) { - raise << maybe(Recipe[r].name) << "'jump-if' requires a label or offset for its second ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'jump-if' requires a label or offset for its second ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -107,15 +107,15 @@ Recipe_ordinal["jump-unless"] = JUMP_UNLESS; :(before "End Primitive Recipe Checks") case JUMP_UNLESS: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'jump-unless' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'jump-unless' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "'jump-unless' requires a boolean for its first ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'jump-unless' requires a boolean for its first ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(1))) { - raise << maybe(Recipe[r].name) << "'jump-unless' requires a label or offset for its second ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'jump-unless' requires a label or offset for its second ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; diff --git a/025compare.cc b/025compare.cc index 74f1e4f1..f7acb64c 100644 --- a/025compare.cc +++ b/025compare.cc @@ -7,7 +7,7 @@ Recipe_ordinal["equal"] = EQUAL; :(before "End Primitive Recipe Checks") case EQUAL: { if (SIZE(inst.ingredients) <= 1) { - raise << maybe(Recipe[r].name) << "'equal' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'equal' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); break; } break; @@ -66,12 +66,12 @@ Recipe_ordinal["greater-than"] = GREATER_THAN; :(before "End Primitive Recipe Checks") case GREATER_THAN: { if (SIZE(inst.ingredients) <= 1) { - raise << maybe(Recipe[r].name) << "'greater-than' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'greater-than' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); break; } for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_number(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'greater-than' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'greater-than' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } @@ -125,12 +125,12 @@ Recipe_ordinal["lesser-than"] = LESSER_THAN; :(before "End Primitive Recipe Checks") case LESSER_THAN: { if (SIZE(inst.ingredients) <= 1) { - raise << maybe(Recipe[r].name) << "'lesser-than' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'lesser-than' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); break; } for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_number(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'lesser-than' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'lesser-than' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } @@ -184,12 +184,12 @@ Recipe_ordinal["greater-or-equal"] = GREATER_OR_EQUAL; :(before "End Primitive Recipe Checks") case GREATER_OR_EQUAL: { if (SIZE(inst.ingredients) <= 1) { - raise << maybe(Recipe[r].name) << "'greater-or-equal' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'greater-or-equal' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); break; } for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_number(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'greater-or-equal' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'greater-or-equal' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } @@ -251,12 +251,12 @@ Recipe_ordinal["lesser-or-equal"] = LESSER_OR_EQUAL; :(before "End Primitive Recipe Checks") case LESSER_OR_EQUAL: { if (SIZE(inst.ingredients) <= 1) { - raise << maybe(Recipe[r].name) << "'lesser-or-equal' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'lesser-or-equal' needs at least two ingredients to compare in '" << inst.to_string() << "'\n" << end(); break; } for (long long int i = 0; i < SIZE(inst.ingredients); ++i) { if (!is_mu_number(inst.ingredients.at(i))) { - raise << maybe(Recipe[r].name) << "'lesser-or-equal' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'lesser-or-equal' can only compare numbers; got " << inst.ingredients.at(i).original_string << '\n' << end(); goto finish_checking_instruction; } } diff --git a/029tools.cc b/029tools.cc index 17dea6ef..d17c9b81 100644 --- a/029tools.cc +++ b/029tools.cc @@ -13,15 +13,15 @@ Recipe_ordinal["trace"] = TRACE; :(before "End Primitive Recipe Checks") case TRACE: { if (SIZE(inst.ingredients) < 3) { - raise << maybe(Recipe[r].name) << "'trace' takes three or more ingredients rather than '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'trace' takes three or more ingredients rather than '" << inst.to_string() << "'\n" << end(); break; } if (!is_mu_number(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'trace' should be a number (depth), but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'trace' should be a number (depth), but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } if (!is_literal_string(inst.ingredients.at(1))) { - raise << maybe(Recipe[r].name) << "second ingredient of 'trace' should be a literal string (label), but got " << inst.ingredients.at(1).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "second ingredient of 'trace' should be a literal string (label), but got " << inst.ingredients.at(1).original_string << '\n' << end(); break; } break; @@ -90,30 +90,30 @@ string print_mu(const reagent& r, const vector<double>& data) { } :(before "End Primitive Recipe Declarations") -HIDE_WARNINGS, +HIDE_ERRORS, :(before "End Primitive Recipe Numbers") -Recipe_ordinal["hide-warnings"] = HIDE_WARNINGS; +Recipe_ordinal["hide-errors"] = HIDE_ERRORS; :(before "End Primitive Recipe Checks") -case HIDE_WARNINGS: { +case HIDE_ERRORS: { break; } :(before "End Primitive Recipe Implementations") -case HIDE_WARNINGS: { - Hide_warnings = true; +case HIDE_ERRORS: { + Hide_errors = true; break; } :(before "End Primitive Recipe Declarations") -SHOW_WARNINGS, +SHOW_ERRORS, :(before "End Primitive Recipe Numbers") -Recipe_ordinal["show-warnings"] = SHOW_WARNINGS; +Recipe_ordinal["show-errors"] = SHOW_ERRORS; :(before "End Primitive Recipe Checks") -case SHOW_WARNINGS: { +case SHOW_ERRORS: { break; } :(before "End Primitive Recipe Implementations") -case SHOW_WARNINGS: { - Hide_warnings = false; +case SHOW_ERRORS: { + Hide_errors = false; break; } @@ -170,11 +170,11 @@ case _CLEAR_TRACE: { //: assert: perform sanity checks at runtime :(scenario assert) -% Hide_warnings = true; // '%' lines insert arbitrary C code into tests before calling 'run' with the lines below. Must be immediately after :(scenario) line. +% Hide_errors = true; // '%' lines insert arbitrary C code into tests before calling 'run' with the lines below. Must be immediately after :(scenario) line. recipe main [ assert 0, [this is an assert in mu] ] -+warn: this is an assert in mu ++error: this is an assert in mu :(before "End Primitive Recipe Declarations") ASSERT, @@ -183,15 +183,15 @@ Recipe_ordinal["assert"] = ASSERT; :(before "End Primitive Recipe Checks") case ASSERT: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'assert' takes exactly two ingredients rather than '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'assert' takes exactly two ingredients rather than '" << inst.to_string() << "'\n" << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "'assert' requires a boolean for its first ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'assert' requires a boolean for its first ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } if (!is_literal_string(inst.ingredients.at(1))) { - raise << maybe(Recipe[r].name) << "'assert' requires a literal string for its second ingredient, but got " << inst.ingredients.at(1).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'assert' requires a literal string for its second ingredient, but got " << inst.ingredients.at(1).original_string << '\n' << end(); break; } break; @@ -199,7 +199,7 @@ case ASSERT: { :(before "End Primitive Recipe Implementations") case ASSERT: { if (!ingredients.at(0).at(0)) { - raise << current_instruction().ingredients.at(1).name << '\n' << end(); + raise_error << current_instruction().ingredients.at(1).name << '\n' << end(); } break; } @@ -255,8 +255,8 @@ _SYSTEM, Recipe_ordinal["$system"] = _SYSTEM; :(before "End Primitive Recipe Checks") case _SYSTEM: { - if (inst.ingredients.empty()) { - raise << maybe(Recipe[r].name) << "'$system' requires exactly one ingredient, but got none\n" << end(); + if (SIZE(inst.ingredients) != 1) { + raise_error << maybe(Recipe[r].name) << "'$system' requires exactly one ingredient, but got none\n" << end(); break; } break; diff --git a/030container.cc b/030container.cc index 0cecdec7..a0b214a0 100644 --- a/030container.cc +++ b/030container.cc @@ -16,7 +16,7 @@ Type[point].elements.push_back(i); //: Tests in this layer often explicitly setup memory before reading it as a //: container. Don't do this in general. I'm tagging exceptions with /raw to -//: avoid warnings. +//: avoid errors. :(scenario copy_multiple_locations) recipe main [ 1:number <- copy 34 @@ -28,11 +28,11 @@ recipe main [ //: trying to copy to a differently-typed destination will fail :(scenario copy_checks_size) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 2:point <- copy 1:number ] -+warn: main: can't copy 1:number to 2:point; types don't match ++error: main: can't copy 1:number to 2:point; types don't match :(before "End Mu Types Initialization") // A more complex container, containing another container as one of its @@ -92,7 +92,7 @@ if (t.kind == container) { for (long long int i = 0; i < SIZE(t.elements); ++i) { // todo: strengthen assertion to disallow mutual type recursion if (types.at(0) == t.elements.at(i).at(0)) { - raise << "container " << t.name << " can't include itself as a member\n" << end(); + raise_error << "container " << t.name << " can't include itself as a member\n" << end(); return 0; } // End size_of(type) Container Cases @@ -126,26 +126,26 @@ Recipe_ordinal["get"] = GET; :(before "End Primitive Recipe Checks") case GET: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'get' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'get' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); break; } reagent base = inst.ingredients.at(0); // Update GET base in Check if (base.types.empty() || Type[base.types.at(0)].kind != container) { - raise << maybe(Recipe[r].name) << "first ingredient of 'get' should be a container, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'get' should be a container, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } type_ordinal base_type = base.types.at(0); reagent offset = inst.ingredients.at(1); if (!is_literal(offset) || !is_mu_scalar(offset)) { - raise << maybe(Recipe[r].name) << "second ingredient of 'get' should have type 'offset', but got " << inst.ingredients.at(1).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "second ingredient of 'get' should have type 'offset', but got " << inst.ingredients.at(1).original_string << '\n' << end(); break; } long long int offset_value = 0; if (is_integer(offset.name)) { // later layers permit non-integer offsets offset_value = to_integer(offset.name); if (offset_value < 0 || offset_value >= SIZE(Type[base_type].elements)) { - raise << maybe(Recipe[r].name) << "invalid offset " << offset_value << " for " << Type[base_type].name << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "invalid offset " << offset_value << " for " << Type[base_type].name << '\n' << end(); break; } } @@ -157,7 +157,7 @@ case GET: { reagent element; element.types = Type[base_type].elements.at(offset_value); if (!types_match(product, element)) { - raise << maybe(Recipe[r].name) << "'get' " << offset.original_string << " (" << offset_value << ") on " << Type[base_type].name << " can't be saved in " << product.original_string << "; type should be " << dump_types(element) << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'get' " << offset.original_string << " (" << offset_value << ") on " << Type[base_type].name << " can't be saved in " << product.original_string << "; type should be " << dump_types(element) << '\n' << end(); break; } break; @@ -168,7 +168,7 @@ case GET: { // Update GET base in Run long long int base_address = base.value; if (base_address == 0) { - raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); break; } type_ordinal base_type = base.types.at(0); @@ -219,34 +219,34 @@ recipe main [ +mem: storing 13 in location 15 :(scenario get_out_of_bounds) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 12:number <- copy 34 13:number <- copy 35 14:number <- copy 36 get 12:point-number/raw, 2:offset # point-number occupies 3 locations but has only 2 fields; out of bounds ] -+warn: main: invalid offset 2 for point-number ++error: main: invalid offset 2 for point-number :(scenario get_out_of_bounds_2) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 12:number <- copy 34 13:number <- copy 35 14:number <- copy 36 get 12:point-number/raw, -1:offset ] -+warn: main: invalid offset -1 for point-number ++error: main: invalid offset -1 for point-number :(scenario get_product_type_mismatch) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 12:number <- copy 34 13:number <- copy 35 14:number <- copy 36 15:address:number <- get 12:point-number/raw, 1:offset ] -+warn: main: 'get' 1:offset (1) on point-number can't be saved in 15:address:number; type should be number ++error: main: 'get' 1:offset (1) on point-number can't be saved in 15:address:number; type should be number :(before "End Primitive Recipe Declarations") GET_ADDRESS, @@ -255,26 +255,26 @@ Recipe_ordinal["get-address"] = GET_ADDRESS; :(before "End Primitive Recipe Checks") case GET_ADDRESS: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'get-address' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'get-address' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); break; } reagent base = inst.ingredients.at(0); // Update GET_ADDRESS base in Check if (base.types.empty() || Type[base.types.at(0)].kind != container) { - raise << maybe(Recipe[r].name) << "first ingredient of 'get-address' should be a container, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'get-address' should be a container, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } type_ordinal base_type = base.types.at(0); reagent offset = inst.ingredients.at(1); if (!is_literal(offset) || !is_mu_scalar(offset)) { - raise << maybe(Recipe[r].name) << "second ingredient of 'get' should have type 'offset', but got " << inst.ingredients.at(1).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "second ingredient of 'get' should have type 'offset', but got " << inst.ingredients.at(1).original_string << '\n' << end(); break; } long long int offset_value = 0; if (is_integer(offset.name)) { // later layers permit non-integer offsets offset_value = to_integer(offset.name); if (offset_value < 0 || offset_value >= SIZE(Type[base_type].elements)) { - raise << maybe(Recipe[r].name) << "invalid offset " << offset_value << " for " << Type[base_type].name << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "invalid offset " << offset_value << " for " << Type[base_type].name << '\n' << end(); break; } } @@ -287,7 +287,7 @@ case GET_ADDRESS: { element.types = Type[base_type].elements.at(offset_value); element.types.insert(element.types.begin(), Type_ordinal["address"]); if (!types_match(product, element)) { - raise << maybe(Recipe[r].name) << "'get-address' " << offset.original_string << " (" << offset_value << ") on " << Type[base_type].name << " can't be saved in " << product.original_string << "; type should be " << dump_types(element) << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'get-address' " << offset.original_string << " (" << offset_value << ") on " << Type[base_type].name << " can't be saved in " << product.original_string << "; type should be " << dump_types(element) << '\n' << end(); break; } break; @@ -298,7 +298,7 @@ case GET_ADDRESS: { // Update GET_ADDRESS base in Run long long int base_address = base.value; if (base_address == 0) { - raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); break; } type_ordinal base_type = base.types.at(0); @@ -316,34 +316,34 @@ case GET_ADDRESS: { } :(scenario get_address_out_of_bounds) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 12:number <- copy 34 13:number <- copy 35 14:number <- copy 36 get-address 12:point-number/raw, 2:offset # point-number occupies 3 locations but has only 2 fields; out of bounds ] -+warn: main: invalid offset 2 for point-number ++error: main: invalid offset 2 for point-number :(scenario get_address_out_of_bounds_2) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 12:number <- copy 34 13:number <- copy 35 14:number <- copy 36 get-address 12:point-number/raw, -1:offset ] -+warn: main: invalid offset -1 for point-number ++error: main: invalid offset -1 for point-number :(scenario get_address_product_type_mismatch) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 12:number <- copy 34 13:number <- copy 35 14:number <- copy 36 15:number <- get-address 12:point-number/raw, 1:offset ] -+warn: main: 'get-address' 1:offset (1) on point-number can't be saved in 15:number; type should be address:number ++error: main: 'get-address' 1:offset (1) on point-number can't be saved in 15:number; type should be address:number //:: Allow containers to be defined in mu code. @@ -427,7 +427,7 @@ void insert_container(const string& command, kind_of_type kind, istream& in) { void skip_bracket(istream& in, string message) { skip_whitespace_and_comments(in); if (in.get() != '[') - raise << message << '\n' << end(); + raise_error << message << '\n' << end(); } :(scenarios run) @@ -482,19 +482,19 @@ assert(Next_type_ordinal < 1000); :(before "End Setup") Next_type_ordinal = 1000; -//:: Allow container definitions anywhere in the codebase, but warn if you -//:: can't find a definition. +//:: Allow container definitions anywhere in the codebase, but complain if you +//:: can't find a definition at the end. -:(scenario run_warns_on_unknown_types) -% Hide_warnings = true; +:(scenario run_complains_on_unknown_types) +% Hide_errors = true; recipe main [ # integer is not a type 1:integer <- copy 0 ] -+warn: unknown type: integer ++error: unknown type: integer :(scenario run_allows_type_definition_after_use) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:bar <- copy 0/raw ] @@ -502,8 +502,8 @@ recipe main [ container bar [ x:number ] --warn: unknown type: bar -$warn: 0 +-error: unknown type: bar +$error: 0 :(after "int main") Transform.push_back(check_invalid_types); @@ -525,17 +525,17 @@ void check_invalid_types(const reagent& r) { for (long long int i = 0; i < SIZE(r.types); ++i) { if (r.types.at(i) == 0) continue; if (Type.find(r.types.at(i)) == Type.end()) - raise << "unknown type: " << r.properties.at(0).second.at(i) << '\n' << end(); + raise_error << "unknown type: " << r.properties.at(0).second.at(i) << '\n' << end(); } } :(scenario container_unknown_field) -% Hide_warnings = true; +% Hide_errors = true; container foo [ x:number y:bar ] -+warn: unknown type for field y in foo ++error: unknown type for field y in foo :(scenario read_container_with_bracket_in_comment) container foo [ @@ -561,7 +561,7 @@ void check_container_field_types() { if (info.elements.at(i).at(j) == 0) continue; if (Type.find(info.elements.at(i).at(j)) != Type.end()) continue; // End Container Type Checks - raise << "unknown type for field " << info.element_names.at(i) << " in " << info.name << '\n' << end(); + raise_error << "unknown type for field " << info.element_names.at(i) << " in " << info.name << '\n' << end(); } } } @@ -630,11 +630,11 @@ map<string, type_ordinal> ingredient_names; if (element.find(':') == string::npos) { // no type; we're defining a generic variable if (next_word(in) != "<-") { - raise << "Element " << element << " of container " << name << " doesn't provide a type.\n" << end(); + raise_error << "Element " << element << " of container " << name << " doesn't provide a type.\n" << end(); break; } if (next_word(in) != "next-type") { - raise << "Type " << element << " of container " << name << " must be defined using 'next-type'\n" << end(); + raise_error << "Type " << element << " of container " << name << " must be defined using 'next-type'\n" << end(); break; } type_ordinal next_type_ordinal = SIZE(info.ingredient_names); diff --git a/031address.cc b/031address.cc index 66172fbe..fd7c61e0 100644 --- a/031address.cc +++ b/031address.cc @@ -25,19 +25,19 @@ recipe main [ :(before "long long int base = x.value" following "void write_memory(reagent x, vector<double> data)") x = canonize(x); if (x.value == 0) { - raise << "can't write to location 0 in '" << current_instruction().to_string() << "'\n" << end(); + raise_error << "can't write to location 0 in '" << current_instruction().to_string() << "'\n" << end(); return; } //: writes to address 0 always loudly fail -:(scenario store_to_0_warns) -% Hide_warnings = true; +:(scenario store_to_0_fails) +% Hide_errors = true; recipe main [ 1:address:number <- copy 0 1:address:number/lookup <- copy 34 ] -mem: storing 34 in location 0 -+warn: can't write to location 0 in '1:address:number/lookup <- copy 34' ++error: can't write to location 0 in '1:address:number/lookup <- copy 34' :(code) reagent canonize(reagent x) { @@ -52,12 +52,12 @@ reagent lookup_memory(reagent x) { static const type_ordinal ADDRESS = Type_ordinal["address"]; reagent result; if (x.types.empty() || x.types.at(0) != ADDRESS) { - raise << maybe(current_recipe_name()) << "tried to /lookup " << x.original_string << " but it isn't an address\n" << end(); + raise_error << maybe(current_recipe_name()) << "tried to /lookup " << x.original_string << " but it isn't an address\n" << end(); return result; } // compute value if (x.value == 0) { - raise << maybe(current_recipe_name()) << "tried to /lookup 0\n" << end(); + raise_error << maybe(current_recipe_name()) << "tried to /lookup 0\n" << end(); return result; } result.set_value(Memory[x.value]); @@ -97,11 +97,11 @@ reagent lookup_memory(reagent x) { bool canonize_type(reagent& r) { while (has_property(r, "lookup")) { if (r.types.empty()) { - raise << "can't lookup non-address: " << r.original_string << '\n' << end(); + raise_error << "can't lookup non-address: " << r.original_string << '\n' << end(); return false; } if (r.types.at(0) != Type_ordinal["address"]) { - raise << "can't lookup non-address: " << r.original_string << '\n' << end(); + raise_error << "can't lookup non-address: " << r.original_string << '\n' << end(); return false; } r.types.erase(r.types.begin()); @@ -180,7 +180,7 @@ recipe main [ properties.push_back(pair<string, vector<string> >("lookup", vector<string>())); } if (name.empty()) - raise << "illegal name " << original_string << '\n' << end(); + raise_error << "illegal name " << original_string << '\n' << end(); } //:: helpers for debugging diff --git a/032array.cc b/032array.cc index f8df003f..1a1b2d17 100644 --- a/032array.cc +++ b/032array.cc @@ -20,26 +20,26 @@ Recipe_ordinal["create-array"] = CREATE_ARRAY; :(before "End Primitive Recipe Checks") case CREATE_ARRAY: { if (inst.products.empty()) { - raise << maybe(Recipe[r].name) << "'create-array' needs one product and no ingredients but got '" << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'create-array' needs one product and no ingredients but got '" << inst.to_string() << '\n' << end(); break; } reagent product = inst.products.at(0); canonize_type(product); if (!is_mu_array(product)) { - raise << maybe(Recipe[r].name) << "'create-array' cannot create non-array " << product.original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'create-array' cannot create non-array " << product.original_string << '\n' << end(); break; } if (SIZE(product.types) == 1) { - raise << maybe(Recipe[r].name) << "create array of what? " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "create array of what? " << inst.to_string() << '\n' << end(); break; } // 'create-array' will need to check properties rather than types if (SIZE(product.properties.at(0).second) <= 2) { - raise << maybe(Recipe[r].name) << "create array of what size? " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "create array of what size? " << inst.to_string() << '\n' << end(); break; } if (!is_integer(product.properties.at(0).second.at(2))) { - raise << maybe(Recipe[r].name) << "'create-array' product should specify size of array after its element type, but got " << product.properties.at(0).second.at(2) << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'create-array' product should specify size of array after its element type, but got " << product.properties.at(0).second.at(2) << '\n' << end(); break; } break; @@ -108,7 +108,7 @@ if (x.types.at(0) == Type_ordinal["array"]) return false; :(before "End size_of(reagent) Cases") if (r.types.at(0) == Type_ordinal["array"]) { if (SIZE(r.types) == 1) { - raise << maybe(current_recipe_name()) << "'" << r.original_string << "' is an array of what?\n" << end(); + raise_error << maybe(current_recipe_name()) << "'" << r.original_string << "' is an array of what?\n" << end(); return 1; } // skip the 'array' type to get at the element type @@ -145,13 +145,13 @@ Recipe_ordinal["index"] = INDEX; :(before "End Primitive Recipe Checks") case INDEX: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'index' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'index' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); break; } reagent base = inst.ingredients.at(0); canonize_type(base); if (!is_mu_array(base)) { - raise << maybe(Recipe[r].name) << "'index' on a non-array " << base.original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'index' on a non-array " << base.original_string << '\n' << end(); break; } if (inst.products.empty()) break; @@ -160,7 +160,7 @@ case INDEX: { reagent element; element.types = array_element(base.types); if (!types_match(product, element)) { - raise << maybe(Recipe[r].name) << "'index' on " << base.original_string << " can't be saved in " << product.original_string << "; type should be " << dump_types(element) << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'index' on " << base.original_string << " can't be saved in " << product.original_string << "; type should be " << dump_types(element) << '\n' << end(); break; } break; @@ -170,14 +170,14 @@ case INDEX: { reagent base = canonize(current_instruction().ingredients.at(0)); long long int base_address = base.value; if (base_address == 0) { - raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); break; } reagent offset = canonize(current_instruction().ingredients.at(1)); vector<double> offset_val(read_memory(offset)); vector<type_ordinal> element_type = array_element(base.types); if (offset_val.at(0) < 0 || offset_val.at(0) >= Memory[base_address]) { - raise << maybe(current_recipe_name()) << "invalid index " << no_scientific(offset_val.at(0)) << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "invalid index " << no_scientific(offset_val.at(0)) << '\n' << end(); break; } long long int src = base_address + 1 + offset_val.at(0)*size_of(element_type); @@ -207,7 +207,7 @@ recipe main [ +mem: storing 15 in location 6 :(scenario index_out_of_bounds) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:array:number:3 <- create-array 2:number <- copy 14 @@ -219,10 +219,10 @@ recipe main [ 8:address:array:point <- copy 1 index *8:address:array:point, 4 # less than size of array in locations, but larger than its length in elements ] -+warn: main: invalid index 4 ++error: main: invalid index 4 :(scenario index_out_of_bounds_2) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:array:point:3 <- create-array 2:number <- copy 14 @@ -234,10 +234,10 @@ recipe main [ 8:address:array:point <- copy 1/raw index *8:address:array:point, -1 ] -+warn: main: invalid index -1 ++error: main: invalid index -1 :(scenario index_product_type_mismatch) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:array:point:3 <- create-array 2:number <- copy 14 @@ -249,7 +249,7 @@ recipe main [ 8:address:array:point <- copy 1/raw 9:number <- index *8:address:array:point, 0 ] -+warn: main: 'index' on *8:address:array:point can't be saved in 9:number; type should be point ++error: main: 'index' on *8:address:array:point can't be saved in 9:number; type should be point //:: To write to elements of containers, you need their address. @@ -270,13 +270,13 @@ Recipe_ordinal["index-address"] = INDEX_ADDRESS; :(before "End Primitive Recipe Checks") case INDEX_ADDRESS: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'index-address' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'index-address' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); break; } reagent base = inst.ingredients.at(0); canonize_type(base); if (!is_mu_array(base)) { - raise << current_recipe_name () << "'index-address' on a non-array " << base.original_string << '\n' << end(); + raise_error << current_recipe_name () << "'index-address' on a non-array " << base.original_string << '\n' << end(); break; } if (inst.products.empty()) break; @@ -286,7 +286,7 @@ case INDEX_ADDRESS: { element.types = array_element(base.types); element.types.insert(element.types.begin(), Type_ordinal["address"]); if (!types_match(product, element)) { - raise << maybe(Recipe[r].name) << "'index' on " << base.original_string << " can't be saved in " << product.original_string << "; type should be " << dump_types(element) << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'index' on " << base.original_string << " can't be saved in " << product.original_string << "; type should be " << dump_types(element) << '\n' << end(); break; } break; @@ -296,14 +296,14 @@ case INDEX_ADDRESS: { reagent base = canonize(current_instruction().ingredients.at(0)); long long int base_address = base.value; if (base_address == 0) { - raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); break; } reagent offset = canonize(current_instruction().ingredients.at(1)); vector<double> offset_val(read_memory(offset)); vector<type_ordinal> element_type = array_element(base.types); if (offset_val.at(0) < 0 || offset_val.at(0) >= Memory[base_address]) { - raise << maybe(current_recipe_name()) << "invalid index " << no_scientific(offset_val.at(0)) << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "invalid index " << no_scientific(offset_val.at(0)) << '\n' << end(); break; } long long int result = base_address + 1 + offset_val.at(0)*size_of(element_type); @@ -313,7 +313,7 @@ case INDEX_ADDRESS: { } :(scenario index_address_out_of_bounds) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:array:point:3 <- create-array 2:number <- copy 14 @@ -325,10 +325,10 @@ recipe main [ 8:address:array:point <- copy 1 # unsafe index-address *8:address:array:point, 4 # less than size of array in locations, but larger than its length in elements ] -+warn: main: invalid index 4 ++error: main: invalid index 4 :(scenario index_address_out_of_bounds_2) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:array:point:3 <- create-array 2:number <- copy 14 @@ -340,10 +340,10 @@ recipe main [ 8:address:array:point <- copy 1/raw index-address *8:address:array:point, -1 ] -+warn: main: invalid index -1 ++error: main: invalid index -1 :(scenario index_address_product_type_mismatch) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:array:point:3 <- create-array 2:number <- copy 14 @@ -355,7 +355,7 @@ recipe main [ 8:address:array:point <- copy 1/raw 9:address:number <- index-address *8:address:array:point, 0 ] -+warn: main: 'index' on *8:address:array:point can't be saved in 9:address:number; type should be address:point ++error: main: 'index' on *8:address:array:point can't be saved in 9:address:number; type should be address:point //:: compute the length of an array @@ -376,13 +376,13 @@ Recipe_ordinal["length"] = LENGTH; :(before "End Primitive Recipe Checks") case LENGTH: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'length' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'length' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); break; } reagent x = inst.ingredients.at(0); canonize_type(x); if (!is_mu_array(x)) { - raise << "tried to calculate length of non-array " << x.original_string << '\n' << end(); + raise_error << "tried to calculate length of non-array " << x.original_string << '\n' << end(); break; } break; @@ -391,7 +391,7 @@ case LENGTH: { case LENGTH: { reagent x = canonize(current_instruction().ingredients.at(0)); if (x.value == 0) { - raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); break; } products.resize(1); diff --git a/033exclusive_container.cc b/033exclusive_container.cc index d4973c7c..388a4f4f 100644 --- a/033exclusive_container.cc +++ b/033exclusive_container.cc @@ -23,7 +23,7 @@ Type[tmp].element_names.push_back("p"); //: Tests in this layer often explicitly setup memory before reading it as an //: array. Don't do this in general. I'm tagging exceptions with /raw to -//: avoid warnings. +//: avoid errors. :(scenario copy_exclusive_container) # Copying exclusive containers copies all their contents and an extra location for the tag. recipe main [ @@ -84,17 +84,17 @@ Recipe_ordinal["maybe-convert"] = MAYBE_CONVERT; :(before "End Primitive Recipe Checks") case MAYBE_CONVERT: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'maybe-convert' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'maybe-convert' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); break; } reagent base = inst.ingredients.at(0); canonize_type(base); if (base.types.empty() || Type[base.types.at(0)].kind != exclusive_container) { - raise << current_recipe_name () << "first ingredient of 'maybe-convert' should be an exclusive-container, but got " << base.original_string << '\n' << end(); + raise_error << current_recipe_name () << "first ingredient of 'maybe-convert' should be an exclusive-container, but got " << base.original_string << '\n' << end(); break; } if (!is_literal(inst.ingredients.at(1))) { - raise << maybe(Recipe[r].name) << "second ingredient of 'maybe-convert' should have type 'variant', but got " << inst.ingredients.at(1).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "second ingredient of 'maybe-convert' should have type 'variant', but got " << inst.ingredients.at(1).original_string << '\n' << end(); break; } break; @@ -104,7 +104,7 @@ case MAYBE_CONVERT: { reagent base = canonize(current_instruction().ingredients.at(0)); long long int base_address = base.value; if (base_address == 0) { - raise << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(current_recipe_name()) << "tried to access location 0 in '" << current_instruction().to_string() << "'\n" << end(); break; } long long int tag = current_instruction().ingredients.at(1).value; diff --git a/034call.cc b/034call.cc index 27a26e90..ebfb9534 100644 --- a/034call.cc +++ b/034call.cc @@ -80,7 +80,7 @@ inline const instruction& current_instruction() { :(after "Defined Recipe Checks") // not a primitive; check that it's present in the book of recipes if (Recipe.find(inst.operation) == Recipe.end()) { - raise << maybe(Recipe[r].name) << "undefined operation in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "undefined operation in '" << inst.to_string() << "'\n" << end(); break; } :(replace{} "default:" following "End Primitive Recipe Implementations") @@ -98,19 +98,19 @@ default: { continue; // not done with caller; don't increment current_step_index() } -:(scenario calling_undefined_recipe_warns) -% Hide_warnings = true; +:(scenario calling_undefined_recipe_fails) +% Hide_errors = true; recipe main [ foo ] -+warn: main: undefined operation in 'foo ' ++error: main: undefined operation in 'foo ' :(scenario calling_undefined_recipe_handles_missing_result) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ x:number <- foo ] -+warn: main: undefined operation in 'x:number <- foo ' ++error: main: undefined operation in 'x:number <- foo ' //:: finally, we need to fix the termination conditions for the run loop @@ -133,7 +133,7 @@ while (current_step_index() >= SIZE(Current_routine->steps())) { Current_routine->calls.pop_front(); if (Current_routine->calls.empty()) return; // Complete Call Fallthrough - // todo: no products returned warning + // todo: fail if no products returned ++current_step_index(); } diff --git a/035call_ingredient.cc b/035call_ingredient.cc index fd8e7508..a56510d6 100644 --- a/035call_ingredient.cc +++ b/035call_ingredient.cc @@ -38,7 +38,7 @@ Recipe_ordinal["next-ingredient"] = NEXT_INGREDIENT; :(before "End Primitive Recipe Checks") case NEXT_INGREDIENT: { if (!inst.ingredients.empty()) { - raise << maybe(Recipe[r].name) << "'next-ingredient' didn't expect any ingredients in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'next-ingredient' didn't expect any ingredients in '" << inst.to_string() << "'\n" << end(); break; } break; @@ -55,7 +55,7 @@ case NEXT_INGREDIENT: { } else { if (SIZE(current_instruction().products) < 2) - raise << maybe(current_recipe_name()) << "no ingredient to save in " << current_instruction().products.at(0).original_string << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "no ingredient to save in " << current_instruction().products.at(0).original_string << '\n' << end(); if (current_instruction().products.empty()) break; products.resize(2); // pad the first product with sufficient zeros to match its type @@ -68,15 +68,15 @@ case NEXT_INGREDIENT: { break; } -:(scenario next_ingredient_warn_on_missing) -% Hide_warnings = true; +:(scenario next_ingredient_fail_on_missing) +% Hide_errors = true; recipe main [ f ] recipe f [ 11:number <- next-ingredient ] -+warn: f: no ingredient to save in 11:number ++error: f: no ingredient to save in 11:number :(scenario rewind_ingredients) recipe main [ @@ -125,11 +125,11 @@ Recipe_ordinal["ingredient"] = INGREDIENT; :(before "End Primitive Recipe Checks") case INGREDIENT: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'ingredient' expects exactly one ingredient, but got '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'ingredient' expects exactly one ingredient, but got '" << inst.to_string() << "'\n" << end(); break; } - if (!is_literal(inst.ingredients.at(0)) && !is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "'ingredient' expects a literal ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + if (!is_literal(inst.ingredients.at(0)) && !is_mu_number(inst.ingredients.at(0))) { + raise_error << maybe(Recipe[r].name) << "'ingredient' expects a literal ingredient, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; diff --git a/036call_reply.cc b/036call_reply.cc index 14fb0c5c..ccf18a2f 100644 --- a/036call_reply.cc +++ b/036call_reply.cc @@ -32,13 +32,13 @@ case REPLY: { const instruction& caller_instruction = current_instruction(); // check types with the caller if (SIZE(caller_instruction.products) > SIZE(ingredients)) { - raise << "too few values replied from " << callee << '\n' << end(); + raise_error << "too few values replied from " << callee << '\n' << end(); break; } for (long long int i = 0; i < SIZE(caller_instruction.products); ++i) { if (has_property(caller_instruction.products.at(i), "skiptypecheck")) continue; // todo: drop this once we have generic containers if (!types_match(caller_instruction.products.at(i), reply_inst.ingredients.at(i))) { - raise << maybe(callee) << "reply ingredient " << reply_inst.ingredients.at(i).original_string << " can't be saved in " << caller_instruction.products.at(i).original_string << '\n' << end(); + raise_error << maybe(callee) << "reply ingredient " << reply_inst.ingredients.at(i).original_string << " can't be saved in " << caller_instruction.products.at(i).original_string << '\n' << end(); goto finish_reply; } } @@ -51,14 +51,14 @@ case REPLY: { if (has_property(reply_inst.ingredients.at(i), "same-as-ingredient")) { vector<string> tmp = property(reply_inst.ingredients.at(i), "same-as-ingredient"); if (SIZE(tmp) != 1) { - raise << maybe(current_recipe_name()) << "'same-as-ingredient' metadata should take exactly one value in " << reply_inst.to_string() << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "'same-as-ingredient' metadata should take exactly one value in " << reply_inst.to_string() << '\n' << end(); goto finish_reply; } long long int ingredient_index = to_integer(tmp.at(0)); if (ingredient_index >= SIZE(caller_instruction.ingredients)) - raise << maybe(current_recipe_name()) << "'same-as-ingredient' metadata overflows ingredients in: " << caller_instruction.to_string() << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "'same-as-ingredient' metadata overflows ingredients in: " << caller_instruction.to_string() << '\n' << end(); if (!is_dummy(caller_instruction.products.at(i)) && caller_instruction.products.at(i).value != caller_instruction.ingredients.at(ingredient_index).value) - raise << maybe(current_recipe_name()) << "'same-as-ingredient' product from call to " << callee << " must be " << caller_instruction.ingredients.at(ingredient_index).original_string << " rather than " << caller_instruction.products.at(i).original_string << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "'same-as-ingredient' product from call to " << callee << " must be " << caller_instruction.ingredients.at(ingredient_index).original_string << " rather than " << caller_instruction.products.at(i).original_string << '\n' << end(); } } // End Reply @@ -81,7 +81,7 @@ recipe f [ +mem: storing 35 in location 4 :(scenario reply_type_mismatch) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 3:number <- f 2 ] @@ -91,7 +91,7 @@ recipe f [ 14:point <- copy 12:point/raw reply 14:point ] -+warn: f: reply ingredient 14:point can't be saved in 3:number ++error: f: reply ingredient 14:point can't be saved in 3:number //: In mu we'd like to assume that any instruction doesn't modify its //: ingredients unless they're also products. The /same-as-ingredient inside @@ -99,7 +99,7 @@ recipe f [ //: 'ingredient-products' (sometimes called in-out parameters in other languages). :(scenario reply_same_as_ingredient) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:number <- copy 0 2:number <- test1 1:number # call with different ingredient and product @@ -108,10 +108,10 @@ recipe test1 [ 10:number <- next-ingredient reply 10:number/same-as-ingredient:0 ] -+warn: main: 'same-as-ingredient' product from call to test1 must be 1:number rather than 2:number ++error: main: 'same-as-ingredient' product from call to test1 must be 1:number rather than 2:number :(scenario reply_same_as_ingredient_dummy) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:number <- copy 0 _ <- test1 1:number # call with different ingredient and product @@ -120,7 +120,7 @@ recipe test1 [ 10:address:number <- next-ingredient reply 10:address:number/same-as-ingredient:0 ] -$warn: 0 +$error: 0 :(code) string to_string(const vector<double>& in) { @@ -182,7 +182,7 @@ if (curr.name == "reply-if") { curr.ingredients.swap(results); } else { - raise << "'reply-if' never yields any products\n" << end(); + raise_error << "'reply-if' never yields any products\n" << end(); } } // rewrite `reply-unless a, b, c, ...` to @@ -205,6 +205,6 @@ if (curr.name == "reply-unless") { curr.ingredients.swap(results); } else { - raise << "'reply-unless' never yields any products\n" << end(); + raise_error << "'reply-unless' never yields any products\n" << end(); } } diff --git a/037recipe.cc b/037recipe.cc index c3f258da..f7dd62d7 100644 --- a/037recipe.cc +++ b/037recipe.cc @@ -43,11 +43,11 @@ Recipe_ordinal["call"] = CALL; :(before "End Primitive Recipe Checks") case CALL: { if (inst.ingredients.empty()) { - raise << maybe(Recipe[r].name) << "'call' requires at least one ingredient (the recipe to call)\n" << end(); + raise_error << maybe(Recipe[r].name) << "'call' requires at least one ingredient (the recipe to call)\n" << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'call' should be a recipe, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'call' should be a recipe, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; diff --git a/038scheduler.cc b/038scheduler.cc index 8f2706ff..ac16db22 100644 --- a/038scheduler.cc +++ b/038scheduler.cc @@ -147,11 +147,11 @@ Recipe_ordinal["start-running"] = START_RUNNING; :(before "End Primitive Recipe Checks") case START_RUNNING: { if (inst.ingredients.empty()) { - raise << maybe(Recipe[r].name) << "'start-running' requires at least one ingredient: the recipe to start running\n" << end(); + raise_error << maybe(Recipe[r].name) << "'start-running' requires at least one ingredient: the recipe to start running\n" << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'start-running' should be a recipe, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'start-running' should be a recipe, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -258,7 +258,7 @@ recipe f1 [ //:: Errors in a routine cause it to terminate. :(scenario scheduler_terminates_routines_after_errors) -% Hide_warnings = true; +% Hide_errors = true; % Scheduling_interval = 2; recipe f1 [ start-running f2:recipe @@ -271,11 +271,11 @@ recipe f2 [ 4:number <- divide-with-remainder 4, 0 ] # f2 should stop after first divide by 0 -+warn: f2: divide by zero in '3:number <- divide-with-remainder 4, 0' --warn: f2: divide by zero in '4:number <- divide-with-remainder 4, 0' ++error: f2: divide by zero in '3:number <- divide-with-remainder 4, 0' +-error: f2: divide by zero in '4:number <- divide-with-remainder 4, 0' :(after "operator<<(ostream& os, unused end)") - if (Trace_stream && Trace_stream->curr_label == "warn" && Current_routine) { + if (Trace_stream && Trace_stream->curr_label == "error" && Current_routine) { Current_routine->state = COMPLETED; } @@ -333,11 +333,11 @@ Recipe_ordinal["routine-state"] = ROUTINE_STATE; :(before "End Primitive Recipe Checks") case ROUTINE_STATE: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'routine-state' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'routine-state' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'routine-state' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'routine-state' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -366,11 +366,11 @@ Recipe_ordinal["restart"] = RESTART; :(before "End Primitive Recipe Checks") case RESTART: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'restart' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'restart' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'restart' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'restart' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -394,11 +394,11 @@ Recipe_ordinal["stop"] = STOP; :(before "End Primitive Recipe Checks") case STOP: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'stop' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'stop' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'stop' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'stop' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -476,15 +476,15 @@ Recipe_ordinal["limit-time"] = LIMIT_TIME; :(before "End Primitive Recipe Checks") case LIMIT_TIME: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'limit-time' requires exactly two ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'limit-time' requires exactly two ingredient, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'limit-time' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'limit-time' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(1))) { - raise << maybe(Recipe[r].name) << "second ingredient of 'limit-time' should be a number (of instructions to run for), but got " << inst.ingredients.at(1).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "second ingredient of 'limit-time' should be a number (of instructions to run for), but got " << inst.ingredients.at(1).original_string << '\n' << end(); break; } break; diff --git a/039wait.cc b/039wait.cc index b21f92ca..314ab1cd 100644 --- a/039wait.cc +++ b/039wait.cc @@ -95,11 +95,11 @@ Recipe_ordinal["wait-for-routine"] = WAIT_FOR_ROUTINE; :(before "End Primitive Recipe Checks") case WAIT_FOR_ROUTINE: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'wait-for-routine' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'wait-for-routine' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } - if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'wait-for-routine' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); + if (!is_mu_number(inst.ingredients.at(0))) { + raise_error << maybe(Recipe[r].name) << "first ingredient of 'wait-for-routine' should be a routine id generated by 'start-running', but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -107,7 +107,7 @@ case WAIT_FOR_ROUTINE: { :(before "End Primitive Recipe Implementations") case WAIT_FOR_ROUTINE: { if (ingredients.at(0).at(0) == Current_routine->id) { - raise << maybe(current_recipe_name()) << "routine can't wait for itself! " << current_instruction().to_string() << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "routine can't wait for itself! " << current_instruction().to_string() << '\n' << end(); break; } Current_routine->state = WAITING; diff --git a/040brace.cc b/040brace.cc index d5e89a6c..ba8e9fd6 100644 --- a/040brace.cc +++ b/040brace.cc @@ -76,7 +76,7 @@ void transform_braces(const recipe_ordinal r) { // check for errors if (inst.name.find("-if") != string::npos || inst.name.find("-unless") != string::npos) { if (inst.ingredients.empty()) { - raise << inst.name << " expects 1 or 2 ingredients, but got none\n" << end(); + raise_error << inst.name << " expects 1 or 2 ingredients, but got none\n" << end(); continue; } } @@ -107,7 +107,7 @@ void transform_braces(const recipe_ordinal r) { target.types.push_back(Type_ordinal["offset"]); target.set_value(0); if (open_braces.empty()) - raise << inst.name << " needs a '{' before\n" << end(); + raise_error << inst.name << " needs a '{' before\n" << end(); else if (inst.name.find("loop") != string::npos) target.set_value(open_braces.top()-index); else // break instruction @@ -132,7 +132,7 @@ long long int matching_brace(long long int index, const list<pair<int, long long stacksize += (p->first ? 1 : -1); if (stacksize == 0) return p->second; } - raise << maybe(Recipe[r].name) << "unbalanced '{'\n" << end(); + raise_error << maybe(Recipe[r].name) << "unbalanced '{'\n" << end(); return SIZE(Recipe[r].steps); // exit current routine } @@ -279,7 +279,7 @@ recipe main [ +after-brace: jump 2:offset :(scenario break_label) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:number <- copy 0 { @@ -361,18 +361,18 @@ recipe test-factorial [ ] +mem: location 2 is 120 -:(scenario break_outside_braces_warns) -% Hide_warnings = true; +:(scenario break_outside_braces_fails) +% Hide_errors = true; recipe main [ break ] -+warn: break needs a '{' before ++error: break needs a '{' before -:(scenario break_conditional_without_ingredient_warns) -% Hide_warnings = true; +:(scenario break_conditional_without_ingredient_fails) +% Hide_errors = true; recipe main [ { break-if } ] -+warn: break-if expects 1 or 2 ingredients, but got none ++error: break-if expects 1 or 2 ingredients, but got none diff --git a/041jump_target.cc b/041jump_target.cc index fad1e3c7..7207c799 100644 --- a/041jump_target.cc +++ b/041jump_target.cc @@ -31,7 +31,7 @@ void transform_labels(const recipe_ordinal r) { offset[inst.label] = i; } else { - raise << maybe(Recipe[r].name) << "duplicate label '" << inst.label << "'" << end(); + raise_error << maybe(Recipe[r].name) << "duplicate label '" << inst.label << "'" << end(); // have all jumps skip some random but noticeable and deterministic amount of code offset[inst.label] = 9999; } @@ -60,19 +60,19 @@ void transform_labels(const recipe_ordinal r) { :(code) void replace_offset(reagent& x, /*const*/ map<string, long long int>& offset, const long long int current_offset, const recipe_ordinal r) { if (!is_literal(x)) { - raise << maybe(Recipe[r].name) << "jump target must be offset or label but is " << x.original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "jump target must be offset or label but is " << x.original_string << '\n' << end(); x.set_value(0); // no jump by default return; } assert(!x.initialized); if (is_integer(x.name)) return; // non-labels will be handled like other number operands if (!is_jump_target(x.name)) { - raise << maybe(Recipe[r].name) << "can't jump to label " << x.name << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "can't jump to label " << x.name << '\n' << end(); x.set_value(0); // no jump by default return; } if (offset.find(x.name) == offset.end()) { - raise << maybe(Recipe[r].name) << "can't find label " << x.name << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "can't find label " << x.name << '\n' << end(); x.set_value(0); // no jump by default return; } @@ -133,18 +133,18 @@ recipe main [ +mem: storing 0 in location 5 -mem: storing 0 in location 4 -:(scenario recipe_warns_on_duplicate_jump_target) -% Hide_warnings = true; +:(scenario recipe_fails_on_duplicate_jump_target) +% Hide_errors = true; recipe main [ +label 1:number <- copy 0 +label 2:number <- copy 0 ] -+warn: main: duplicate label '+label' ++error: main: duplicate label '+label' :(scenario jump_ignores_nontarget_label) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ # first a few lines of padding to exercise the offset computation 1:number <- copy 0 @@ -155,4 +155,4 @@ recipe main [ $target 5:number <- copy 0 ] -+warn: main: can't jump to label $target ++error: main: can't jump to label $target diff --git a/042name.cc b/042name.cc index fbc83abd..99fda76c 100644 --- a/042name.cc +++ b/042name.cc @@ -10,12 +10,13 @@ recipe main [ +mem: storing 0 in location 1 :(scenarios transform) -:(scenario transform_names_warns) -% Hide_warnings = true; +:(scenario transform_names_fails_on_use_before_define) +% Hide_errors = true; recipe main [ x:number <- copy y:number ] -+warn: main: use before set: y ++error: main: use before set: y +# todo: detect conditional defines :(after "int main") Transform.push_back(transform_names); @@ -44,7 +45,7 @@ void transform_names(const recipe_ordinal r) { if (is_named_location(inst.ingredients.at(in))) names_used = true; if (disqualified(inst.ingredients.at(in), inst, Recipe[r].name)) continue; if (!already_transformed(inst.ingredients.at(in), names)) { - raise << maybe(Recipe[r].name) << "use before set: " << inst.ingredients.at(in).name << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "use before set: " << inst.ingredients.at(in).name << '\n' << end(); } inst.ingredients.at(in).set_value(lookup_name(inst.ingredients.at(in), r)); } @@ -61,12 +62,12 @@ void transform_names(const recipe_ordinal r) { } } if (names_used && numeric_locations_used) - raise << maybe(Recipe[r].name) << "mixing variable names and numeric addresses\n" << end(); + raise_error << maybe(Recipe[r].name) << "mixing variable names and numeric addresses\n" << end(); } bool disqualified(/*mutable*/ reagent& x, const instruction& inst, const string& recipe_name) { if (x.types.empty()) { - raise << maybe(recipe_name) << "missing type for " << x.original_string << " in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(recipe_name) << "missing type for " << x.original_string << " in '" << inst.to_string() << "'\n" << end(); return true; } if (is_raw(x)) return true; @@ -89,7 +90,7 @@ type_ordinal skip_addresses(const vector<type_ordinal>& types, const string& rec for (long long int i = 0; i < SIZE(types); ++i) { if (types.at(i) != Type_ordinal["address"]) return types.at(i); } - raise << maybe(recipe_name) << "expected a container" << '\n' << end(); + raise_error << maybe(recipe_name) << "expected a container" << '\n' << end(); return -1; } @@ -98,7 +99,7 @@ int find_element_name(const type_ordinal t, const string& name, const string& re for (long long int i = 0; i < SIZE(container.element_names); ++i) { if (container.element_names.at(i) == name) return i; } - raise << maybe(recipe_name) << "unknown element " << name << " in container " << Type[t].name << '\n' << end(); + raise_error << maybe(recipe_name) << "unknown element " << name << " in container " << Type[t].name << '\n' << end(); return -1; } @@ -134,44 +135,44 @@ recipe main [ //: an escape hatch to suppress name conversion that we'll use later :(scenarios run) :(scenario transform_names_passes_raw) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ x:number/raw <- copy 0 ] -name: assign x 1 -+warn: can't write to location 0 in 'x:number/raw <- copy 0' ++error: can't write to location 0 in 'x:number/raw <- copy 0' :(scenarios transform) -:(scenario transform_names_warns_when_mixing_names_and_numeric_locations) -% Hide_warnings = true; +:(scenario transform_names_fails_when_mixing_names_and_numeric_locations) +% Hide_errors = true; recipe main [ x:number <- copy 1:number ] -+warn: main: mixing variable names and numeric addresses ++error: main: mixing variable names and numeric addresses -:(scenario transform_names_warns_when_mixing_names_and_numeric_locations_2) -% Hide_warnings = true; +:(scenario transform_names_fails_when_mixing_names_and_numeric_locations_2) +% Hide_errors = true; recipe main [ x:number <- copy 1 1:number <- copy x:number ] -+warn: main: mixing variable names and numeric addresses ++error: main: mixing variable names and numeric addresses -:(scenario transform_names_does_not_warn_when_mixing_names_and_raw_locations) -% Hide_warnings = true; +:(scenario transform_names_does_not_fail_when_mixing_names_and_raw_locations) +% Hide_errors = true; recipe main [ x:number <- copy 1:number/raw ] --warn: main: mixing variable names and numeric addresses -$warn: 0 +-error: main: mixing variable names and numeric addresses +$error: 0 -:(scenario transform_names_does_not_warn_when_mixing_names_and_literals) -% Hide_warnings = true; +:(scenario transform_names_does_not_fail_when_mixing_names_and_literals) +% Hide_errors = true; recipe main [ x:number <- copy 1 ] --warn: main: mixing variable names and numeric addresses -$warn: 0 +-error: main: mixing variable names and numeric addresses +$error: 0 //:: Support element names for containers in 'get' and 'get-address'. @@ -193,11 +194,11 @@ recipe main [ if (inst.operation == Recipe_ordinal["get"] || inst.operation == Recipe_ordinal["get-address"]) { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "exactly 2 ingredients expected in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "exactly 2 ingredients expected in '" << inst.to_string() << "'\n" << end(); break; } if (!is_literal(inst.ingredients.at(1))) - raise << maybe(Recipe[r].name) << "expected ingredient 1 of " << (inst.operation == Recipe_ordinal["get"] ? "'get'" : "'get-address'") << " to have type 'offset'; got " << inst.ingredients.at(1).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "expected ingredient 1 of " << (inst.operation == Recipe_ordinal["get"] ? "'get'" : "'get-address'") << " to have type 'offset'; got " << inst.ingredients.at(1).original_string << '\n' << end(); if (inst.ingredients.at(1).name.find_first_not_of("0123456789") != string::npos) { // since first non-address in base type must be a container, we don't have to canonize type_ordinal base_type = skip_addresses(inst.ingredients.at(0).types, Recipe[r].name); @@ -233,7 +234,7 @@ recipe main [ // convert variant names of exclusive containers if (inst.operation == Recipe_ordinal["maybe-convert"]) { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "exactly 2 ingredients expected in '" << current_instruction().to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "exactly 2 ingredients expected in '" << current_instruction().to_string() << "'\n" << end(); break; } assert(is_literal(inst.ingredients.at(1))); diff --git a/043new.cc b/043new.cc index 6bd733d1..f821fad3 100644 --- a/043new.cc +++ b/043new.cc @@ -34,13 +34,13 @@ if (inst.operation == Recipe_ordinal["new"]) { // End NEW Transform Special-cases // first arg must be of type 'type' if (inst.ingredients.empty()) - raise << maybe(Recipe[r].name) << "'new' expects one or two ingredients\n" << end(); + raise_error << maybe(Recipe[r].name) << "'new' expects one or two ingredients\n" << end(); if (inst.ingredients.at(0).properties.empty() || inst.ingredients.at(0).properties.at(0).second.empty() || inst.ingredients.at(0).properties.at(0).second.at(0) != "type") - raise << maybe(Recipe[r].name) << "first ingredient of 'new' should be a type, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'new' should be a type, but got " << inst.ingredients.at(0).original_string << '\n' << end(); if (Type_ordinal.find(inst.ingredients.at(0).name) == Type_ordinal.end()) - raise << maybe(Recipe[r].name) << "unknown type " << inst.ingredients.at(0).name << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "unknown type " << inst.ingredients.at(0).name << '\n' << end(); inst.ingredients.at(0).set_value(Type_ordinal[inst.ingredients.at(0).name]); trace(Primitive_recipe_depth, "new") << inst.ingredients.at(0).name << " -> " << inst.ingredients.at(0).name << end(); end_new_transform:; @@ -56,12 +56,12 @@ Recipe_ordinal["new"] = NEW; :(before "End Primitive Recipe Checks") case NEW: { if (inst.ingredients.empty() || SIZE(inst.ingredients) > 2) { - raise << maybe(Recipe[r].name) << "'new' requires one or two ingredients, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'new' requires one or two ingredients, but got " << inst.to_string() << '\n' << end(); break; } reagent type = inst.ingredients.at(0); if (!is_mu_scalar(type) && !is_literal(type)) { - raise << maybe(Recipe[r].name) << "first ingredient of 'new' should be a type, but got " << type.original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'new' should be a type, but got " << type.original_string << '\n' << end(); break; } break; @@ -221,13 +221,13 @@ Recipe_ordinal["abandon"] = ABANDON; :(before "End Primitive Recipe Checks") case ABANDON: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'abandon' requires one ingredient, but got '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'abandon' requires one ingredient, but got '" << inst.to_string() << "'\n" << end(); break; } reagent types = inst.ingredients.at(0); canonize_type(types); if (types.types.empty() || types.types.at(0) != Type_ordinal["address"]) { - raise << maybe(Recipe[r].name) << "first ingredient of 'abandon' should be an address, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'abandon' should be an address, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -260,7 +260,7 @@ if (Free_list[size]) { Free_list[size] = Memory[result]; for (long long int curr = result+1; curr < result+size; ++curr) { if (Memory[curr] != 0) { - raise << maybe(current_recipe_name()) << "memory in free list was not zeroed out: " << curr << '/' << result << "; somebody wrote to us after free!!!\n" << end(); + raise_error << maybe(current_recipe_name()) << "memory in free list was not zeroed out: " << curr << '/' << result << "; somebody wrote to us after free!!!\n" << end(); break; // always fatal } } diff --git a/044space.cc b/044space.cc index 59b292a5..55e3cc23 100644 --- a/044space.cc +++ b/044space.cc @@ -52,7 +52,7 @@ reagent absolutize(reagent x) { if (is_raw(x) || is_dummy(x)) return x; if (x.name == "default-space") return x; if (!x.initialized) { - raise << current_instruction().to_string() << ": reagent not initialized: " << x.original_string << '\n' << end(); + raise_error << current_instruction().to_string() << ": reagent not initialized: " << x.original_string << '\n' << end(); return x; } reagent r = x; @@ -133,12 +133,12 @@ if (curr.name == "new-default-space") { vector<double> result; result.push_back(Name[Recipe_ordinal[current_recipe_name()]][""]); if (result.back() == 0) - raise << "no space allocated for default-space in recipe " << current_recipe_name() << "; are you using names\n" << end(); + raise_error << "no space allocated for default-space in recipe " << current_recipe_name() << "; are you using names\n" << end(); return result; } :(after "void write_memory(reagent x, vector<double> data)") if (x.name == "number-of-locals") { - raise << maybe(current_recipe_name()) << "can't write to special name 'number-of-locals'\n" << end(); + raise_error << maybe(current_recipe_name()) << "can't write to special name 'number-of-locals'\n" << end(); return; } @@ -185,11 +185,11 @@ void try_reclaim_locals() { void rewrite_default_space_instruction(instruction& curr) { curr.operation = Recipe_ordinal["new"]; if (!curr.ingredients.empty()) - raise << "new-default-space can't take any ingredients\n" << end(); + raise_error << "new-default-space can't take any ingredients\n" << end(); curr.ingredients.push_back(reagent("location:type")); curr.ingredients.push_back(reagent("number-of-locals:literal")); if (!curr.products.empty()) - raise << "new-default-space can't take any results\n" << end(); + raise_error << "new-default-space can't take any results\n" << end(); curr.products.push_back(reagent("default-space:address:array:location")); } @@ -204,7 +204,7 @@ long long int address(long long int offset, long long int base) { if (base == 0) return offset; // raw if (offset >= static_cast<long long int>(Memory[base])) { // todo: test - raise << "location " << offset << " is out of bounds " << no_scientific(Memory[base]) << " at " << base << '\n' << end(); + raise_error << "location " << offset << " is out of bounds " << no_scientific(Memory[base]) << " at " << base << '\n' << end(); } return base+1 + offset; } @@ -212,7 +212,7 @@ long long int address(long long int offset, long long int base) { :(after "void write_memory(reagent x, vector<double> data)") if (x.name == "default-space") { if (!scalar(data)) - raise << maybe(current_recipe_name()) << "'default-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "'default-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end(); Current_routine->calls.front().default_space = data.at(0); return; } diff --git a/045space_surround.cc b/045space_surround.cc index 94a717a0..a29ad67c 100644 --- a/045space_surround.cc +++ b/045space_surround.cc @@ -42,7 +42,7 @@ long long int space_index(const reagent& x) { for (long long int i = /*skip name:type*/1; i < SIZE(x.properties); ++i) { if (x.properties.at(i).first == "space") { if (SIZE(x.properties.at(i).second) != 1) - raise << maybe(current_recipe_name()) << "/space metadata should take exactly one value in " << x.original_string << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "/space metadata should take exactly one value in " << x.original_string << '\n' << end(); return to_integer(x.properties.at(i).second.at(0)); } } diff --git a/046closure_name.cc b/046closure_name.cc index eef4753f..82ba5db3 100644 --- a/046closure_name.cc +++ b/046closure_name.cc @@ -50,19 +50,19 @@ void collect_surrounding_spaces(const recipe_ordinal r) { || inst.products.at(j).types.at(0) != Type_ordinal["address"] || inst.products.at(j).types.at(1) != Type_ordinal["array"] || inst.products.at(j).types.at(2) != Type_ordinal["location"]) { - raise << "slot 0 should always have type address:array:location, but is " << inst.products.at(j).to_string() << '\n' << end(); + raise_error << "slot 0 should always have type address:array:location, but is " << inst.products.at(j).to_string() << '\n' << end(); continue; } vector<string> s = property(inst.products.at(j), "names"); if (s.empty()) { - raise << "slot 0 requires a /names property in recipe " << Recipe[r].name << end(); + raise_error << "slot 0 requires a /names property in recipe " << Recipe[r].name << end(); continue; } - if (SIZE(s) > 1) raise << "slot 0 should have a single value in /names, but got " << inst.products.at(j).to_string() << '\n' << end(); + if (SIZE(s) > 1) raise_error << "slot 0 should have a single value in /names, but got " << inst.products.at(j).to_string() << '\n' << end(); string surrounding_recipe_name = s.at(0); if (Surrounding_space.find(r) != Surrounding_space.end() && Surrounding_space[r] != Recipe_ordinal[surrounding_recipe_name]) { - raise << "recipe " << Recipe[r].name << " can have only one 'surrounding' recipe but has " << Recipe[Surrounding_space[r]].name << " and " << surrounding_recipe_name << '\n' << end(); + raise_error << "recipe " << Recipe[r].name << " can have only one 'surrounding' recipe but has " << Recipe[Surrounding_space[r]].name << " and " << surrounding_recipe_name << '\n' << end(); continue; } trace("name") << "recipe " << Recipe[r].name << " is surrounded by " << surrounding_recipe_name << end(); @@ -77,11 +77,11 @@ void collect_surrounding_spaces(const recipe_ordinal r) { :(replace{} "long long int lookup_name(const reagent& r, const recipe_ordinal default_recipe)") long long int lookup_name(const reagent& x, const recipe_ordinal default_recipe) { if (!has_property(x, "space")) { - if (Name[default_recipe].empty()) raise << "name not found: " << x.name << '\n' << end(); + if (Name[default_recipe].empty()) raise_error << "name not found: " << x.name << '\n' << end(); return Name[default_recipe][x.name]; } vector<string> p = property(x, "space"); - if (SIZE(p) != 1) raise << "/space property should have exactly one (non-negative integer) value\n" << end(); + if (SIZE(p) != 1) raise_error << "/space property should have exactly one (non-negative integer) value\n" << end(); long long int n = to_integer(p.at(0)); assert(n >= 0); recipe_ordinal surrounding_recipe = lookup_surrounding_recipe(default_recipe, n); @@ -95,11 +95,11 @@ long long int lookup_name(const reagent& x, const recipe_ordinal default_recipe) long long int lookup_name(const reagent& x, const recipe_ordinal r, set<recipe_ordinal>& done, vector<recipe_ordinal>& path) { if (!Name[r].empty()) return Name[r][x.name]; if (done.find(r) != done.end()) { - raise << "can't compute address of " << x.to_string() << " because " << end(); + raise_error << "can't compute address of " << x.to_string() << " because " << end(); for (long long int i = 1; i < SIZE(path); ++i) { - raise << path.at(i-1) << " requires computing names of " << path.at(i) << '\n' << end(); + raise_error << path.at(i-1) << " requires computing names of " << path.at(i) << '\n' << end(); } - raise << path.at(SIZE(path)-1) << " requires computing names of " << r << "..ad infinitum\n" << end(); + raise_error << path.at(SIZE(path)-1) << " requires computing names of " << r << "..ad infinitum\n" << end(); return 0; } done.insert(r); @@ -112,20 +112,20 @@ long long int lookup_name(const reagent& x, const recipe_ordinal r, set<recipe_o recipe_ordinal lookup_surrounding_recipe(const recipe_ordinal r, long long int n) { if (n == 0) return r; if (Surrounding_space.find(r) == Surrounding_space.end()) { - raise << "don't know surrounding recipe of " << Recipe[r].name << '\n' << end(); + raise_error << "don't know surrounding recipe of " << Recipe[r].name << '\n' << end(); return 0; } assert(Surrounding_space[r]); return lookup_surrounding_recipe(Surrounding_space[r], n-1); } -//: weaken use-before-set warnings just a tad +//: weaken use-before-set detection just a tad :(replace{} "bool already_transformed(const reagent& r, const map<string, long long int>& names)") bool already_transformed(const reagent& r, const map<string, long long int>& names) { if (has_property(r, "space")) { vector<string> p = property(r, "space"); if (SIZE(p) != 1) { - raise << "/space property should have exactly one (non-negative integer) value in " << r.original_string << '\n' << end(); + raise_error << "/space property should have exactly one (non-negative integer) value in " << r.original_string << '\n' << end(); return false; } if (p.at(0) != "0") return true; diff --git a/047global.cc b/047global.cc index 00e8ff15..d0a3d47e 100644 --- a/047global.cc +++ b/047global.cc @@ -31,10 +31,15 @@ long long int global_space; global_space = 0; :(after "void write_memory(reagent x, vector<double> data)") if (x.name == "global-space") { - if (!scalar(data)) - raise << maybe(current_recipe_name()) << "'global-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end(); + if (!scalar(data) + || SIZE(x.types) != 3 + || x.types.at(0) != Type_ordinal["address"] + || x.types.at(1) != Type_ordinal["array"] + || x.types.at(2) != Type_ordinal["location"]) { + raise_error << maybe(current_recipe_name()) << "'global-space' should be of type address:array:location, but tried to write " << to_string(data) << '\n' << end(); + } if (Current_routine->global_space) - raise << "routine already has a global-space; you can't over-write your globals" << end(); + raise_error << "routine already has a global-space; you can't over-write your globals" << end(); Current_routine->global_space = data.at(0); return; } @@ -43,7 +48,7 @@ global_space = 0; :(after "long long int space_base(const reagent& x)") if (is_global(x)) { if (!Current_routine->global_space) - raise << "routine has no global space\n" << end(); + raise_error << "routine has no global space\n" << end(); return Current_routine->global_space; } @@ -51,14 +56,14 @@ global_space = 0; //: don't want to make them too comfortable to use. :(scenario global_space_with_names) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ global-space:address:array:location <- new location:type, 10 x:number <- copy 23 1:number/space:global <- copy 24 ] -# don't warn that we're mixing numeric addresses and names -$warn: 0 +# don't complain about mixing numeric addresses and names +$error: 0 :(after "bool is_numeric_location(const reagent& x)") if (is_global(x)) return false; diff --git a/048check_type_by_name.cc b/048check_type_by_name.cc index cd113631..e96c54f2 100644 --- a/048check_type_by_name.cc +++ b/048check_type_by_name.cc @@ -6,13 +6,13 @@ //: every single time. You can't use the same name with multiple types in a //: single recipe. -:(scenario transform_warns_on_reusing_name_with_different_type) -% Hide_warnings = true; +:(scenario transform_fails_on_reusing_name_with_different_type) +% Hide_errors = true; recipe main [ x:number <- copy 1 x:boolean <- copy 1 ] -+warn: main: x used with multiple types ++error: main: x used with multiple types :(after "int main") Transform.push_back(check_types_by_name); @@ -38,11 +38,11 @@ void check_metadata(map<string, vector<type_ordinal> >& metadata, const reagent& if (is_raw(x)) return; // if you use raw locations you're probably doing something unsafe if (is_integer(x.name)) return; - if (x.types.empty()) return; // will throw a more precise warning elsewhere + if (x.types.empty()) return; // will throw a more precise error elsewhere if (metadata.find(x.name) == metadata.end()) metadata[x.name] = x.types; if (metadata[x.name] != x.types) - raise << maybe(Recipe[r].name) << x.name << " used with multiple types\n" << end(); + raise_error << maybe(Recipe[r].name) << x.name << " used with multiple types\n" << end(); } :(scenario transform_fills_in_missing_types) @@ -74,18 +74,18 @@ recipe main [ ] +mem: storing 2 in location 1 -:(scenario transform_warns_on_missing_types_in_first_mention) -% Hide_warnings = true; +:(scenario transform_fails_on_missing_types_in_first_mention) +% Hide_errors = true; recipe main [ x <- copy 1 x:number <- copy 2 ] -+warn: main: missing type for x in 'x <- copy 1' ++error: main: missing type for x in 'x <- copy 1' -:(scenario typo_in_address_type_warns) -% Hide_warnings = true; +:(scenario typo_in_address_type_fails) +% Hide_errors = true; recipe main [ y:address:charcter <- new character:type *y <- copy 67 ] -+warn: unknown type: charcter ++error: unknown type: charcter diff --git a/050scenario.cc b/050scenario.cc index 5f92fec8..6dbd9f56 100644 --- a/050scenario.cc +++ b/050scenario.cc @@ -75,7 +75,7 @@ scenario parse_scenario(istream& in) { scenario result; result.name = next_word(in); if (Scenario_names.find(result.name) != Scenario_names.end()) - raise << "duplicate scenario name: " << result.name << '\n' << end(); + raise_error << "duplicate scenario name: " << result.name << '\n' << end(); Scenario_names.insert(result.name); skip_whitespace_and_comments(in); assert(in.peek() == '['); @@ -224,7 +224,7 @@ recipe main [ +mem: storing 13 in location 1 +mem: storing 13 in location 2 -//: 'memory-should-contain' raises warnings if specific locations aren't as expected +//: 'memory-should-contain' raises errors if specific locations aren't as expected //: Also includes some special support for checking strings. :(before "End Globals") @@ -234,14 +234,14 @@ Scenario_testing_scenario = false; :(scenario memory_check) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ memory-should-contain [ 1 <- 13 ] ] +run: checking location 1 -+warn: expected location 1 to contain 13 but saw 0 ++error: expected location 1 to contain 13 but saw 0 :(before "End Primitive Recipe Declarations") MEMORY_SHOULD_CONTAIN, @@ -277,16 +277,16 @@ void check_memory(const string& s) { skip_whitespace_and_comments(in); double value = 0; in >> value; if (locations_checked.find(address) != locations_checked.end()) - raise << "duplicate expectation for location " << address << '\n' << end(); + raise_error << "duplicate expectation for location " << address << '\n' << end(); trace(Primitive_recipe_depth, "run") << "checking location " << address << end(); if (Memory[address] != value) { if (Current_scenario && !Scenario_testing_scenario) { // genuine test in a mu file - raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain " << no_scientific(value) << " but saw " << no_scientific(Memory[address]) << '\n' << end(); + raise_error << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain " << no_scientific(value) << " but saw " << no_scientific(Memory[address]) << '\n' << end(); } else { // just testing scenario support - raise << "expected location " << address << " to contain " << no_scientific(value) << " but saw " << no_scientific(Memory[address]) << '\n' << end(); + raise_error << "expected location " << address << " to contain " << no_scientific(value) << " but saw " << no_scientific(Memory[address]) << '\n' << end(); } if (!Scenario_testing_scenario) { Passed = false; @@ -314,16 +314,16 @@ void check_type(const string& lhs, istream& in) { check_string(address, literal); return; } - raise << "don't know how to check memory for " << lhs << '\n' << end(); + raise_error << "don't know how to check memory for " << lhs << '\n' << end(); } void check_string(long long int address, const string& literal) { trace(Primitive_recipe_depth, "run") << "checking string length at " << address << end(); if (Memory[address] != SIZE(literal)) { if (Current_scenario && !Scenario_testing_scenario) - raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << no_scientific(Memory[address]) << '\n' << end(); + raise_error << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << no_scientific(Memory[address]) << '\n' << end(); else - raise << "expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << no_scientific(Memory[address]) << '\n' << end(); + raise_error << "expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << no_scientific(Memory[address]) << '\n' << end(); if (!Scenario_testing_scenario) { Passed = false; ++Num_failures; @@ -336,11 +336,11 @@ void check_string(long long int address, const string& literal) { if (Memory[address+i] != literal.at(i)) { if (Current_scenario && !Scenario_testing_scenario) { // genuine test in a mu file - raise << "\nF - " << Current_scenario->name << ": expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << no_scientific(Memory[address+i]) << '\n' << end(); + raise_error << "\nF - " << Current_scenario->name << ": expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << no_scientific(Memory[address+i]) << '\n' << end(); } else { // just testing scenario support - raise << "expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << no_scientific(Memory[address+i]) << '\n' << end(); + raise_error << "expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << no_scientific(Memory[address+i]) << '\n' << end(); } if (!Scenario_testing_scenario) { Passed = false; @@ -353,18 +353,18 @@ void check_string(long long int address, const string& literal) { :(scenario memory_check_multiple) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ memory-should-contain [ 1 <- 0 1 <- 0 ] ] -+warn: duplicate expectation for location 1 ++error: duplicate expectation for location 1 :(scenario memory_check_string_length) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:number <- copy 3 2:number <- copy 97 # 'a' @@ -374,7 +374,7 @@ recipe main [ 1:string <- [ab] ] ] -+warn: expected location 1 to contain length 2 of string [ab] but saw 3 ++error: expected location 1 to contain length 2 of string [ab] but saw 3 :(scenario memory_check_string) recipe main [ @@ -397,16 +397,16 @@ recipe main [ // that the lines are present *and* in the specified sequence. (There can be // other lines in between.) -:(scenario trace_check_warns_on_failure) +:(scenario trace_check_fails) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ trace-should-contain [ a: b a: d ] ] -+warn: missing [b] in trace with label a ++error: missing [b] in trace with label a :(before "End Primitive Recipe Declarations") TRACE_SHOULD_CONTAIN, @@ -424,7 +424,7 @@ case TRACE_SHOULD_CONTAIN: { } :(code) -// simplified version of check_trace_contents() that emits warnings rather +// simplified version of check_trace_contents() that emits errors rather // than just printing to stderr bool check_trace(const string& expected) { Trace_stream->newline(); @@ -441,8 +441,8 @@ bool check_trace(const string& expected) { } } - raise << "missing [" << expected_lines.at(curr_expected_line).contents << "] " - << "in trace with label " << expected_lines.at(curr_expected_line).label << '\n' << end(); + raise_error << "missing [" << expected_lines.at(curr_expected_line).contents << "] " + << "in trace with label " << expected_lines.at(curr_expected_line).label << '\n' << end(); Passed = false; return false; } @@ -459,9 +459,9 @@ vector<trace_line> parse_trace(const string& expected) { return result; } -:(scenario trace_check_warns_on_failure_in_later_line) +:(scenario trace_check_fails_in_nonfirst_line) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ run [ trace 1, [a], [b] @@ -471,11 +471,11 @@ recipe main [ a: d ] ] -+warn: missing [d] in trace with label a ++error: missing [d] in trace with label a :(scenario trace_check_passes_silently) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ run [ trace 1, [a], [b] @@ -484,16 +484,16 @@ recipe main [ a: b ] ] --warn: missing [b] in trace with label a -$warn: 0 +-error: missing [b] in trace with label a +$error: 0 //: 'trace-should-not-contain' is like the '-' lines in our scenarios so far //: Each trace line is separately checked for absense. Order is *not* //: important, so you can't say things like "B should not exist after A." -:(scenario trace_negative_check_warns_on_failure) +:(scenario trace_negative_check_fails) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ run [ trace 1, [a], [b] @@ -502,7 +502,7 @@ recipe main [ a: b ] ] -+warn: unexpected [b] in trace with label a ++error: unexpected [b] in trace with label a :(before "End Primitive Recipe Declarations") TRACE_SHOULD_NOT_CONTAIN, @@ -520,14 +520,14 @@ case TRACE_SHOULD_NOT_CONTAIN: { } :(code) -// simplified version of check_trace_contents() that emits warnings rather +// simplified version of check_trace_contents() that emits errors rather // than just printing to stderr bool check_trace_missing(const string& in) { Trace_stream->newline(); vector<trace_line> lines = parse_trace(in); for (long long int i = 0; i < SIZE(lines); ++i) { if (trace_count(lines.at(i).label, lines.at(i).contents) != 0) { - raise << "unexpected [" << lines.at(i).contents << "] in trace with label " << lines.at(i).label << '\n' << end(); + raise_error << "unexpected [" << lines.at(i).contents << "] in trace with label " << lines.at(i).label << '\n' << end(); Passed = false; return false; } @@ -537,18 +537,18 @@ bool check_trace_missing(const string& in) { :(scenario trace_negative_check_passes_silently) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ trace-should-not-contain [ a: b ] ] --warn: unexpected [b] in trace with label a -$warn: 0 +-error: unexpected [b] in trace with label a +$error: 0 -:(scenario trace_negative_check_warns_on_any_unexpected_line) +:(scenario trace_negative_check_fails_on_any_unexpected_line) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ run [ trace 1, [a], [d] @@ -558,7 +558,7 @@ recipe main [ a: d ] ] -+warn: unexpected [d] in trace with label a ++error: unexpected [d] in trace with label a :(scenario trace_count_check) recipe main [ @@ -575,15 +575,15 @@ Recipe_ordinal["check-trace-count-for-label"] = CHECK_TRACE_COUNT_FOR_LABEL; :(before "End Primitive Recipe Checks") case CHECK_TRACE_COUNT_FOR_LABEL: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'check-trace-for-label' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(Recipe[r].name) << "'check-trace-for-label' requires exactly two ingredients, but got '" << inst.to_string() << "'\n" << end(); break; } - if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'check-trace-for-label' should be a number (count), but got " << inst.ingredients.at(0).original_string << '\n' << end(); + if (!is_mu_number(inst.ingredients.at(0))) { + raise_error << maybe(Recipe[r].name) << "first ingredient of 'check-trace-for-label' should be a number (count), but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } if (!is_literal_string(inst.ingredients.at(1))) { - raise << maybe(Recipe[r].name) << "second ingredient of 'check-trace-for-label' should be a literal string (label), but got " << inst.ingredients.at(1).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "second ingredient of 'check-trace-for-label' should be a literal string (label), but got " << inst.ingredients.at(1).original_string << '\n' << end(); break; } break; @@ -597,13 +597,13 @@ case CHECK_TRACE_COUNT_FOR_LABEL: { if (count != expected_count) { if (Current_scenario && !Scenario_testing_scenario) { // genuine test in a mu file - raise << "\nF - " << Current_scenario->name << ": " << maybe(current_recipe_name()) << "expected " << expected_count << " lines in trace with label " << label << " in trace: "; + raise_error << "\nF - " << Current_scenario->name << ": " << maybe(current_recipe_name()) << "expected " << expected_count << " lines in trace with label " << label << " in trace: "; DUMP(label); - raise; + raise_error; } else { // just testing scenario support - raise << maybe(current_recipe_name()) << "expected " << expected_count << " lines in trace with label " << label << " in trace\n" << end(); + raise_error << maybe(current_recipe_name()) << "expected " << expected_count << " lines in trace with label " << label << " in trace\n" << end(); } if (!Scenario_testing_scenario) { Passed = false; @@ -615,14 +615,14 @@ case CHECK_TRACE_COUNT_FOR_LABEL: { :(scenario trace_count_check_2) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ run [ trace 1, [a], [foo] ] check-trace-count-for-label 2, [a] ] -+warn: main: expected 2 lines in trace with label a in trace ++error: main: expected 2 lines in trace with label a in trace //: Minor detail: ignore 'system' calls in scenarios, since anything we do //: with them is by definition impossible to test through mu. diff --git a/052tangle.cc b/052tangle.cc index 84b96d7f..08c5f790 100644 --- a/052tangle.cc +++ b/052tangle.cc @@ -39,7 +39,7 @@ else if (command == "before") { if (is_waypoint(label)) Before_fragments[label].steps.insert(Before_fragments[label].steps.end(), tmp.steps.begin(), tmp.steps.end()); else - raise << "can't tangle before label " << label << '\n' << end(); + raise_error << "can't tangle before label " << label << '\n' << end(); } else if (command == "after") { string label = next_word(in); @@ -47,7 +47,7 @@ else if (command == "after") { if (is_waypoint(label)) After_fragments[label].steps.insert(After_fragments[label].steps.begin(), tmp.steps.begin(), tmp.steps.end()); else - raise << "can't tangle after label " << label << '\n' << end(); + raise_error << "can't tangle after label " << label << '\n' << end(); } //: after all recipes are loaded, insert fragments at appropriate labels. @@ -130,7 +130,7 @@ bool is_waypoint(string label) { return *label.begin() == '<' && *label.rbegin() == '>'; } -//: warn about unapplied fragments +//: complain about unapplied fragments :(before "End Globals") bool Transform_check_insert_fragments_Ran = false; :(before "End One-time Setup") @@ -141,11 +141,11 @@ void check_insert_fragments(unused recipe_ordinal) { Transform_check_insert_fragments_Ran = true; for (map<string, recipe>::iterator p = Before_fragments.begin(); p != Before_fragments.end(); ++p) { if (Fragments_used.find(p->first) == Fragments_used.end()) - raise << "could not locate insert before " << p->first << '\n' << end(); + raise_error << "could not locate insert before " << p->first << '\n' << end(); } for (map<string, recipe>::iterator p = After_fragments.begin(); p != After_fragments.end(); ++p) { if (Fragments_used.find(p->first) == Fragments_used.end()) - raise << "could not locate insert after " << p->first << '\n' << end(); + raise_error << "could not locate insert after " << p->first << '\n' << end(); } } @@ -170,7 +170,7 @@ after <label1> [ $mem: 4 :(scenario tangle_ignores_jump_target) -% Hide_warnings = true; +% Hide_errors = true; recipe main [ 1:number <- copy 0 +label1 @@ -179,7 +179,7 @@ recipe main [ before +label1 [ 2:number <- copy 0 ] -+warn: can't tangle before label +label1 ++error: can't tangle before label +label1 +mem: storing 0 in location 1 +mem: storing 0 in location 4 # label1 diff --git a/053continuation.cc b/053continuation.cc index 18174cc1..c9a6a5cb 100644 --- a/053continuation.cc +++ b/053continuation.cc @@ -45,7 +45,7 @@ Recipe_ordinal["continue-from"] = CONTINUE_FROM; :(before "End Primitive Recipe Checks") case CONTINUE_FROM: { if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'continue-from' should be a continuation id generated by 'current-continuation', but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'continue-from' should be a continuation id generated by 'current-continuation', but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -214,7 +214,7 @@ case REPLY_DELIMITED_CONTINUATION: { call_stack::iterator find_reset(call_stack& c); // manual prototype containing '::' call_stack::iterator reset = find_reset(Current_routine->calls); if (reset == Current_routine->calls.end()) { - raise << maybe(current_recipe_name()) << "couldn't find a 'reset' call to jump out to\n" << end(); + raise_error << maybe(current_recipe_name()) << "couldn't find a 'reset' call to jump out to\n" << end(); break; } Delimited_continuation[Next_delimited_continuation_id] = call_stack(Current_routine->calls.begin(), reset); @@ -244,7 +244,7 @@ call_stack::iterator find_reset(call_stack& c) { // copy multiple calls on to current call stack assert(scalar(ingredients.at(0))); if (Delimited_continuation.find(ingredients.at(0).at(0)) == Delimited_continuation.end()) { - raise << maybe(current_recipe_name()) << "no such delimited continuation " << current_instruction().ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(current_recipe_name()) << "no such delimited continuation " << current_instruction().ingredients.at(0).original_string << '\n' << end(); } const call_stack& new_calls = Delimited_continuation[ingredients.at(0).at(0)]; for (call_stack::const_reverse_iterator p = new_calls.rbegin(); p != new_calls.rend(); ++p) diff --git a/064random.cc b/064random.cc index de304714..12e1b848 100644 --- a/064random.cc +++ b/064random.cc @@ -36,11 +36,11 @@ Recipe_ordinal["round"] = ROUND; :(before "End Primitive Recipe Checks") case ROUND: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'round' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'round' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } - if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'round' should be a number, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + if (!is_mu_number(inst.ingredients.at(0))) { + raise_error << maybe(Recipe[r].name) << "first ingredient of 'round' should be a number, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; diff --git a/070display.cc b/070display.cc index 8859a909..49668a99 100644 --- a/070display.cc +++ b/070display.cc @@ -22,9 +22,9 @@ case OPEN_CONSOLE: { long long int height = tb_height(); if (width > 222 || height > 222) tb_shutdown(); if (width > 222) - raise << "sorry, mu doesn't support windows wider than 222 characters. Please resize your window.\n" << end(); + raise_error << "sorry, mu doesn't support windows wider than 222 characters. Please resize your window.\n" << end(); if (height > 222) - raise << "sorry, mu doesn't support windows taller than 222 characters. Please resize your window.\n" << end(); + raise_error << "sorry, mu doesn't support windows taller than 222 characters. Please resize your window.\n" << end(); break; } @@ -99,6 +99,26 @@ PRINT_CHARACTER_TO_DISPLAY, Recipe_ordinal["print-character-to-display"] = PRINT_CHARACTER_TO_DISPLAY; :(before "End Primitive Recipe Checks") case PRINT_CHARACTER_TO_DISPLAY: { + if (inst.ingredients.empty()) { + raise_error << maybe(Recipe[r].name) << "'print-character-to-display' requires at least one ingredient, but got " << inst.to_string() << '\n' << end(); + break; + } + if (!is_mu_number(inst.ingredients.at(0))) { + raise_error << maybe(Recipe[r].name) << "first ingredient of 'print-character-to-display' should be a character, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + break; + } + if (SIZE(inst.ingredients) > 1) { + if (!is_mu_number(inst.ingredients.at(1))) { + raise_error << maybe(Recipe[r].name) << "second ingredient of 'print-character-to-display' should be a foreground color number, but got " << inst.ingredients.at(1).original_string << '\n' << end(); + break; + } + } + if (SIZE(inst.ingredients) > 2) { + if (!is_mu_number(inst.ingredients.at(2))) { + raise_error << maybe(Recipe[r].name) << "third ingredient of 'print-character-to-display' should be a background color number, but got " << inst.ingredients.at(2).original_string << '\n' << end(); + break; + } + } break; } :(before "End Primitive Recipe Implementations") @@ -106,29 +126,13 @@ case PRINT_CHARACTER_TO_DISPLAY: { int h=tb_height(), w=tb_width(); long long int height = (h >= 0) ? h : 0; long long int width = (w >= 0) ? w : 0; - if (ingredients.empty()) { - raise << maybe(current_recipe_name()) << "'print-character-to-display' requires at least one ingredient, but got " << current_instruction().to_string() << '\n' << end(); - break; - } - if (!scalar(ingredients.at(0))) { - raise << maybe(current_recipe_name()) << "first ingredient of 'print-character-to-display' should be a character, but got " << current_instruction().ingredients.at(0).original_string << '\n' << end(); - break; - } long long int c = ingredients.at(0).at(0); int color = TB_BLACK; if (SIZE(ingredients) > 1) { - if (!scalar(ingredients.at(1))) { - raise << maybe(current_recipe_name()) << "second ingredient of 'print-character-to-display' should be a foreground color number, but got " << current_instruction().ingredients.at(1).original_string << '\n' << end(); - break; - } color = ingredients.at(1).at(0); } int bg_color = TB_BLACK; if (SIZE(ingredients) > 2) { - if (!scalar(ingredients.at(2))) { - raise << maybe(current_recipe_name()) << "third ingredient of 'print-character-to-display' should be a background color number, but got " << current_instruction().ingredients.at(2).original_string << '\n' << end(); - break; - } bg_color = ingredients.at(2).at(0); if (bg_color == 0) bg_color = TB_BLACK; } @@ -182,15 +186,15 @@ Recipe_ordinal["move-cursor-on-display"] = MOVE_CURSOR_ON_DISPLAY; :(before "End Primitive Recipe Checks") case MOVE_CURSOR_ON_DISPLAY: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'move-cursor-on-display' requires two ingredients, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'move-cursor-on-display' requires two ingredients, but got " << inst.to_string() << '\n' << end(); break; } - if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'move-cursor-on-display' should be a row number, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + if (!is_mu_number(inst.ingredients.at(0))) { + raise_error << maybe(Recipe[r].name) << "first ingredient of 'move-cursor-on-display' should be a row number, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } - if (!is_mu_scalar(inst.ingredients.at(1))) { - raise << maybe(Recipe[r].name) << "second ingredient of 'move-cursor-on-display' should be a column number, but got " << inst.ingredients.at(1).original_string << '\n' << end(); + if (!is_mu_number(inst.ingredients.at(1))) { + raise_error << maybe(Recipe[r].name) << "second ingredient of 'move-cursor-on-display' should be a column number, but got " << inst.ingredients.at(1).original_string << '\n' << end(); break; } break; diff --git a/072scenario_screen.cc b/072scenario_screen.cc index 76900238..4ecbbd4d 100644 --- a/072scenario_screen.cc +++ b/072scenario_screen.cc @@ -68,7 +68,7 @@ scenario screen-in-scenario-color [ :(scenario screen_in_scenario_error) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; scenario screen-in-scenario-error [ assume-screen 5/width, 3/height run [ @@ -81,11 +81,11 @@ scenario screen-in-scenario-error [ . . ] ] -+warn: expected screen location (0, 0) to contain 98 ('b') instead of 97 ('a') ++error: expected screen location (0, 0) to contain 98 ('b') instead of 97 ('a') :(scenario screen_in_scenario_color_error) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; # screen-should-contain can check unicode characters in the fake screen scenario screen-in-scenario-color [ assume-screen 5/width, 3/height @@ -99,21 +99,21 @@ scenario screen-in-scenario-color [ . . ] ] -+warn: expected screen location (0, 0) to be in color 2 instead of 1 ++error: expected screen location (0, 0) to be in color 2 instead of 1 //: allow naming just for 'screen' :(before "End is_special_name Cases") if (s == "screen") return true; :(scenarios run) -:(scenario convert_names_does_not_warn_when_mixing_special_names_and_numeric_locations) +:(scenario convert_names_does_not_fail_when_mixing_special_names_and_numeric_locations) % Scenario_testing_scenario = true; -% Hide_warnings = true; +% Hide_errors = true; recipe main [ screen:number <- copy 1:number ] --warn: mixing variable names and numeric addresses in main -$warn: 0 +-error: mixing variable names and numeric addresses in main +$error: 0 :(scenarios run_mu_scenario) :(before "End Globals") @@ -227,11 +227,11 @@ void check_screen(const string& expected_contents, const int color) { // contents match but color is off if (Current_scenario && !Scenario_testing_scenario) { // genuine test in a mu file - raise << "\nF - " << Current_scenario->name << ": expected screen location (" << row << ", " << column << ", address " << addr << ", value " << no_scientific(Memory[addr]) << ") to be in color " << color << " instead of " << no_scientific(Memory[addr+cell_color_offset]) << "\n" << end(); + raise_error << "\nF - " << Current_scenario->name << ": expected screen location (" << row << ", " << column << ", address " << addr << ", value " << no_scientific(Memory[addr]) << ") to be in color " << color << " instead of " << no_scientific(Memory[addr+cell_color_offset]) << "\n" << end(); } else { // just testing check_screen - raise << "expected screen location (" << row << ", " << column << ") to be in color " << color << " instead of " << no_scientific(Memory[addr+cell_color_offset]) << '\n' << end(); + raise_error << "expected screen location (" << row << ", " << column << ") to be in color " << color << " instead of " << no_scientific(Memory[addr+cell_color_offset]) << '\n' << end(); } if (!Scenario_testing_scenario) { Passed = false; @@ -241,7 +241,7 @@ void check_screen(const string& expected_contents, const int color) { } // really a mismatch - // can't print multi-byte unicode characters in warnings just yet. not very useful for debugging anyway. + // can't print multi-byte unicode characters in errors just yet. not very useful for debugging anyway. char expected_pretty[10] = {0}; if (curr < 256 && !iscntrl(curr)) { // " ('<curr>')" @@ -257,12 +257,12 @@ void check_screen(const string& expected_contents, const int color) { if (color != -1) color_phrase << " in color " << color; if (Current_scenario && !Scenario_testing_scenario) { // genuine test in a mu file - raise << "\nF - " << Current_scenario->name << ": expected screen location (" << row << ", " << column << ") to contain " << curr << expected_pretty << color_phrase.str() << " instead of " << no_scientific(Memory[addr]) << actual_pretty << '\n' << end(); + raise_error << "\nF - " << Current_scenario->name << ": expected screen location (" << row << ", " << column << ") to contain " << curr << expected_pretty << color_phrase.str() << " instead of " << no_scientific(Memory[addr]) << actual_pretty << '\n' << end(); dump_screen(); } else { // just testing check_screen - raise << "expected screen location (" << row << ", " << column << ") to contain " << curr << expected_pretty << color_phrase.str() << " instead of " << no_scientific(Memory[addr]) << actual_pretty << '\n' << end(); + raise_error << "expected screen location (" << row << ", " << column << ") to contain " << curr << expected_pretty << color_phrase.str() << " instead of " << no_scientific(Memory[addr]) << actual_pretty << '\n' << end(); } if (!Scenario_testing_scenario) { Passed = false; @@ -281,7 +281,7 @@ raw_string_stream::raw_string_stream(const string& backing) :index(0), max(SIZE( bool raw_string_stream::at_end() const { if (index >= max) return true; if (tb_utf8_char_length(buf[index]) > max-index) { - raise << "unicode string seems corrupted at index "<< index << " character " << static_cast<int>(buf[index]) << '\n' << end(); + raise_error << "unicode string seems corrupted at index "<< index << " character " << static_cast<int>(buf[index]) << '\n' << end(); return true; } return false; diff --git a/075scenario_console.cc b/075scenario_console.cc index 44bed831..ab6aba94 100644 --- a/075scenario_console.cc +++ b/075scenario_console.cc @@ -74,7 +74,7 @@ case ASSUME_CONSOLE: { else if (Key.find(key) != Key.end()) Memory[Current_routine->alloc+1] = Key[key]; else - raise << "assume-console: can't press " << key << '\n' << end(); + raise_error << "assume-console: can't press " << key << '\n' << end(); if (Memory[Current_routine->alloc+1] < 256) // these keys are in ascii Memory[Current_routine->alloc] = /*tag for 'text' variant of 'event' exclusive-container*/0; @@ -235,7 +235,7 @@ case REPLACE_IN_CONSOLE: { case REPLACE_IN_CONSOLE: { assert(scalar(ingredients.at(0))); if (!Memory[CONSOLE]) { - raise << "console not initialized\n" << end(); + raise_error << "console not initialized\n" << end(); break; } long long int console_data = Memory[Memory[CONSOLE]+1]; diff --git a/081run_interactive.cc b/081run_interactive.cc index 224998ec..7eb0cc8c 100644 --- a/081run_interactive.cc +++ b/081run_interactive.cc @@ -17,9 +17,9 @@ recipe main [ # result is null +mem: storing 0 in location 1 -//: run code in 'interactive mode', i.e. with warnings off and return: +//: run code in 'interactive mode', i.e. with errors+warnings off and return: //: stringified output in case we want to print it to screen -//: any warnings encountered +//: any errors+warnings encountered //: simulated screen any prints went to //: any 'app' layer traces generated :(before "End Primitive Recipe Declarations") @@ -29,11 +29,11 @@ Recipe_ordinal["run-interactive"] = RUN_INTERACTIVE; :(before "End Primitive Recipe Checks") case RUN_INTERACTIVE: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'run-interactive' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'run-interactive' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'run-interactive' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'run-interactive' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end(); break; } break; @@ -44,7 +44,7 @@ case RUN_INTERACTIVE: { if (!new_code_pushed_to_stack) { products.resize(5); products.at(0).push_back(0); - products.at(1).push_back(trace_contents("warn")); + products.at(1).push_back(trace_error_warning_contents()); products.at(2).push_back(0); products.at(3).push_back(trace_contents("app")); products.at(4).push_back(1); // completed @@ -94,7 +94,7 @@ bool run_interactive(long long int address) { "]\n"); transform_all(); Current_routine = save_current_routine; - if (trace_count("warn") > 0) return false; + if (trace_count("error") > 0) return false; // now call 'sandbox' which will run 'interactive' in a separate routine, // and wait for it Current_routine->calls.push_front(call(Recipe_ordinal["sandbox"])); @@ -104,17 +104,20 @@ bool run_interactive(long long int address) { void run_code_begin() { // stuff to undo later, in run_code_end() Hide_warnings = true; + Hide_errors = true; Disable_redefine_warnings = true; Save_trace_stream = Trace_stream; Save_trace_file = Trace_file; Trace_file = ""; Trace_stream = new trace_stream; + Trace_stream->collect_layers.insert("error"); Trace_stream->collect_layers.insert("warn"); Trace_stream->collect_layers.insert("app"); } void run_code_end() { Hide_warnings = false; + Hide_errors = false; Disable_redefine_warnings = false; delete Trace_stream; Trace_stream = Save_trace_stream; @@ -136,7 +139,7 @@ load(string( "sandbox-state:number <- routine-state r/routine_id\n" + "completed?:boolean <- equal sandbox-state, 1/completed\n" + "output:address:array:character <- $most-recent-products\n" + - "warnings:address:array:character <- save-trace [warn]\n" + + "warnings:address:array:character <- save-errors-warnings\n" + "stashes:address:array:character <- save-trace [app]\n" + "$cleanup-run-interactive\n" + "reply output, warnings, screen, stashes, completed?\n" + @@ -144,7 +147,7 @@ load(string( transform_all(); recently_added_recipes.clear(); -//: adjust warnings in the sandbox +//: adjust errors/warnings in the sandbox :(after "string maybe(string s)") if (s == "interactive") return ""; @@ -210,6 +213,21 @@ case _MOST_RECENT_PRODUCTS: { } :(before "End Primitive Recipe Declarations") +SAVE_ERRORS_WARNINGS, +:(before "End Primitive Recipe Numbers") +Recipe_ordinal["save-errors-warnings"] = SAVE_ERRORS_WARNINGS; +:(before "End Primitive Recipe Checks") +case SAVE_ERRORS_WARNINGS: { + break; +} +:(before "End Primitive Recipe Implementations") +case SAVE_ERRORS_WARNINGS: { + products.resize(1); + products.at(0).push_back(trace_error_warning_contents()); + break; +} + +:(before "End Primitive Recipe Declarations") SAVE_TRACE, :(before "End Primitive Recipe Numbers") Recipe_ordinal["save-trace"] = SAVE_TRACE; @@ -263,15 +281,15 @@ recipe main [ +mem: storing 97 in location 11 +mem: storing 98 in location 12 -:(scenario "run_interactive_returns_warnings") +:(scenario "run_interactive_returns_errors") recipe main [ - # run a command that generates a warning + # run a command that generates an error 1:address:array:character <- new [x:number <- copy 34 get x:number, foo:offset] 2:address:array:character, 3:address:array:character <- run-interactive 1:address:array:character 10:array:character <- copy 3:address:array:character/lookup ] -# warning should be "unknown element foo in container number" +# error should be "unknown element foo in container number" +mem: storing 117 in location 11 +mem: storing 110 in location 12 +mem: storing 107 in location 13 @@ -295,7 +313,7 @@ void track_most_recent_products(const instruction& instruction, const vector<vec if (is_mu_string(instruction.products.at(i))) { if (!scalar(products.at(i))) { tb_shutdown(); - cerr << read_mu_string(trace_contents("warn")) << '\n'; + cerr << read_mu_string(trace_error_warning_contents()) << '\n'; cerr << SIZE(products.at(i)) << ": "; for (long long int j = 0; j < SIZE(products.at(i)); ++j) cerr << no_scientific(products.at(i).at(j)) << ' '; @@ -336,6 +354,20 @@ long long int stringified_value_of_location(long long int address) { return new_mu_string(out.str()); } +long long int trace_error_warning_contents() { + if (!Trace_stream) return 0; + ostringstream out; + for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { + if (p->label != "warn" && p->label != "error") continue; + out << p->contents; + if (*--p->contents.end() != '\n') out << '\n'; + } + string result = out.str(); + if (result.empty()) return 0; + truncate(result); + return new_mu_string(result); +} + long long int trace_contents(const string& layer) { if (!Trace_stream) return 0; if (trace_count(layer) <= 0) return 0; @@ -361,7 +393,7 @@ void truncate(string& x) { } //: simpler version of run-interactive: doesn't do any running, just loads -//: recipes and reports warnings. +//: recipes and reports errors+warnings. :(before "End Primitive Recipe Declarations") RELOAD, @@ -370,11 +402,11 @@ Recipe_ordinal["reload"] = RELOAD; :(before "End Primitive Recipe Checks") case RELOAD: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'reload' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'reload' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } if (!is_mu_scalar(inst.ingredients.at(0))) { - raise << maybe(Recipe[r].name) << "first ingredient of 'reload' should be a literal string, but got " << inst.ingredients.at(0).original_string << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'reload' should be a literal string, but got " << inst.ingredients.at(0).original_string << '\n' << end(); break; } break; @@ -398,12 +430,12 @@ case RELOAD: { Trace_stream->newline(); // flush trace Current_routine = save_current_routine; products.resize(1); - products.at(0).push_back(trace_contents("warn")); + products.at(0).push_back(trace_error_warning_contents()); run_code_end(); // wait until we're done with the trace contents break; } -:(scenario reload_continues_past_warning) +:(scenario reload_continues_past_error) recipe main [ local-scope x:address:array:character <- new [recipe foo [ diff --git a/082persist.cc b/082persist.cc index 0a0064d3..a43a4395 100644 --- a/082persist.cc +++ b/082persist.cc @@ -9,7 +9,7 @@ Recipe_ordinal["restore"] = RESTORE; :(before "End Primitive Recipe Checks") case RESTORE: { if (SIZE(inst.ingredients) != 1) { - raise << maybe(Recipe[r].name) << "'restore' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'restore' requires exactly one ingredient, but got " << inst.to_string() << '\n' << end(); break; } string filename; @@ -20,7 +20,7 @@ case RESTORE: { ; } else { - raise << maybe(Recipe[r].name) << "first ingredient of 'restore' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'restore' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end(); break; } break; @@ -73,7 +73,7 @@ Recipe_ordinal["save"] = SAVE; :(before "End Primitive Recipe Checks") case SAVE: { if (SIZE(inst.ingredients) != 2) { - raise << maybe(Recipe[r].name) << "'save' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "'save' requires exactly two ingredients, but got " << inst.to_string() << '\n' << end(); break; } if (is_literal_string(inst.ingredients.at(0))) { @@ -83,11 +83,11 @@ case SAVE: { ; } else { - raise << maybe(Recipe[r].name) << "first ingredient of 'save' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end(); + raise_error << maybe(Recipe[r].name) << "first ingredient of 'save' should be a string, but got " << inst.ingredients.at(0).to_string() << '\n' << end(); break; } - if (!is_mu_scalar(inst.ingredients.at(1))) { - raise << maybe(Recipe[r].name) << "second ingredient of 'save' should be an address:array:character, but got " << inst.ingredients.at(1).to_string() << '\n' << end(); + if (!is_mu_string(inst.ingredients.at(1))) { + raise_error << maybe(Recipe[r].name) << "second ingredient of 'save' should be an address:array:character, but got " << inst.ingredients.at(1).to_string() << '\n' << end(); break; } break; @@ -111,7 +111,7 @@ case SAVE: { // explicitly say '--all' for git 1.9 int status = system("cd lesson; git add --all .; git diff HEAD --exit-code >/dev/null || git commit -a -m . >/dev/null"); if (status != 0) - raise << "error in commit: contents " << contents << '\n' << end(); + raise_error << "error in commit: contents " << contents << '\n' << end(); break; } |