:(scenario convert_names)
recipe main [
x:integer <- copy 0:literal
]
+name: assign x 1
+run: instruction main/0
+mem: storing 0 in location 1
:(scenario convert_names_warns)
% Hide_warnings = true;
recipe main [
x:integer <- copy y:integer
]
+warn: use before set: y in main
:(after "int main")
Transform.push_back(transform_names);
:(before "End Globals")
map<recipe_number, map<string, index_t> > Name;
:(after "Clear Other State For recently_added_recipes")
for (index_t i = 0; i < recently_added_recipes.size(); ++i) {
Name.erase(recently_added_recipes[i]);
}
:(code)
void transform_names(const recipe_number r) {
map<string, index_t>& names = Name[r];
index_t& curr_idx = names[""];
++curr_idx;
for (index_t i = 0; i < Recipe[r].steps.size(); ++i) {
instruction& inst = Recipe[r].steps[i];
for (index_t in = 0; in < inst.ingredients.size(); ++in) {
if (is_raw(inst.ingredients[in])) continue;
if (inst.ingredients[in].name == "default-space")
inst.ingredients[in].initialized = true;
if (inst.ingredients[in].types.empty())
raise << "missing type in " << inst.to_string() << '\n';
assert(!inst.ingredients[in].types.empty());
if (inst.ingredients[in].types[0]
&& !inst.ingredients[in].initialized
&& !is_number(inst.ingredients[in].name)) {
if (!already_transformed(inst.ingredients[in], names)) {
raise << "use before set: " << inst.ingredients[in].name << " in " << Recipe[r].name << '\n';
}
inst.ingredients[in].set_value(lookup_name(inst.ingredients[in], r));
}
}
for (index_t out = 0; out < inst.products.size(); ++out) {
if (is_raw(inst.products[out])) continue;
if (inst.products[out].name == "default-space")
inst.products[out].initialized = true;
if (inst.products[out].types[0]
&& !inst.products[out].initialized
&& !is_number(inst.products[out].name)) {
if (names.find(inst.products[out].name) == names.end()) {
trace("name") << "assign " << inst.products[out].name << " " << curr_idx;
names[inst.products[out].name] = curr_idx;
curr_idx += size_of(inst.products[out]);
}
inst.products[out].set_value(lookup_name(inst.products[out], r));
}
}
}
}
bool already_transformed(const reagent& r, const map<string, index_t>& names) {
return names.find(r.name) != names.end();
}
index_t lookup_name(const reagent& r, const recipe_number default_recipe) {
return Name[default_recipe][r.name];
}
type_number skip_addresses(const vector<type_number>& types) {
for (index_t i = 0; i < types.size(); ++i) {
if (types[i] != Type_number["address"]) return types[i];
}
raise << "expected a container" << '\n' << die();
return -1;
}
int find_element_name(const type_number t, const string& name) {
co//: Clean syntax to manipulate and check the console in scenarios.
//: Instruction 'assume-console' implicitly creates a variable called
//: 'console' that is accessible inside other 'run' instructions in the
//: scenario. Like with the fake screen, 'assume-console' transparently
//: supports unicode.
//: first make sure we don't mangle this instruction in other transforms
:(before "End initialize_transform_rewrite_literal_string_to_text()")
recipes_taking_literal_strings.insert("assume-console");
:(code)
void test_keyboard_in_scenario() {
run_mu_scenario(
"scenario keyboard-in-scenario [\n"
" assume-console [\n"
" type [abc]\n"
" ]\n"
" run [\n"
" 1:char, 2:bool <- read-key console\n"
" 3:char, 4:bool <- read-key console\n"
" 5:char, 6:bool <- read-key console\n"
" 7:char, 8:bool, 9:bool <- read-key console\n"
" ]\n"
" memory-should-contain [\n"
" 1 <- 97\n" // 'a'
" 2 <- 1\n"
" 3 <- 98\n" // 'b'
" 4 <- 1\n"
" 5 <- 99\n" // 'c'
" 6 <- 1\n"
" 7 <- 0\n" // unset
" 8 <- 1\n"
" 9 <- 1\n" // end of test events
" ]\n"
"]\n"
);
}
:(before "End Scenario Globals")
extern const int CONSOLE = next_predefined_global_for_scenarios(/*size_of(address:console)*/2);
//: give 'console' a fixed location in scenarios
:(before "End Special Scenario Variable Names(r)")
Name[r]["console"] = CONSOLE;
//: make 'console' always a raw location in scenarios
:(before "End is_special_name Special-cases")
if (s == "console") return true;
:(before