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("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
71
72
73
74 :(delete{} "int& current_step_index()")
75 :(delete{} "recipe_ordinal currently_running_recipe()")
76 :(delete{} "const string& current_recipe_name()")
77 :(delete{} "const recipe& current_recipe()")
78 :(delete{} "const instruction& current_instruction()")
79
80 :(before "End Includes")
81 #define current_call() Current_routine->calls.front()
82 #define current_step_index() current_call().running_step_index
83 #define currently_running_recipe() current_call().running_recipe
84 #define current_recipe() get(Recipe, currently_running_recipe())
85 #define current_recipe_name() current_recipe().name
86 #define to_instruction(call) get(Recipe, (call).running_recipe).steps.at((call).running_step_index)
87 #define current_instruction() to_instruction(current_call())
88
89
90
91 :(code)
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 :(after "Defined Recipe Checks")
135
136 if (!contains_key(Recipe, inst.operation)) {
137 raise << maybe(get(Recipe, r).name) << "undefined operation in '" << to_original_string(inst) << "'\n" << end();
138 break;
139 }
140 :(replace{} "default:" following "End Primitive Recipe Implementations")
141 default: {
142 if (contains_key(Recipe, current_instruction().operation)) {
143 ¦
144 ¦ if (Trace_stream) {
145 ¦ ¦ ++Trace_stream->callstack_depth;
146 ¦ ¦ trace("trace") << "incrementing callstack depth to " << Trace_stream->callstack_depth << end();
147 ¦ ¦ assert(Trace_stream->callstack_depth < 9000);
148 ¦ }
149 ¦ const call& caller_frame = current_call();
150 ¦ Current_routine->calls.push_front(call(to_instruction(caller_frame).operation));
151 ¦ finish_call_housekeeping(to_instruction(caller_frame), ingredients);
152 ¦
153 ¦ write_products = false;
154 ¦ fall_through_to_next_instruction = false;
155 ¦
156 }
157 }
158 :(code)
159 void finish_call_housekeeping(const instruction& call_instruction, const vector<vector<double> >& ingredients) {
160
161 }
162
163 :(scenario calling_undefined_recipe_fails)
164 % Hide_errors = true;
165 def main [
166 foo
167 ]
168 +error: main: undefined operation in 'foo'
169
170 :(scenario calling_undefined_recipe_handles_missing_result)
171 % Hide_errors = true;
172 def main [
173 x:num <- foo
174 ]
175 +error: main: undefined operation in 'x:num <- foo'
176
177
178
179 :(replace{} "bool routine::completed() const")
180 bool routine::completed() const {
181 return calls.empty();
182 }
183
184 :(replace{} "const vector<instruction>& routine::steps() const")
185 const vector<instruction>& routine::steps() const {
186 assert(!calls.empty());
187 return get(Recipe, calls.front().running_recipe).steps;
188 }
189
190 :(after "Running One Instruction")
191
192
193 while (current_step_index() >= SIZE(Current_routine->steps())) {
194
195 if (Trace_stream) {
196 ¦ trace("trace") << "fall-through: exiting " << current_recipe_name() << "; decrementing callstack depth from " << Trace_stream->callstack_depth << end();
197 ¦ --Trace_stream->callstack_depth;
198 ¦ assert(Trace_stream->callstack_depth >= 0);
199 }
200 Current_routine->calls.pop_front();
201 if (Current_routine->calls.empty()) goto stop_running_current_routine;
202
203
204 ++current_step_index();
205 }
206
207 :(before "End Primitive Recipe Declarations")
208 _DUMP_CALL_STACK,
209 :(before "End Primitive Recipe Numbers")
210 put(Recipe_ordinal, "$dump-call-stack", _DUMP_CALL_STACK);
211 :(before "End Primitive Recipe Checks")
212 case _DUMP_CALL_STACK: {
213 break;
214 }
215 :(before "End Primitive Recipe Implementations")
216 case _DUMP_CALL_STACK: {
217 for (call_stack::const_reverse_iterator p = Current_routine->calls.rbegin(); p != Current_routine->calls.rend(); ++p)
218 ¦ cerr << get(Recipe, p->running_recipe).name << ":" << p->running_step_index << " -- " << to_string(to_instruction(*p)) << '\n';
219 break;
220 }