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