From 204dae921abff0c70e017215bb3c91fa6ca11aff Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 26 Dec 2016 11:44:14 -0800 Subject: 3710 Turns out we don't need to explicitly add anchors for each line. Vim's TOhtml has magic for that out of the box. --- html/085scenario_console.cc.html | 628 +++++++++++++++++++-------------------- 1 file changed, 314 insertions(+), 314 deletions(-) (limited to 'html/085scenario_console.cc.html') diff --git a/html/085scenario_console.cc.html b/html/085scenario_console.cc.html index 7b56bc57..0402ddda 100644 --- a/html/085scenario_console.cc.html +++ b/html/085scenario_console.cc.html @@ -56,320 +56,320 @@ if ('onhashchange' in window) {
-  1 //: Clean syntax to manipulate and check the console in scenarios.
-  2 //: Instruction 'assume-console' implicitly creates a variable called
-  3 //: 'console' that is accessible inside other 'run' instructions in the
-  4 //: scenario. Like with the fake screen, 'assume-console' transparently
-  5 //: supports unicode.
-  6 
-  7 //: first make sure we don't mangle these functions in other transforms
-  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  # 'a'
- 25     2 <- 1
- 26     3 <- 98  # 'b'
- 27     4 <- 1
- 28     5 <- 99  # 'c'
- 29     6 <- 1
- 30     7 <- 0  # unset
- 31     8 <- 1
- 32     9 <- 1  # end of test events
- 33   ]
- 34 ]
- 35 
- 36 :(before "End Scenario Globals")
- 37 extern const int CONSOLE = Next_predefined_global_for_scenarios++;
- 38 //: give 'console' a fixed location in scenarios
- 39 :(before "End Special Scenario Variable Names(r)")
- 40 Name[r]["console"] = CONSOLE;
- 41 //: make 'console' always a raw location in scenarios
- 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   // create a temporary recipe just for parsing; it won't contain valid instructions
- 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   // initialize the events like in new-fake-console
- 61   int size = /*space for refcount and length*/2 + num_events*size_of_event();
- 62   int event_data_address = allocate(size);
- 63   // store length
- 64   put(Memory, event_data_address+/*skip refcount*/1, num_events);
- 65   int curr_address = event_data_address + /*skip refcount and length*/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(9999, "mem") << "storing 'left-click' event starting at " << Current_routine->alloc << end();
- 70       put(Memory, curr_address, /*tag for 'touch-event' variant of 'event' exclusive-container*/2);
- 71       put(Memory, curr_address+/*skip tag*/1+/*offset of 'type' in 'mouse-event'*/0, TB_KEY_MOUSE_LEFT);
- 72       put(Memory, curr_address+/*skip tag*/1+/*offset of 'row' in 'mouse-event'*/1, to_integer(inst.ingredients.at(0).name));
- 73       put(Memory, curr_address+/*skip tag*/1+/*offset of 'column' in 'mouse-event'*/2, to_integer(inst.ingredients.at(1).name));
- 74       curr_address += size_of_event();
- 75     }
- 76     else if (inst.name == "press") {
- 77       trace(9999, "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         // these keys are in ascii
- 87         put(Memory, curr_address, /*tag for 'text' variant of 'event' exclusive-container*/0);
- 88       else {
- 89         // distinguish from unicode
- 90         put(Memory, curr_address, /*tag for 'keycode' variant of 'event' exclusive-container*/1);
- 91       }
- 92       curr_address += size_of_event();
- 93     }
- 94     // End Event Handlers
- 95     else {
- 96       // keyboard input
- 97       assert(inst.name == "type");
- 98       trace(9999, "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(9999, "mem") << "storing 'text' tag at " << curr_address << end();
-105         put(Memory, curr_address, /*tag for 'text' variant of 'event' exclusive-container*/0);
-106         uint32_t curr_character;
-107         assert(curr < SIZE(contents));
-108         tb_utf8_char_to_unicode(&curr_character, &raw_contents[curr]);
-109         trace(9999, "mem") << "storing character " << curr_character << " at " << curr_address+/*skip exclusive container tag*/1 << end();
-110         put(Memory, curr_address+/*skip exclusive container tag*/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   // wrap the array of events in a console object
-118   int console_address = allocate(size_of_console());
-119   trace(9999, "mem") << "storing console in " << console_address << end();
-120   put(Memory, CONSOLE, console_address);
-121   trace(9999, "mem") << "storing console data in " << console_address+/*skip refcount*/1+/*offset of 'data' in container 'events'*/1 << end();
-122   put(Memory, console_address+/*skip refcount*/1+/*offset of 'data' in container 'events'*/1, event_data_address);
-123   // increment refcount for event data
-124   put(Memory, event_data_address, 1);
-125   // increment refcount for console
-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;  // ignore CR/LF distinction; there is only 'enter'
-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 }
-189 
-190 :(after "Begin check_or_set_invalid_types(r)")
-191 if (is_scenario(caller))
-192   initialize_special_name(r);
-193 :(code)
-194 bool is_scenario(const recipe& caller) {
-195   return starts_with(caller.name, "scenario_");
-196 }
-197 void initialize_special_name(reagent& r) {
-198   if (r.type) return;
-199   // no need for screen
-200   if (r.name == "console") r.type = new_type_tree("address:console");
-201   // End Initialize Type Of Special Name In Scenario(r)
-202 }
-203 
-204 :(scenario events_in_scenario)
-205 scenario events-in-scenario [
-206   assume-console [
-207     type [abc]
-208     left-click 0, 1
-209     press up-arrow
-210     type [d]
-211   ]
-212   run [
-213     # 3 keyboard events; each event occupies 4 locations
-214     1:event <- read-event console
-215     5:event <- read-event console
-216     9:event <- read-event console
-217     # mouse click
-218     13:event <- read-event console
-219     # non-character keycode
-220     17:event <- read-event console
-221     # final keyboard event
-222     21:event <- read-event console
-223   ]
-224   memory-should-contain [
-225     1 <- 0  # 'text'
-226     2 <- 97  # 'a'
-227     3 <- 0  # unused
-228     4 <- 0  # unused
-229     5 <- 0  # 'text'
-230     6 <- 98  # 'b'
-231     7 <- 0  # unused
-232     8 <- 0  # unused
-233     9 <- 0  # 'text'
-234     10 <- 99  # 'c'
-235     11 <- 0  # unused
-236     12 <- 0  # unused
-237     13 <- 2  # 'mouse'
-238     14 <- 65513  # mouse click
-239     15 <- 0  # row
-240     16 <- 1  # column
-241     17 <- 1  # 'keycode'
-242     18 <- 65517  # up arrow
-243     19 <- 0  # unused
-244     20 <- 0  # unused
-245     21 <- 0  # 'text'
-246     22 <- 100  # 'd'
-247     23 <- 0  # unused
-248     24 <- 0  # unused
-249     25 <- 0
-250   ]
-251 ]
-252 
-253 //: Deal with special keys and unmatched brackets by allowing each test to
-254 //: independently choose the unicode symbol to denote them.
-255 :(before "End Primitive Recipe Declarations")
-256 REPLACE_IN_CONSOLE,
-257 :(before "End Primitive Recipe Numbers")
-258 put(Recipe_ordinal, "replace-in-console", REPLACE_IN_CONSOLE);
-259 :(before "End Primitive Recipe Checks")
-260 case REPLACE_IN_CONSOLE: {
-261   break;
-262 }
-263 :(before "End Primitive Recipe Implementations")
-264 case REPLACE_IN_CONSOLE: {
-265   assert(scalar(ingredients.at(0)));
-266   if (!get_or_insert(Memory, CONSOLE)) {
-267     raise << "console not initialized\n" << end();
-268     break;
-269   }
-270   int console_address = get_or_insert(Memory, CONSOLE);
-271   int console_data = get_or_insert(Memory, console_address+1);
-272   int length = get_or_insert(Memory, console_data);  // array length
-273   for (int i = 0, curr = console_data+1;  i < length;  ++i, curr+=size_of_event()) {
-274     if (get_or_insert(Memory, curr) != /*text*/0) continue;
-275     if (get_or_insert(Memory, curr+1) != ingredients.at(0).at(0)) continue;
-276     for (int n = 0;  n < size_of_event();  ++n)
-277       put(Memory, curr+n, ingredients.at(1).at(n));
-278   }
-279   break;
-280 }
-281 
-282 :(code)
-283 int count_events(const recipe& r) {
-284   int result = 0;
-285   for (int i = 0;  i < SIZE(r.steps);  ++i) {
-286     const instruction& curr = r.steps.at(i);
-287     if (curr.name == "type")
-288       result += unicode_length(curr.ingredients.at(0).name);
-289     else
-290       ++result;
-291   }
-292   return result;
-293 }
-294 
-295 int size_of_event() {
-296   // memoize result if already computed
-297   static int result = 0;
-298   if (result) return result;
-299   type_tree* type = new type_tree("event");
-300   result = size_of(type);
-301   delete type;
-302   return result;
-303 }
-304 
-305 int size_of_console() {
-306   // memoize result if already computed
-307   static int result = 0;
-308   if (result) return result;
-309   assert(get(Type_ordinal, "console"));
-310   type_tree* type = new type_tree("console");
-311   result = size_of(type)+/*refcount*/1;
-312   delete type;
-313   return result;
-314 }
+  1 //: Clean syntax to manipulate and check the console in scenarios.
+  2 //: Instruction 'assume-console' implicitly creates a variable called
+  3 //: 'console' that is accessible inside other 'run' instructions in the
+  4 //: scenario. Like with the fake screen, 'assume-console' transparently
+  5 //: supports unicode.
+  6 
+  7 //: first make sure we don't mangle these functions in other transforms
+  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  # 'a'
+ 25     2 <- 1
+ 26     3 <- 98  # 'b'
+ 27     4 <- 1
+ 28     5 <- 99  # 'c'
+ 29     6 <- 1
+ 30     7 <- 0  # unset
+ 31     8 <- 1
+ 32     9 <- 1  # end of test events
+ 33   ]
+ 34 ]
+ 35 
+ 36 :(before "End Scenario Globals")
+ 37 extern const int CONSOLE = Next_predefined_global_for_scenarios++;
+ 38 //: give 'console' a fixed location in scenarios
+ 39 :(before "End Special Scenario Variable Names(r)")
+ 40 Name[r]["console"] = CONSOLE;
+ 41 //: make 'console' always a raw location in scenarios
+ 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   // create a temporary recipe just for parsing; it won't contain valid instructions
+ 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   // initialize the events like in new-fake-console
+ 61   int size = /*space for refcount and length*/2 + num_events*size_of_event();
+ 62   int event_data_address = allocate(size);
+ 63   // store length
+ 64   put(Memory, event_data_address+/*skip refcount*/1, num_events);
+ 65   int curr_address = event_data_address + /*skip refcount and length*/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(9999, "mem") << "storing 'left-click' event starting at " << Current_routine->alloc << end();
+ 70       put(Memory, curr_address, /*tag for 'touch-event' variant of 'event' exclusive-container*/2);
+ 71       put(Memory, curr_address+/*skip tag*/1+/*offset of 'type' in 'mouse-event'*/0, TB_KEY_MOUSE_LEFT);
+ 72       put(Memory, curr_address+/*skip tag*/1+/*offset of 'row' in 'mouse-event'*/1, to_integer(inst.ingredients.at(0).name));
+ 73       put(Memory, curr_address+/*skip tag*/1+/*offset of 'column' in 'mouse-event'*/2, to_integer(inst.ingredients.at(1).name));
+ 74       curr_address += size_of_event();
+ 75     }
+ 76     else if (inst.name == "press") {
+ 77       trace(9999, "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         // these keys are in ascii
+ 87         put(Memory, curr_address, /*tag for 'text' variant of 'event' exclusive-container*/0);
+ 88       else {
+ 89         // distinguish from unicode
+ 90         put(Memory, curr_address, /*tag for 'keycode' variant of 'event' exclusive-container*/1);
+ 91       }
+ 92       curr_address += size_of_event();
+ 93     }
+ 94     // End Event Handlers
+ 95     else {
+ 96       // keyboard input
+ 97       assert(inst.name == "type");
+ 98       trace(9999, "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(9999, "mem") << "storing 'text' tag at " << curr_address << end();
+105         put(Memory, curr_address, /*tag for 'text' variant of 'event' exclusive-container*/0);
+106         uint32_t curr_character;
+107         assert(curr < SIZE(contents));
+108         tb_utf8_char_to_unicode(&curr_character, &raw_contents[curr]);
+109         trace(9999, "mem") << "storing character " << curr_character << " at " << curr_address+/*skip exclusive container tag*/1 << end();
+110         put(Memory, curr_address+/*skip exclusive container tag*/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   // wrap the array of events in a console object
+118   int console_address = allocate(size_of_console());
+119   trace(9999, "mem") << "storing console in " << console_address << end();
+120   put(Memory, CONSOLE, console_address);
+121   trace(9999, "mem") << "storing console data in " << console_address+/*skip refcount*/1+/*offset of 'data' in container 'events'*/1 << end();
+122   put(Memory, console_address+/*skip refcount*/1+/*offset of 'data' in container 'events'*/1, event_data_address);
+123   // increment refcount for event data
+124   put(Memory, event_data_address, 1);
+125   // increment refcount for console
+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;  // ignore CR/LF distinction; there is only 'enter'
+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 }
+189 
+190 :(after "Begin check_or_set_invalid_types(r)")
+191 if (is_scenario(caller))
+192   initialize_special_name(r);
+193 :(code)
+194 bool is_scenario(const recipe& caller) {
+195   return starts_with(caller.name, "scenario_");
+196 }
+197 void initialize_special_name(reagent& r) {
+198   if (r.type) return;
+199   // no need for screen
+200   if (r.name == "console") r.type = new_type_tree("address:console");
+201   // End Initialize Type Of Special Name In Scenario(r)
+202 }
+203 
+204 :(scenario events_in_scenario)
+205 scenario events-in-scenario [
+206   assume-console [
+207     type [abc]
+208     left-click 0, 1
+209     press up-arrow
+210     type [d]
+211   ]
+212   run [
+213     # 3 keyboard events; each event occupies 4 locations
+214     1:event <- read-event console
+215     5:event <- read-event console
+216     9:event <- read-event console
+217     # mouse click
+218     13:event <- read-event console
+219     # non-character keycode
+220     17:event <- read-event console
+221     # final keyboard event
+222     21:event <- read-event console
+223   ]
+224   memory-should-contain [
+225     1 <- 0  # 'text'
+226     2 <- 97  # 'a'
+227     3 <- 0  # unused
+228     4 <- 0  # unused
+229     5 <- 0  # 'text'
+230     6 <- 98  # 'b'
+231     7 <- 0  # unused
+232     8 <- 0  # unused
+233     9 <- 0  # 'text'
+234     10 <- 99  # 'c'
+235     11 <- 0  # unused
+236     12 <- 0  # unused
+237     13 <- 2  # 'mouse'
+238     14 <- 65513  # mouse click
+239     15 <- 0  # row
+240     16 <- 1  # column
+241     17 <- 1  # 'keycode'
+242     18 <- 65517  # up arrow
+243     19 <- 0  # unused
+244     20 <- 0  # unused
+245     21 <- 0  # 'text'
+246     22 <- 100  # 'd'
+247     23 <- 0  # unused
+248     24 <- 0  # unused
+249     25 <- 0
+250   ]
+251 ]
+252 
+253 //: Deal with special keys and unmatched brackets by allowing each test to
+254 //: independently choose the unicode symbol to denote them.
+255 :(before "End Primitive Recipe Declarations")
+256 REPLACE_IN_CONSOLE,
+257 :(before "End Primitive Recipe Numbers")
+258 put(Recipe_ordinal, "replace-in-console", REPLACE_IN_CONSOLE);
+259 :(before "End Primitive Recipe Checks")
+260 case REPLACE_IN_CONSOLE: {
+261   break;
+262 }
+263 :(before "End Primitive Recipe Implementations")
+264 case REPLACE_IN_CONSOLE: {
+265   assert(scalar(ingredients.at(0)));
+266   if (!get_or_insert(Memory, CONSOLE)) {
+267     raise << "console not initialized\n" << end();
+268     break;
+269   }
+270   int console_address = get_or_insert(Memory, CONSOLE);
+271   int console_data = get_or_insert(Memory, console_address+1);
+272   int length = get_or_insert(Memory, console_data);  // array length
+273   for (int i = 0, curr = console_data+1;  i < length;  ++i, curr+=size_of_event()) {
+274     if (get_or_insert(Memory, curr) != /*text*/0) continue;
+275     if (get_or_insert(Memory, curr+1) != ingredients.at(0).at(0)) continue;
+276     for (int n = 0;  n < size_of_event();  ++n)
+277       put(Memory, curr+n, ingredients.at(1).at(n));
+278   }
+279   break;
+280 }
+281 
+282 :(code)
+283 int count_events(const recipe& r) {
+284   int result = 0;
+285   for (int i = 0;  i < SIZE(r.steps);  ++i) {
+286     const instruction& curr = r.steps.at(i);
+287     if (curr.name == "type")
+288       result += unicode_length(curr.ingredients.at(0).name);
+289     else
+290       ++result;
+291   }
+292   return result;
+293 }
+294 
+295 int size_of_event() {
+296   // memoize result if already computed
+297   static int result = 0;
+298   if (result) return result;
+299   type_tree* type = new type_tree("event");
+300   result = size_of(type);
+301   delete type;
+302   return result;
+303 }
+304 
+305 int size_of_console() {
+306   // memoize result if already computed
+307   static int result = 0;
+308   if (result) return result;
+309   assert(get(Type_ordinal, "console"));
+310   type_tree* type = new type_tree("console");
+311   result = size_of(type)+/*refcount*/1;
+312   delete type;
+313   return result;
+314 }
 
-- cgit 1.4.1-2-gfad0