From b1bbe92da37dd44df458ffa122e052612bb9eff3 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Tue, 17 Mar 2015 08:42:38 -0700 Subject: 945 - move 'transform' layer to before 'run' --- cpp/019address | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 cpp/019address (limited to 'cpp/019address') diff --git a/cpp/019address b/cpp/019address new file mode 100644 index 00000000..cd4f180e --- /dev/null +++ b/cpp/019address @@ -0,0 +1,177 @@ +//: Instructions can read from addresses pointing at other locations using the +//: 'deref' property. +:(scenario "copy_indirect") +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 main/2 ++mem: location 1 is 2 ++mem: location 2 is 34 ++mem: storing in location 3 + +:(replace{} "vector read_memory(reagent x)") +vector read_memory(reagent x) { + vector 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); + size_t size = size_of(x); + for (size_t offset = 0; offset < size; ++offset) { + int val = Memory[base+offset]; + trace("mem") << "location " << base+offset << " is " << val; + result.push_back(val); + } + return result; +} + +//: similarly, write to addresses pointing at other locations using the +//: 'deref' property +:(scenario "store_indirect") +recipe main [ + 1:address:integer <- copy 2:literal + 1:address:integer/deref <- copy 34:literal +] ++run: instruction main/1 ++mem: location 1 is 2 ++mem: storing in location 2 + +:(replace{} "void write_memory(reagent x, vector data)") +void write_memory(reagent x, vector data) { + x = canonize(x); + int base = to_int(x.name); + if (!Type[x.types[0]].is_array && size_of(x) != data.size()) + raise << "size mismatch in storing to " << x.to_string(); + for (size_t offset = 0; offset < data.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; +} + +//: 'get' can read from record address +:(scenario "get_indirect") +recipe main [ + 1:integer <- copy 2:literal + 2:integer <- copy 34:literal + 3:integer <- copy 35:literal + 4:integer <- get 1:address:point/deref, 0:offset +] ++run: instruction main/3 ++run: address to copy is 2 ++run: product 0 is 34 ++mem: storing in location 4 + +:(replace{} "case GET:") +case GET: { + 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_record); + trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name; + assert(instructions[pc].ingredients[1].types.size() == 1); + assert(instructions[pc].ingredients[1].types[0] == 0); // must be literal + size_t offset = to_int(instructions[pc].ingredients[1].name); + int src = base_address; + for (size_t i = 0; i < offset; ++i) { + src += size_of(reagent(Type[base_type].elements[i][0])); + } + trace("run") << "address to copy is " << src; + assert(Type[base_type].is_record); + assert(Type[base_type].elements.size() > offset); + int src_type = Type[base_type].elements[offset][0]; + trace("run") << "its type is " << src_type; + ostringstream s; + s << src; + reagent tmp(s.str()); + tmp.types.push_back(src_type); + vector result(read_memory(tmp)); + trace("run") << "product 0 is " << result[0]; + write_memory(instructions[pc].products[0], result); + break; +} + +:(scenario "get_address_indirect") +# 'get' can read from record address +recipe main [ + 1:integer <- copy 2:literal + 2:integer <- copy 34:literal + 3:integer <- copy 35:literal + 4:integer <- get-address 1:address:point/deref, 0:offset +] ++run: instruction main/3 ++run: address to copy is 2 ++run: product 0 is 2 + +:(replace{} "case GET_ADDRESS:") +case GET_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_record); + trace("run") << "ingredient 1 is " << instructions[pc].ingredients[1].name; + assert(instructions[pc].ingredients[1].types.size() == 1); + assert(instructions[pc].ingredients[1].types[0] == 0); // must be literal + size_t offset = to_int(instructions[pc].ingredients[1].name); + int src = base_address; + for (size_t i = 0; i < offset; ++i) { + src += size_of(reagent(Type[base_type].elements[i][0])); + } + trace("run") << "address to copy is " << src; + vector result; + result.push_back(src); + trace("run") << "product 0 is " << result[0]; + write_memory(instructions[pc].products[0], result); + break; +} + -- cgit 1.4.1-2-gfad0