From 6d8ef6b12d37336a92c7a6b20b4b66f3ab424464 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 24 Apr 2015 22:49:29 -0700 Subject: 1189 - add extensions to all layers I'm sick of fighting vim's filetype detection. No modeline and files highlight in random colors. I add a modeline and it stops highlighting tangle comments. Even though it read my #$%# vimrc! Fuck this shite. --- cpp/041name.cc | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 cpp/041name.cc (limited to 'cpp/041name.cc') diff --git a/cpp/041name.cc b/cpp/041name.cc new file mode 100644 index 00000000..20d1222f --- /dev/null +++ b/cpp/041name.cc @@ -0,0 +1,199 @@ +//: A big convenience high-level languages provide is the ability to name memory +//: locations. In mu, a transform called 'convert-names' provides this +//: convenience. + +:(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 > Name; +:(after "Clear Other State For recently_added_recipes") +for (size_t i = 0; i < recently_added_recipes.size(); ++i) { + Name.erase(recently_added_recipes[i]); +} + +:(code) +void transform_names(const recipe_number r) { + map& names = Name[r]; + int curr_idx = 1; +//? cout << "Recipe " << r << '\n'; //? 2 +//? cout << Recipe[r].steps.size(); //? 1 + for (size_t i = 0; i < Recipe[r].steps.size(); ++i) { +//? cout << "instruction " << i << '\n'; //? 2 + instruction& inst = Recipe[r].steps[i]; + // Per-recipe Transforms + // map names to addresses + for (size_t in = 0; in < inst.ingredients.size(); ++in) { +//? cout << "ingredients\n"; //? 2 + if (is_raw(inst.ingredients[in])) continue; +//? cout << "ingredient " << inst.ingredients[in].name << '\n'; //? 2 + if (inst.ingredients[in].name == "default-space") + inst.ingredients[in].initialized = true; + assert(!inst.ingredients[in].types.empty()); + if (inst.ingredients[in].types[0] // not a literal + && !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)); +//? cout << "lookup ingredient " << Recipe[r].name << "/" << i << ": " << inst.ingredients[in].to_string() << '\n'; //? 1 + } + } + for (size_t out = 0; out < inst.products.size(); ++out) { +//? cout << "products\n"; //? 1 + if (is_raw(inst.products[out])) continue; +//? cout << "product " << out << '/' << inst.products.size() << " " << inst.products[out].name << '\n'; //? 4 +//? cout << inst.products[out].types[0] << '\n'; //? 1 + if (inst.products[out].name == "default-space") + inst.products[out].initialized = true; + if (inst.products[out].types[0] // not a literal + && !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)); +//? cout << "lookup product " << Recipe[r].name << "/" << i << ": " << inst.products[out].to_string() << '\n'; //? 1 + } + } + } +} + +bool already_transformed(const reagent& r, const map& names) { + return names.find(r.name) != names.end(); +} + +size_t lookup_name(const reagent& r, const recipe_number default_recipe) { + return Name[default_recipe][r.name]; +} + +type_number skip_addresses(const vector& types) { + for (size_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) { + const type_info& container = Type[t]; +//? cout << "looking for element " << name << " in type " << container.name << " with " << container.element_names.size() << " elements\n"; //? 1 + for (size_t i = 0; i < container.element_names.size(); ++i) { + if (container.element_names[i] == name) return i; + } + raise << "unknown element " << name << " in container " << t << '\n' << die(); + return -1; +} + +bool is_raw(const reagent& r) { + for (size_t i = /*skip value+type*/1; i < r.properties.size(); ++i) { + if (r.properties[i].first == "raw") return true; + } + return false; +} + +:(scenario convert_names_passes_dummy) +# _ is just a dummy result that never gets consumed +recipe main [ + _, x:integer <- copy 0:literal +] ++name: assign x 1 +-name: assign _ 1 + +//: one reserved word that we'll need later +:(scenario convert_names_passes_default_space) +recipe main [ + default-space:integer, x:integer <- copy 0:literal +] ++name: assign x 1 +-name: assign default-space 1 + +//: an escape hatch to suppress name conversion that we'll use later +:(scenario convert_names_passes_raw) +recipe main [ + x:integer/raw <- copy 0:literal +] +-name: assign x 1 + +//:: Support element names for containers in 'get' and 'get-address'. + +//: update our running example container for the next test +:(before "End Mu Types Initialization") +Type[point].element_names.push_back("x"); +Type[point].element_names.push_back("y"); +:(scenario convert_names_transforms_container_elements) +recipe main [ + a:integer <- get 0:point, y:offset + b:integer <- get 0:point, x:offset +] ++name: element y of type point is at offset 1 ++name: element x of type point is at offset 0 + +:(after "Per-recipe Transforms") +// replace element names of containers with offsets +if (inst.operation == Recipe_number["get"] + || inst.operation == Recipe_number["get-address"]) { + // at least 2 args, and second arg is offset + assert(inst.ingredients.size() >= 2); +//? cout << inst.ingredients[1].to_string() << '\n'; //? 1 + assert(isa_literal(inst.ingredients[1])); + if (inst.ingredients[1].name.find_first_not_of("0123456789") == string::npos) continue; + // since first non-address in base type must be a container, we don't have to canonize + type_number base_type = skip_addresses(inst.ingredients[0].types); + inst.ingredients[1].set_value(find_element_name(base_type, inst.ingredients[1].name)); + trace("name") << "element " << inst.ingredients[1].name << " of type " << Type[base_type].name << " is at offset " << inst.ingredients[1].value; +} + +//: this test is actually illegal so can't call run +:(scenarios transform) +:(scenario convert_names_handles_containers) +recipe main [ + a:point <- copy 0:literal + b:integer <- copy 0:literal +] ++name: assign a 1 ++name: assign b 3 + +//:: Support variant names for exclusive containers in 'maybe-convert'. + +:(scenarios run) +:(scenario maybe_convert_named) +recipe main [ + 12:integer <- copy 1:literal + 13:integer <- copy 35:literal + 14:integer <- copy 36:literal + 20:address:point <- maybe-convert 12:integer-or-point, p:variant +] ++name: variant p of type integer-or-point has tag 1 ++mem: storing 13 in location 20 + +:(after "Per-recipe Transforms") +// convert variant names of exclusive containers +if (inst.operation == Recipe_number["maybe-convert"]) { + // at least 2 args, and second arg is offset + assert(inst.ingredients.size() >= 2); + assert(isa_literal(inst.ingredients[1])); + if (inst.ingredients[1].name.find_first_not_of("0123456789") == string::npos) continue; + // since first non-address in base type must be an exclusive container, we don't have to canonize + type_number base_type = skip_addresses(inst.ingredients[0].types); + inst.ingredients[1].set_value(find_element_name(base_type, inst.ingredients[1].name)); + trace("name") << "variant " << inst.ingredients[1].name << " of type " << Type[base_type].name << " has tag " << inst.ingredients[1].value; +} -- cgit 1.4.1-2-gfad0