From 4690ce81e079fc58cae8d6d583e5e3eb3ed81a83 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Wed, 9 Mar 2016 02:56:27 -0800 Subject: 2743 Looks like "TOhtml | " doesn't work on Mac OS X for some reason.. --- html/041jump_target.cc.html | 116 +++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 51 deletions(-) (limited to 'html/041jump_target.cc.html') diff --git a/html/041jump_target.cc.html b/html/041jump_target.cc.html index b9354279..76766b30 100644 --- a/html/041jump_target.cc.html +++ b/html/041jump_target.cc.html @@ -3,35 +3,28 @@ Mu - 041jump_target.cc - - + + - - + - - -
+
 //: Support jumps to special labels called 'targets'. Targets must be in the
 //: same recipe as the jump, and must be unique in that recipe. Targets always
 //: start with a '+'.
@@ -42,7 +35,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; }
 //: iteration of some containing loop nest.
 
 :(scenario jump_to_label)
-recipe main [
+def main [
   jump +target:label
   1:number <- copy 0
   +target
@@ -56,69 +49,77 @@ put(Type_ordinal,
 Transform.push_back(transform_labels);  // idempotent
 
 :(code)
-void transform_labels(const recipe_ordinal r) {
-  map<string, long long int> offset;
-  for (long long int i = 0; i < SIZE(get(Recipe, r).steps); ++i) {
-    const instruction& inst = get(Recipe, r).steps.at(i);
-    if (!inst.label.empty() && inst.label.at(0) == '+') {
-      if (!contains_key(offset, inst.label)) {
+void transform_labels(const recipe_ordinal r) {
+  map<string, long long int> offset;
+  for (long long int i = 0; i < SIZE(get(Recipe, r).steps); ++i) {
+    const instruction& inst = get(Recipe, r).steps.at(i);
+    if (!inst.label.empty() && inst.label.at(0) == '+') {
+      if (!contains_key(offset, inst.label)) {
         put(offset, inst.label, i);
       }
-      else {
-        raise_error << maybe(get(Recipe, r).name) << "duplicate label '" << inst.label << "'" << end();
+      else {
+        raise << maybe(get(Recipe, r).name) << "duplicate label '" << inst.label << "'" << end();
         // have all jumps skip some random but noticeable and deterministic amount of code
         put(offset, inst.label, 9999);
       }
     }
   }
-  for (long long int i = 0; i < SIZE(get(Recipe, r).steps); ++i) {
+  for (long long int i = 0; i < SIZE(get(Recipe, r).steps); ++i) {
     instruction& inst = get(Recipe, r).steps.at(i);
-    if (inst.name == "jump") {
+    if (inst.name == "jump") {
+      if (inst.ingredients.empty()) {
+        raise << maybe(get(Recipe, r).name) << "'jump' expects an ingredient but got none\n" << end();
+        return;
+      }
       replace_offset(inst.ingredients.at(0), offset, i, r);
     }
-    if (inst.name == "jump-if" || inst.name == "jump-unless") {
+    if (inst.name == "jump-if" || inst.name == "jump-unless") {
+      if (SIZE(inst.ingredients) < 2) {
+        raise << maybe(get(Recipe, r).name) << "'" << inst.name << "' expects 2 ingredients but got " << SIZE(inst.ingredients) << '\n' << end();
+        return;
+      }
       replace_offset(inst.ingredients.at(1), offset, i, r);
     }
-    if ((inst.name == "loop" || inst.name == "break")
-        && SIZE(inst.ingredients) == 1) {
+    if ((inst.name == "loop" || inst.name == "break")
+        && SIZE(inst.ingredients) >= 1) {
       replace_offset(inst.ingredients.at(0), offset, i, r);
     }
-    if ((inst.name == "loop-if" || inst.name == "loop-unless"
+    if ((inst.name == "loop-if" || inst.name == "loop-unless"
             || inst.name == "break-if" || inst.name == "break-unless")
-        && SIZE(inst.ingredients) == 2) {
+        && SIZE(inst.ingredients) >= 2) {
       replace_offset(inst.ingredients.at(1), offset, i, r);
     }
   }
 }
 
 :(code)
-void replace_offset(reagent& x, /*const*/ map<string, long long int>& offset, const long long int current_offset, const recipe_ordinal r) {
-  if (!is_literal(x)) {
-    raise_error << maybe(get(Recipe, r).name) << "jump target must be offset or label but is " << x.original_string << '\n' << end();
+void replace_offset(reagent& x, /*const*/ map<string, long long int>& offset, const long long int current_offset, const recipe_ordinal r) {
+  if (!is_literal(x)) {
+    raise << maybe(get(Recipe, r).name) << "jump target must be offset or label but is " << x.original_string << '\n' << end();
     x.set_value(0);  // no jump by default
     return;
   }
-  if (x.initialized) return;
-  if (is_integer(x.name)) return;  // non-labels will be handled like other number operands
-  if (!is_jump_target(x.name)) {
-    raise_error << maybe(get(Recipe, r).name) << "can't jump to label " << x.name << '\n' << end();
+  if (x.initialized) return;
+  if (is_integer(x.name)) return;  // non-labels will be handled like other number operands
+  if (!is_jump_target(x.name)) {
+    raise << maybe(get(Recipe, r).name) << "can't jump to label " << x.name << '\n' << end();
     x.set_value(0);  // no jump by default
     return;
   }
-  if (!contains_key(offset, x.name)) {
-    raise_error << maybe(get(Recipe, r).name) << "can't find label " << x.name << '\n' << end();
+  if (!contains_key(offset, x.name)) {
+    raise << maybe(get(Recipe, r).name) << "can't find label " << x.name << '\n' << end();
     x.set_value(0);  // no jump by default
     return;
   }
   x.set_value(get(offset, x.name) - current_offset);
 }
 
-bool is_jump_target(string label) {
+bool is_jump_target(string label) {
   return label.at(0) == '+';
 }
 
 :(scenario break_to_label)
-recipe main [
+def main [
   {
     {
       break +target:label
@@ -130,10 +131,10 @@ recipe main [
 -mem: storing 0 in location 1
 
 :(scenario jump_if_to_label)
-recipe main [
+def main [
   {
     {
-      jump-if 1, +target:label
+      jump-if 1, +target:label
       1:number <- copy 0
     }
   }
@@ -142,7 +143,7 @@ recipe main [
 -mem: storing 0 in location 1
 
 :(scenario loop_unless_to_label)
-recipe main [
+def main [
   {
     {
       loop-unless 0, +target:label  # loop/break with a label don't care about braces
@@ -154,7 +155,7 @@ recipe main [
 -mem: storing 0 in location 1
 
 :(scenario jump_runs_code_after_label)
-recipe main [
+def main [
   # first a few lines of padding to exercise the offset computation
   1:number <- copy 0
   2:number <- copy 0
@@ -167,9 +168,23 @@ recipe main [
 +mem: storing 0 in location 5
 -mem: storing 0 in location 4
 
+:(scenario jump_fails_without_target)
+% Hide_errors = true;
+def main [
+  jump
+]
++error: main: 'jump' expects an ingredient but got none
+
+:(scenario jump_fails_without_target_2)
+% Hide_errors = true;
+def main [
+  jump-if 1/true
+]
++error: main: 'jump-if' expects 2 ingredients but got 1
+
 :(scenario recipe_fails_on_duplicate_jump_target)
 % Hide_errors = true;
-recipe main [
+def main [
   +label
   1:number <- copy 0
   +label
@@ -179,7 +194,7 @@ recipe main [
 
 :(scenario jump_ignores_nontarget_label)
 % Hide_errors = true;
-recipe main [
+def main [
   # first a few lines of padding to exercise the offset computation
   1:number <- copy 0
   2:number <- copy 0
@@ -193,4 +208,3 @@ recipe main [
 
- -- cgit 1.4.1-2-gfad0