about summary refs log tree commit diff stats
path: root/040brace.cc
diff options
context:
space:
mode:
Diffstat (limited to '040brace.cc')
-rw-r--r--040brace.cc550
1 files changed, 321 insertions, 229 deletions
diff --git a/040brace.cc b/040brace.cc
index 8eead4ab..89ff7b01 100644
--- a/040brace.cc
+++ b/040brace.cc
@@ -19,17 +19,21 @@
 //: benefits of the control-flow primitives we're used to in other languages,
 //: like 'if', 'while', 'for', etc.
 
-:(scenarios transform)
-:(scenario brace_conversion)
-def main [
-  {
-    break
-    1:num <- copy 0
-  }
-]
-+transform: --- transform braces for recipe main
-+transform: jump 1:offset
-+transform: copy ...
+void test_brace_conversion() {
+  transform(
+      "def main [\n"
+      "  {\n"
+      "    break\n"
+      "    1:num <- copy 0\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: jump 1:offset\n"
+      "transform: copy ...\n"
+  );
+}
 
 :(before "End Instruction Modifying Transforms")
 Transform.push_back(transform_braces);  // idempotent
@@ -143,244 +147,332 @@ int matching_brace(int index, const list<pair<bool, int> >& braces, recipe_ordin
   return SIZE(get(Recipe, r).steps);  // exit current routine
 }
 
-:(scenario loop)
-def main [
-  1:num <- copy 0
-  2:num <- copy 0
-  {
-    3:num <- copy 0
-    loop
-  }
-]
-+transform: --- transform braces for recipe main
-+transform: copy ...
-+transform: copy ...
-+transform: copy ...
-+transform: jump -2:offset
+void test_loop() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  2:num <- copy 0\n"
+      "  {\n"
+      "    3:num <- copy 0\n"
+      "    loop\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: copy ...\n"
+      "transform: copy ...\n"
+      "transform: copy ...\n"
+      "transform: jump -2:offset\n"
+  );
+}
 
-:(scenario break_empty_block)
-def main [
-  1:num <- copy 0
-  {
-    break
-  }
-]
-+transform: --- transform braces for recipe main
-+transform: copy ...
-+transform: jump 0:offset
+void test_break_empty_block() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  {\n"
+      "    break\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: copy ...\n"
+      "transform: jump 0:offset\n"
+  );
+}
 
-:(scenario break_cascading)
-def main [
-  1:num <- copy 0
-  {
-    break
-  }
-  {
-    break
-  }
-]
-+transform: --- transform braces for recipe main
-+transform: copy ...
-+transform: jump 0:offset
-+transform: jump 0:offset
+void test_break_cascading() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  {\n"
+      "    break\n"
+      "  }\n"
+      "  {\n"
+      "    break\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: copy ...\n"
+      "transform: jump 0:offset\n"
+      "transform: jump 0:offset\n"
+  );
+}
 
-:(scenario break_cascading_2)
-def main [
-  1:num <- copy 0
-  2:num <- copy 0
-  {
-    break
-    3:num <- copy 0
-  }
-  {
-    break
-  }
-]
-+transform: --- transform braces for recipe main
-+transform: copy ...
-+transform: copy ...
-+transform: jump 1:offset
-+transform: copy ...
-+transform: jump 0:offset
+void test_break_cascading_2() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  2:num <- copy 0\n"
+      "  {\n"
+      "    break\n"
+      "    3:num <- copy 0\n"
+      "  }\n"
+      "  {\n"
+      "    break\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: copy ...\n"
+      "transform: copy ...\n"
+      "transform: jump 1:offset\n"
+      "transform: copy ...\n"
+      "transform: jump 0:offset\n"
+  );
+}
 
