about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-01-19 18:46:39 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-01-19 18:46:39 -0800
commitbb33c5e89993338f6e554210e87b27a5220ead98 (patch)
tree59cab2622fa19c0aa0f625c989145dfa59d2b1dc
parent5002169370c854b6f532b420225b80e7ef18d6ad (diff)
downloadmu-bb33c5e89993338f6e554210e87b27a5220ead98.tar.gz
2573 - check product type of 'new'
I realize that my current doesn't allow nesting a:b:c linear type syntax
inside a dilated property. So you can't currently say:

  (recipe address:number)

Need to fix that at some point. Non-trivial since linear syntax is
oblivious to dilated syntax. I should probably make the dilated syntax
more fundamental and introduce it at an earlier layer.
-rw-r--r--038new.cc33
-rw-r--r--055parse_tree.cc9
-rw-r--r--070text.mu4
-rw-r--r--chessboard.mu2
4 files changed, 38 insertions, 10 deletions
diff --git a/038new.cc b/038new.cc
index 33902c3a..21273cfa 100644
--- a/038new.cc
+++ b/038new.cc
@@ -35,14 +35,39 @@ NEW,
 put(Recipe_ordinal, "new", NEW);
 :(before "End Primitive Recipe Checks")
 case NEW: {
+  const recipe& caller = get(Recipe, r);
   if (inst.ingredients.empty() || SIZE(inst.ingredients) > 2) {
-    raise_error << maybe(get(Recipe, r).name) << "'new' requires one or two ingredients, but got " << inst.to_string() << '\n' << end();
+    raise_error << maybe(caller.name) << "'new' requires one or two ingredients, but got " << inst.to_string() << '\n' << end();
     break;
   }
   // End NEW Check Special-cases
   reagent type = inst.ingredients.at(0);
   if (!is_mu_type_literal(type)) {
-    raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'new' should be a type, but got " << type.original_string << '\n' << end();
+    raise_error << maybe(caller.name) << "first ingredient of 'new' should be a type, but got " << type.original_string << '\n' << end();
+    break;
+  }
+  if (inst.products.empty()) {
+    raise_error << maybe(caller.name) << "result of 'new' should never be ignored\n" << end();
+    break;
+  }
+  reagent product(inst.products.at(0));
+  canonize_type(product);
+  drop_address_from_type(product);
+  if (SIZE(inst.ingredients) > 1) {
+    // array allocation, so drop an 'array' as well from product.type
+    type_tree* tmp = product.type;
+    if (tmp->value != get(Type_ordinal, "array")) {
+      raise_error << maybe(caller.name) << "result of 'new' should start with 'address:array:...' in " << inst.to_string() << '\n' << end();
+      break;
+    }
+    product.type = tmp->right;
+    tmp->right = NULL;
+    delete tmp;
+  }
+  reagent expected_product("x:"+type.name);
+  // End Post-processing(expected_product) When Checking 'new'
+  if (!types_strictly_match(product, expected_product)) {
+    raise_error << maybe(caller.name) << "product of 'new' has incorrect type: " << inst.to_string() << '\n' << end();
     break;
   }
   break;
@@ -277,8 +302,8 @@ if (Free_list[size]) {
 recipe main [
   1:address:number <- new number:type
   abandon 1:address:number
-  2:address:number <- new number:type, 2  # different size
-  3:boolean <- equal 1:address:number, 2:address:number
+  2:address:array:number <- new number:type, 2  # different size
+  3:boolean <- equal 1:address:number, 2:address:array:number
 ]
 # no reuse
 +mem: storing 0 in location 3
diff --git a/055parse_tree.cc b/055parse_tree.cc
index 33537344..947093b9 100644
--- a/055parse_tree.cc
+++ b/055parse_tree.cc
@@ -71,10 +71,13 @@ container bar [
 
 :(scenario dilated_reagent_with_new)
 recipe main [
-  x:address:number <- new {(foo bar): type}
+  x:address:address:number <- new {(address number): type}
 ]
-# type isn't defined so size is meaningless, but at least we parse the type correctly
-+new: size of <"foo" : <"bar" : <>>> is 1
++new: size of <"address" : <"number" : <>>> is 1
 
+:(before "End Post-processing(expected_product) When Checking 'new'")
+expected_product.properties.at(0).second = parse_string_tree(expected_product.properties.at(0).second);
+delete expected_product.type;
+expected_product.type = new_type_tree(expected_product.properties.at(0).second);
 :(before "End Post-processing(type_name) When Converting 'new'")
 type_name = parse_string_tree(type_name);
diff --git a/070text.mu b/070text.mu
index 930b4587..37acdfd5 100644
--- a/070text.mu
+++ b/070text.mu
@@ -1080,7 +1080,7 @@ recipe split s:address:array:character, delim:character -> result:address:array:
   {
     empty?:boolean <- equal len, 0
     break-unless empty?
-    result <- new location:type, 0
+    result <- new {(address array character): type}, 0
     reply
   }
   # count #pieces we need room for
@@ -1095,7 +1095,7 @@ recipe split s:address:array:character, delim:character -> result:address:array:
     loop
   }
   # allocate space
-  result <- new location:type, count
+  result <- new {(address array character): type}, count
   # repeatedly copy slices start..end until delimiter into result[curr-result]
   curr-result:number <- copy 0
   start:number <- copy 0
diff --git a/chessboard.mu b/chessboard.mu
index 3347e253..f1bd8853 100644
--- a/chessboard.mu
+++ b/chessboard.mu
@@ -116,7 +116,7 @@ recipe new-board initial-position:address:array:character -> board:address:array
   correct-length?:boolean <- equal len, 64
   assert correct-length?, [chessboard had incorrect size]
   # board is an array of pointers to files; file is an array of characters
-  board <- new location:type, 8
+  board <- new {(address array character): type}, 8
   col:number <- copy 0
   {
     done?:boolean <- equal col, 8