about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-07-08 11:43:59 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-07-08 12:50:07 -0700
commit260c3de2bfad49c0587547b8af1be5bc3e2dacd5 (patch)
tree2b80d1217be2dc5af051194d7f91a2a3d444b0ee
parenta2372bee56a110e7dfd83c3b52f430c75b2cf0e7 (diff)
downloadmu-260c3de2bfad49c0587547b8af1be5bc3e2dacd5.tar.gz
1721 - hide warnings inside interactive routines
We will need many other forms of isolation for these. For starters we're
going to have to replace most asserts with warnings that can be traced
so that the environment doesn't crash because of illegal code typed into
it.

New test is still failing. Just getting it to fail right was hard
enough.
-rw-r--r--034call.cc6
-rw-r--r--036call_reply.cc6
-rw-r--r--050scenario.cc30
-rw-r--r--072scenario_screen.cc20
-rw-r--r--081run_interactive.cc9
-rw-r--r--edit.mu54
6 files changed, 107 insertions, 18 deletions
diff --git a/034call.cc b/034call.cc
index 4c368bbf..6d820809 100644
--- a/034call.cc
+++ b/034call.cc
@@ -107,8 +107,12 @@ inline const vector<instruction>& routine::steps() const {
 // when we reach the end of one call, we may reach the end of the one below
 // it, and the one below that, and so on
 while (current_step_index() >= SIZE(Current_routine->steps())) {
+  if (current_recipe_name() == "interactive") {
+//?     trace("foo") << "showing warnings again"; //? 1
+    Hide_warnings = false;
+  }
   --Callstack_depth;
-//?   cerr << "reply " << Current_routine->calls.size() << '\n'; //? 1
+//?   cerr << "reply " << Current_routine->calls.size() << '\n'; //? 2
   Current_routine->calls.pop_front();
   if (Current_routine->calls.empty()) return;
   // todo: no results returned warning
diff --git a/036call_reply.cc b/036call_reply.cc
index 0bc46323..d09763fe 100644
--- a/036call_reply.cc
+++ b/036call_reply.cc
@@ -20,6 +20,10 @@ Recipe_ordinal["reply"] = REPLY;
 case REPLY: {
   const instruction& reply_inst = current_instruction();  // save pointer into recipe before pop
   const string& callee = current_recipe_name();
+  if (callee == "interactive") {
+    trace("foo") << "showing warnings again";
+    Hide_warnings = true;
+  }
   --Callstack_depth;
 //?   if (tb_is_active()) { //? 1
 //?     tb_clear(); //? 1
@@ -44,8 +48,6 @@ case REPLY: {
         raise << current_recipe_name() << ": 'same-as-ingredient' result " << caller_instruction.products.at(i).value << " from call to " << callee << " must be location " << caller_instruction.ingredients.at(ingredient_index).value << '\n';
     }
   }
-  if (current_recipe_name() == "interactive") {
-  }
   break;  // continue to process rest of *caller* instruction
 }
 
diff --git a/050scenario.cc b/050scenario.cc
index 836ff9f8..58f4dd81 100644
--- a/050scenario.cc
+++ b/050scenario.cc
@@ -211,7 +211,13 @@ recipe main [
 //: 'memory-should-contain' raises warnings if specific locations aren't as expected
 //: Also includes some special support for checking strings.
 
+:(before "End Globals")
+bool Scenario_testing_scenario = false;
+:(before "End Setup")
+Scenario_testing_scenario = false;
+
 :(scenario memory_check)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   memory-should-contain [
@@ -255,7 +261,7 @@ void check_memory(const string& s) {
       raise << "duplicate expectation for location " << address << '\n';
     trace(Primitive_recipe_depth, "run") << "checking location " << address;
     if (Memory[address] != value) {
-      if (Current_scenario && !Hide_warnings) {
+      if (Current_scenario && !Scenario_testing_scenario) {
         // genuine test in a mu file
         raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain " << value << " but saw " << Memory[address] << '\n';
       }
@@ -263,7 +269,7 @@ void check_memory(const string& s) {
         // just testing scenario support
         raise << "expected location " << address << " to contain " << value << " but saw " << Memory[address] << '\n';
       }
-      if (!Hide_warnings) {
+      if (!Scenario_testing_scenario) {
         Passed = false;
         ++Num_failures;
       }
@@ -295,11 +301,11 @@ void check_type(const string& lhs, istream& in) {
 void check_string(long long int address, const string& literal) {
   trace(Primitive_recipe_depth, "run") << "checking string length at " << address;
   if (Memory[address] != SIZE(literal)) {
-    if (Current_scenario && !Hide_warnings)
+    if (Current_scenario && !Scenario_testing_scenario)
       raise << "\nF - " << Current_scenario->name << ": expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << Memory[address] << '\n';
     else
       raise << "expected location " << address << " to contain length " << SIZE(literal) << " of string [" << literal << "] but saw " << Memory[address] << '\n';
-    if (!Hide_warnings) {
+    if (!Scenario_testing_scenario) {
       Passed = false;
       ++Num_failures;
     }
@@ -309,7 +315,7 @@ void check_string(long long int address, const string& literal) {
   for (long long int i = 0; i < SIZE(literal); ++i) {
     trace(Primitive_recipe_depth, "run") << "checking location " << address+i;
     if (Memory[address+i] != literal.at(i)) {
-      if (Current_scenario && !Hide_warnings) {
+      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 " << Memory[address+i] << '\n';
       }
@@ -317,7 +323,7 @@ void check_string(long long int address, const string& literal) {
         // just testing scenario support
         raise << "expected location " << (address+i) << " to contain " << literal.at(i) << " but saw " << Memory[address+i] << '\n';
       }
-      if (!Hide_warnings) {
+      if (!Scenario_testing_scenario) {
         Passed = false;
         ++Num_failures;
       }
@@ -327,6 +333,7 @@ void check_string(long long int address, const string& literal) {
 }
 
 :(scenario memory_check_multiple)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   memory-should-contain [
@@ -337,6 +344,7 @@ recipe main [
 +warn: duplicate expectation for location 1
 
 :(scenario memory_check_string_length)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   1:number <- copy 3:literal
@@ -369,12 +377,9 @@ recipe main [
 // Like runs of contiguous '+' lines, order is important. The trace checks
 // that the lines are present *and* in the specified sequence. (There can be
 // other lines in between.)
-//
-// Be careful not to mix setting Hide_warnings and checking the trace in .mu
-// files. It'll work in C++ scenarios, but the test failure gets silently
-// hidden in mu scenarios.
 
 :(scenario trace_check_warns_on_failure)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   trace-should-contain [
@@ -435,6 +440,7 @@ vector<trace_line> parse_trace(const string& expected) {
 }
 
 :(scenario trace_check_warns_on_failure_in_later_line)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   run [
@@ -448,6 +454,7 @@ recipe main [
 +warn: missing [d] in trace layer a
 
 :(scenario trace_check_passes_silently)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   run [
@@ -465,6 +472,7 @@ $warn: 0
 //: important, so you can't say things like "B should not exist after A."
 
 :(scenario trace_negative_check_warns_on_failure)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   run [
@@ -504,6 +512,7 @@ bool check_trace_missing(const string& in) {
 }
 
 :(scenario trace_negative_check_passes_silently)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   trace-should-not-contain [
@@ -514,6 +523,7 @@ recipe main [
 $warn: 0
 
 :(scenario trace_negative_check_warns_on_any_unexpected_line)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   run [
diff --git a/072scenario_screen.cc b/072scenario_screen.cc
index 14ac3a36..8e3f0d9c 100644
--- a/072scenario_screen.cc
+++ b/072scenario_screen.cc
@@ -71,6 +71,7 @@ scenario screen-in-scenario-color [
 ]
 
 :(scenario screen_in_scenario_error)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 scenario screen-in-scenario-error [
   assume-screen 5:literal/width, 3:literal/height
@@ -87,6 +88,7 @@ scenario screen-in-scenario-error [
 +warn: 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;
 # screen-should-contain can check unicode characters in the fake screen
 scenario screen-in-scenario-color [
@@ -109,6 +111,7 @@ if (s == "screen") return true;
 
 :(scenarios run)
 :(scenario convert_names_does_not_warn_when_mixing_special_names_and_numeric_locations)
+% Scenario_testing_scenario = true;
 % Hide_warnings = true;
 recipe main [
   screen:number <- copy 1:number
@@ -209,23 +212,29 @@ void check_screen(const string& expected_contents, const int color) {
   long long int addr = screen_data_start+1;  // skip length
 //?   cerr << "screen height " << screen_height << '\n'; //? 1
   for (long long int row = 0; row < screen_height; ++row) {
-//?     cerr << "row: " << row << '\n'; //? 1
+//?     cerr << "row: " << row << '\n'; //? 3
+//?     cerr << "contents: " << cursor.buf+cursor.index << "$\n"; //? 1
     cursor.skip_whitespace_and_comments();
     if (cursor.at_end()) break;
+//?     cerr << "row2\n"; //? 2
     assert(cursor.get() == '.');
     for (long long int column = 0;  column < screen_width;  ++column, addr+= /*size of screen-cell*/2) {
       const int cell_color_offset = 1;
       uint32_t curr = cursor.get();
+//?       cerr << "col: " << column << '\n'; //? 1
       if (Memory[addr] == 0 && isspace(curr)) continue;
 //?       cerr << color << " vs " << Memory[addr+1] << '\n'; //? 1
       if (curr == ' ' && color != -1 && color != Memory[addr+cell_color_offset]) {
         // filter out other colors
         continue;
       }
+//?       cerr << "col3 " << column << ": " << Memory[addr] << " " << curr << '\n'; //? 1
       if (Memory[addr] != 0 && Memory[addr] == curr) {
+//?         cerr << "col4\n"; //? 1
         if (color == -1 || color == Memory[addr+cell_color_offset]) continue;
+//?         cerr << "col5: " << column << '\n'; //? 1
         // contents match but color is off
-        if (Current_scenario && !Hide_warnings) {
+        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 " << Memory[addr] << ") to be in color " << color << " instead of " << Memory[addr+cell_color_offset] << "\n";
         }
@@ -233,13 +242,14 @@ void check_screen(const string& expected_contents, const int color) {
           // just testing check_screen
           raise << "expected screen location (" << row << ", " << column << ") to be in color " << color << " instead of " << Memory[addr+cell_color_offset] << '\n';
         }
-        if (!Hide_warnings) {
+        if (!Scenario_testing_scenario) {
           Passed = false;
           ++Num_failures;
         }
         return;
       }
 
+//?       cerr << "col6 " << column << ": " << Memory[addr] << " " << curr << '\n'; //? 1
       // really a mismatch
       // can't print multi-byte unicode characters in warnings just yet. not very useful for debugging anyway.
       char expected_pretty[10] = {0};
@@ -253,7 +263,7 @@ void check_screen(const string& expected_contents, const int color) {
         actual_pretty[0] = ' ', actual_pretty[1] = '(', actual_pretty[2] = '\'', actual_pretty[3] = static_cast<unsigned char>(Memory[addr]), actual_pretty[4] = '\'', actual_pretty[5] = ')', actual_pretty[6] = '\0';
       }
 
-      if (Current_scenario && !Hide_warnings) {
+      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 << " instead of " << Memory[addr] << actual_pretty << '\n';
         dump_screen();
@@ -262,7 +272,7 @@ void check_screen(const string& expected_contents, const int color) {
         // just testing check_screen
         raise << "expected screen location (" << row << ", " << column << ") to contain " << curr << expected_pretty << " instead of " << Memory[addr] << actual_pretty << '\n';
       }
-      if (!Hide_warnings) {
+      if (!Scenario_testing_scenario) {
         Passed = false;
         ++Num_failures;
       }
diff --git a/081run_interactive.cc b/081run_interactive.cc
index 5e6f3f1a..abb67b17 100644
--- a/081run_interactive.cc
+++ b/081run_interactive.cc
@@ -71,6 +71,7 @@ case RUN_INTERACTIVE: {
 // reads a string. if it's a variable, stores its value as a string and returns false.
 // if it's lines of code, calls them and returns true (no result available yet to be stored)
 bool run_interactive(long long int address, long long int* result) {
+//?   cerr << "run interactive\n"; //? 1
   long long int size = Memory[address];
   if (size == 0) {
 //?     trace(1, "foo") << "AAA"; //? 2
@@ -99,9 +100,17 @@ bool run_interactive(long long int address, long long int* result) {
   }
 //?   trace(1, "foo") << "DDD"; //? 2
   Recipe.erase(Recipe_ordinal["interactive"]);
+//?   trace("foo") << "hiding warnings\n"; //? 2
+  Hide_warnings = true;
   // call run(string) but without the scheduling
   load("recipe interactive [\n"+command+"\n]\n");
   transform_all();
+  if (trace_count("warn") > 0) {
+    Hide_warnings = false;
+    *result = 0;
+    return false;
+  }
+//?   cerr << "call interactive: " << Current_routine->calls.size() << '\n'; //? 1
   Current_routine->calls.push_front(call(Recipe_ordinal["interactive"]));
   *result = 0;
   return true;
diff --git a/edit.mu b/edit.mu
index 38c9dc78..2500991f 100644
--- a/edit.mu
+++ b/edit.mu
@@ -1888,6 +1888,8 @@ recipe run-sandboxes [
   default-space:address:array:location <- new location:type, 30:literal
   editor:address:editor-data <- next-ingredient
   screen:address <- next-ingredient
+#?   $print [run sandboxes
+#? ] #? 2
   # todo: load code in left editor
   # compute result of running editor contents
   curr:address:editor-data <- get editor:address:editor-data/deref, next-editor:offset
@@ -1929,6 +1931,58 @@ scenario run-instruction-silently [
   ]
 ]
 
+scenario run-instruction-and-print-warnings [
+#?   $print [=====
+#? ] #? 2
+  assume-screen 60:literal/width, 5:literal/height
+  # left editor is empty
+  1:address:array:character <- new []
+  2:address:editor-data <- new-editor 1:address:array:character, screen:address, 0:literal/top, 0:literal/left, 5:literal/right
+  # right editor contains an illegal instruction
+  3:address:array:character <- new [get 1234:number, foo:offset]
+  4:address:address:editor-data <- get-address 2:address:editor-data/deref, next-editor:offset
+  4:address:address:editor-data/deref <- new-editor 3:address:array:character, screen:address, 0:literal/top, 5:literal/left, 40:literal/right
+  reset-focus 2:address:editor-data
+  # run the code in the editors
+  assume-console [
+    press 65527  # F9
+  ]
+  run [
+    # now run query for it
+#?     $print [about to start event loop
+#? ] #? 1
+    event-loop screen:address, console:address, 2:address:editor-data
+  ]
+  # check that screen prints the value in location 12
+#?   $print [a0
+#? ] #? 1
+#?   $dump-screen #? 1
+#?   get 1234:number, foo:offset #? 1
+  screen-should-contain [
+    .     get 1234:number, foo:offset                            .
+    .     unknown element foo in container number                .
+    .                                                            .
+  ]
+#?   $print [a1
+#? ] #? 1
+#?   $dump-trace #? 1
+#?   $exit #? 2
+  screen-should-contain-in-color 7:literal/white, [
+    .     get 1234:number, foo:offset                            .
+    .                                                            .
+    .                                                            .
+  ]
+#?   $print [a2
+#? ] #? 1
+  screen-should-contain-in-color, 1:literal/red, [
+    .                                                            .
+    .     unknown element foo in container number                .
+    .                                                            .
+  ]
+#?   $print [a3
+#? ] #? 1
+]
+
 ## helpers for drawing editor borders
 
 recipe draw-box [