about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-10-07 00:22:49 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-10-07 00:22:49 -0700
commit7afe09fbfeb88e3be98dfe4f0db43f66724d4abf (patch)
tree0592cc6cf3e98aa25ec9c35b638a56baeff1d5e3
parent857adbc496dca7d41e46cbece815a24d32c735fe (diff)
downloadmu-7afe09fbfeb88e3be98dfe4f0db43f66724d4abf.tar.gz
2262 - strengthen some type checks
-rw-r--r--037recipe.cc11
-rw-r--r--038scheduler.cc12
-rw-r--r--043new.cc16
-rw-r--r--044space.cc8
-rw-r--r--053continuation.cc13
-rw-r--r--081run_interactive.cc21
6 files changed, 55 insertions, 26 deletions
diff --git a/037recipe.cc b/037recipe.cc
index f7dd62d7..55522bd9 100644
--- a/037recipe.cc
+++ b/037recipe.cc
@@ -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;
+}
diff --git a/038scheduler.cc b/038scheduler.cc
index ac16db22..f66d5c80 100644
--- a/038scheduler.cc
+++ b/038scheduler.cc
@@ -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;
   }
diff --git a/043new.cc b/043new.cc
index f821fad3..e28284ae 100644
--- a/043new.cc
+++ b/043new.cc
@@ -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";
+}
diff --git a/044space.cc b/044space.cc
index 55e3cc23..2d1a18f0 100644
--- a/044space.cc
+++ b/044space.cc
@@ -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;
   }
diff --git a/053continuation.cc b/053continuation.cc
index c9a6a5cb..9ccd6311 100644
--- a/053continuation.cc
+++ b/053continuation.cc
@@ -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;
diff --git a/081run_interactive.cc b/081run_interactive.cc
index e4c847f1..81c49d42 100644
--- a/081run_interactive.cc
+++ b/081run_interactive.cc
@@ -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;