about summary refs log tree commit diff stats
path: root/015immediate_addressing.cc
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-10-31 19:50:41 -0700
committerKartik Agaram <vc@akkartik.com>2020-10-31 19:50:41 -0700
commit3f30e4c6e6598eb281331626f0f021005ba608f3 (patch)
tree1c588100afd9bf98b01f82cfe94bdad5429d903f /015immediate_addressing.cc
parent8c44afcccc12ce0715f780ee70c312bd546c57c7 (diff)
downloadmu-3f30e4c6e6598eb281331626f0f021005ba608f3.tar.gz
7146
Diffstat (limited to '015immediate_addressing.cc')
0 files changed, 0 insertions, 0 deletions
07' href='#n107'>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
//: For convenience, allow Mu types to be abbreviated.

:(scenarios transform)
:(scenario type_abbreviations)
type foo = number
def main [
  a:foo <- copy 34
]
+transform: product type after expanding abbreviations: "number"

:(before "End Globals")
map<string, type_tree*> Type_abbreviations, Type_abbreviations_snapshot;

//:: Defining type abbreviations.

:(before "End Command Handlers")
else if (command == "type") {
  load_type_abbreviations(in);
}

:(code)
void load_type_abbreviations(istream& in) {
  string new_type_name = next_word(in);
  assert(has_data(in) || !new_type_name.empty());
  if (!has_data(in) || new_type_name.empty()) {
    raise << "incomplete 'type' statement; must be of the form 'type <new type name> = <type expression>'\n" << end();
    return;
  }
  string arrow = next_word(in);
  assert(has_data(in) || !arrow.empty());
  if (arrow.empty()) {
    raise << "incomplete 'type' statement 'type " << new_type_name << "'\n" << end();
    return;
  }
  if (arrow != "=") {
    raise << "'type' statements must be of the form 'type <new type name> = <type expression>' but got 'type " << new_type_name << ' ' << arrow << "'\n" << end();
    return;
  }
  if (!has_data(in)) {
    raise << "incomplete 'type' statement 'type " << new_type_name << " ='\n" << end();
    return;
  }
  string old = next_word(in);
  if (old.empty()) {
    raise << "incomplete 'type' statement 'type " << new_type_name << " ='\n" << end();
    raise << "'type' statements must be of the form 'type <new type name> = <type expression>' but got 'type " << new_type_name << ' ' << arrow << "'\n" << end();
    return;
  }
  if (contains_key(Type_abbreviations, new_type_name)) {
    raise << "'type' conflict: '" << new_type_name << "' defined as both '" << names_to_string_without_quotes(get(Type_abbreviations, new_type_name)) << "' and '" << old << "'\n" << end();
    return;
  }
  trace(9990, "type") << "alias " << new_type_name << " = " << old << end();
  type_tree* old_type = new_type_tree(old);
  put(Type_abbreviations, new_type_name, old_type);
}

type_tree* new_type_tree(const string& x) {
  string_tree* type_names = starts_with(x, "(") ? parse_string_tree(x) : parse_string_list(x);
  type_tree* result = new_type_tree(type_names);
  delete type_names;
  expand_type_abbreviations(result);
  return result;
}

string_tree* parse_string_list(const string& s) {
  istringstream in(s);
  in >> std::noskipws;
  return parse_property_list(in);
}

:(scenario type_error1)
% Hide_errors = true;
type foo
+error: incomplete 'type' statement 'type foo'

:(scenario type_error2)
% Hide_errors = true;
type foo =
+error: incomplete 'type' statement 'type foo ='

:(scenario type_error3)
% Hide_errors = true;
type foo bar baz
+error: 'type' statements must be of the form 'type <new type name> = <type expression>' but got 'type foo bar'

:(scenario type_conflict_error)
% Hide_errors = true;
type foo = bar
type foo = baz
+error: 'type' conflict: 'foo' defined as both 'bar' and 'baz'

:(scenario type_abbreviation_for_compound)
type foo = address:number
def main [
  1:foo <- copy null
]
+transform: product type after expanding abbreviations: ("address" "number")

