about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--010vm.cc4
-rw-r--r--030container.cc4
-rw-r--r--032array.cc102
3 files changed, 84 insertions, 26 deletions
diff --git a/010vm.cc b/010vm.cc
index 41a63e2c..c9bfaa5d 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -196,7 +196,9 @@ reagent::reagent(string s) :original_string(s), value(0), initialized(false) {
   name = properties.at(0).first;
   for (long long int i = 0; i < SIZE(properties.at(0).second); ++i) {
     string type = properties.at(0).second.at(i);
-    if (Type_ordinal.find(type) == Type_ordinal.end()) {
+    if (Type_ordinal.find(type) == Type_ordinal.end()
+        // types can contain integers, like for array sizes
+        && !is_integer(type)) {
 //?       cerr << type << " is " << Next_type_ordinal << '\n'; //? 1
       Type_ordinal[type] = Next_type_ordinal++;
     }
diff --git a/030container.cc b/030container.cc
index ac198929..808b64fe 100644
--- a/030container.cc
+++ b/030container.cc
@@ -325,7 +325,9 @@ void insert_container(const string& command, kind_of_type kind, istream& in) {
     vector<type_ordinal> types;
     while (!inner.eof()) {
       string type_name = slurp_until(inner, ':');
-      if (Type_ordinal.find(type_name) == Type_ordinal.end()) {
+      if (Type_ordinal.find(type_name) == Type_ordinal.end()
+          // types can contain integers, like for array sizes
+          && !is_integer(type_name)) {
 //?         cerr << type_name << " is " << Next_type_ordinal << '\n'; //? 1
         Type_ordinal[type_name] = Next_type_ordinal++;
       }
diff --git a/032array.cc b/032array.cc
index 412f6878..173b773b 100644
--- a/032array.cc
+++ b/032array.cc
@@ -5,18 +5,72 @@
 //: elements of a fixed size, so you can't create containers containing arrays.
 //: Create containers containing addresses to arrays instead.
 
-//: Tests in this layer often explicitly setup memory before reading it as an
-//: array. Don't do this in general. I'm tagging exceptions with /raw to
-//: avoid warnings.
+//: You can create arrays using 'create-array'.
+:(scenario create_array)
+recipe main [
+  # create an array occupying locations 1 (for the size) and 2-4 (for the elements)
+  1:array:number:3 <- create-array
+  # write to it
+  2:number <- copy 34
+  3:number <- copy 35
+  4:number <- copy 36
+  reply 1:array:number:3
+]
++run: creating array of size 4
+
+:(before "End Primitive Recipe Declarations")
+CREATE_ARRAY,
+:(before "End Primitive Recipe Numbers")
+Recipe_ordinal["create-array"] = CREATE_ARRAY;
+:(before "End Primitive Recipe Implementations")
+case CREATE_ARRAY: {
+  if (current_instruction().products.empty()) {
+    raise << current_recipe_name () << ": 'create-array' needs one product and no ingredients but got '" << current_instruction().to_string() << '\n' << end();
+    break;
+  }
+  reagent product = canonize(current_instruction().products.at(0));
+  if (!is_mu_array(product)) {
+    raise << current_recipe_name () << ": 'create-array' cannot create non-array " << product.original_string << '\n' << end();
+    break;
+  }
+  long long int base_address = product.value;
+  if (SIZE(product.types) == 1) {
+    raise << current_recipe_name () << ": create array of what? " << current_instruction().to_string() << '\n' << end();
+    break;
+  }
+  // 'create-array' will need to check properties rather than types
+  if (SIZE(product.properties.at(0).second) <= 2) {
+    raise << current_recipe_name () << ": create array of what size? " << current_instruction().to_string() << '\n' << end();
+    break;
+  }
+  if (!is_integer(product.properties.at(0).second.at(2))) {
+    raise << current_recipe_name () << ": 'create-array' product should specify size of array after its element type, but got " << product.properties.at(0).second.at(2) << '\n' << end();
+    break;
+  }
+  long long int array_size= to_integer(product.properties.at(0).second.at(2));
+  // initialize array size, so that size_of will work
+  Memory[base_address] = array_size;  // in array elements
+  long long int size = size_of(product);  // in locations
+  trace("run") << "creating array of size " << size << '\n' << end();
+  // initialize array
+  for (long long int i = 1; i <= size_of(product); ++i) {
+    Memory[base_address+i] = 0;
+  }
+  // dummy product; doesn't actually do anything
+  products.resize(1);
+  products.at(0).push_back(array_size);
+  break;
+}
+
 :(scenario copy_array)
 # Arrays can be copied around with a single instruction just like numbers,
 # no matter how large they are.
 recipe main [
-  1:number <- copy 3  # length
+  1:array:number:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
-  5:array:number <- copy 1:array:number/raw  # unsafe
+  5:array:number <- copy 1:array:number:3
 ]
 +mem: storing 3 in location 5
 +mem: storing 14 in location 6
@@ -25,11 +79,11 @@ recipe main [
 
 :(scenario copy_array_indirect)
 recipe main [
-  1:number <- copy 3  # length
+  1:array:number:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
-  5:address:array:number <- copy 1
+  5:address:array:number <- copy 1  # unsafe
   6:array:number <- copy *5:address:array:number
 ]
 +mem: storing 3 in location 6
@@ -39,11 +93,11 @@ recipe main [
 
 :(scenario stash_array)
 recipe main [
-  1:number <- copy 3  # length
+  1:array:number:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
-  stash [foo: ], 1:array:number
+  stash [foo: ], 1:array:number:3
 ]
 +app: foo: 3 14 15 16
 
@@ -64,22 +118,22 @@ if (r.types.at(0) == Type_ordinal["array"]) {
 
 :(scenario index)
 recipe main [
-  1:number <- copy 3  # length
+  1:array:number:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
-  5:number <- index 1:array:number/raw, 0  # unsafe
+  5:number <- index 1:array:number:3, 0
 ]
 +mem: storing 14 in location 5
 
 :(scenario index_direct_offset)
 recipe main [
-  1:number <- copy 3  # length
+  1:array:number:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
   5:number <- copy 0
-  6:number <- index 1:array:number/raw, 5:number  # unsafe
+  6:number <- index 1:array:number, 5:number
 ]
 +mem: storing 14 in location 6
 
@@ -127,7 +181,7 @@ vector<type_ordinal> array_element(const vector<type_ordinal>& types) {
 
 :(scenario index_indirect)
 recipe main [
-  1:number <- copy 3  # length
+  1:array:number:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
@@ -139,7 +193,7 @@ recipe main [
 :(scenario index_out_of_bounds)
 % Hide_warnings = true;
 recipe main [
-  1:number <- copy 3  # 3 points
+  1:array:number:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
@@ -154,7 +208,7 @@ recipe main [
 :(scenario index_out_of_bounds_2)
 % Hide_warnings = true;
 recipe main [
-  1:number <- copy 3  # 3 points
+  1:array:point:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
@@ -170,11 +224,11 @@ recipe main [
 
 :(scenario index_address)
 recipe main [
-  1:number <- copy 3  # length
+  1:array:number:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
-  5:number <- index-address 1:array:number/raw, 0  # unsafe
+  5:number <- index-address 1:array:number, 0
 ]
 +mem: storing 2 in location 5
 
@@ -214,14 +268,14 @@ case INDEX_ADDRESS: {
 :(scenario index_address_out_of_bounds)
 % Hide_warnings = true;
 recipe main [
-  1:number <- copy 3  # 3 points
+  1:array:point:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
   5:number <- copy 14
   6:number <- copy 15
   7:number <- copy 16
-  8:address:array:point <- copy 1
+  8:address:array:point <- copy 1  # unsafe
   index-address *8:address:array:point, 4  # less than size of array in locations, but larger than its length in elements
 ]
 +warn: main: invalid index 4
@@ -229,14 +283,14 @@ recipe main [
 :(scenario index_address_out_of_bounds_2)
 % Hide_warnings = true;
 recipe main [
-  1:number <- copy 3  # 3 points
+  1:array:point:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
   5:number <- copy 14
   6:number <- copy 15
   7:number <- copy 16
-  8:address:array:point <- copy 1
+  8:address:array:point <- copy 1  # unsafe
   index-address *8:address:array:point, -1
 ]
 +warn: main: invalid index -1
@@ -245,11 +299,11 @@ recipe main [
 
 :(scenario array_length)
 recipe main [
-  1:number <- copy 3  # length
+  1:array:number:3 <- create-array
   2:number <- copy 14
   3:number <- copy 15
   4:number <- copy 16
-  5:number <- length 1:array:number/raw  # unsafe
+  5:number <- length 1:array:number:3
 ]
 +mem: storing 3 in location 5