//: 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 34 in location 3 :(before "int base = x.value" following "vector read_memory(reagent x)") x = canonize(x); //: 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 34 in location 2 :(before "int base = x.value" following "void write_memory(reagent x, vector data)") x = canonize(x); :(code) reagent canonize(reagent x) { //? cout << "canonize\n"; //? 1 reagent r = x; //? cout << x.to_string() << " => " << r.to_string() << '\n'; //? 1 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) { //? cout << "deref: " << x.to_string() << "\n"; //? 2 static const int ADDRESS = Type_number["address"]; reagent result; assert(x.types[0] == ADDRESS); // compute value result.set_value(Memory[x.value]); trace("mem") << "location " << x.value << " is " << result.value; // 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(); for (i = 0; i < len; ++i) { if (x.properties[i].first == "deref") break; result.properties.push_back(x.properties[i]); } ++i; // skip first deref for (; i < len; ++i) { 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 34 in location 4 :(scenario "include_nonderef_properties") recipe main [ 1:integer <- copy 2:literal 2:integer <- copy 34:literal 3:integer <- copy 35:literal 4:integer <- get 1:address:point/deref/foo, 0:offset ] +run: instruction main/3 +run: address to copy is 2 +run: product 0 is 34 +mem: storing 34 in location 4 :(after "reagent base = " following "case GET:") base = canonize(base); :(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 :(after "reagent base = " following "case GET_ADDRESS:") base = canonize(base);