about summary refs log tree commit diff stats
path: root/cpp
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 /cpp
parent9dc2948276388d2ca6556f4a8d13d55406775ac7 (diff)
downloadmu-b291f85b8d0ece9312b066a84cbeca1b367fe85f.tar.gz
798 - start of record support
Diffstat (limited to 'cpp')
-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
href='#n380'>380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442