diff options
-rw-r--r-- | cpp/.traces/copy_indirect | 20 | ||||
-rw-r--r-- | cpp/018address | 84 |
2 files changed, 104 insertions, 0 deletions
diff --git a/cpp/.traces/copy_indirect b/cpp/.traces/copy_indirect new file mode 100644 index 00000000..f757f05a --- /dev/null +++ b/cpp/.traces/copy_indirect @@ -0,0 +1,20 @@ +parse/0: instruction: 1 +parse/0: ingredient: {name: "2", type: 0} +parse/0: product: {name: "1", type: 2-1} +parse/0: instruction: 1 +parse/0: ingredient: {name: "34", type: 0} +parse/0: product: {name: "2", type: 1} +parse/0: instruction: 1 +parse/0: ingredient: {name: "1", type: 2-1, property: deref:} +parse/0: product: {name: "3", type: 1} +run/0: instruction 0 +run/0: ingredient 0 is 2 +mem/0: storing in location 1 +run/0: instruction 1 +run/0: ingredient 0 is 34 +mem/0: storing in location 2 +run/0: instruction 2 +run/0: ingredient 0 is 1 +mem/0: location 1 is 2 +mem/0: location 2 is 34 +mem/0: storing in location 3 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; +} |