about summary refs log tree commit diff stats
path: root/cpp/031scenario
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-04-08 00:47:04 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-04-08 00:47:04 -0700
commite38c85a1eb6a0107ed43d7d7dbc9f4080a917c59 (patch)
tree4507d37728f9ed4ebb1dab2960d751415bbaf10f /cpp/031scenario
parentfd2cba359fbf6897741dbd14f23f32a9ce638e14 (diff)
downloadmu-e38c85a1eb6a0107ed43d7d7dbc9f4080a917c59.tar.gz
1037 - support scenarios in mu files
I'd forgotten that I hadn't yet committed this change in my comment to
commit 1031. Now if I don't freeze things after loading the string-equal
tests do fail as expected because the recipe was deleted.
Diffstat (limited to 'cpp/031scenario')
-rw-r--r--cpp/031scenario100
1 files changed, 89 insertions, 11 deletions
diff --git a/cpp/031scenario b/cpp/031scenario
index 2fbd2ffc..2b665449 100644
--- a/cpp/031scenario
+++ b/cpp/031scenario
@@ -12,7 +12,13 @@ vector<scenario> Scenarios;
 //? cout << "AAA\n"; //? 1
 for (size_t i = 0; i < Scenarios.size(); ++i) {
 //?   cout << "BBB\n"; //? 1
+  setup();
+  Trace_stream = new trace_stream;
+//?   Trace_stream->dump_layer = "all"; //? 1
+//?   cout << "Before:\n";  dump_memory(); //? 1
+//?   cout << Scenarios[i].to_run; //? 1
   run(Scenarios[i].to_run);
+//?   cout << "After:\n";  dump_memory(); //? 1
   for (map<int, int>::iterator p = Scenarios[i].memory_expectations.begin();
        p != Scenarios[i].memory_expectations.end();
        ++p) {
@@ -34,20 +40,92 @@ else if (command == "scenario") {
 scenario parse_scenario(istream& in) {
   scenario x;
   x.name = next_word(in);
-//?   cout << "AAA scenario name " << x.name << '\n'; //? 1
-  skip_whitespace(in);  skip_comments_and_newlines(in);  skip_whitespace(in);
-  assert(in.get() == '[');
-  int brace_depth = 1;
+  trace("parse") << "reading scenario " << x.name;
+  skip_bracket(in, "'scenario' must begin with '['");
+  ostringstream buffer;
+  slurp_until_matching_bracket(in, buffer);
+//?   cout << "inner buffer: ^" << buffer.str() << "$\n"; //? 1
+  istringstream inner(buffer.str());
+  inner >> std::noskipws;
+  while (!inner.eof()) {
+    skip_whitespace_and_comments(inner);
+    string scenario_command = next_word(inner);
+    if (scenario_command.empty() && inner.eof()) break;
+    // Scenario Command Handlers
+    if (scenario_command == "run") {
+      handle_scenario_run_directive(inner, x);
+      trace("parse") << "scenario will run: " << x.to_run;
+    }
+    else if (scenario_command == "memory") {
+      handle_scenario_memory_directive(inner, x);
+    }
+    // End Scenario Command Handlers
+    else {
+      raise << "unknown command in scenario: ^" << scenario_command << "$";
+    }
+  }
+  return x;
+}
+
+void handle_scenario_run_directive(istream& in, scenario& result) {
+  skip_bracket(in, "'run' inside scenario must begin with '['");
+  ostringstream buffer;
+  slurp_until_matching_bracket(in, buffer);
+  result.to_run = "recipe test-"+result.name+" [" + buffer.str() + "]";
+}
+
+void handle_scenario_memory_directive(istream& in, scenario& out) {
+  if (next_word(in) != "should") {
+    raise << "'memory' directive inside scenario must continue 'memory should'";
+  }
+  if (next_word(in) != "contain") {
+    raise << "'memory' directive inside scenario must continue 'memory should contain'";
+  }
+  skip_whitespace_and_comments(in);
+  if (in.get() != '[') {
+    raise << "'memory' directive inside scenario must begin with 'memory should contain ['";
+  }
+  while (true) {
+    skip_whitespace_and_comments(in);
+    if (in.eof()) break;
+//?     cout << "a: " << in.peek() << '\n'; //? 1
+    if (in.peek() == ']') break;
+    int address = 0;  in >> address;
+//?     cout << "address: " << address << '\n'; //? 2
+//?     cout << "b: " << in.peek() << '\n'; //? 1
+    skip_whitespace_and_comments(in);
+//?     cout << "c: " << in.peek() << '\n'; //? 1
+    string _assign;  in >> _assign;  assert(_assign == "<-");
+    skip_whitespace_and_comments(in);
+    int value = 0;  in >> value;
+    out.memory_expectations[address] = value;
+    trace("parse") << "memory expectation: *" << address << " == " << value;
+  }
+  skip_whitespace(in);
+  assert(in.get() == ']');
+}
+
+void slurp_until_matching_bracket(istream& in, ostream& out) {
+  int brace_depth = 1;  // just scanned '['
   char c;
   while (in >> c) {
-    x.to_run += c;
     if (c == '[') ++brace_depth;
     if (c == ']') --brace_depth;
-    if (brace_depth == 0) break;
+    if (brace_depth == 0) break;  // drop final ']'
+    out << c;
+  }
+}
+
+void skip_bracket(istream& in, string message) {
+  skip_whitespace(in);  skip_comments_and_newlines(in);  skip_whitespace(in);
+  if (in.get() != '[')
+    raise << message;
+}
+
+void skip_whitespace_and_comments(istream& in) {
+  while (true) {
+    if (isspace(in.peek())) in.get();
+    else if (in.peek() == '#') skip_comment(in);
+    else break;
   }
-  x.to_run = "recipe main [\n"
-             "  1:integer/raw <- add 3:literal, 3:literal\n"
-             "]";
-  x.memory_expectations[1] = 6;
-  return x;
 }