From 204dae921abff0c70e017215bb3c91fa6ca11aff Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 26 Dec 2016 11:44:14 -0800 Subject: 3710 Turns out we don't need to explicitly add anchors for each line. Vim's TOhtml has magic for that out of the box. --- html/041jump_target.cc.html | 366 ++++++++++++++++++++++---------------------- 1 file changed, 183 insertions(+), 183 deletions(-) (limited to 'html/041jump_target.cc.html') diff --git a/html/041jump_target.cc.html b/html/041jump_target.cc.html index f0c69dde..1b10b1de 100644 --- a/html/041jump_target.cc.html +++ b/html/041jump_target.cc.html @@ -58,189 +58,189 @@ if ('onhashchange' in window) {
-  1 //: Support jumps to a specific label (the 'jump target') in the same recipe.
-  2 //: Jump targets must be unique and unambiguous within any recipe.
-  3 //:
-  4 //: The 'break' and 'loop' pseudo instructions can also take jump targets.
-  5 //: Which instruction you use is just documentation about intent; use 'break'
-  6 //: to indicate you're exiting one or more loop nests, and 'loop' to indicate
-  7 //: you're skipping to the next iteration of some containing loop nest.
-  8 
-  9 //: Since they have to be unique in a recipe, not all labels can be jump
- 10 //: targets.
- 11 bool is_jump_target(const string& label) {
- 12   if (label == "{" || label == "}") return false;
- 13   // End is_jump_target Special-cases
- 14   return is_label_word(label);
- 15 }
- 16 
- 17 :(scenario jump_to_label)
- 18 def main [
- 19   jump +target:label
- 20   1:num <- copy 0
- 21   +target
- 22 ]
- 23 -mem: storing 0 in location 1
- 24 
- 25 :(before "End Mu Types Initialization")
- 26 put(Type_ordinal, "label", 0);
- 27 
- 28 :(before "End Instruction Modifying Transforms")
- 29 Transform.push_back(transform_labels);  // idempotent
- 30 
- 31 :(code)
- 32 void transform_labels(const recipe_ordinal r) {
- 33   map<string, int> offset;
- 34   for (int i = 0;  i < SIZE(get(Recipe, r).steps);  ++i) {
- 35     const instruction& inst = get(Recipe, r).steps.at(i);
- 36     if (!inst.is_label) continue;
- 37     if (is_jump_target(inst.label)) {
- 38       if (!contains_key(offset, inst.label)) {
- 39         put(offset, inst.label, i);
- 40       }
- 41       else {
- 42         raise << maybe(get(Recipe, r).name) << "duplicate label '" << inst.label << "'" << end();
- 43         // have all jumps skip some random but noticeable and deterministic amount of code
- 44         put(offset, inst.label, 9999);
- 45       }
- 46     }
- 47   }
- 48   for (int i = 0;  i < SIZE(get(Recipe, r).steps);  ++i) {
- 49     instruction& inst = get(Recipe, r).steps.at(i);
- 50     if (inst.name == "jump") {
- 51       if (inst.ingredients.empty()) {
- 52         raise << maybe(get(Recipe, r).name) << "'jump' expects an ingredient but got none\n" << end();
- 53         return;
- 54       }
- 55       replace_offset(inst.ingredients.at(0), offset, i, r);
- 56     }
- 57     if (inst.name == "jump-if" || inst.name == "jump-unless") {
- 58       if (SIZE(inst.ingredients) < 2) {
- 59         raise << maybe(get(Recipe, r).name) << "'" << inst.name << "' expects 2 ingredients but got " << SIZE(inst.ingredients) << '\n' << end();
- 60         return;
- 61       }
- 62       replace_offset(inst.ingredients.at(1), offset, i, r);
- 63     }
- 64     if ((inst.name == "loop" || inst.name == "break")
- 65         && SIZE(inst.ingredients) >= 1) {
- 66       replace_offset(inst.ingredients.at(0), offset, i, r);
- 67     }
- 68     if ((inst.name == "loop-if" || inst.name == "loop-unless"
- 69             || inst.name == "break-if" || inst.name == "break-unless")
- 70         && SIZE(inst.ingredients) >= 2) {
- 71       replace_offset(inst.ingredients.at(1), offset, i, r);
- 72     }
- 73   }
- 74 }
- 75 
- 76 void replace_offset(reagent& x, /*const*/ map<string, int>& offset, const int current_offset, const recipe_ordinal r) {
- 77   if (!is_literal(x)) {
- 78     raise << maybe(get(Recipe, r).name) << "jump target must be offset or label but is '" << x.original_string << "'\n" << end();
- 79     x.set_value(0);  // no jump by default
- 80     return;
- 81   }
- 82   if (x.initialized) return;
- 83   if (is_integer(x.name)) return;  // non-labels will be handled like other number operands
- 84   if (!is_jump_target(x.name)) {
- 85     raise << maybe(get(Recipe, r).name) << "can't jump to label '" << x.name << "'\n" << end();
- 86     x.set_value(0);  // no jump by default
- 87     return;
- 88   }
- 89   if (!contains_key(offset, x.name)) {
- 90     raise << maybe(get(Recipe, r).name) << "can't find label '" << x.name << "'\n" << end();
- 91     x.set_value(0);  // no jump by default
- 92     return;
- 93   }
- 94   x.set_value(get(offset, x.name) - current_offset);
- 95 }
- 96 
- 97 :(scenario break_to_label)
- 98 def main [
- 99   {
-100     {
-101       break +target:label
-102       1:num <- copy 0
-103     }
-104   }
-105   +target
-106 ]
-107 -mem: storing 0 in location 1
-108 
-109 :(scenario jump_if_to_label)
-110 def main [
-111   {
-112     {
-113       jump-if 1, +target:label
-114       1:num <- copy 0
-115     }
-116   }
-117   +target
-118 ]
-119 -mem: storing 0 in location 1
-120 
-121 :(scenario loop_unless_to_label)
-122 def main [
-123   {
-124     {
-125       loop-unless 0, +target:label  # loop/break with a label don't care about braces
-126       1:num <- copy 0
-127     }
-128   }
-129   +target
-130 ]
-131 -mem: storing 0 in location 1
-132 
-133 :(scenario jump_runs_code_after_label)
-134 def main [
-135   # first a few lines of padding to exercise the offset computation
-136   1:num <- copy 0
-137   2:num <- copy 0
-138   3:num <- copy 0
-139   jump +target:label
-140   4:num <- copy 0
-141   +target
-142   5:num <- copy 0
-143 ]
-144 +mem: storing 0 in location 5
-145 -mem: storing 0 in location 4
-146 
-147 :(scenario jump_fails_without_target)
-148 % Hide_errors = true;
-149 def main [
-150   jump
-151 ]
-152 +error: main: 'jump' expects an ingredient but got none
-153 
-154 :(scenario jump_fails_without_target_2)
-155 % Hide_errors = true;
-156 def main [
-157   jump-if 1/true
-158 ]
-159 +error: main: 'jump-if' expects 2 ingredients but got 1
-160 
-161 :(scenario recipe_fails_on_duplicate_jump_target)
-162 % Hide_errors = true;
-163 def main [
-164   +label
-165   1:num <- copy 0
-166   +label
-167   2:num <- copy 0
-168 ]
-169 +error: main: duplicate label '+label'
-170 
-171 :(scenario jump_ignores_nontarget_label)
-172 % Hide_errors = true;
-173 def main [
-174   # first a few lines of padding to exercise the offset computation
-175   1:num <- copy 0
-176   2:num <- copy 0
-177   3:num <- copy 0
-178   jump $target:label
-179   4:num <- copy 0
-180   $target
-181   5:num <- copy 0
-182 ]
-183 +error: main: can't jump to label '$target'
+  1 //: Support jumps to a specific label (the 'jump target') in the same recipe.
+  2 //: Jump targets must be unique and unambiguous within any recipe.
+  3 //:
+  4 //: The 'break' and 'loop' pseudo instructions can also take jump targets.
+  5 //: Which instruction you use is just documentation about intent; use 'break'
+  6 //: to indicate you're exiting one or more loop nests, and 'loop' to indicate
+  7 //: you're skipping to the next iteration of some containing loop nest.
+  8 
+  9 //: Since they have to be unique in a recipe, not all labels can be jump
+ 10 //: targets.
+ 11 bool is_jump_target(const string& label) {
+ 12   if (label == "{" || label == "}") return false;
+ 13   // End is_jump_target Special-cases
+ 14   return is_label_word(label);
+ 15 }
+ 16 
+ 17 :(scenario jump_to_label)
+ 18 def main [
+ 19   jump +target:label
+ 20   1:num <- copy 0
+ 21   +target
+ 22 ]
+ 23 -mem: storing 0 in location 1
+ 24 
+ 25 :(before "End Mu Types Initialization")
+ 26 put(Type_ordinal, "label", 0);
+ 27 
+ 28 :(before "End Instruction Modifying Transforms")
+ 29 Transform.push_back(transform_labels);  // idempotent
+ 30 
+ 31 :(code)
+ 32 void transform_labels(const recipe_ordinal r) {
+ 33   map<string, int> offset;
+ 34   for (int i = 0;  i < SIZE(get(Recipe, r).steps);  ++i) {
+ 35     const instruction& inst = get(Recipe, r).steps.at(i);
+ 36     if (!inst.is_label) continue;
+ 37     if (is_jump_target(inst.label)) {
+ 38       if (!contains_key(offset, inst.label)) {
+ 39         put(offset, inst.label, i);
+ 40       }
+ 41       else {
+ 42         raise << maybe(get(Recipe, r).name) << "duplicate label '" << inst.label << "'" << end();
+ 43         // have all jumps skip some random but noticeable and deterministic amount of code
+ 44         put(offset, inst.label, 9999);
+ 45       }
+ 46     }
+ 47   }
+ 48   for (int i = 0;  i < SIZE(get(Recipe, r).steps);  ++i) {
+ 49     instruction& inst = get(Recipe, r).steps.at(i);
+ 50     if (inst.name == "jump") {
+ 51       if (inst.ingredients.empty()) {
+ 52         raise << maybe(get(Recipe, r).name) << "'jump' expects an ingredient but got none\n" << end();
+ 53         return;
+ 54       }
+ 55       replace_offset(inst.ingredients.at(0), offset, i, r);
+ 56     }
+ 57     if (inst.name == "jump-if" || inst.name == "jump-unless") {
+ 58       if (SIZE(inst.ingredients) < 2) {
+ 59         raise << maybe(get(Recipe, r).name) << "'" << inst.name << "' expects 2 ingredients but got " << SIZE(inst.ingredients) << '\n' << end();
+ 60         return;
+ 61       }
+ 62       replace_offset(inst.ingredients.at(1), offset, i, r);
+ 63     }
+ 64     if ((inst.name == "loop" || inst.name == "break")
+ 65         && SIZE(inst.ingredients) >= 1) {
+ 66       replace_offset(inst.ingredients.at(0), offset, i, r);
+ 67     }
+ 68     if ((inst.name == "loop-if" || inst.name == "loop-unless"
+ 69             || inst.name == "break-if" || inst.name == "break-unless")
+ 70         && SIZE(inst.ingredients) >= 2) {
+ 71       replace_offset(inst.ingredients.at(1), offset, i, r);
+ 72     }
+ 73   }
+ 74 }
+ 75 
+ 76 void replace_offset(reagent& x, /*const*/ map<string, int>& offset, const int current_offset, const recipe_ordinal r) {
+ 77   if (!is_literal(x)) {
+ 78     raise << maybe(get(Recipe, r).name) << "jump target must be offset or label but is '" << x.original_string << "'\n" << end();
+ 79     x.set_value(0);  // no jump by default
+ 80     return;
+ 81   }
+ 82   if (x.initialized) return;
+ 83   if (is_integer(x.name)) return;  // non-labels will be handled like other number operands
+ 84   if (!is_jump_target(x.name)) {
+ 85     raise << maybe(get(Recipe, r).name) << "can't jump to label '" << x.name << "'\n" << end();
+ 86     x.set_value(0);  // no jump by default
+ 87     return;
+ 88   }
+ 89   if (!contains_key(offset, x.name)) {
+ 90     raise << maybe(get(Recipe, r).name) << "can't find label '" << x.name << "'\n" << end();
+ 91     x.set_value(0);  // no jump by default
+ 92     return;
+ 93   }
+ 94   x.set_value(get(offset, x.name) - current_offset);
+ 95 }
+ 96 
+ 97 :(scenario break_to_label)
+ 98 def main [
+ 99   {
+100     {
+101       break +target:label
+102       1:num <- copy 0
+103     }
+104   }
+105   +target
+106 ]
+107 -mem: storing 0 in location 1
+108 
+109 :(scenario jump_if_to_label)
+110 def main [
+111   {
+112     {
+113       jump-if 1, +target:label
+114       1:num <- copy 0
+115     }
+116   }
+117   +target
+118 ]
+119 -mem: storing 0 in location 1
+120 
+121 :(scenario loop_unless_to_label)
+122 def main [
+123   {
+124     {
+125       loop-unless 0, +target:label  # loop/break with a label don't care about braces
+126       1:num <- copy 0
+127     }
+128   }
+129   +target
+130 ]
+131 -mem: storing 0 in location 1
+132 
+133 :(scenario jump_runs_code_after_label)
+134 def main [
+135   # first a few lines of padding to exercise the offset computation
+136   1:num <- copy 0
+137   2:num <- copy 0
+138   3:num <- copy 0
+139   jump +target:label
+140   4:num <- copy 0
+141   +target
+142   5:num <- copy 0
+143 ]
+144 +mem: storing 0 in location 5
+145 -mem: storing 0 in location 4
+146 
+147 :(scenario jump_fails_without_target)
+148 % Hide_errors = true;
+149 def main [
+150   jump
+151 ]
+152 +error: main: 'jump' expects an ingredient but got none
+153 
+154 :(scenario jump_fails_without_target_2)
+155 % Hide_errors = true;
+156 def main [
+157   jump-if 1/true
+158 ]
+159 +error: main: 'jump-if' expects 2 ingredients but got 1
+160 
+161 :(scenario recipe_fails_on_duplicate_jump_target)
+162 % Hide_errors = true;
+163 def main [
+164   +label
+165   1:num <- copy 0
+166   +label
+167   2:num <- copy 0
+168 ]
+169 +error: main: duplicate label '+label'
+170 
+171 :(scenario jump_ignores_nontarget_label)
+172 % Hide_errors = true;
+173 def main [
+174   # first a few lines of padding to exercise the offset computation
+175   1:num <- copy 0
+176   2:num <- copy 0
+177   3:num <- copy 0
+178   jump $target:label
+179   4:num <- copy 0
+180   $target
+181   5:num <- copy 0
+182 ]
+183 +error: main: can't jump to label '$target'
 
-- cgit 1.4.1-2-gfad0