about summary refs log tree commit diff stats
path: root/tangle/003tangle.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-03-12 18:56:55 -0700
committerKartik Agaram <vc@akkartik.com>2019-03-12 19:14:12 -0700
commit4a943d4ed313eff001504c2b5c472266e86a38af (patch)
treea5757233a8c81b303a808f251180c7344071ed51 /tangle/003tangle.cc
parent43711b0e9f18e0225ce14687fb6ea0902aa6fc61 (diff)
downloadmu-4a943d4ed313eff001504c2b5c472266e86a38af.tar.gz
5001 - drop the :(scenario) DSL
I've been saying for a while[1][2][3] that adding extra abstractions makes
things harder for newcomers, and adding new notations doubly so. And then
I notice this DSL in my own backyard. Makes me feel like a hypocrite.

[1] https://news.ycombinator.com/item?id=13565743#13570092
[2] https://lobste.rs/s/to8wpr/configuration_files_are_canary_warning
[3] https://lobste.rs/s/mdmcdi/little_languages_by_jon_bentley_1986#c_3miuf2

The implementation of the DSL was also highly hacky:

a) It was happening in the tangle/ tool, but was utterly unrelated to tangling
layers.

b) There were several persnickety constraints on the different kinds of
lines and the specific order they were expected in. I kept finding bugs
where the translator would silently do the wrong thing. Or the error messages
sucked, and readers may be stuck looking at the generated code to figure
out what happened. Fixing error messages would require a lot more code,
which is one of my arguments against DSLs in the first place: they may
be easy to implement, but they're hard to design to go with the grain of
the underlying platform. They require lots of iteration. Is that effort
worth prioritizing in this project?

On the other hand, the DSL did make at least some readers' life easier,
the ones who weren't immediately put off by having to learn a strange syntax.
There were fewer quotes to parse, fewer backslash escapes.

Anyway, since there are also people who dislike having to put up with strange
syntaxes, we'll call that consideration a wash and tear this DSL out.

---

