From bb33c5e89993338f6e554210e87b27a5220ead98 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Tue, 19 Jan 2016 18:46:39 -0800 Subject: 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. --- 038new.cc | 33 +++++++++++++++++++++++++++++---- 055parse_tree.cc | 9 ++++++--- 070text.mu | 4 ++-- chessboard.mu | 2 +- 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 -- cgit 1.4.1-2-gfad0