From b75d9d456cb36ad41ab735586473adbbf3444643 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Thu, 15 Sep 2016 13:46:13 -0700 Subject: 3365 - create strings out of arbitrary types The implementation is quite hacky. Let's see how future needs develop before we try to clean it up. --- 059to_text.mu | 17 +++++++++++++++++ 061text.mu | 29 ++++++++++++++++++++++++++++- 062convert_ingredients_to_text.cc | 29 +++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/059to_text.mu b/059to_text.mu index 207ade78..30761eb9 100644 --- a/059to_text.mu +++ b/059to_text.mu @@ -29,3 +29,20 @@ scenario array-to-text-line-early-warning-for-static-dispatch [ x:text <- array-to-text-line n # just ensure there were no errors ] + +# finally, a specialization for single characters +def to-text c:character -> y:text [ + local-scope + load-ingredients + y <- new character:type, 1/capacity + *y <- put-index *y, 0, c +] + +scenario character-to-text [ + 1:character <- copy 111/o + 2:text <- to-text 1:character + 3:array:character <- copy *2:text + memory-should-contain [ + 3:array:character <- [o] + ] +] diff --git a/061text.mu b/061text.mu index a5b653ec..6961199e 100644 --- a/061text.mu +++ b/061text.mu @@ -299,10 +299,24 @@ def buffer-to-array in:address:buffer -> result:text [ } ] -def append -> result:text [ +# Append any number of texts together. +# A later layer also translates calls to this to implicitly call to-text, so +# append to string becomes effectively dynamically typed. +# +# Beware though: this hack restricts how much 'append' can be overridden. Any +# new variants that match: +# append _:text, ___ +# will never ever get used. +def append first:text -> result:text [ local-scope load-ingredients buf:address:buffer <- new-buffer 30 + # append first ingredient + { + break-unless first + buf <- append buf, first + } + # append remaining ingredients { arg:text, arg-found?:boolean <- next-ingredient break-unless arg-found? @@ -366,6 +380,19 @@ scenario text-append-multiary [ ] ] +scenario text-append-multiary-heterogeneous-types [ + run [ + local-scope + n:number <- copy 34 + c:character <- copy 111/o + z:text <- append [abc ], n, c + 10:array:character/raw <- copy *z + ] + memory-should-contain [ + 10:array:character <- [abc 34o] + ] +] + scenario replace-character-in-text [ run [ local-scope diff --git a/062convert_ingredients_to_text.cc b/062convert_ingredients_to_text.cc index bdba51d2..eb5fbd22 100644 --- a/062convert_ingredients_to_text.cc +++ b/062convert_ingredients_to_text.cc @@ -60,6 +60,7 @@ Transform.push_back(convert_ingredients_to_text); void convert_ingredients_to_text(recipe_ordinal r) { recipe& caller = get(Recipe, r); trace(9991, "transform") << "--- convert some ingredients to text in recipe " << caller.name << end(); +//? cerr << "--- convert some ingredients to text in recipe " << caller.name << '\n'; // in recipes without named locations, 'stash' is still not extensible if (contains_numeric_locations(caller)) return; convert_ingredients_to_text(caller); @@ -69,8 +70,10 @@ void convert_ingredients_to_text(recipe& caller) { vector new_instructions; for (int i = 0; i < SIZE(caller.steps); ++i) { instruction& inst = caller.steps.at(i); + // all these cases are getting hairy. how can we make this extensible? if (inst.name == "stash") { for (int j = 0; j < SIZE(inst.ingredients); ++j) { + if (is_literal_string(inst.ingredients.at(j))) continue; ostringstream ingredient_name; ingredient_name << "stash_" << i << '_' << j << ":address:array:character"; convert_ingredient_to_text(inst.ingredients.at(j), new_instructions, ingredient_name.str()); @@ -78,11 +81,26 @@ void convert_ingredients_to_text(recipe& caller) { } else if (inst.name == "trace") { for (int j = /*skip*/2; j < SIZE(inst.ingredients); ++j) { + if (is_literal_string(inst.ingredients.at(j))) continue; ostringstream ingredient_name; ingredient_name << "trace_" << i << '_' << j << ":address:array:character"; convert_ingredient_to_text(inst.ingredients.at(j), new_instructions, ingredient_name.str()); } } + else if (inst.old_name == "append") { + // override only variants that try to append to a string + // Beware: this hack restricts how much 'append' can be overridden. Any + // new variants that match: + // append _:text, ___ + // will never ever get used. + if (is_literal_string(inst.ingredients.at(0)) || is_mu_string(inst.ingredients.at(0))) { + for (int j = 0; j < SIZE(inst.ingredients); ++j) { + ostringstream ingredient_name; + ingredient_name << "append_" << i << '_' << j << ":address:array:character"; + convert_ingredient_to_text(inst.ingredients.at(j), new_instructions, ingredient_name.str()); + } + } + } trace(9993, "transform") << to_string(inst) << end(); new_instructions.push_back(inst); } @@ -93,7 +111,6 @@ void convert_ingredients_to_text(recipe& caller) { // replace r with converted text void convert_ingredient_to_text(reagent& r, vector& out, const string& tmp_var) { if (!r.type) return; // error; will be handled elsewhere - if (is_literal(r)) return; if (is_mu_string(r)) return; // don't try to extend static arrays if (is_static_array(r)) return; @@ -127,10 +144,18 @@ bool is_static_array(const reagent& x) { return !x.type->atom && x.type->left->atom && x.type->left->name == "array"; } +:(scenarios run) +:(scenario append_other_types_to_text) +def main [ + local-scope + a:text <- append [abc], 10, 11 + expected:text <- new [abc1011] + 10:boolean/raw <- equal a, expected +] + //: Make sure that the new system is strictly better than just the 'stash' //: primitive by itself. -:(scenarios run) :(scenario rewrite_stash_continues_to_fall_back_to_default_implementation) # type without a to-text implementation container foo [ -- cgit 1.4.1-2-gfad0