about summary refs log tree commit diff stats
path: root/apps/ex6.mu
Commit message (Expand)AuthorAgeFilesLines
* .Kartik K. Agaram2021-07-161-0/+32
='n21' href='#n21'>21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 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
// Support for arrays.
:(before "End Mu Types")
// We'll use this array as a running example:
int integer_array = Type_number["integer-array"] = Next_type_number++;
Type[integer_array].is_array = true;
Type[integer_array].element.push_back(integer);

:(scenario copy_array)
# Arrays can be copied around with a single instruction just like integers,
# no matter how large they are.
recipe main [
  1:integer <- copy 3:literal
  2:integer <- copy 14:literal
  3:integer <- copy 15:literal
  4:integer <- copy 16:literal
  5:integer-array <- copy 1:integer-array
]
+run: instruction main/4
+run: ingredient 0 is 1
+mem: location 1 is 3
+mem: location 2 is 14
+mem: location 3 is 15
+mem: location 4 is 16
+mem: storing in location 5
+mem: storing in location 6
+mem: storing in location 7
+mem: storing in location 8

:(replace{} "size_t size_of(reagent r)")
size_t size_of(reagent r) {
  type_info t = Type[r.types[0]];
  if (t.is_record) {
    int result = 0;
    for (size_t i = 0; i < t.size; ++i) {
      ostringstream out;
      out << result;
      reagent x(out.str());
      copy(t.elements[i].begin(), t.elements[i].end(), inserter(x.types, x.types.begin()));
      result += size_of(x);
    }
    return result;
  }
  if (t.is_array) {
    assert(!r.name.empty());
    int base = to_int(r.name);
    if (Memory[base] == 0) return 0;
    ostringstream out;
    out << base+1;
    reagent x(out.str());
    x.types.push_back(t.element[0]);
    return 1 + Memory[base]*size_of(x);
  }
  // scalar
  return t.size;
}

:(before "End Globals")
// Operator to look at elements of arrays.
const int INDEX = 20;
:(before "End Primitive Recipe Numbers")
Recipe_number["index"] = INDEX;
Next_recipe_number++;
:(before "End Primitive Recipe Implementations")
case INDEX: {
  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
  reagent base = canonize(instructions[pc].ingredients[0]);
  int base_address = to_int(base.name);
  int base_type = base.types[0];
  assert(Type[base_type].is_array);
  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
  size_t offset = to_int(instructions[pc].ingredients[1].name);
  int src = base_address + 1 + offset*size_of(reagent(Type[base_type].element[0]));
  trace("run") << "address to copy is " << src;
  int src_type = Type[base_type].element[0];
  trace("run") << "its type is " << src_type;
  ostringstream s;
  s << src;
  reagent tmp(s.str());
  tmp.types.push_back(src_type);
  vector<int> result(read_memory(tmp));
  trace("run") << "product 0 is " << result[0];
  write_memory(instructions[pc].products[0], result);
  break;
}

:(scenario "index")
recipe main [
  1:integer <- copy 3:literal
  2:integer <- copy 14:literal
  3:integer <- copy 15:literal
  4:integer <- copy 16:literal
  5:integer <- index 1:integer-array, 0:literal
]
+run: instruction main/4
+run: ingredient 0 is 1
+run: ingredient 1 is 0
+run: address to copy is 2
+run: its type is 1
+mem: location 2 is 14
+run: product 0 is 14
+mem: storing in location 5

:(before "End Globals")
// To write to fields of records, you need their address.
const int INDEX_ADDRESS = 21;
:(before "End Primitive Recipe Numbers")
Recipe_number["index-address"] = INDEX_ADDRESS;
Next_recipe_number++;
:(before "End Primitive Recipe Implementations")
case INDEX_ADDRESS: {
  trace("run") << "ingredient 0 is " << instructions[pc].ingredients[0].name;
  reagent base = canonize(instructions[pc].ingredients[0]);
  int base_address = to_int(base.name);
  int base_type = base.types[0];
  assert(Type[base_type].is_array);
  trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name;
  size_t offset = to_int(instructions[pc].ingredients[1].name);
  int src = base_address + 1 + offset*size_of(reagent(Type[base_type].element[0]));
  trace("run") << "address to copy is " << src;
  vector<int> result;
  result.push_back(src);
  trace("run") << "product 0 is " << result[0];
  write_memory(instructions[pc].products[0], result);
  break;
}

:(scenario "index_address")
recipe main [
  1:integer <- copy 3:literal
  2:integer <- copy 14:literal
  3:integer <- copy 15:literal
  4:integer <- copy 16:literal
  5:integer <- index-address 1:integer-array, 0:literal
]
+run: instruction main/4
+run: ingredient 0 is 1
+run: ingredient 1 is 0
+run: address to copy is 2
+mem: storing in location 5