This commit was sheer drudgery. Hopefully it won't need to be redone with
a new DSL because I grow sick of backslashes.
Diffstat (limited to 'tangle/003tangle.cc')
-rw-r--r--tangle/003tangle.cc149
1 files changed, 0 insertions, 149 deletions
diff --git a/tangle/003tangle.cc b/tangle/003tangle.cc
index bcb3c315..64c841f1 100644
--- a/tangle/003tangle.cc
+++ b/tangle/003tangle.cc
@@ -100,7 +100,6 @@ void process_next_hunk(istream& in, const string& directive, const string& filen
 
   // first slurp all lines until next directive
   list<Line> hunk;
-  bool end_of_scenario_input = false;
   {
     string curr_line;
     while (!in.eof()) {
@@ -115,22 +114,6 @@ void process_next_hunk(istream& in, const string& directive, const string& filen
         ++line_number;
         continue;
       }
-      if (cmd == "scenario") {
-        // ignore mu comments in scenarios, but only after the end of input
-        if (!starts_with(curr_line, "#") && !is_input(curr_line)) {
-          // remaining lines are checks
-          end_of_scenario_input = true;
-        }
-        else if (end_of_scenario_input && starts_with(curr_line, "#")) {
-          ++line_number;
-          continue;
-        }
-        if (trim(curr_line).empty()) {
-          // ignore empty lines in scenarios, whether in input of after
-          ++line_number;
-          continue;
-        }
-      }
       hunk.push_back(Line(curr_line, filename, line_number));
       ++line_number;
     }
@@ -141,21 +124,6 @@ void process_next_hunk(istream& in, const string& directive, const string& filen
     return;
   }
 
-  if (cmd == "scenarios") {
-    Toplevel = next_tangle_token(directive_stream);
-    return;
-  }
-
-  if (cmd == "scenario") {
-    list<Line> result;
-    string name = next_tangle_token(directive_stream);
-    emit_test(name, hunk, result);
-//?     cerr << out.size() << " " << result.size() << '\n';
-    out.insert(out.end(), result.begin(), result.end());
-//?     cerr << out.size() << " " << result.size() << '\n';
-    return;
-  }
-
   if (cmd == "before" || cmd == "after" || cmd == "replace" || cmd == "replace{}" || cmd == "delete" || cmd == "delete{}") {
     list<Line>::iterator target = locate_target(out, directive_stream);
     if (target == out.end()) {
@@ -291,111 +259,6 @@ list<Line>::iterator balancing_curly(list<Line>::iterator curr) {
   return curr;
 }
 
-// A scenario is one or more sessions separated by calls to CLEAR_TRACE ('===')
-//   A session is:
-//     one or more lines of escaped setup in C/C++ ('%')
-//   followed by one or more lines of input,
-//   followed optionally by (in order):
-//     one or more lines expected in trace in order ('+') and one or more lines trace shouldn't include ('-')
-//     one or more lines expressing counts of specific layers emitted in trace ('$')
-//     a directive to print the trace just for debugging ('?')
-// Remember to update is_input below if you add to this format.
-//
-// Allowing interleaving of '+' and '-' lines is a kludgy way to indicate that
-// two sets of trace lines can occur in any order. We should come up with a
-// better way to specify order-independence.
-void emit_test(const string& name, list<Line>& lines, list<Line>& result) {
-  result.push_back(Line("void test_"+name+"() {", front(lines).filename, front(lines).line_number-1));  // use line number of directive
-//?   result.push_back("cerr << \""+name+"\\n\";");  // debug: uncomment this to print scenario names as you run them
-  while (!lines.empty()) {
-    while (!lines.empty() && starts_with(front(lines).contents, "% ")) {
-      result.push_back(Line("  "+front(lines).contents.substr(strlen("% ")), front(lines)));
-      lines.pop_front();
-    }
-    if (lines.empty()) break;
-    emit_input_lines(lines, result);
-    emit_expected_in_trace(lines, result);
-    while (!lines.empty() && !front(lines).contents.empty() && front(lines).contents.at(0) == '-') {
-      result.push_back(expected_not_in_trace(front(lines)));
-      lines.pop_front();
-    }
-    if (!lines.empty() && front(lines).contents.at(0) == '$') {
-      const string& in = front(lines).contents;
-      size_t pos = in.find(": ");
-      string layer = in.substr(1, pos-1);
-      string count = in.substr(pos+2);
-      result.push_back(Line("  CHECK_TRACE_COUNT(\""+layer+"\", "+count+");", front(lines)));
-      lines.pop_front();
-    }
-    if (!lines.empty() && front(lines).contents == "===") {
-      result.push_back(Line("  CLEAR_TRACE;", front(lines)));
-      lines.pop_front();
-    }
-    if (!lines.empty() && front(lines).contents == "?") {
-      result.push_back(Line("  DUMP(\"\");", front(lines)));
-      lines.pop_front();
-    }
-  }
-  result.push_back(Line("}"));
-}
-
-bool is_input(const string& line) {
-  if (line.empty()) return true;
-  return line != "===" && line.find_first_of("+-$?%") != 0;
-}
-
-void emit_input_lines(list<Line>& hunk, list<Line>& out) {
-  assert(!hunk.empty());
-  if (!is_input(front(hunk).contents)) return;
-  Line curr_out;
-  curr_out.line_number = hunk.front().line_number;
-  curr_out.filename = hunk.front().filename;
-  curr_out.contents = "  "+Toplevel+"(";
-  out.push_back(curr_out);
-  for (/*nada*/;  !hunk.empty() && is_input(front(hunk).contents);  hunk.pop_front()) {
-    Line curr_out;
-    curr_out.line_number = front(hunk).line_number;
-    curr_out.filename = front(hunk).filename;
-    curr_out.contents = "      \""+escape(front(hunk).contents+'')+"\"";
-    out.push_back(curr_out);
-  }
-  curr_out.line_number = out.back().line_number;
-  curr_out.filename = out.back().filename;
-  curr_out.contents = "  );";
-  out.push_back(curr_out);
-}
-
-// pull lines starting with '+' out of 'hunk', and append translated lines to 'out'
-void emit_expected_in_trace(list<Line>& hunk, list<Line>& out) {
-  if (hunk.empty()) return;
-  if (front(hunk).contents.empty()) return;
-  if (front(hunk).contents.at(0) != '+') return;
-  Line curr_out;
-  curr_out.line_number = front(hunk).line_number;
-  curr_out.filename = front(hunk).filename;
-  curr_out.contents = "  CHECK_TRACE_CONTENTS(";
-  out.push_back(curr_out);
-  for (/*nada*/;  !hunk.empty() && front(hunk).contents.at(0) == '+';  hunk.pop_front()) {
-    Line curr_out;
-    curr_out.line_number = front(hunk).line_number;
-    curr_out.filename = front(hunk).filename;
-    curr_out.contents = "      \""+escape(front(hunk).contents.substr(1))+"\"";
-    out.push_back(curr_out);
-  }
-  curr_out.line_number = out.back().line_number;
-  curr_out.filename = out.back().filename;
-  curr_out.contents = "  );";
-  out.push_back(curr_out);
-}
-
-Line expected_not_in_trace(const Line& line) {
-  Line result;
-  result.line_number = line.line_number;
-  result.filename = line.filename;
-  result.contents = "  CHECK_TRACE_DOESNT_CONTAIN(\""+escape(line.contents.substr(1))+"\");";
-  return result;
-}
-
 list<Line>::iterator find_substr(list<Line>& in, const string& pat) {
   for (list<Line>::iterator p = in.begin(); p != in.end(); ++p)
     if (p->contents.find(pat) != string::npos)
@@ -430,18 +293,6 @@ string replace_all(string s, const string& a, const string& b) {
   return s;
 }
 
-bool any_line_starts_with(const list<Line>& lines, const string& pat) {
-  for (list<Line>::const_iterator p = lines.begin(); p != lines.end(); ++p)
-    if (starts_with(p->contents, pat)) return true;
-  return false;
-}
-
-bool any_non_input_line(const list<Line>& lines) {
-  for (list<Line>::const_iterator p = lines.begin(); p != lines.end(); ++p)
-    if (!is_input(p->contents)) return true;
-  return false;
-}
-
 // does s start with pat, after skipping whitespace?
 // pat can't start with whitespace
 bool starts_with(const string& s, const string& pat) {