about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-02-19 23:49:13 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-02-19 23:49:13 -0800
commitb291f85b8d0ece9312b066a84cbeca1b367fe85f (patch)
treee3e443337918a47ac2f3707b1b77957c34a6131d
parent9dc2948276388d2ca6556f4a8d13d55406775ac7 (diff)
downloadmu-b291f85b8d0ece9312b066a84cbeca1b367fe85f.tar.gz
798 - start of record support
-rw-r--r--cpp/.traces/copy_multiple_locations21
-rw-r--r--cpp/010vm11
-rw-r--r--cpp/012run19
-rw-r--r--cpp/017and-record27
4 files changed, 70 insertions, 8 deletions
diff --git a/cpp/.traces/copy_multiple_locations b/cpp/.traces/copy_multiple_locations
new file mode 100644
index 00000000..d721dafb
--- /dev/null
+++ b/cpp/.traces/copy_multiple_locations
@@ -0,0 +1,21 @@
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "34", type: 0}
+parse/0:   product: {name: "1", type: 1}
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "0", type: 0}
+parse/0:   product: {name: "2", type: 2}
+parse/0: instruction: 1
+parse/0:   ingredient: {name: "1", type: 3}
+parse/0:   product: {name: "3", type: 3}
+run/0: instruction 0
+run/0: ingredient 0 is 34
+mem/0: storing in location 1
+run/0: instruction 1
+run/0: ingredient 0 is 0
+mem/0: storing in location 2
+run/0: instruction 2
+run/0: ingredient 0 is 1
+mem/0: location 1 is 34
+mem/0: location 2 is 0
+mem/0: storing in location 3
+mem/0: storing in location 4
diff --git a/cpp/010vm b/cpp/010vm
index b864179e..342eeb9a 100644
--- a/cpp/010vm
+++ b/cpp/010vm
@@ -77,6 +77,8 @@ void setup_types() {
   int integer = Type_number["integer"] = 1;
   Type[integer].size = 1;
   Next_type_number++;
+  int boolean = Type_number["boolean"] = Next_type_number++;
+  Type[boolean].size = 1;
   // End Mu Types.
 }
 :(before "End Setup")
@@ -86,14 +88,19 @@ void setup_types() {
 // You can construct arbitrary new types. Types are either 'records', containing
 // 'fields' of other types, 'array's of a single type repeated over and over,
 // or 'addresses' pointing at a location elsewhere in memory.
+//
+// For example:
+//  storing bank balance next to a person's name might require a record, and
+//  high scores in a game might need an array of numbers.
+// You'll see examples using addresses later.
 struct type_info {
-  int size;
+  size_t size;
   bool is_address;
   bool is_record;
   bool is_array;
   vector<type_number> target;  // only if is_address
   vector<vector<type_number> > elements;  // only if is_record or is_array
-  type_info() :size(0) {}
+  type_info() :size(0), is_address(false), is_record(false), is_array(false) {}
 };
 
 :(before "End Globals")
diff --git a/cpp/012run b/cpp/012run
index acc423a4..a1778705 100644
--- a/cpp/012run
+++ b/cpp/012run
@@ -47,16 +47,23 @@ vector<int> read_memory(reagent x) {
     result.push_back(to_int(x.name));
     return result;
   }
-  int val = Memory[to_int(x.name)];
-  trace("mem") << "location " << x.name << " is " << val;
-  result.push_back(val);
+  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;
 }
 
 void write_memory(reagent x, vector<int> data) {
-  int dest = to_int(x.name);
-  trace("mem") << "storing in location " << dest;
-  Memory[dest] = data[0];
+  int base = to_int(x.name);
+  size_t size = Type[x.types[0]].size;
+  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)
diff --git a/cpp/017and-record b/cpp/017and-record
new file mode 100644
index 00000000..a9a3c0a0
--- /dev/null
+++ b/cpp/017and-record
@@ -0,0 +1,27 @@
+// Support for records.
+:(before "End Mu Types")
+// We'll use this record as a running example, with two fields: an integer and
+// a boolean.
+int integer_boolean = Type_number["integer-boolean"] = Next_type_number++;
+Type[integer_boolean].size = 2;
+Type[integer_boolean].is_record = true;
+vector<type_number> i;
+i.push_back(integer);
+Type[integer_boolean].elements.push_back(i);
+vector<type_number> b;
+b.push_back(boolean);
+Type[integer_boolean].elements.push_back(b);
+
+// Records can be copied around with a single instruction just like integers,
+// no matter how large they are.
+:(scenario copy_multiple_locations)
+recipe main [
+  1:integer <- copy 34:literal
+  2:boolean <- copy 0:literal
+  3:integer-boolean <- copy 1:integer-boolean
+]
++run: ingredient 0 is 1
++mem: location 1 is 34
++mem: location 2 is 0
++mem: storing in location 3
++mem: storing in location 4