2262 - strengthen some type checks

This commit is contained in:
Kartik K. Agaram 2015-10-07 00:22:49 -07:00
parent 857adbc496
commit 7afe09fbfe
6 changed files with 55 additions and 26 deletions

View File

@ -46,7 +46,7 @@ case CALL: {
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))) {
if (!is_mu_recipe(inst.ingredients.at(0))) {
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;
}
@ -59,3 +59,12 @@ case CALL: {
ingredients.erase(ingredients.begin()); // drop the callee
goto call_housekeeping;
}
:(code)
bool is_mu_recipe(reagent r) {
if (r.types.empty()) return false;
if (r.types.at(0) == Type_ordinal["recipe"]) return true;
if (r.types.at(0) == Type_ordinal["recipe-ordinal"]) return true;
// End is_mu_recipe Cases
return false;
}

View File

@ -150,7 +150,7 @@ case START_RUNNING: {
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))) {
if (!is_mu_recipe(inst.ingredients.at(0))) {
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;
}
@ -336,7 +336,7 @@ case ROUTINE_STATE: {
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))) {
if (!is_mu_number(inst.ingredients.at(0))) {
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;
}
@ -369,7 +369,7 @@ case RESTART: {
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))) {
if (!is_mu_number(inst.ingredients.at(0))) {
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;
}
@ -397,7 +397,7 @@ case STOP: {
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))) {
if (!is_mu_number(inst.ingredients.at(0))) {
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;
}
@ -479,11 +479,11 @@ case LIMIT_TIME: {
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))) {
if (!is_mu_number(inst.ingredients.at(0))) {
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))) {
if (!is_mu_number(inst.ingredients.at(1))) {
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;
}

View File

@ -35,9 +35,7 @@ if (inst.operation == Recipe_ordinal["new"]) {
// first arg must be of type 'type'
if (inst.ingredients.empty())
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")
if (!is_mu_type_literal(inst.ingredients.at(0)))
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_error << maybe(Recipe[r].name) << "unknown type " << inst.ingredients.at(0).name << '\n' << end();
@ -59,8 +57,9 @@ case NEW: {
raise_error << maybe(Recipe[r].name) << "'new' requires one or two ingredients, but got " << inst.to_string() << '\n' << end();
break;
}
// End NEW Checks
reagent type = inst.ingredients.at(0);
if (!is_mu_scalar(type) && !is_literal(type)) {
if (!is_mu_type_literal(type)) {
raise_error << maybe(Recipe[r].name) << "first ingredient of 'new' should be a type, but got " << type.original_string << '\n' << end();
break;
}
@ -323,9 +322,10 @@ recipe main [
goto end_new_transform;
}
:(before "End NEW Checks")
if (is_literal_string(inst.ingredients.at(0))) break;
:(after "case NEW" following "Primitive Recipe Implementations")
if (is_literal(current_instruction().ingredients.at(0))
&& current_instruction().ingredients.at(0).properties.at(0).second.at(0) == "literal-string") {
if (is_literal_string(current_instruction().ingredients.at(0))) {
products.resize(1);
products.at(0).push_back(new_mu_string(current_instruction().ingredients.at(0).name));
break;
@ -428,3 +428,7 @@ string read_mu_string(long long int address) {
}
return tmp.str();
}
bool is_mu_type_literal(reagent r) {
return is_literal(r) && !r.properties.empty() && !r.properties.at(0).second.empty() && r.properties.at(0).second.at(0) == "type";
}

View File

@ -27,6 +27,7 @@ recipe main [
//:: first disable name conversion for 'default-space'
:(scenario convert_names_passes_default_space)
% Hide_errors = true;
recipe main [
default-space:number, x:number <- copy 0, 1
]
@ -211,8 +212,13 @@ 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))
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()) << "'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;
}

View File

@ -44,8 +44,8 @@ CONTINUE_FROM,
Recipe_ordinal["continue-from"] = CONTINUE_FROM;
:(before "End Primitive Recipe Checks")
case CONTINUE_FROM: {
if (!is_mu_scalar(inst.ingredients.at(0))) {
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();
if (!is_mu_continuation(inst.ingredients.at(0))) {
raise_error << maybe(Recipe[r].name) << "first ingredient of 'continue-from' should be a continuation generated by 'current-continuation', but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;
@ -57,6 +57,12 @@ case CONTINUE_FROM: {
continue; // skip rest of this instruction
}
:(code)
bool is_mu_continuation(const reagent& x) {
if (x.types.empty()) return false;
return x.types.at(0) == Type_ordinal["continuation"];
}
:(scenario continuation)
# simulate a loop using continuations
recipe main [
@ -253,3 +259,6 @@ call_stack::iterator find_reset(call_stack& c) {
ingredients.erase(ingredients.begin()); // drop the callee
goto call_housekeeping;
}
:(before "End is_mu_recipe Cases")
if (r.types.at(0) == Type_ordinal["continuation"]) return true;

View File

@ -12,10 +12,11 @@ recipe main [
:(scenario run_interactive_empty)
recipe main [
1:address:array:character <- run-interactive 0
1:address:array:character <- copy 0/raw
2:address:array:character <- run-interactive 1:address:array:character
]
# result is null
+mem: storing 0 in location 1
+mem: storing 0 in location 2
//: run code in 'interactive mode', i.e. with errors+warnings off and return:
//: stringified output in case we want to print it to screen
@ -32,7 +33,7 @@ case RUN_INTERACTIVE: {
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))) {
if (!is_mu_string(inst.ingredients.at(0))) {
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;
}
@ -138,7 +139,7 @@ load(string(
"completed?:boolean <- equal sandbox-state, 1/completed\n" +
"output:address:array:character <- $most-recent-products\n" +
"warnings:address:array:character <- save-errors-warnings\n" +
"stashes:address:array:character <- save-trace [app]\n" +
"stashes:address:array:character <- save-app-trace\n" +
"$cleanup-run-interactive\n" +
"reply output, warnings, screen, stashes, completed?\n" +
"]\n");
@ -217,15 +218,15 @@ case SAVE_ERRORS_WARNINGS: {
}
:(before "End Primitive Recipe Declarations")
SAVE_TRACE,
SAVE_APP_TRACE,
:(before "End Primitive Recipe Numbers")
Recipe_ordinal["save-trace"] = SAVE_TRACE;
Recipe_ordinal["save-app-trace"] = SAVE_APP_TRACE;
:(before "End Primitive Recipe Checks")
case SAVE_TRACE: {
case SAVE_APP_TRACE: {
break;
}
:(before "End Primitive Recipe Implementations")
case SAVE_TRACE: {
case SAVE_APP_TRACE: {
products.resize(1);
products.at(0).push_back(trace_app_contents());
break;
@ -393,8 +394,8 @@ case RELOAD: {
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_error << maybe(Recipe[r].name) << "first ingredient of 'reload' should be a literal string, but got " << inst.ingredients.at(0).original_string << '\n' << end();
if (!is_mu_string(inst.ingredients.at(0))) {
raise_error << maybe(Recipe[r].name) << "first ingredient of 'reload' should be a string, but got " << inst.ingredients.at(0).original_string << '\n' << end();
break;
}
break;