about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-04-13 09:03:06 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-04-13 09:03:06 -0700
commitb8348923fbc89c4cf7ec71c187b729fc0fa42d46 (patch)
tree19a7f8d830e7fe1323557420435b570f7413fbe7
parent80411d01a3a31a8a08819b3d415811f746baab3a (diff)
downloadmu-b8348923fbc89c4cf7ec71c187b729fc0fa42d46.tar.gz
2831 - bugfix in static arrays
I'd started using size_of() in transforms at some point, but not gotten
around to actually updating it to support arrays before run-time. Wish
there was a way I could statically enforce that something is only called
at transform time vs runtime.

Thanks Ella and Caleb Couch for finding this issue. Static arrays are
likely still half-baked, but should get a thorough working-over in
coming weeks.
-rw-r--r--032array.cc33
-rw-r--r--042name.cc18
2 files changed, 41 insertions, 10 deletions
diff --git a/032array.cc b/032array.cc
index 0fd1d0a4..bd28fef3 100644
--- a/032array.cc
+++ b/032array.cc
@@ -49,24 +49,26 @@ case CREATE_ARRAY: {
   reagent product = current_instruction().products.at(0);
   canonize(product);
   int base_address = product.value;
-  int array_size = to_integer(product.type->right->right->name);
+  int array_length = to_integer(product.type->right->right->name);
   // initialize array size, so that size_of will work
-  put(Memory, base_address, array_size);  // in array elements
+  put(Memory, base_address, array_length);  // in array elements
   int size = size_of(product);  // in locations
   trace(9998, "run") << "creating array of size " << size << '\n' << end();
   // initialize array
   for (int i = 1; i <= size_of(product); ++i) {
     put(Memory, base_address+i, 0);
   }
-  // dummy product; doesn't actually do anything
-  products.resize(1);
-  products.at(0).push_back(array_size);
-  break;
+  // no need to update product
+  goto finish_instruction;
 }
 
 :(scenario copy_array)
 # Arrays can be copied around with a single instruction just like numbers,
 # no matter how large they are.
+# You don't need to pass the size around, since each array variable stores its
+# size in memory at run-time. We'll call a variable with an explicit size a
+# 'static' array, and one without a 'dynamic' array since it can contain
+# arrays of many different sizes.
 def main [
   1:array:number:3 <- create-array
   2:number <- copy 14
@@ -103,18 +105,20 @@ def main [
 ]
 +app: foo: 3 14 15 16
 
-//: disable the size mismatch check since the destination array need not be initialized
-:(before "End size_mismatch(x) Cases")
-if (x.type && x.type->value == get(Type_ordinal, "array")) return false;
 :(before "End size_of(reagent) Cases")
 if (r.type && r.type->value == get(Type_ordinal, "array")) {
   if (!r.type->right) {
     raise << maybe(current_recipe_name()) << "'" << r.original_string << "' is an array of what?\n" << end();
     return 1;
   }
-  return 1 + get_or_insert(Memory, r.value)*size_of(array_element(r.type));
+  return 1 + array_length(r)*size_of(array_element(r.type));
 }
 
+//: disable the size mismatch check for arrays since the destination array
+//: need not be initialized
+:(before "End size_mismatch(x) Cases")
+if (x.type && x.type->value == get(Type_ordinal, "array")) return false;
+
 //: arrays are disallowed inside containers unless their length is fixed in
 //: advance
 
@@ -233,6 +237,15 @@ type_tree* array_element(const type_tree* type) {
   return type->right;
 }
 
+int array_length(const reagent& x) {
+  if (x.type->right->right) {
+    return to_integer(x.type->right->right->name);
+  }
+  // this should never happen at transform time
+  // x should already be canonized.
+  return get_or_insert(Memory, x.value);
+}
+
 :(scenario index_indirect)
 def main [
   1:array:number:3 <- create-array
diff --git a/042name.cc b/042name.cc
index d0d114fb..ade9c069 100644
--- a/042name.cc
+++ b/042name.cc
@@ -149,6 +149,24 @@ bool is_special_name(const string& s) {
   return false;
 }
 
+:(scenario transform_names_supports_containers)
+def main [
+  x:point <- merge 34, 35
+  y:number <- copy 3
+]
++name: assign x 1
+# skip location 2 because x occupies two locations
++name: assign y 3
+
+:(scenario transform_names_supports_static_arrays)
+def main [
+  x:array:number:3 <- create-array
+  y:number <- copy 3
+]
++name: assign x 1
+# skip locations 2, 3, 4 because x occupies four locations
++name: assign y 5
+
 :(scenario transform_names_passes_dummy)
 # _ is just a dummy result that never gets consumed
 def main [