//: cleaning up type abbreviations between tests and before exiting

:(before "End save_snapshots")
Type_abbreviations_snapshot = Type_abbreviations;
:(before "End restore_snapshots")
restore_type_abbreviations();
:(before "End One-time Setup")
atexit(clear_type_abbreviations);
:(code)
void restore_type_abbreviations() {
  for (map<string, type_tree*>::iterator p = Type_abbreviations.begin();  p != Type_abbreviations.end();  ++p) {
    if (!contains_key(Type_abbreviations_snapshot, p->first))
      delete p->second;
  }
  Type_abbreviations.clear();
  Type_abbreviations = Type_abbreviations_snapshot;
}
void clear_type_abbreviations() {
  for (map<string, type_tree*>::iterator p = Type_abbreviations.begin();  p != Type_abbreviations.end();  ++p)
    delete p->second;
  Type_abbreviations.clear();
}

//:: A few default abbreviations.

:(before "End Mu Types Initialization")
put(Type_abbreviations, "&", new_type_tree("address"));
put(Type_abbreviations, "@", new_type_tree("array"));
put(Type_abbreviations, "num", new_type_tree("number"));
put(Type_abbreviations, "bool", new_type_tree("boolean"));
put(Type_abbreviations, "char", new_type_tree("character"));

:(scenario use_type_abbreviations_when_declaring_type_abbreviations)
type foo = &:num
def main [
  1:foo <- copy null
]
+transform: product type after expanding abbreviations: ("address" "number")

//:: Expand type aliases before running.
//: We'll do this in a transform so that we don't need to define abbreviations
//: before we use them.

:(scenario abbreviations_for_address_and_array)
def main [
  f 1:&:num  # abbreviation for 'address:number'
  f 2:@:num  # abbreviation for 'array:number'
  f 3:&:@:num  # combining '&' and '@'
  f 4:&:&:@:&:@:num  # ..any number of times
  f {5: (array (& num) 3)}  # support for dilated reagents and more complex parse trees
]
def f [
]
+transform: --- expand type abbreviations in recipe 'main'
+transform: ingredient type after expanding abbreviations: ("address" "number")
+transform: ingredient type after expanding abbreviations: ("array" "number")
+transform: ingredient type after expanding abbreviations: ("address" "array" "number")
+transform: ingredient type after expanding abbreviations: ("address" "address" "array" "address" "array" "number")
+transform: ingredient type after expanding abbreviations: ("array" ("address" "number") "3")

:(before "Transform.push_back(update_instruction_operations)")
Transform.push_back(expand_type_abbreviations);  // idempotent
// Begin Type Modifying Transforms
// End Type Modifying Transforms

:(code)
void expand_type_abbreviations(const recipe_ordinal r) {
  expand_type_abbreviations(get(Recipe, r));
}

void expand_type_abbreviations(const recipe& caller) {
  trace(9991, "transform") << "--- expand type abbreviations in recipe '" << caller.name << "'" << end();
  for (int i = 0;  i < SIZE(caller.steps);  ++i) {
    const instruction& inst = caller.steps.at(i);
    trace(9991, "transform") << "instruction '" << to_original_string(inst) << end();
    for (long int i = 0;  i < SIZE(inst.ingredients);  ++i) {
      expand_type_abbreviations(inst.ingredients.at(i).type);
      trace(9992, "transform") << "ingredient type after expanding abbreviations: " << names_to_string(inst.ingredients.at(i).type) << end();
    }
    for (long int i = 0;  i < SIZE(inst.products);  ++i) {
      expand_type_abbreviations(inst.products.at(i).type);
      trace(9992, "transform") << "product type after expanding abbreviations: " << names_to_string(inst.products.at(i).type) << end();
    }
  }
  // End Expand Type Abbreviations(caller)
}

void expand_type_abbreviations(type_tree* type) {
  if (!type) return;
  if (!type->atom) {
    expand_type_abbreviations(type->left);
    expand_type_abbreviations(type->right);
    return;
  }
  if (contains_key(Type_abbreviations, type->name))
    *type = type_tree(*get(Type_abbreviations, type->name));
}