-:(scenario break_if)
-def main [
-  1:num <- copy 0
-  2:num <- copy 0
-  {
-    break-if 2:num
-    3:num <- copy 0
-  }
-  {
-    break
-  }
-]
-+transform: --- transform braces for recipe main
-+transform: copy ...
-+transform: copy ...
-+transform: jump-if 2, 1:offset
-+transform: copy ...
-+transform: jump 0:offset
+void test_break_if() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  2:num <- copy 0\n"
+      "  {\n"
+      "    break-if 2:num\n"
+      "    3:num <- copy 0\n"
+      "  }\n"
+      "  {\n"
+      "    break\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: copy ...\n"
+      "transform: copy ...\n"
+      "transform: jump-if 2, 1:offset\n"
+      "transform: copy ...\n"
+      "transform: jump 0:offset\n"
+  );
+}
 
-:(scenario break_nested)
-def main [
-  1:num <- copy 0
-  {
-    2:num <- copy 0
-    break
-    {
-      3:num <- copy 0
-    }
-    4:num <- copy 0
-  }
-]
-+transform: jump 4:offset
+void test_break_nested() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  {\n"
+      "    2:num <- copy 0\n"
+      "    break\n"
+      "    {\n"
+      "      3:num <- copy 0\n"
+      "    }\n"
+      "    4:num <- copy 0\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: jump 4:offset\n"
+  );
+}
 
-:(scenario break_nested_degenerate)
-def main [
-  1:num <- copy 0
-  {
-    2:num <- copy 0
-    break
-    {
-    }
-    4:num <- copy 0
-  }
-]
-+transform: jump 3:offset
+void test_break_nested_degenerate() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  {\n"
+      "    2:num <- copy 0\n"
+      "    break\n"
+      "    {\n"
+      "    }\n"
+      "    4:num <- copy 0\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: jump 3:offset\n"
+  );
+}
 
-:(scenario break_nested_degenerate_2)
-def main [
-  1:num <- copy 0
-  {
-    2:num <- copy 0
-    break
-    {
-    }
-  }
-]
-+transform: jump 2:offset
+void test_break_nested_degenerate_2() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  {\n"
+      "    2:num <- copy 0\n"
+      "    break\n"
+      "    {\n"
+      "    }\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: jump 2:offset\n"
+  );
+}
 
-:(scenario break_label)
-% Hide_errors = true;
-def main [
-  1:num <- copy 0
-  {
-    break +foo:offset
-  }
-]
-+transform: jump +foo:offset
+void test_break_label() {
+  Hide_errors = true;
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  {\n"
+      "    break +foo:offset\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: jump +foo:offset\n"
+  );
+}
 
-:(scenario break_unless)
-def main [
-  1:num <- copy 0
-  2:num <- copy 0
-  {
-    break-unless 2:num
-    3:num <- copy 0
-  }
-]
-+transform: --- transform braces for recipe main
-+transform: copy ...
-+transform: copy ...
-+transform: jump-unless 2, 1:offset
-+transform: copy ...
+void test_break_unless() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  2:num <- copy 0\n"
+      "  {\n"
+      "    break-unless 2:num\n"
+      "    3:num <- copy 0\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: copy ...\n"
+      "transform: copy ...\n"
+      "transform: jump-unless 2, 1:offset\n"
+      "transform: copy ...\n"
+  );
+}
 
-:(scenario loop_unless)
-def main [
-  1:num <- copy 0
-  2:num <- copy 0
-  {
-    loop-unless 2:num
-    3:num <- copy 0
-  }
-]
-+transform: --- transform braces for recipe main
-+transform: copy ...
-+transform: copy ...
-+transform: jump-unless 2, -1:offset
-+transform: copy ...
+void test_loop_unless() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  2:num <- copy 0\n"
+      "  {\n"
+      "    loop-unless 2:num\n"
+      "    3:num <- copy 0\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: copy ...\n"
+      "transform: copy ...\n"
+      "transform: jump-unless 2, -1:offset\n"
+      "transform: copy ...\n"
+  );
+}
 
