summary refs log tree commit diff stats
path: root/doc
diff options
context:
space:
mode:
authorhut <hut@lavabit.com>2011-09-08 19:42:48 +0200
committerhut <hut@lavabit.com>2011-09-08 19:42:48 +0200
commit82e00fd6f00c0202a36be49461d7a1151633c651 (patch)
tree5a73caeaaf5dd4b358c0deadd891c730ac17aa27 /doc
parent1b0782bbe6c5922d002a21644893f303e6c34ed2 (diff)
downloadranger-82e00fd6f00c0202a36be49461d7a1151633c651.tar.gz
core.actions: throw some signals before and after executing files
Diffstat (limited to 'doc')
0 files changed, 0 insertions, 0 deletions
='#n97'>97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 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
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")
unordered_map<recipe_number, unordered_map<string, int> > 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) {
  unordered_map<string, int>& 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 unordered_map<string, int>& 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<type_number>& 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;
}