about summary refs log tree commit diff stats
path: root/030container.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-07 15:06:53 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-07 15:29:13 -0700
commit0487a30e7078861ed7de42bdb21b5c71fb9b54a1 (patch)
treef7ccc4040b510403da90477947c1cf07ea91b627 /030container.cc
parent94fa5c95ad9c8beead183bb7c4b88c7c2c7ca6ec (diff)
downloadmu-0487a30e7078861ed7de42bdb21b5c71fb9b54a1.tar.gz
1298 - better ingredient/product handling
All primitives now always write to all their products. If a product is
not used that's fine, but if an instruction seems to expect too many
products mu will complain.

In the process, many primitives can operate on more than two ingredients
where it seems intuitive. You can add or divide more than two numbers
together, copy or negate multiple corresponding locations, etc.

There's one remaining bit of ugliness. Some instructions like
get/get-address, index/index-address, wait-for-location, these can
unnecessarily load values from memory when they don't need to.

Useful vim commands:
  %s/ingredients\[\([^\]]*\)\]/ingredients.at(\1)/gc
  %s/products\[\([^\]]*\)\]/products.at(\1)/gc
  .,$s/\[\(.\)]/.at(\1)/gc
Diffstat (limited to '030container.cc')
-rw-r--r--030container.cc82
1 files changed, 52 insertions, 30 deletions
diff --git a/030container.cc b/030container.cc
index 9de3aad7..071e3ea5 100644
--- a/030container.cc
+++ b/030container.cc
@@ -11,9 +11,10 @@ i.push_back(integer);
 Type[point].elements.push_back(i);
 Type[point].elements.push_back(i);
 
+//: Containers can be copied around with a single instruction just like
+//: integers, no matter how large they are.
+
 :(scenario copy_multiple_locations)
-# Containers can be copied around with a single instruction just like integers,
-# no matter how large they are.
 recipe main [
   1:integer <- copy 34:literal
   2:integer <- copy 35:literal
@@ -48,13 +49,40 @@ recipe main [
 ]
 +mem: storing 36 in location 17
 
+//: Containers can be checked for equality with a single instruction just like
+//: integers, no matter how large they are.
+
+:(scenario compare_multiple_locations)
+recipe main [
+  1:integer <- copy 34:literal  # first
+  2:integer <- copy 35:literal
+  3:integer <- copy 36:literal
+  4:integer <- copy 34:literal  # second
+  5:integer <- copy 35:literal
+  6:integer <- copy 36:literal
+  7:boolean <- equal 1:point-integer, 4:point-integer
+]
++mem: storing 1 in location 7
+
+:(scenario compare_multiple_locations2)
+recipe main [
+  1:integer <- copy 34:literal  # first
+  2:integer <- copy 35:literal
+  3:integer <- copy 36:literal
+  4:integer <- copy 34:literal  # second
+  5:integer <- copy 35:literal
+  6:integer <- copy 37:literal  # different
+  7:boolean <- equal 1:point-integer, 4:point-integer
+]
++mem: storing 0 in location 7
+
 :(before "End size_of(types) Cases")
-type_info t = Type[types[0]];
+type_info t = Type[types.at(0)];
 if (t.kind == container) {
   // size of a container is the sum of the sizes of its elements
   size_t result = 0;
   for (index_t i = 0; i < t.elements.size(); ++i) {
-    result += size_of(t.elements[i]);
+    result += size_of(t.elements.at(i));
   }
   return result;
 }
@@ -72,7 +100,7 @@ recipe main [
 +run: address to copy is 13
 +run: its type is 1
 +mem: location 13 is 35
-+run: product 0 is 35
++run: product 0 is 15
 +mem: storing 35 in location 15
 
 :(before "End Primitive Recipe Declarations")
@@ -81,29 +109,26 @@ GET,
 Recipe_number["get"] = GET;
 :(before "End Primitive Recipe Implementations")
 case GET: {
-  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
-  reagent base = current_instruction().ingredients[0];
+  reagent base = current_instruction().ingredients.at(0);
   index_t base_address = base.value;
-  type_number base_type = base.types[0];
+  type_number base_type = base.types.at(0);
   assert(Type[base_type].kind == container);
-  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
-  assert(isa_literal(current_instruction().ingredients[1]));
-  index_t offset = current_instruction().ingredients[1].value;
+  assert(isa_literal(current_instruction().ingredients.at(1)));
+  assert(ingredients.at(1).size() == 1);  // scalar
+  index_t offset = ingredients.at(1).at(0);
   index_t src = base_address;
   for (index_t i = 0; i < offset; ++i) {
-    src += size_of(Type[base_type].elements[i]);
+    src += size_of(Type[base_type].elements.at(i));
   }
   trace("run") << "address to copy is " << src;
   assert(Type[base_type].kind == container);
   assert(Type[base_type].elements.size() > offset);
-  type_number src_type = Type[base_type].elements[offset][0];
+  type_number src_type = Type[base_type].elements[offset].at(0);
   trace("run") << "its type is " << src_type;
   reagent tmp;
   tmp.set_value(src);
   tmp.types.push_back(src_type);
-  vector<long long int> result(read_memory(tmp));
-  trace("run") << "product 0 is " << result[0];
-  write_memory(current_instruction().products[0], result);
+  products.push_back(read_memory(tmp));
   break;
 }
 
@@ -125,7 +150,7 @@ recipe main [
 +run: address to copy is 14
 +run: its type is 1
 +mem: location 14 is 36
-+run: product 0 is 36
++run: product 0 is 15
 +mem: storing 36 in location 15
 
 //:: To write to elements of containers, you need their address.
@@ -148,22 +173,19 @@ GET_ADDRESS,
 Recipe_number["get-address"] = GET_ADDRESS;
 :(before "End Primitive Recipe Implementations")
 case GET_ADDRESS: {
-  trace("run") << "ingredient 0 is " << current_instruction().ingredients[0].name;
-  reagent base = current_instruction().ingredients[0];
+  reagent base = current_instruction().ingredients.at(0);
   index_t base_address = base.value;
-  type_number base_type = base.types[0];
+  type_number base_type = base.types.at(0);
   assert(Type[base_type].kind == container);
-  trace("run") << "ingredient 1 is " << current_instruction().ingredients[1].name;
-  assert(isa_literal(current_instruction().ingredients[1]));
-  index_t offset = current_instruction().ingredients[1].value;
-  index_t src = base_address;
+  assert(isa_literal(current_instruction().ingredients.at(1)));
+  assert(ingredients.at(1).size() == 1);  // scalar
+  index_t offset = ingredients.at(1).at(0);
+  index_t result = base_address;
   for (index_t i = 0; i < offset; ++i) {
-    src += size_of(Type[base_type].elements[i]);
+    result += size_of(Type[base_type].elements.at(i));
   }
-  trace("run") << "address to copy is " << src;
-  vector<long long int> result;
-  result.push_back(src);
-  trace("run") << "product 0 is " << result[0];
-  write_memory(current_instruction().products[0], result);
+  trace("run") << "address to copy is " << result;
+  products.resize(1);
+  products.at(0).push_back(result);
   break;
 }