From 0edd9b9fc60440213e4df926ea511419ee291f1e Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 15 Jun 2018 22:12:03 -0700 Subject: 4257 - abortive attempt at safe fat pointers I've been working on this slowly over several weeks, but it's too hard to support 0 as the null value for addresses. I constantly have to add exceptions for scalar value corresponding to an address type (now occupying 2 locations). The final straw is the test for 'reload': x:num <- reload text 'reload' returns an address. But there's no way to know that for arbitrary instructions. New plan: let's put this off for a bit and first create support for literals. Then use 'null' instead of '0' for addresses everywhere. Then it'll be easy to just change what 'null' means. --- 038new_text.cc | 72 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 30 deletions(-) (limited to '038new_text.cc') diff --git a/038new_text.cc b/038new_text.cc index 4b666f1c..b2a5db75 100644 --- a/038new_text.cc +++ b/038new_text.cc @@ -4,23 +4,25 @@ :(before "End Mu Types Initialization") put(Type_abbreviations, "text", new_type_tree("address:array:character")); -:(scenario new_string) +:(scenario new_text) def main [ 1:text <- new [abc def] - 2:char <- index *1:text, 5 + # location 2 is part of 1:text + 3:char <- index *1:text, 5 ] # number code for 'e' -+mem: storing 101 in location 2 ++mem: storing 101 in location 3 -:(scenario new_string_handles_unicode) +:(scenario new_text_handles_unicode) def main [ 1:text <- new [a«c] - 2:num <- length *1:text - 3:char <- index *1:text, 1 + # location 2 is part of 1:text + 3:num <- length *1:text + 4:char <- index *1:text, 1 ] -+mem: storing 3 in location 2 ++mem: storing 3 in location 3 # unicode for '«' -+mem: storing 171 in location 3 ++mem: storing 171 in location 4 :(before "End NEW Check Special-cases") if (is_literal_text(inst.ingredients.at(0))) break; @@ -29,6 +31,7 @@ if (inst.name == "new" && !inst.ingredients.empty() && is_literal_text(inst.ingr :(after "case NEW" following "Primitive Recipe Implementations") if (is_literal_text(current_instruction().ingredients.at(0))) { products.resize(1); + products.at(0).push_back(/*alloc id*/0); products.at(0).push_back(new_mu_text(current_instruction().ingredients.at(0).name)); trace("mem") << "new string alloc: " << products.at(0).at(0) << end(); break; @@ -40,8 +43,9 @@ int new_mu_text(const string& contents) { int string_length = unicode_length(contents); //? Total_alloc += string_length+1; //? ++Num_alloc; - int result = allocate(string_length+/*array length*/1); + int result = allocate(/*array length*/1 + string_length); int curr_address = result; + ++curr_address; // skip alloc id trace("mem") << "storing string length " << string_length << " in location " << curr_address << end(); put(Memory, curr_address, string_length); ++curr_address; // skip length @@ -62,16 +66,16 @@ int new_mu_text(const string& contents) { //: a new kind of typo -:(scenario string_literal_without_instruction) +:(scenario literal_text_without_instruction) % Hide_errors = true; def main [ [abc] ] +error: main: instruction '[abc]' has no recipe in '[abc]' -//: stash recognizes strings +//: stash recognizes texts -:(scenario stash_string) +:(scenario stash_text) def main [ 1:text <- new [abc] stash [foo:], 1:text @@ -80,30 +84,29 @@ def main [ :(before "End inspect Special-cases(r, data)") if (is_mu_text(r)) { - assert(scalar(data)); - return read_mu_text(data.at(0)); + return read_mu_text(data.at(/*skip alloc id*/1)); } :(before "End $print Special-cases") else if (is_mu_text(current_instruction().ingredients.at(i))) { - cout << read_mu_text(ingredients.at(i).at(0)); + cout << read_mu_text(ingredients.at(i).at(/*skip alloc id*/1)); } -:(scenario unicode_string) +:(scenario unicode_text) def main [ 1:text <- new [♠] stash [foo:], 1:text ] +app: foo: ♠ -:(scenario stash_space_after_string) +:(scenario stash_space_after_text) def main [ 1:text <- new [abc] stash 1:text, [foo] ] +app: abc foo -:(scenario stash_string_as_array) +:(scenario stash_text_as_array) def main [ 1:text <- new [abc] stash *1:text @@ -114,15 +117,16 @@ def main [ :(before "End Preprocess is_mu_text(reagent x)") if (!canonize_type(x)) return false; -//: Allocate more to routine when initializing a literal string -:(scenario new_string_overflow) -% Initial_memory_per_routine = 2; +//: Allocate more to routine when initializing a literal text +:(scenario new_text_overflow) +% Initial_memory_per_routine = 3; def main [ 1:address:num/raw <- new number:type - 2:text/raw <- new [a] # not enough room in initial page, if you take the array length into account + # location 2 is part of 1:address + 3:text/raw <- new [a] # not enough room in initial page, if you take the array length into account ] -+new: routine allocated memory from 1000 to 1002 -+new: routine allocated memory from 1002 to 1004 ++new: routine allocated memory from 1000 to 1003 ++new: routine allocated memory from 1003 to 1006 //: helpers :(code) @@ -140,9 +144,9 @@ int unicode_length(const string& s) { string read_mu_text(int address) { if (address == 0) return ""; - int length = get_or_insert(Memory, address); + int length = get_or_insert(Memory, address+/*alloc id*/1); if (length == 0) return ""; - return read_mu_characters(address+1, length); + return read_mu_characters(address+/*alloc id*/1+/*length*/1, length); } string read_mu_characters(int start, int length) { @@ -156,13 +160,21 @@ string read_mu_characters(int start, int length) { //: assert: perform sanity checks at runtime -:(scenario assert) +:(scenario assert_literal) % Hide_errors = true; // '%' lines insert arbitrary C code into tests before calling 'run' with the lines below. Must be immediately after :(scenario) line. def main [ assert 0, [this is an assert in Mu] ] +error: this is an assert in Mu +:(scenario assert) +% Hide_errors = true; // '%' lines insert arbitrary C code into tests before calling 'run' with the lines below. Must be immediately after :(scenario) line. +def main [ + 1:text <- new [this is an assert in Mu] + assert 0, 1:text +] ++error: this is an assert in Mu + :(before "End Primitive Recipe Declarations") ASSERT, :(before "End Primitive Recipe Numbers") @@ -173,7 +185,7 @@ case ASSERT: { raise << maybe(get(Recipe, r).name) << "'assert' takes exactly two ingredients rather than '" << to_original_string(inst) << "'\n" << end(); break; } - if (!is_mu_scalar(inst.ingredients.at(0))) { + if (!is_mu_address(inst.ingredients.at(0)) && !is_mu_scalar(inst.ingredients.at(0))) { raise << maybe(get(Recipe, r).name) << "'assert' requires a boolean for its first ingredient, but got '" << inst.ingredients.at(0).original_string << "'\n" << end(); break; } @@ -185,11 +197,11 @@ case ASSERT: { } :(before "End Primitive Recipe Implementations") case ASSERT: { - if (!ingredients.at(0).at(0)) { + if (!scalar_ingredient(ingredients, 0)) { if (is_literal_text(current_instruction().ingredients.at(1))) raise << current_instruction().ingredients.at(1).name << '\n' << end(); else - raise << read_mu_text(ingredients.at(1).at(0)) << '\n' << end(); + raise << read_mu_text(ingredients.at(1).at(/*skip alloc id*/1)) << '\n' << end(); if (!Hide_errors) exit(1); } break; -- cgit 1.4.1-2-gfad0