about summary refs log tree commit diff stats
path: root/038new.cc
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 /038new.cc
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.
Diffstat (limited to '038new.cc')
-rw-r--r--038new.cc33
1 files changed, 29 insertions, 4 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