1 //: Jump primitives
  2 
  3 :(scenario jump_can_skip_instructions)
  4 def main [
  5   jump 1:offset
  6   1:num <- copy 1
  7 ]
  8 +run: jump {1: "offset"}
  9 -run: {1: "number"} <- copy {1: "literal"}
 10 -mem: storing 1 in location 1
 11 
 12 :(before "End Primitive Recipe Declarations")
 13 JUMP,
 14 :(before "End Primitive Recipe Numbers")
 15 put(Recipe_ordinal, "jump", JUMP);
 16 :(before "End Primitive Recipe Checks")
 17 case JUMP: {
 18   if (SIZE(inst.ingredients) != 1) {
 19     raise << maybe(get(Recipe, r).name) << "'" << to_original_string(inst) << "' should get exactly one ingredient\n" << end();
 20     break;
 21   }
 22   if (!is_literal(inst.ingredients.at(0))) {
 23     raise << maybe(get(Recipe, r).name) << "first ingredient of '" << to_original_string(inst) << "' should be a label or offset, but '" << inst.ingredients.at(0).name << "' has type '" << names_to_string_without_quotes(inst.ingredients.at(0).type) << "'\n" << end();
 24     break;
 25   }
 26   if (!inst.products.empty()) {
 27     raise << maybe(get(Recipe, r).name) << "'jump' instructions write no products\n" << end();
 28     break;
 29   }
 30   break;
 31 }
 32 :(before "End Primitive Recipe Implementations")
 33 case JUMP: {
 34   assert(current_instruction().ingredients.at(0).initialized);
 35   current_step_index() += ingredients.at(0).at(0)+1;
 36   trace(9998, "run") << "jumping to instruction " << current_step_index() << end();
 37   // skip rest of this instruction
 38   write_products = false;
 39   fall_through_to_next_instruction = false;
 40   break;
 41 }
 42 
 43 //: special type to designate jump targets
 44 :(before "End Mu Types Initialization")
 45 put(Type_ordinal, "offset", 0);
 46 
 47 :(scenario jump_backward)
 48 def main [
 49   jump 1:offset  # 0 -+
 50   jump 3:offset  #    |   +-+ 1
 51                  #   \/  /\ |
 52   jump -2:offset #  2 +-->+ |
 53 ]                #         \/ 3
 54 +run: jump {1: "offset"}
 55 +run: jump {-2: "offset"}
 56 +run: jump {3: "offset"}
 57 
 58 :(scenario jump_takes_no_products)
 59 % Hide_errors = true;
 60 def main [
 61   1:num <- jump 1
 62 ]
 63 +error: main: 'jump' instructions write no products
 64 
 65 :(before "End Primitive Recipe Declarations")
 66 JUMP_IF,
 67 :(before "End Primitive Recipe Numbers")
 68 put(Recipe_ordinal, "jump-if", JUMP_IF);
 69 :(before "End Primitive Recipe Checks")
 70 case JUMP_IF: {
 71   if (SIZE(inst.ingredients) != 2) {
 72     raise << maybe(get(Recipe, r).name) << "'" << to_original_string(inst) << "' should get exactly two ingredients\n" << end();
 73     break;
 74   }
 75   if (!is_mu_address(inst.ingredients.at(0)) && !is_mu_scalar(inst.ingredients.at(0))) {
 76     raise << maybe(get(Recipe, r).name) << "'" << to_original_string(inst) << "' requires a boolean for its first ingredient, but '" << inst.ingredients.at(0).name << "' has type '" << names_to_string_without_quotes(inst.ingredients.at(0).type) << "'\n" << end();
 77     break;
 78   }
 79   if (!is_literal(inst.ingredients.at(1))) {
 80     raise << maybe(get(Recipe, r).name) << "'" << to_original_string(inst) << "' requires a label or offset for its second ingredient, but '" << inst.ingredients.at(1).name << "' has type '" << names_to_string_without_quotes(inst.ingredients.at(1).type) << "'\n" << end();
 81     break;
 82   }
 83   if (!inst.products.empty()) {
 84     raise << maybe(get(Recipe, r).name) << "'jump-if' instructions write no products\n" << end();
 85     break;
 86   }
 87   // End JUMP_IF Checks
 88   break;
 89 }
 90 :(before "End Primitive Recipe Implementations")
 91 case JUMP_IF: {
 92   assert(current_instruction().ingredients.at(1).initialized);
 93   if (!scalar_ingredient(ingredients, 0)) {
 94     trace(9998, "run") << "jump-if fell through" << end();
 95     break;
 96   }
 97   current_step_index() += ingredients.at(1).at(0)+1;
 98   trace(9998, "run") << "jumping to instruction " << current_step_index() << end();
 99   // skip rest of this instruction
100   write_products = false;
101   fall_through_to_next_instruction = false;
102   break;
103 }
104 
105 :(scenario jump_if)
106 def main [
107   jump-if 999, 1:offset
108   123:num <- copy 1
109 ]
110 +run: jump-if {999: "literal"}, {1: "offset"}
111 +run: jumping to instruction 2
112 -run: {123: "number"} <- copy {1: "literal"}
113 -mem: storing 1 in location 123
114 
115 :(scenario jump_if_fallthrough)
116 def main [
117   jump-if 0, 1:offset
118   123:num <- copy 1
119 ]
120 +run: jump-if {0: "literal"}, {1: "offset"}
121 +run: jump-if fell through
122 +run: {123: "number"} <- copy {1: "literal"}
123 +mem: storing 1 in location 123
124 
125 :(scenario jump_if_on_address)
126 def main [
127   10:num/alloc-id, 11:num <- copy 0, 999
128   jump-if 10:&:number, 1:offset
129   123:num <- copy 1
130 ]
131 +run: jump-if {10: ("address" "number")}, {1: "offset"}
132 +run: jumping to instruction 3
133 -run: {123: "number"} <- copy {1: "literal"}
134 -mem: storing 1 in location 123
135 
136 :(before "End Primitive Recipe Declarations")
137 JUMP_UNLESS,
138 :(before "End Primitive Recipe Numbers")
139 put(Recipe_ordinal, "jump-unless", JUMP_UNLESS);
140 :(before "End Primitive Recipe Checks")
141 case JUMP_UNLESS: {
142   if (SIZE(inst.ingredients) != 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - continuation2.mu</title>
<meta name="Generator" content="Vim/8.0">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="none">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #aaaaaa; background-color: #080808; }
body { font-size: 12pt; font-family: monospace; color: #aaaaaa; background-color: #080808; }
a { color:#eeeeee; text-decoration: none; }
a:hover { text-decoration: underline; }
* { font-size: 12pt; font-size: 1em; }
.muControl { color: #c0a020; }
.muRecipe { color: #ff8700; }
.LineNr { color: #444444; }
.Delimiter { color: #800080; }
.Constant { color: #00a0a0; }
.Special { color: #c00000; }
.Comment { color: #9090ff; }
.Comment a { color:#0000ee; text-decoration:underline; }
-->
</style>

<script type='text/javascript'>
<!--

/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
  var