1
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 break;
27 }
28 :(before "End Primitive Recipe Implementations")
29 case JUMP: {
30 assert(current_instruction().ingredients.at(0).initialized);
31 current_step_index() += ingredients.at(0).at(0)+1;
32 trace(9998, "run") << "jumping to instruction " << current_step_index() << end();
33
34 write_products = false;
35 fall_through_to_next_instruction = false;
36 break;
37 }
38
39
40 :(before "End Mu Types Initialization")
41 put(Type_ordinal, "offset", 0);
42
43 :(scenario jump_backward)
44 def main [
45 jump 1:offset
46 jump 3:offset
47
48 jump -2:offset
49 ]
50 +run: jump {1: "offset"}
51 +run: jump {-2: "offset"}
52 +run: jump {3: "offset"}
53
54 :(before "End Primitive Recipe Declarations")
55 JUMP_IF,
56 :(before "End Primitive Recipe Numbers")
57 put(Recipe_ordinal, "jump-if", JUMP_IF);
58 :(before "End Primitive Recipe Checks")
59 case JUMP_IF: {
60 if (SIZE(inst.ingredients) != 2) {
61 raise << maybe(get(Recipe, r).name) << "'" << to_original_string(inst) << "' should get exactly two ingredients\n" << end();
62 break;
63 }
64 if (!is_mu_scalar(inst.ingredients.at(0))) {
65 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();
66 break;
67 }
68 if (!is_literal(inst.ingredients.at(1))) {
69 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();
70 break;
71 }
72
73 break;
74 }
75 :(before "End Primitive Recipe Implementations")
76 case JUMP_IF: {
77 assert(current_instruction().ingredients.at(1).initialized);
78 if (!ingredients.at(0).at(0)) {
79 trace(9998, "run") << "jump-if fell through" << end();
80 break;
81 }
82 current_step_index() += ingredients.at(1).at(0)+1;
83 trace(9998, "run") << "jumping to instruction " << current_step_index() << end();
84
85 write_products = false;
86 fall_through_to_next_instruction = false;
87 break;
88 }
89
90 :(scenario jump_if)
91 def main [
92 jump-if 999, 1:offset
93 123:num <- copy 1
94 ]
95 +run: jump-if {999: "literal"}, {1: "offset"}
96 +run: jumping to instruction 2
97 -run: {1: "number"} <- copy {1: "literal"}
98 -mem: storing 1 in location 123
99
100 :(scenario jump_if_fallthrough)
101 def main [
102 jump-if 0, 1:offset
103 123:num <- copy 1
104 ]
105 +run: jump-if {0: "literal"}, {1: "offset"}
106 +run: jump-if fell through
107 +run: {123: "number"} <- copy {1: "literal"}
108 +mem: storing 1 in location 123
109
110 :(before "End Primitive Recipe Declarations")
111 JUMP_UNLESS,
112 :(before "End Primitive Recipe Numbers")
113 put(Recipe_ordinal, "jump-unless", JUMP_UNLESS);
114 :(before "End Primitive Recipe Checks")
115 case JUMP_UNLESS: {
116 if (SIZE(inst.ingredients) != 2) {
117 raise << maybe(get(Recipe, r).name) << "'" << to_original_string(inst) << "' should get exactly two ingredients\n" << end();
118 break;
119 }
120 if (!is_mu_scalar(inst.ingredients.at(0))) {
121 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();
122 break;
123 }
124 if (!is_literal(inst.ingredients.at(1))) {
125 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();
126 break;
127 }
128
129 break;
130 }
131 :(before "End Primitive Recipe Implementations")
132 case JUMP_UNLESS: {
133 assert(current_instruction().ingredients.at(1).initialized);
134 if (ingredients.at(0).at(0)) {
135 trace(9998, "run") << "jump-unless fell through" << end();
136 break;
137 }
138 current_step_index() += ingredients.at(1).at(0)+1;
139 trace(9998, "run") << "jumping to instruction " << current_step_index() << end();
140
141 write_products = false;
142 fall_through_to_next_instruction = false;
143 break;
144 }
145
146 :(scenario jump_unless)
147 def main [
148 jump-unless 0, 1:offset
149 123:num <- copy 1
150 ]
151 +run: jump-unless {0: "literal"}, {1: "offset"}
152 +run: jumping to instruction 2
153 -run: {123: "number"} <- copy {1: "literal"}
154 -mem: storing 1 in location 123
155
156 :(scenario jump_unless_fallthrough)
157 def main [
158 jump-unless 999, 1:offset
159 123:num <- copy 1
160 ]
161 +run: jump-unless {999: "literal"}, {1: "offset"}
162 +run: jump-unless fell through
163 +run: {123: "number"} <- copy {1: "literal"}
164 +mem: storing 1 in location 123