https://github.com/akkartik/mu/blob/master/085scenario_console.cc
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(2);
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 = 1 + 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 + 1 + 1;
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_