about summary refs log tree commit diff stats
path: root/cpp/018address
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/018address')
-rw-r--r--cpp/018address84
1 files changed, 84 insertions, 0 deletions
diff --git a/cpp/018address b/cpp/018address
new file mode 100644
index 00000000..4a5bcd51
--- /dev/null
+++ b/cpp/018address
@@ -0,0 +1,84 @@
+:(scenario "copy_indirect")
+# Instructions can read from addresses pointing at other locations using the 'deref' property.
+recipe main [
+  1:address:integer <- copy 2:literal
+  2:integer <- copy 34:literal
+  # This loads location 1 as an address and looks up *that* location.
+  3:integer <- copy 1:address:integer/deref
+]
++run: instruction 2
++mem: location 1 is 2
++mem: location 2 is 34
++mem: storing in location 3
+
+:(replace{} "vector<int> read_memory(reagent x)")
+vector<int> read_memory(reagent x) {
+  vector<int> result;
+  if (x.types[0] == 0) {  // literal
+    result.push_back(to_int(x.name));
+    return result;
+  }
+  x = canonize(x);
+  int base = to_int(x.name);
+  for (size_t offset = 0; offset < Type[x.types[0]].size; ++offset) {
+    int val = Memory[base+offset];
+    trace("mem") << "location " << base+offset << " is " << val;
+    result.push_back(val);
+  }
+  return result;
+}
+
+:(replace{} "void write_memory(reagent x, vector<int> data)")
+void write_memory(reagent x, vector<int> data) {
+  int base = to_int(x.name);
+  size_t size = size_of(x.types[0]);
+  if (size != data.size()) raise << "size mismatch in storing to " << x.to_string();
+  for (size_t offset = 0; offset < size; ++offset) {
+    trace("mem") << "storing in location " << base+offset;
+    Memory[base+offset] = data[offset];
+  }
+}
+
+:(code)
+reagent canonize(reagent x) {
+  reagent r = x;
+  while (has_property(r, "deref"))
+    r = deref(r);
+  return r;
+}
+
+bool has_property(reagent x, string name) {
+  for (size_t i = 0; i < x.properties.size(); ++i) {
+    if (x.properties[i].first == name) return true;
+  }
+  return false;
+}
+
+reagent deref(reagent x) {
+  reagent result("");
+  assert(x.types[0] == 2);  // address
+
+  // compute name
+  ostringstream out;
+  out << Memory[to_int(x.name)];
+  result.name = out.str();
+  trace("mem") << "location " << x.name << " is " << result.name;
+
+  // populate types
+  copy(++x.types.begin(), x.types.end(), inserter(result.types, result.types.begin()));
+
+  // drop-one 'deref'
+  int i = 0;
+  int len = x.properties.size();
+  while (true) {
+    assert(i < len);
+    if (x.properties[i].first == "deref") break;
+    result.properties.push_back(x.properties[i]);
+    ++i;
+  }
+  ++i;  // skip first deref
+  while (i < len) {
+    result.properties.push_back(x.properties[i]);
+  }
+  return result;
+}