-:(scenario loop_nested)
-def main [
-  1:num <- copy 0
-  {
-    2:num <- copy 0
-    {
-      3:num <- copy 0
-    }
-    loop-if 4:bool
-    5:num <- copy 0
-  }
-]
-+transform: --- transform braces for recipe main
-+transform: jump-if 4, -5:offset
+void test_loop_nested() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  {\n"
+      "    2:num <- copy 0\n"
+      "    {\n"
+      "      3:num <- copy 0\n"
+      "    }\n"
+      "    loop-if 4:bool\n"
+      "    5:num <- copy 0\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: jump-if 4, -5:offset\n"
+  );
+}
 
-:(scenario loop_label)
-def main [
-  1:num <- copy 0
-  +foo
-  2:num <- copy 0
-]
-+transform: --- transform braces for recipe main
-+transform: copy ...
-+transform: copy ...
+void test_loop_label() {
+  transform(
+      "def main [\n"
+      "  1:num <- copy 0\n"
+      "  +foo\n"
+      "  2:num <- copy 0\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "transform: --- transform braces for recipe main\n"
+      "transform: copy ...\n"
+      "transform: copy ...\n"
+  );
+}
 
 //: test how things actually run
-:(scenarios run)
-:(scenario brace_conversion_and_run)
-def test-factorial [
-  1:num <- copy 5
-  2:num <- copy 1
-  {
-    3:bool <- equal 1:num, 1
-    break-if 3:bool
-#    $print 1:num
-    2:num <- multiply 2:num, 1:num
-    1:num <- subtract 1:num, 1
-    loop
-  }
-  4:num <- copy 2:num  # trigger a read
-]
-+mem: location 2 is 120
+void test_brace_conversion_and_run() {
+  run(
+      "def test-factorial [\n"
+      "  1:num <- copy 5\n"
+      "  2:num <- copy 1\n"
+      "  {\n"
+      "    3:bool <- equal 1:num, 1\n"
+      "    break-if 3:bool\n"
+      "    2:num <- multiply 2:num, 1:num\n"
+      "    1:num <- subtract 1:num, 1\n"
+      "    loop\n"
+      "  }\n"
+      "  4:num <- copy 2:num\n"  // trigger a read
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "mem: location 2 is 120\n"
+  );
+}
 
-:(scenario break_outside_braces_fails)
-% Hide_errors = true;
-def main [
-  break
-]
-+error: main: 'break' needs a '{' before
+void test_break_outside_braces_fails() {
+  Hide_errors = true;
+  run(
+      "def main [\n"
+      "  break\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "error: main: 'break' needs a '{' before\n"
+  );
+}
 
-:(scenario break_conditional_without_ingredient_fails)
-% Hide_errors = true;
-def main [
-  {
-    break-if
-  }
-]
-+error: main: 'break-if' expects 1 or 2 ingredients, but got none
+void test_break_conditional_without_ingredient_fails() {
+  Hide_errors = true;
+  run(
+      "def main [\n"
+      "  {\n"
+      "    break-if\n"
+      "  }\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "error: main: 'break-if' expects 1 or 2 ingredients, but got none\n"
+  );
+}
 
 //: Using break we can now implement conditional returns.
 
-:(scenario return_if)
-def main [
-  1:num <- test1
-]
-def test1 [
-  return-if 0, 34
-  return 35
-]
-+mem: storing 35 in location 1
+void test_return_if() {
+  run(
+      "def main [\n"
+      "  1:num <- test1\n"
+      "]\n"
+      "def test1 [\n"
+      "  return-if 0, 34\n"
+      "  return 35\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "mem: storing 35 in location 1\n"
+  );
+}
 
-:(scenario return_if_2)
-def main [
-  1:num <- test1
-]
-def test1 [
-  return-if 1, 34
-  return 35
-]
-+mem: storing 34 in location 1
+void test_return_if_2() {
+  run(
+      "def main [\n"
+      "  1:num <- test1\n"
+      "]\n"
+      "def test1 [\n"
+      "  return-if 1, 34\n"
+      "  return 35\n"
+      "]\n"
+  );
+  CHECK_TRACE_CONTENTS(
+      "mem: storing 34 in location 1\n"
+  );
+}
 
 :(before "End Rewrite Instruction(curr, recipe result)")
 // rewrite 'return-if a, b, c, ...' to