From 93d4cc937ee480952cb93f21e5a04a96296c8302 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Thu, 10 Nov 2016 21:39:02 -0800 Subject: 3663 - fix a refcounting bug: '(type)' != 'type' This was a large commit, and most of it is a follow-up to commit 3309, undoing what is probably the final ill-considered optimization I added to s-expressions in Mu: I was always representing (a b c) as (a b . c), etc. That is now gone. Why did I need to take it out? The key problem was the error silently ignored in layer 30. That was causing size_of("(type)") to silently return garbage rather than loudly complain (assuming 'type' was a simple type). But to take it out I had to modify types_strictly_match (layer 21) to actually strictly match and not just do a prefix match. In the process of removing the prefix match, I had to make extracting recipe types from recipe headers more robust. So far it only matched the first element of each ingredient's type; these matched: (recipe address:number -> address:number) (recipe address -> address) I didn't notice because the dotted notation optimization was actually representing this as: (recipe address:number -> address number) --- One final little thing in this commit: I added an alias for 'assert' called 'assert_for_now', to indicate that I'm not sure something's really an invariant, that it might be triggered by (invalid) user programs, and so require more thought on error handling down the road. But this may well be an ill-posed distinction. It may be overwhelmingly uneconomic to continually distinguish between model invariants and error states for input. I'm starting to grow sympathetic to Google Analytics's recent approach of just banning assertions altogether. We'll see.. --- 032array.cc | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to '032array.cc') diff --git a/032array.cc b/032array.cc index 4e233bff..b586f930 100644 --- a/032array.cc +++ b/032array.cc @@ -98,6 +98,10 @@ def main [ ] +app: foo: 3 14 15 16 +:(before "End types_coercible Special-cases") +if (is_mu_array(from) && is_mu_array(to)) + return types_strictly_match(array_element(from.type), array_element(to.type)); + :(before "End size_of(reagent r) Special-cases") if (!r.type->atom && r.type->left->atom && r.type->left->value == get(Type_ordinal, "array")) { if (!r.type->right) { @@ -111,10 +115,10 @@ if (!r.type->atom && r.type->left->atom && r.type->left->value == get(Type_ordin if (type->left->value == get(Type_ordinal, "array")) return static_array_length(type); :(code) int static_array_length(const type_tree* type) { - if (!type->atom && !type->right->atom && type->right->right->atom // exactly 3 types - && is_integer(type->right->right->name)) { // third 'type' is a number + if (!type->atom && type->right && !type->right->atom && type->right->right && !type->right->right->atom && !type->right->right->right // exactly 3 types + && type->right->right->left && type->right->right->left->atom && is_integer(type->right->right->left->name)) { // third 'type' is a number // get size from type - return to_integer(type->right->right->name); + return to_integer(type->right->right->left->name); } cerr << to_string(type) << '\n'; assert(false); @@ -159,7 +163,7 @@ container foo [ raise << "container '" << name << "' doesn't specify type of array elements for '" << info.elements.back().name << "'\n" << end(); continue; } - if (type->right->atom) { // array has no length + if (!type->right->right || !is_integer(type->right->right->left->name)) { // array has no length raise << "container '" << name << "' cannot determine size of element '" << info.elements.back().name << "'\n" << end(); continue; } @@ -365,20 +369,29 @@ type_tree* copy_array_element(const type_tree* type) { type_tree* array_element(const type_tree* type) { assert(type->right); - // hack: don't require parens for either array:num:3 array:address:num - if (!type->right->atom && type->right->right && type->right->right->atom && is_integer(type->right->right->name)) + if (type->right->atom) { + return type->right; + } + else if (!type->right->right) { + return type->right->left; + } + // hack: support array:num:3 without requiring extra parens + else if (type->right->right->left && type->right->right->left->atom && is_integer(type->right->right->left->name)) { + assert(!type->right->right->right); return type->right->left; + } return type->right; } int array_length(const reagent& x) { // x should already be canonized. - if (!x.type->atom && !x.type->right->atom && x.type->right->right->atom // exactly 3 types - && is_integer(x.type->right->right->name)) { // third 'type' is a number + // hack: look for length in type + if (!x.type->atom && x.type->right && !x.type->right->atom && x.type->right->right && !x.type->right->right->atom && !x.type->right->right->right // exactly 3 types + && x.type->right->right->left && x.type->right->right->left->atom && is_integer(x.type->right->right->left->name)) { // third 'type' is a number // get size from type - return to_integer(x.type->right->right->name); + return to_integer(x.type->right->right->left->name); } - // we should never get here at transform time + // this should never happen at transform time return get_or_insert(Memory, x.value); } @@ -393,6 +406,11 @@ void test_array_length_compound() { CHECK_EQ(array_length(x), 3); } +void test_array_length_static() { + reagent x("1:array:num:3"); + CHECK_EQ(array_length(x), 3); +} + :(scenario index_truncates) def main [ 1:array:num:3 <- create-array -- cgit 1.4.1-2-gfad0