1
2
3
4
5
6
7
8 :(before "End initialize_transform_rewrite_literal_string_to_text()")
9 recipes_taking_literal_strings.insert("assume-console");
10
11 :(scenarios run_mu_scenario)
12 :(scenario keyboard_in_scenario)
13 scenario keyboard-in-scenario [
14 assume-console [
15 ¦ type [abc]
16 ]
17 run [
18 ¦ 1:char, 2:bool <- read-key console
19 ¦ 3:char, 4:bool <- read-key console
20 ¦ 5:char, 6:bool <- read-key console
21 ¦ 7:char, 8:bool, 9:bool <- read-key console
22 ]
23 memory-should-contain [
24 ¦ 1 <- 97
25 ¦ 2 <- 1
26 ¦ 3 <- 98
27 ¦ 4 <- 1
28 ¦ 5 <- 99
29 ¦ 6 <- 1
30 ¦ 7 <- 0
31 ¦ 8 <- 1
32 ¦ 9 <- 1
33 ]
34 ]
35
36 :(before "End Scenario Globals")
37 extern const int CONSOLE = Next_predefined_global_for_scenarios++;
38
39 :(before "End Special Scenario Variable Names(r)")
40 Name[r]["console"] = CONSOLE;
41
42 :(before "End is_special_name Special-cases")
43 if (s == "console") return true;
44
45 :(before "End Primitive Recipe Declarations")
46 ASSUME_CONSOLE,
47 :(before "End Primitive Recipe Numbers")
48 put(Recipe_ordinal, "assume-console", ASSUME_CONSOLE);
49 :(before "End Primitive Recipe Checks")
50 case ASSUME_CONSOLE: {
51 break;
52 }
53 :(before "End Primitive Recipe Implementations")
54 case ASSUME_CONSOLE: {
55
56 istringstream in("[" + current_instruction().ingredients.at(0).name + "]");
57 recipe r;
58 slurp_body(in, r);
59 int num_events = count_events(r);
60
61 int size = 2 + num_events*size_of_event();
62 int event_data_address = allocate(size);
63
64 put(Memory, event_data_address+1, num_events);
65 int curr_address = event_data_address + 2;
66 for (int i = 0; i < SIZE(r.steps); ++i) {
67 ¦ const instruction& inst = r.steps.at(i);
68 ¦ if (inst.name == "left-click") {
69 ¦ ¦ trace("mem") << "storing 'left-click' event starting at " << Current_routine->alloc << end();
70 ¦ ¦ put(Memory, curr_address, 2);
71 ¦ ¦ put(Memory, curr_address+1+0, TB_KEY_MOUSE_LEFT);
72 ¦ ¦ put(Memory, curr_address+1+1, to_integer(inst.ingredients.at(0).name));
73 ¦ ¦ put(Memory, curr_address+1+2, to_integer(inst.ingredients.at(1).name));
74 ¦ ¦ curr_address += size_of_event();
75 ¦ }
76 ¦ else if (inst.name == "press") {
77 ¦ ¦ trace("mem") << "storing 'press' event starting at " << curr_address << end();
78 ¦ ¦ string key = inst.ingredients.at(0).name;
79 ¦ ¦ if (is_integer(key))
80 ¦ ¦ ¦ put(Memory, curr_address+1, to_integer(key));
81 ¦ ¦ else if (contains_key(Key, key))
82 ¦ ¦ ¦ put(Memory, curr_address+1, Key[key]);
83 ¦ ¦ else
84 ¦ ¦ ¦ raise << "assume-console: can't press '" << key << "'\n" << end();
85 ¦ ¦ if (get_or_insert(Memory, curr_address+1) < 256)
86 ¦ ¦ ¦
87 ¦ ¦ ¦ put(Memory, curr_address, 0);
88 ¦ ¦ else {
89 ¦ ¦ ¦
90 ¦ ¦ ¦ put(Memory, curr_address, 1);
91 ¦ ¦ }
92 ¦ ¦ curr_address += size_of_event();
93 ¦ }
94 ¦
95 ¦ else {
96 ¦ ¦
97 ¦ ¦ assert(inst.name == "type");
98 ¦ ¦ trace("mem") << "storing 'type' event starting at " << curr_address << end();
99 ¦ ¦ const string& contents = inst.ingredients.at(0).name;
100 ¦ ¦ const char* raw_contents = contents.c_str();
101 ¦ ¦ int num_keyboard_events = unicode_length(contents);
102 ¦ ¦ int curr = 0;
103 ¦ ¦ for (int i = 0; i < num_keyboard_events; ++i) {
104 ¦ ¦ ¦ trace("mem") << "storing 'text' tag at " << curr_address << end();
105 ¦ ¦ ¦ put(Memory, curr_address, 0);
106 ¦ ¦ ¦ uint32_t curr_character;
107 ¦ ¦ ¦ assert(curr < SIZE(contents));
108 ¦ ¦ ¦ tb_utf8_char_to_unicode(&curr_character, &raw_contents[curr]);
109 ¦ ¦ ¦ trace("mem") << "storing character " << curr_character << " at " << curr_address+1 << end();
110 ¦ ¦ ¦ put(Memory, curr_address+1, curr_character);
111 ¦ ¦ ¦ curr += tb_utf8_char_length(raw_contents[curr]);
112 ¦ ¦ ¦ curr_address += size_of_event();
113 ¦ ¦ }
114 ¦ }
115 }
116 assert(curr_address == event_data_address+size);
117
118 int console_address = allocate(size_of_console());
119 trace("mem") << "storing console in " << console_address << end();
120 put(Memory, CONSOLE, console_address);
121 trace("mem") << "storing console data in " << console_address+1+1 << end();
122 put(Memory, console_address+1+1, event_data_address);
123
124 put(Memory, event_data_address, 1);
125
126 put(Memory, console_address, 1);
127 break;
128 }
129
130 :(before "End Globals")
131 map<string, int> Key;
132 :(before "End One-time Setup")
133 initialize_key_names();
134 :(code)
135 void initialize_key_names() {
136 Key["F1"] = TB_KEY_F1;
137 Key["F2"] = TB_KEY_F2;
138 Key["F3"] = TB_KEY_F3;
139 Key["F4"] = TB_KEY_F4;
140 Key["F5"] = TB_KEY_F5;
141 Key["F6"] = TB_KEY_F6;
142 Key["F7"] = TB_KEY_F7;
143 Key["F8"] = TB_KEY_F8;
144 Key["F9"] = TB_KEY_F9;
145 Key["F10"] = TB_KEY_F10;
146 Key["F11"] = TB_KEY_F11;
147 Key["F12"] = TB_KEY_F12;
148 Key["insert"] = TB_KEY_INSERT;
149 Key["delete"] = TB_KEY_DELETE;
150 Key["home"] = TB_KEY_HOME;
151 Key["end"] = TB_KEY_END;
152 Key["page-up"] = TB_KEY_PGUP;
153 Key["page-down"] = TB_KEY_PGDN;
154 Key["up-arrow"] = TB_KEY_ARROW_UP;
155 Key["down-arrow"] = TB_KEY_ARROW_DOWN;
156 Key["left-arrow"] = TB_KEY_ARROW_LEFT;
157 Key["right-arrow"] = TB_KEY_ARROW_RIGHT;
158 Key["ctrl-a"] = TB_KEY_CTRL_A;
159 Key["ctrl-b"] = TB_KEY_CTRL_B;
160 Key["ctrl-c"] = TB_KEY_CTRL_C;
161 Key["ctrl-d"] = TB_KEY_CTRL_D;
162 Key["ctrl-e"] = TB_KEY_CTRL_E;
163 Key["ctrl-f"] = TB_KEY_CTRL_F;
164 Key["ctrl-g"] = TB_KEY_CTRL_G;
165 Key["backspace"] = TB_KEY_BACKSPACE;
166 Key["ctrl-h"] = TB_KEY_CTRL_H;
167 Key["tab"] = TB_KEY_TAB;
168 Key["ctrl-i"] = TB_KEY_CTRL_I;
169 Key["ctrl-j"] = TB_KEY_CTRL_J;
170 Key["enter"] = TB_KEY_NEWLINE;
171 Key["ctrl-k"] = TB_KEY_CTRL_K;
172 Key["ctrl-l"] = TB_KEY_CTRL_L;
173 Key["ctrl-m"] = TB_KEY_CTRL_M;
174 Key["ctrl-n"] = TB_KEY_CTRL_N;
175 Key["ctrl-o"] = TB_KEY_CTRL_O;
176 Key["ctrl-p"] = TB_KEY_CTRL_P;
177 Key["ctrl-q"] = TB_KEY_CTRL_Q;
178 Key["ctrl-r"] = TB_KEY_CTRL_R;
179 Key["ctrl-s"] = TB_KEY_CTRL_S;
180 Key["ctrl-t"] = TB_KEY_CTRL_T;
181 Key["ctrl-u"] = TB_KEY_CTRL_U;
182 Key["ctrl-v"] = TB_KEY_CTRL_V;
183 Key["ctrl-w"] = TB_KEY_CTRL_W;
184 Key["ctrl-x"] = TB_KEY_CTRL_X;
185 Key["ctrl-y"] = TB_KEY_CTRL_Y;
186 Key["ctrl-z"] = TB_KEY_CTRL_Z;
187 Key["escape"] = TB_KEY_ESC;
188 Key["ctrl-slash"] = TB_KEY_CTRL_SLASH;
189 }
190
191 :(after "Begin check_or_set_invalid_types(r)")
192 if (is_scenario(caller))
193 initialize_special_name(r);
194 :(code)
195 bool is_scenario(const recipe& caller) {
196 return starts_with(caller.name, "scenario_");
197 }
198 void initialize_special_name(reagent& r) {
199 if (r.type) return;
200
201 if (r.name == "console") r.type = new_type_tree("address:console");
202
203 }
204
205 :(scenario events_in_scenario)
206 scenario events-in-scenario [
207 assume-console [
208 ¦ type [abc]
209 ¦ left-click 0, 1
210 ¦ press up-arrow
211 ¦ type [d]
212 ]
213 run [
214 ¦
215 ¦ 1:event <- read-event console
216 ¦ 5:event <- read-event console
217 ¦ 9:event <- read-event console
218 ¦
219 ¦ 13:event <- read-event console
220 ¦
221 ¦ 17:event <- read-event console
222 ¦
223 ¦ 21:event <- read-event console
224 ]
225 memory-should-contain [
226 ¦ 1 <- 0
227 ¦ 2 <- 97
228 ¦ 3 <- 0
229 ¦ 4 <- 0
230 ¦ 5 <- 0
231 ¦ 6 <- 98
232 ¦ 7 <- 0
233 ¦ 8 <- 0
234 ¦ 9 <- 0
235 ¦ 10 <- 99
236 ¦ 11 <- 0
237 ¦ 12 <- 0
238 ¦ 13 <- 2
239 ¦ 14 <- 65513
240 ¦ 15 <- 0
241 ¦ 16 <- 1
242 ¦ 17 <- 1
243 ¦ 18 <- 65517
244 ¦ 19 <- 0
245 ¦ 20 <- 0
246 ¦ 21 <- 0
247 ¦ 22 <- 100
248 ¦ 23 <- 0
249 ¦ 24 <- 0
250 ¦ 25 <- 0
251 ]
252 ]
253
254
255
256 :(before "End Primitive Recipe Declarations")
257 REPLACE_IN_CONSOLE,
258 :(before "End Primitive Recipe Numbers")
259 put(Recipe_ordinal, "replace-in-console", REPLACE_IN_CONSOLE);
260 :(before "End Primitive Recipe Checks")
261 case REPLACE_IN_CONSOLE: {
262 break;
263 }
264 :(before "End Primitive Recipe Implementations")
265 case REPLACE_IN_CONSOLE: {
266 assert(scalar(ingredients.at(0)));
267 if (!get_or_insert(Memory, CONSOLE)) {
268 ¦ raise << "console not initialized\n" << end();
269 ¦ break;
270 }
271 int console_address = get_or_insert(Memory, CONSOLE);
272 int console_data = get_or_insert(Memory, console_address+1);
273 int length = get_or_insert(Memory, console_data);
274 for (int i = 0, curr = console_data+1; i < length; ++i, curr+=size_of_event()) {
275 ¦ if (get_or_insert(Memory, curr) != 0) continue;
276 ¦ if (get_or_insert(Memory, curr+1) != ingredients.at(0).at(0)) continue;
277 ¦ for (int n = 0; n < size_of_event(); ++n)
278 ¦ ¦ put(Memory, curr+n, ingredients.at(1).at(n));
279 }
280 break;
281 }
282
283 :(code)
284 int count_events(const recipe& r) {
285 int result = 0;
286 for (int i = 0; i < SIZE(r.steps); ++i) {
287 ¦ const instruction& curr = r.steps.at(i);
288 ¦ if (curr.name == "type")
289 ¦ ¦ result += unicode_length(curr.ingredients.at(0).name);
290 ¦ else
291 ¦ ¦ ++result;
292 }
293 return result;
294 }
295
296 int size_of_event() {
297
298 static int result = 0;
299 if (result) return result;
300 type_tree* type = new type_tree("event");
301 result = size_of(type);
302 delete type;
303 return result;
304 }
305
306 int size_of_console() {
307
308 static int result = 0;
309 if (result) return result;
310 assert(get(Type_ordinal, "console"));
311 type_tree* type = new type_tree("console");
312 result = size_of(type)+1;
313 delete type;
314 return result;
315 }