about summary refs log tree commit diff stats
path: root/cpp/072scenario_screen.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-04 10:31:52 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-04 10:31:52 -0700
commitde49fb426aa44984d308f5856ec836360ba0bdce (patch)
tree5522203f99d3d387439c4cd0385e0375ccd8ed0d /cpp/072scenario_screen.cc
parenta11d9c4a3375906bf8ae1117c6043776d2f08d17 (diff)
downloadmu-de49fb426aa44984d308f5856ec836360ba0bdce.tar.gz
1248 - syntax for using screens in scenarios
Still ugly as hell.
Diffstat (limited to 'cpp/072scenario_screen.cc')
-rw-r--r--cpp/072scenario_screen.cc105
1 files changed, 105 insertions, 0 deletions
diff --git a/cpp/072scenario_screen.cc b/cpp/072scenario_screen.cc
new file mode 100644
index 00000000..a0f9c78e
--- /dev/null
+++ b/cpp/072scenario_screen.cc
@@ -0,0 +1,105 @@
+//: Some cleaner way to manipulate and check the screen in scenarios.
+
+:(scenarios run_mu_scenario)
+:(scenario screen_in_scenario)
+scenario screen-in-scenario [
+#?   $start-tracing
+  assume-screen 5:literal/width, 3:literal/height
+  run [
+    screen:address <- print-character screen:address, 97:literal  # 'a'
+  ]
+  screen-should-contain [
+  #  01234
+    .a    .
+    .     .
+    .     .
+  ]
+#?   $exit
+]
+
+:(scenario screen_in_scenario_error)
+#? % cerr << "AAA\n";
+% Hide_warnings = true;
+scenario screen-in-scenario-error [
+  assume-screen 5:literal/width, 3:literal/height
+  run [
+    screen:address <- print-character screen:address, 97:literal  # 'a'
+  ]
+  screen-should-contain [
+  #  01234
+    .b    .
+    .     .
+    .     .
+  ]
+]
++warn: expected screen location (0, 0) to contain 'b' instead of 'a'
+
+:(before "End Rewrite Instruction(curr)")
+// rewrite `assume-screen width, height` to
+// `screen:address <- init-fake-screen width, height`
+//? cout << "before: " << curr.to_string() << '\n'; //? 1
+if (curr.name == "assume-screen") {
+  curr.operation = Recipe_number["init-fake-screen"];
+  assert(curr.products.empty());
+  curr.products.push_back(reagent("screen:address"));
+  curr.products[0].set_value(Reserved_for_tests-1);
+//? cout << "after: " << curr.to_string() << '\n'; //? 1
+//? cout << "AAA " << Recipe_number["init-fake-screen"] << '\n'; //? 1
+}
+
+//: screen-should-contain is a regular instruction
+:(before "End Primitive Recipe Declarations")
+SCREEN_SHOULD_CONTAIN,
+:(before "End Primitive Recipe Numbers")
+Recipe_number["screen-should-contain"] = SCREEN_SHOULD_CONTAIN;
+:(before "End Primitive Recipe Implementations")
+case SCREEN_SHOULD_CONTAIN: {
+//?   cout << "AAA\n"; //? 1
+  check_screen(current_instruction().ingredients[0].name);
+  break;
+}
+
+:(code)
+void check_screen(const string& contents) {
+  static const int screen_variable = Reserved_for_tests-1;
+  assert(!Current_routine->calls.top().default_space);  // not supported
+  size_t screen_location = Memory[screen_variable];
+  int data_offset = find_element_name(Type_number["screen"], "data");
+  assert(data_offset >= 0);
+  size_t screen_data_location = screen_location+data_offset;  // type: address:array:character
+  size_t screen_data_start = Memory[screen_data_location];  // type: array:character
+  int width_offset = find_element_name(Type_number["screen"], "num-columns");
+  size_t screen_width = Memory[screen_location+width_offset];
+  int height_offset = find_element_name(Type_number["screen"], "num-rows");
+  size_t screen_height = Memory[screen_location+height_offset];
+  string expected_contents;
+  istringstream in(contents);
+  in >> std::noskipws;
+  for (size_t row = 0; row < screen_height; ++row) {
+    skip_whitespace_and_comments(in);
+    assert(!in.eof());
+    assert(in.get() == '.');
+    for (size_t column = 0; column < screen_width; ++column) {
+      assert(!in.eof());
+      expected_contents += in.get();
+    }
+    assert(in.get() == '.');
+  }
+  skip_whitespace_and_comments(in);
+//?   assert(in.get() == ']');
+  trace("run") << "checking screen size at " << screen_data_start;
+//?   cout << expected_contents.size() << '\n'; //? 1
+  if (Memory[screen_data_start] > static_cast<signed>(expected_contents.size()))
+    raise << "expected contents are larger than screen size " << Memory[screen_data_start] << '\n';
+  ++screen_data_start;  // now skip length
+  for (size_t i = 0; i < expected_contents.size(); ++i) {
+    trace("run") << "checking location " << screen_data_start+i;
+    if ((!Memory[screen_data_start+i] && !isspace(expected_contents[i]))  // uninitialized memory => spaces
+        || (Memory[screen_data_start+i] && Memory[screen_data_start+i] != expected_contents[i])) {
+//?       cerr << "CCC " << Trace_stream << " " << Hide_warnings << '\n'; //? 1
+      raise << "expected screen location (" << i/screen_width << ", " << i%screen_width << ") to contain '" << expected_contents[i] << "' instead of '" << static_cast<char>(Memory[screen_data_start+i]) << "'\n";
+      Passed = false;
+      return;
+    }
+  }
+}