1
2
3 :(scenario calling_recipe)
4 def main [
5 f
6 ]
7 def f [
8 3:num <- add 2, 2
9 ]
10 +mem: storing 4 in location 3
11
12 :(scenario return_on_fallthrough)
13 def main [
14 f
15 1:num <- copy 0
16 2:num <- copy 0
17 3:num <- copy 0
18 ]
19 def f [
20 4:num <- copy 0
21 5:num <- copy 0
22 ]
23 +run: f
24
25 +run: {4: "number"} <- copy {0: "literal"}
26 +run: {5: "number"} <- copy {0: "literal"}
27
28 +run: {1: "number"} <- copy {0: "literal"}
29 +run: {2: "number"} <- copy {0: "literal"}
30 +run: {3: "number"} <- copy {0: "literal"}
31
32 :(before "struct routine {")
33
34
35
36 struct call {
37 recipe_ordinal running_recipe;
38 int running_step_index;
39
40 call(recipe_ordinal r) {
41 ¦ running_recipe = r;
42 ¦ running_step_index = 0;
43 ¦
44 }
45 ~call() {
46 ¦
47 }
48 };
49 typedef list<call> call_stack;
50
51 :(replace{} "struct routine")
52 struct routine {
53 call_stack calls;
54
55 routine(recipe_ordinal r);
56 bool completed() const;
57 const vector<instruction>& steps() const;
58 };
59 :(code)
60 routine::routine(recipe_ordinal r) {
61 if (Trace_stream) {
62 ¦ ++Trace_stream->callstack_depth;
63 ¦ trace(9999, "trace") << "new routine; incrementing callstack depth to " << Trace_stream->callstack_depth << end();
64 ¦ assert(Trace_stream->callstack_depth < 9000);
65 }
66 calls.push_front(call(r));
67
68 }
69
70 :(code)
71 call& current_call() {
72 return Current_routine->calls.front();
73 }
74
75
76
77 :(replace{} "int& current_step_index()")
78 int& current_step_index() {
79 assert(!Current_routine->calls.empty());
80 return current_call().running_step_index;
81 }
82 :(replace{} "const string& current_recipe_name()")
83 const string& current_recipe_name() {
84 assert(!Current_routine->calls.empty());
85 return get(Recipe, current_call().running_recipe).name;
86 }
87 :(replace{} "const recipe& current_recipe()")
88 const recipe& current_recipe() {
89 assert(!Current_routine->calls.empty());
90 return get(Recipe, current_call().running_recipe);
91 }
92 :(replace{} "const instruction& current_instruction()")
93 const instruction& current_instruction() {
94 assert(!Current_routine->calls.empty());
95 return to_instruction(current_call());
96 }
97 :(code)
98 const instruction& to_instruction(const call& call) {
99 return get(Recipe, call.running_recipe).steps.at(call.running_step_index);
100 }
101
102 :(after "Defined Recipe Checks")
103
104 if (!contains_key(Recipe, inst.operation)) {
105 raise << maybe(get(Recipe, r).name) << "undefined operation in '" << inst.original_string << "'\n" << end();
106 break;
107 }
108 :(replace{} "default:" following "End Primitive Recipe Implementations")
109 default: {
110 const instruction& call_instruction = current_instruction();
111 if (Recipe.find(current_instruction().operation) == Recipe.end()) {
112 ¦
113 ¦ ++current_step_index();
114 ¦ continue;
115 }
116
117 if (Trace_stream) {
118 ¦ ++Trace_stream->callstack_depth;
119 ¦ trace(9999, "trace") << "incrementing callstack depth to " << Trace_stream->callstack_depth << end();
120 ¦ assert(Trace_stream->callstack_depth < 9000);
121 }
122 Current_routine->calls.push_front(call(current_instruction().operation));
123 finish_call_housekeeping(call_instruction, ingredients);
124 continue;
125 }
126 :(code)
127 void finish_call_housekeeping(const instruction& call_instruction, const vector<vector<double> >& ingredients) {
128
129 }
130
131 :(scenario calling_undefined_recipe_fails)
132 % Hide_errors = true;
133 def main [
134 foo
135 ]
136 +error: main: undefined operation in 'foo'
137
138 :(scenario calling_undefined_recipe_handles_missing_result)
139 % Hide_errors = true;
140 def main [
141 x:num <- foo
142 ]
143 +error: main: undefined operation in 'x:num <- foo'
144
145
146
147 :(replace{} "bool routine::completed() const")
148 bool routine::completed() const {
149 return calls.empty();
150 }
151
152 :(replace{} "const vector<instruction>& routine::steps() const")
153 const vector<instruction>& routine::steps() const {
154 assert(!calls.empty());
155 return get(Recipe, calls.front().running_recipe).steps;
156 }
157
158 :(after "Running One Instruction")
159
160
161 while (current_step_index() >= SIZE(Current_routine->steps())) {
162
163 if (Trace_stream) {
164 ¦ trace(9999, "trace") << "fall-through: exiting " << current_recipe_name() << "; decrementing callstack depth from " << Trace_stream->callstack_depth << end();
165 ¦ --Trace_stream->callstack_depth;
166 ¦ assert(Trace_stream->callstack_depth >= 0);
167 }
168 Current_routine->calls.pop_front();
169 if (Current_routine->calls.empty()) goto stop_running_current_routine;
170
171
172 ++current_step_index();
173 }