From d2bd40bfcb995fecb947035b0c896342ca22cdd6 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 15 Nov 2015 12:47:48 -0800 Subject: 2447 --- html/010vm.cc.html | 21 +- html/021check_instruction.cc.html | 14 +- html/029tools.cc.html | 1 + html/035call_ingredient.cc.html | 15 +- html/041jump_target.cc.html | 2 +- html/057static_dispatch.cc.html | 22 +- html/058shape_shifting_container.cc.html | 3 +- html/059shape_shifting_recipe.cc.html | 252 +++++++++++++++++++++-- html/073list.mu.html | 11 +- html/075duplex_list.mu.html | 338 ++++++++++++++----------------- html/091run_interactive.cc.html | 3 +- html/edit/001-editor.mu.html | 20 +- html/edit/002-typing.mu.html | 28 +-- html/edit/003-shortcuts.mu.html | 60 +++--- html/edit/005-sandbox.mu.html | 6 +- html/edit/006-sandbox-edit.mu.html | 2 +- html/edit/011-editor-undo.mu.html | 38 ++-- 17 files changed, 523 insertions(+), 313 deletions(-) (limited to 'html') diff --git a/html/010vm.cc.html b/html/010vm.cc.html index 20c502ba..f476aa61 100644 --- a/html/010vm.cc.html +++ b/html/010vm.cc.html @@ -467,11 +467,11 @@ string instruction::to_string() const (const recipe& x) { ostringstream out; - out << "recipe " << x.name << '\n'; + out << "- recipe " << x.name << '\n'; // Begin debug_string(recipe x) for (long long int index = 0; index < SIZE(x.steps); ++index) { const instruction& inst = x.steps.at(index); - out << " inst: " << inst.to_string() << '\n'; + out << "inst: " << inst.to_string() << '\n'; out << " ingredients\n"; for (long long int i = 0; i < SIZE(inst.ingredients); ++i) out << " " << debug_string(inst.ingredients.at(i)) << '\n'; @@ -518,6 +518,23 @@ bool deeply_equal(const string_tree* a(a->right, b->right); } +:(before "End Globals") +set<string> Literal_type_names; +:(before "End One-time Setup") +Literal_type_names.insert("literal"); +Literal_type_names.insert("number"); +Literal_type_names.insert("character"); +:(code) +bool deeply_equal_types(const string_tree* a, const string_tree* b) { + if (!a) return !b; + if (!b) return !a; + if (Literal_type_names.find(a->value) != Literal_type_names.end()) + return Literal_type_names.find(b->value) != Literal_type_names.end(); + return a->value == b->value + && deeply_equal_types(a->left, b->left) + && deeply_equal_types(a->right, b->right); +} + void dump_memory() { for (map<long long int, double>::iterator p = Memory.begin(); p != Memory.end(); ++p) { cout << p->first << ": " << no_scientific(p->second) << '\n'; diff --git a/html/021check_instruction.cc.html b/html/021check_instruction.cc.html index f0238926..e203a386 100644 --- a/html/021check_instruction.cc.html +++ b/html/021check_instruction.cc.html @@ -113,13 +113,19 @@ bool types_match(reagent lhs// to sidestep type-checking, use /raw in the source. // this is unsafe, and will be highlighted in red inside vim. just for some tests. if (is_raw(rhs)) return true; - // allow writing 0 to any address - if (rhs.name == "0" && is_mu_address(lhs)) return true; - if (is_literal(rhs)) return !is_mu_array(lhs) && !is_mu_address(lhs) && size_of(rhs) == size_of(lhs); + if (is_literal(rhs)) return valid_type_for_literal(lhs, rhs) && size_of(rhs) == size_of(lhs); if (!lhs.type) return !rhs.type; return types_match(lhs.type, rhs.type); } +bool valid_type_for_literal(const reagent& lhs, const reagent& literal_rhs) { + if (is_mu_array(lhs)) return false; + // End valid_type_for_literal Special-cases + // allow writing 0 to any address + if (is_mu_address(lhs)) return literal_rhs.name == "0"; + return true; +} + // two types match if the second begins like the first // (trees perform the same check recursively on each subtree) bool types_match(type_tree* lhs, type_tree* rhs) { @@ -129,6 +135,8 @@ bool types_match(type_tree* lhs(lhs->value == get(Type_ordinal, "address")) return false; return size_of(rhs) == size_of(lhs); } + if (lhs->value == get(Type_ordinal, "character") && rhs->value == get(Type_ordinal, "number")) return true; + if (lhs->value == get(Type_ordinal, "number") && rhs->value == get(Type_ordinal, "character")) return true; if (lhs->value != rhs->value) return false; return types_match(lhs->left, rhs->left) && types_match(lhs->right, rhs->right); } diff --git a/html/029tools.cc.html b/html/029tools.cc.html index 018e0f01..4f5242fe 100644 --- a/html/029tools.cc.html +++ b/html/029tools.cc.html @@ -285,6 +285,7 @@ case _PRINT: { } } } + cout.flush(); break; } diff --git a/html/035call_ingredient.cc.html b/html/035call_ingredient.cc.html index 104c66dc..ff46da6f 100644 --- a/html/035call_ingredient.cc.html +++ b/html/035call_ingredient.cc.html @@ -91,11 +91,16 @@ case NEXT_INGREDIENT: { if (current_call().next_ingredient_to_process < SIZE(current_call().ingredient_atoms)) { reagent product = current_instruction().products.at(0); canonize_type(product); - if (!types_match(product, - current_call().ingredient_types.at(current_call().next_ingredient_to_process), - current_call().ingredient_atoms.at(current_call().next_ingredient_to_process) - )) { - raise_error << maybe(current_recipe_name()) << "wrong type for ingredient " << current_instruction().products.at(0).original_string << '\n' << end(); + if (current_recipe_name() == "main") { + // no ingredient types since the call might be implicit; assume ingredients are always strings + // todo: how to test this? + if (!is_mu_string(product)) + raise_error << "main: wrong type for ingredient " << product.original_string << '\n' << end(); + } + else if (!types_match(product, + current_call().ingredient_types.at(current_call().next_ingredient_to_process), + current_call().ingredient_atoms.at(current_call().next_ingredient_to_process))) { + raise_error << maybe(current_recipe_name()) << "wrong type for ingredient " << product.original_string << '\n' << end(); } products.push_back( current_call().ingredient_atoms.at(current_call().next_ingredient_to_process)); diff --git a/html/041jump_target.cc.html b/html/041jump_target.cc.html index 53f93910..e85829db 100644 --- a/html/041jump_target.cc.html +++ b/html/041jump_target.cc.html @@ -98,7 +98,7 @@ void replace_offset(reagent& x.set_value(0); // no jump by default return; } - assert(!x.initialized); + if (x.initialized) return; if (is_integer(x.name)) return; // non-labels will be handled like other number operands if (!is_jump_target(x.name)) { raise_error << maybe(get(Recipe, r).name) << "can't jump to label " << x.name << '\n' << end(); diff --git a/html/057static_dispatch.cc.html b/html/057static_dispatch.cc.html index ec362d4a..243b9c28 100644 --- a/html/057static_dispatch.cc.html +++ b/html/057static_dispatch.cc.html @@ -14,10 +14,11 @@ pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background- body { font-family: monospace; color: #eeeeee; background-color: #080808; } * { font-size: 1.05em; } .traceContains { color: #008000; } +.Identifier { color: #804000; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .Special { color: #ff6060; } -.Identifier { color: #804000; } +.CommentedCode { color: #6c6c6c; } .Constant { color: #00a0a0; } --> @@ -64,8 +65,9 @@ for (map<string,:(before "End Load Recipe Header(result)") if (contains_key(Recipe_ordinal, result.name)) { const recipe_ordinal r = get(Recipe_ordinal, result.name); +//? if (variant_already_exists(result)) cerr << "AAAAAAAAAAAAAAAAAA variant already exists " << result.name << '\n'; if ((!contains_key(Recipe, r) || get(Recipe, r).has_header) - && !header_already_exists(result)) { + && !variant_already_exists(result)) { string new_name = next_unused_recipe_name(result.name); put(Recipe_ordinal, new_name, Next_recipe_ordinal++); get(Recipe_variants, result.name).push_back(get(Recipe_ordinal, new_name)); @@ -79,10 +81,10 @@ else { } :(code) -bool header_already_exists(const recipe& rr) { +bool variant_already_exists(const recipe& rr) { const vector<recipe_ordinal>& variants = get(Recipe_variants, rr.name); for (long long int i = 0; i < SIZE(variants); ++i) { - if (Recipe.find(variants.at(i)) != Recipe.end() + if (contains_key(Recipe, variants.at(i)) && all_reagents_match(rr, get(Recipe, variants.at(i)))) { return true; } @@ -94,12 +96,16 @@ bool all_reagents_match(const recipe& r1(SIZE(r1.ingredients) != SIZE(r2.ingredients)) return false; if (SIZE(r1.products) != SIZE(r2.products)) return false; for (long long int i = 0; i < SIZE(r1.ingredients); ++i) { - if (!exact_match(r1.ingredients.at(i).type, r2.ingredients.at(i).type)) + if (!deeply_equal_types(r1.ingredients.at(i).properties.at(0).second, + r2.ingredients.at(i).properties.at(0).second)) { return false; + } } for (long long int i = 0; i < SIZE(r1.products); ++i) { - if (!exact_match(r1.products.at(i).type, r2.products.at(i).type)) + if (!deeply_equal_types(r1.products.at(i).properties.at(0).second, + r2.products.at(i).properties.at(0).second)) { return false; + } } return true; } @@ -115,7 +121,7 @@ string next_unused_recipe_name(const string& for (long long int i = 2; ; ++i) { ostringstream out; out << recipe_name << '_' << i; - if (Recipe_ordinal.find(out.str()) == Recipe_ordinal.end()) + if (!contains_key(Recipe_ordinal, out.str())) return out.str(); } } @@ -143,7 +149,6 @@ Transform.push_back(:(code) void resolve_ambiguous_calls(recipe_ordinal r) { recipe& caller_recipe = get(Recipe, r); - if (!caller_recipe.has_header) return; trace(9991, "transform") << "--- resolve ambiguous calls for recipe " << caller_recipe.name << end(); for (long long int index = 0; index < SIZE(caller_recipe.steps); ++index) { instruction& inst = caller_recipe.steps.at(index); @@ -152,6 +157,7 @@ void resolve_ambiguous_calls(recipe_ordinal r(!get(Recipe_variants, inst.name).empty()); replace_best_variant(inst, caller_recipe); } +//? if (caller_recipe.name == "main") cerr << "=============== " << debug_string(caller_recipe) << '\n'; } void replace_best_variant(instruction& inst, const recipe& caller_recipe) { diff --git a/html/058shape_shifting_container.cc.html b/html/058shape_shifting_container.cc.html index 4a4fb2cc..0402d54b 100644 --- a/html/058shape_shifting_container.cc.html +++ b/html/058shape_shifting_container.cc.html @@ -21,6 +21,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .Delimiter { color: #a04060; } .SalientComment { color: #00ffff; } .Identifier { color: #804000; } +.CommentedCode { color: #6c6c6c; } --> @@ -131,7 +132,7 @@ long long int size_of_type_ingredient(const type_ assert(!curr->left); // unimplemented if (!contains_key(Type, curr->value)) { // temporarily while we're still ironing out kinks; eventually replace with a raise_error - DUMP(""); +//? DUMP(""); cerr << "missing type " << debug_string(curr) << '\n'; exit(0); } diff --git a/html/059shape_shifting_recipe.cc.html b/html/059shape_shifting_recipe.cc.html index 2df37fa3..13c436c4 100644 --- a/html/059shape_shifting_recipe.cc.html +++ b/html/059shape_shifting_recipe.cc.html @@ -16,6 +16,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } .traceContains { color: #008000; } .Special { color: #ff6060; } .cSpecial { color: #008000; } +.CommentedCode { color: #6c6c6c; } .Comment { color: #9090ff; } .Delimiter { color: #a04060; } .SalientComment { color: #00ffff; } @@ -54,11 +55,26 @@ recipe foo a:_t -> result:_t [ +mem: storing 14 in location 11 +mem: storing 15 in location 12 -//: Before anything else, disable transforms for shape-shifting recipes. +//: Before anything else, disable transforms for shape-shifting recipes and +//: make sure we never try to actually run a shape-shifting recipe. We should +//: be rewriting such instructions to *specializations* with the type +//: ingredients filled in. :(before "End Transform Checks") if (any_type_ingredient_in_header(/*recipe_ordinal*/p->first)) continue; +:(after "Running One Instruction") +if (Current_routine->calls.front().running_step_index == 0 + && any_type_ingredient_in_header(Current_routine->calls.front().running_recipe)) { +//? DUMP(""); + raise_error << "ran into unspecialized shape-shifting recipe " << current_recipe_name() << '\n' << end(); +} + +//: Make sure we don't match up literals with type ingredients without +//: specialization. +:(before "End valid_type_for_literal Special-cases") +if (contains_type_ingredient_name(lhs)) return false; + //: We'll be creating recipes without loading them from anywhere by //: *specializing* existing recipes, so make sure we don't clear any of those //: when we start running tests. @@ -68,24 +84,35 @@ recently_added_types.clear:(before "End Instruction Dispatch(inst, best_score)") if (best_score == -1) { +//? if (inst.name == "push-duplex") Trace_stream = new trace_stream; trace(9992, "transform") << "no variant found; searching for variant with suitable type ingredients" << end(); recipe_ordinal exemplar = pick_matching_shape_shifting_variant(variants, inst, best_score); if (exemplar) { trace(9992, "transform") << "found variant to specialize: " << exemplar << ' ' << get(Recipe, exemplar).name << end(); variants.push_back(new_variant(exemplar, inst, caller_recipe)); +//? cerr << "-- replacing " << inst.name << " with " << get(Recipe, variants.back()).name << '\n' << debug_string(get(Recipe, variants.back())); inst.name = get(Recipe, variants.back()).name; trace(9992, "transform") << "new specialization: " << inst.name << end(); } +//? if (inst.name == "push-duplex") { +//? cerr << "======== {\n"; +//? cerr << inst.to_string() << '\n'; +//? DUMP(""); +//? cerr << "======== }\n"; +//? } } :(code) recipe_ordinal pick_matching_shape_shifting_variant(vector<recipe_ordinal>& variants, const instruction& inst, long long int& best_score) { +//? cerr << "---- " << inst.name << ": " << non_ghost_size(variants) << '\n'; recipe_ordinal result = 0; for (long long int i = 0; i < SIZE(variants); ++i) { if (variants.at(i) == -1) continue; // ghost from a previous test +//? cerr << "-- variant " << i << "\n" << debug_string(get(Recipe, variants.at(i))); trace(9992, "transform") << "checking shape-shifting variant " << i << end(); long long int current_score = shape_shifting_variant_score(inst, variants.at(i)); trace(9992, "transform") << "final score: " << current_score << end(); +//? cerr << get(Recipe, variants.at(i)).name << ": " << current_score << '\n'; if (current_score > best_score) { trace(9992, "transform") << "matches" << end(); result = variants.at(i); @@ -96,6 +123,7 @@ recipe_ordinal pick_matching_shape_shifting_variant(} long long int shape_shifting_variant_score(const instruction& inst, recipe_ordinal variant) { +//? cerr << "======== " << inst.to_string() << '\n'; if (!any_type_ingredient_in_header(variant)) { trace(9993, "transform") << "no type ingredients" << end(); return -1; @@ -106,7 +134,7 @@ long long int shape_shifting_variant_score(const return -1; } for (long long int i = 0; i < SIZE(header_ingredients); ++i) { - if (!non_type_ingredients_match(header_ingredients.at(i), inst.ingredients.at(i))) { + if (!deeply_equal_concrete_types(header_ingredients.at(i), inst.ingredients.at(i))) { trace(9993, "transform") << "mismatch: ingredient " << i << end(); return -1; } @@ -117,7 +145,7 @@ long long int shape_shifting_variant_score(const } const vector<reagent>& header_products = get(Recipe, variant).products; for (long long int i = 0; i < SIZE(inst.products); ++i) { - if (!non_type_ingredients_match(header_products.at(i), inst.products.at(i))) { + if (!deeply_equal_concrete_types(header_products.at(i), inst.products.at(i))) { trace(9993, "transform") << "mismatch: product " << i << end(); return -1; } @@ -139,9 +167,29 @@ bool any_type_ingredient_in_header(recipe_ordinal return false; } -bool non_type_ingredients_match(const reagent& lhs, const reagent& rhs) { - if (contains_type_ingredient_name(lhs)) return true; - return types_match(lhs, rhs); +bool deeply_equal_concrete_types(reagent lhs, reagent rhs) { +//? cerr << debug_string(lhs) << " vs " << debug_string(rhs) << '\n'; +//? bool result = deeply_equal_concrete_types(lhs.properties.at(0).second, rhs.properties.at(0).second, rhs); +//? cerr << " => " << result << '\n'; +//? return result; +//? cerr << "== " << debug_string(lhs) << " vs " << debug_string(rhs) << '\n'; + canonize_type(lhs); + canonize_type(rhs); + return deeply_equal_concrete_types(lhs.properties.at(0).second, rhs.properties.at(0).second, rhs); +} + +bool deeply_equal_concrete_types(const string_tree* lhs, const string_tree* rhs, const reagent& rhs_reagent) { + if (!lhs) return !rhs; + if (!rhs) return !lhs; + if (is_type_ingredient_name(lhs->value)) return true; // type ingredient matches anything + if (Literal_type_names.find(lhs->value) != Literal_type_names.end()) + return Literal_type_names.find(rhs->value) != Literal_type_names.end(); + if (rhs->value == "literal" && lhs->value == "address") + return rhs_reagent.name == "0"; +//? cerr << lhs->value << " vs " << rhs->value << '\n'; + return lhs->value == rhs->value + && deeply_equal_concrete_types(lhs->left, rhs->left, rhs_reagent) + && deeply_equal_concrete_types(lhs->right, rhs->right, rhs_reagent); } bool contains_type_ingredient_name(const reagent& x) { @@ -183,7 +231,7 @@ recipe_ordinal new_variant(recipe_ordinal exempla delete p->second; if (error) return exemplar; } - ensure_all_concrete_types(new_recipe); + ensure_all_concrete_types(new_recipe, get(Recipe, exemplar)); // finally, perform all transforms on the new specialization for (long long int t = 0; t < SIZE(Transform); ++t) { (*Transform.at(t))(new_recipe_ordinal); @@ -227,14 +275,17 @@ void save_or_deduce_type_name(reagent& x} void compute_type_ingredient_mappings(const recipe& exemplar, const instruction& inst, map<string, const string_tree*>& mappings, const recipe& caller_recipe, bool* error) { - for (long long int i = 0; i < SIZE(exemplar.ingredients); ++i) { + long long int limit = min(SIZE(inst.ingredients), SIZE(exemplar.ingredients)); + for (long long int i = 0; i < limit; ++i) { const reagent& exemplar_reagent = exemplar.ingredients.at(i); reagent ingredient = inst.ingredients.at(i); assert(ingredient.properties.at(0).second); canonize_type(ingredient); + if (is_mu_address(exemplar_reagent) && ingredient.name == "0") continue; // assume it matches accumulate_type_ingredients(exemplar_reagent, ingredient, mappings, exemplar, inst, caller_recipe, error); } - for (long long int i = 0; i < SIZE(exemplar.products); ++i) { + limit = min(SIZE(inst.products), SIZE(exemplar.products)); + for (long long int i = 0; i < limit; ++i) { const reagent& exemplar_reagent = exemplar.products.at(i); reagent product = inst.products.at(i); assert(product.properties.at(0).second); @@ -243,6 +294,10 @@ void compute_type_ingredient_mappings(const recip } } +inline long long int min(long long int a, long long int b) { + return (a < b) ? a : b; +} + void accumulate_type_ingredients(const reagent& exemplar_reagent, reagent& refinement, map<string, const string_tree*>& mappings, const recipe& exemplar, const instruction& call_instruction, const recipe& caller_recipe, bool* error) { assert(refinement.properties.at(0).second); accumulate_type_ingredients(exemplar_reagent.properties.at(0).second, refinement.properties.at(0).second, mappings, exemplar, exemplar_reagent, call_instruction, caller_recipe, error); @@ -262,11 +317,15 @@ void accumulate_type_ingredients(const string_tre } if (!contains_key(mappings, exemplar_type->value)) { trace(9993, "transform") << "adding mapping from " << exemplar_type->value << " to " << debug_string(refinement_type) << end(); - put(mappings, exemplar_type->value, new string_tree(*refinement_type)); + if (refinement_type->value == "literal") + put(mappings, exemplar_type->value, new string_tree("number")); + else + put(mappings, exemplar_type->value, new string_tree(*refinement_type)); } else { - if (!deeply_equal(get(mappings, exemplar_type->value), refinement_type)) { + if (!deeply_equal_types(get(mappings, exemplar_type->value), refinement_type)) { raise_error << maybe(caller_recipe.name) << "no call found for '" << call_instruction.to_string() << "'\n" << end(); +//? cerr << exemplar_type->value << ": " << debug_string(get(mappings, exemplar_type->value)) << " vs " << debug_string(refinement_type) << '\n'; *error = true; return; } @@ -330,31 +389,39 @@ void replace_type_ingredients(string_tree* type(type->right, mappings); } -void ensure_all_concrete_types(const recipe& new_recipe) { +void ensure_all_concrete_types(/*const*/ recipe& new_recipe, const recipe& exemplar) { for (long long int i = 0; i < SIZE(new_recipe.ingredients); ++i) - ensure_all_concrete_types(new_recipe.ingredients.at(i).type); + ensure_all_concrete_types(new_recipe.ingredients.at(i), exemplar); for (long long int i = 0; i < SIZE(new_recipe.products); ++i) - ensure_all_concrete_types(new_recipe.products.at(i).type); + ensure_all_concrete_types(new_recipe.products.at(i), exemplar); for (long long int i = 0; i < SIZE(new_recipe.steps); ++i) { - const instruction& inst = new_recipe.steps.at(i); + instruction& inst = new_recipe.steps.at(i); for (long long int j = 0; j < SIZE(inst.ingredients); ++j) - ensure_all_concrete_types(inst.ingredients.at(j).type); + ensure_all_concrete_types(inst.ingredients.at(j), exemplar); for (long long int j = 0; j < SIZE(inst.products); ++j) - ensure_all_concrete_types(inst.products.at(j).type); + ensure_all_concrete_types(inst.products.at(j), exemplar); } } -void ensure_all_concrete_types(const type_tree* x) { - if (!x) { - raise << "null type\n" << end(); +void ensure_all_concrete_types(/*const*/ reagent& x, const recipe& exemplar) { + if (!x.type) { + raise_error << maybe(exemplar.name) << "failed to map a type to " << x.original_string << '\n' << end(); + x.type = new type_tree(0); // just to prevent crashes later return; } - if (x->value == -1) { - raise << "unknown type\n" << end(); + if (x.type->value == -1) { + raise_error << maybe(exemplar.name) << "failed to map a type to the unknown " << x.original_string << '\n' << end(); return; } } +long long int non_ghost_size(vector<recipe_ordinal>& variants) { + long long int result = 0; + for (long long int i = 0; i < SIZE(variants); ++i) + if (variants.at(i) != -1) ++result; + return result; +} + :(scenario shape_shifting_recipe_2) recipe main [ 10:point <- merge 14, 15 @@ -476,6 +543,147 @@ recipe foo a:_t -> b:_t [ b <- copy a ] +error: main: no call found for 'b:address:number <- foo a' + +:(scenario specialize_inside_recipe_without_header) +recipe main [ + foo 3 +] +recipe foo [ + local-scope + x:number <- next-ingredient # ensure no header + 1:number/raw <- bar x # call a shape-shifting recipe +] +recipe bar x:_elem -> y:_elem [ + local-scope + load-ingredients + y <- add x, 1 +] ++mem: storing 4 in location 1 + +:(scenario specialize_with_literal) +recipe main [ + local-scope + # permit literal to map to number + 1:number/raw <- foo 3 +] +recipe foo x:_elem -> y:_elem [ + local-scope + load-ingredients + y <- add x, 1 +] ++mem: storing 4 in location 1 + +:(scenario specialize_with_literal_2) +recipe main [ + local-scope + # permit literal to map to character + 1:character/raw <- foo 3 +] +recipe foo x:_elem -> y:_elem [ + local-scope + load-ingredients + y <- add x, 1 +] ++mem: storing 4 in location 1 + +:(scenario specialize_with_literal_3) +% Hide_errors = true; +recipe main [ + local-scope + # permit '0' to map to address to shape-shifting type-ingredient + 1:address:character/raw <- foo 0 +] +recipe foo x:address:_elem -> y:address:_elem [ + local-scope + load-ingredients + y <- copy x +] ++mem: storing 0 in location 1 +$error: 0 + +:(scenario specialize_with_literal_4) +% Hide_errors = true; +recipe main [ + local-scope + # ambiguous call: what's the type of its ingredient?! + foo 0 +] +recipe foo x:address:_elem -> y:address:_elem [ + local-scope + load-ingredients + y <- copy x +] ++error: foo: failed to map a type to x ++error: foo: failed to map a type to y + +:(scenario specialize_with_literal_5) +recipe main [ + foo 3, 4 # recipe mapping two variables to literals +] +recipe foo x:_elem, y:_elem [ + local-scope + load-ingredients + 1:number/raw <- add x, y +] ++mem: storing 7 in location 1 + +:(scenario multiple_shape_shifting_variants) +# try to call two different shape-shifting recipes with the same name +recipe main [ + e1:d1:number <- merge 3 + e2:d2:number <- merge 4, 5 + 1:number/raw <- foo e1 + 2:number/raw <- foo e2 +] +# the two shape-shifting definitions +recipe foo a:d1:_elem -> b:number [ + local-scope + load-ingredients + reply 34 +] +recipe foo a:d2:_elem -> b:number [ + local-scope + load-ingredients + reply 35 +] +# the shape-shifting containers they use +container d1:_elem [ + x:_elem +] +container d2:_elem [ + x:number + y:_elem +] ++mem: storing 34 in location 1 ++mem: storing 35 in location 2 + +:(scenario multiple_shape_shifting_variants_2) +# static dispatch between shape-shifting variants, _including pointer lookups_ +recipe main [ + e1:d1:number <- merge 3 + e2:address:d2:number <- new {(d2 number): type} + 1:number/raw <- foo e1 + 2:number/raw <- foo *e2 # different from previous scenario +] +recipe foo a:d1:_elem -> b:number [ + local-scope + load-ingredients + reply 34 +] +recipe foo a:d2:_elem -> b:number [ + local-scope + load-ingredients + reply 35 +] +container d1:_elem [ + x:_elem +] +container d2:_elem [ + x:number + y:_elem +] ++mem: storing 34 in location 1 ++mem: storing 35 in location 2 diff --git a/html/073list.mu.html b/html/073list.mu.html index 5db8f8af..c274436b 100644 --- a/html/073list.mu.html +++ b/html/073list.mu.html @@ -66,18 +66,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } result <- get *in, next:offset ] -recipe force-specialization-list-number [ - 1:address:list:number <- push 2:number, 1:address:list:number - 2:number <- first 1:address:list:number - 1:address:list:number <- rest 1:address:list:number -] - -# todo: automatically specialize code in scenarios scenario list-handling [ run [ - 1:address:list:number <- copy 0 - 2:number <- copy 3 - 1:address:list:number <- push 2:number, 1:address:list:number + 1:address:list:number <- push 3, 0 1:address:list:number <- push 4, 1:address:list:number 1:address:list:number <- push 5, 1:address:list:number 2:number <- first 1:address:list:number diff --git a/html/075duplex_list.mu.html b/html/075duplex_list.mu.html index c7452600..f2094cde 100644 --- a/html/075duplex_list.mu.html +++ b/html/075duplex_list.mu.html @@ -40,7 +40,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } prev:address:duplex-list:_elem ] -recipe push-duplex x:_elem, in:address:duplex-list:_elem -> result:address:duplex-list:_elem [ +recipe push x:_elem, in:address:duplex-list:_elem -> result:address:duplex-list:_elem [ local-scope load-ingredients result <- new {(duplex-list _elem): type} @@ -53,21 +53,21 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *prev <- copy result ] -recipe first-duplex in:address:duplex-list:_elem -> result:_elem [ +recipe first in:address:duplex-list:_elem -> result:_elem [ local-scope load-ingredients reply-unless in, 0 result <- get *in, value:offset ] -recipe next-duplex in:address:duplex-list:_elem -> result:address:duplex-list:_elem [ +recipe next in:address:duplex-list:_elem -> result:address:duplex-list:_elem [ local-scope load-ingredients reply-unless in, 0 result <- get *in, next:offset ] -recipe prev-duplex in:address:duplex-list:_elem -> result:address:duplex-list:_elem [ +recipe prev in:address:duplex-list:_elem -> result:address:duplex-list:_elem [ local-scope load-ingredients reply-unless in, 0 @@ -80,24 +80,23 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } # reserve locations 0, 1 and 2 to check for missing null check 1:number <- copy 34 2:number <- copy 35 - 3:address:duplex-list:character <- copy 0 - 3:address:duplex-list:character <- push-duplex 3, 3:address:duplex-list:character - 3:address:duplex-list:character <- push-duplex 4, 3:address:duplex-list:character - 3:address:duplex-list:character <- push-duplex 5, 3:address:duplex-list:character + 3:address:duplex-list:character <- push 3, 0 + 3:address:duplex-list:character <- push 4, 3:address:duplex-list:character + 3:address:duplex-list:character <- push 5, 3:address:duplex-list:character 4:address:duplex-list:character <- copy 3:address:duplex-list:character - 5:character <- first-duplex 4:address:duplex-list:character - 4:address:duplex-list:character <- next-duplex 4:address:duplex-list:character - 6:character <- first-duplex 4:address:duplex-list:character - 4:address:duplex-list:character <- next-duplex 4:address:duplex-list:character - 7:character <- first-duplex 4:address:duplex-list:character - 8:address:duplex-list:character <- next-duplex 4:address:duplex-list:character - 9:character <- first-duplex 8:address:duplex-list:character - 10:address:duplex-list:character <- next-duplex 8:address:duplex-list:character - 11:address:duplex-list:character <- prev-duplex 8:address:duplex-list:character - 4:address:duplex-list:character <- prev-duplex 4:address:duplex-list:character - 12:character <- first-duplex 4:address:duplex-list:character - 4:address:duplex-list:character <- prev-duplex 4:address:duplex-list:character - 13:character <- first-duplex 4:address:duplex-list:character + 5:character <- first 4:address:duplex-list:character + 4:address:duplex-list:character <- next 4:address:duplex-list:character + 6:character <- first 4:address:duplex-list:character + 4:address:duplex-list:character <- next 4:address:duplex-list:character + 7:character <- first 4:address:duplex-list:character + 8:address:duplex-list:character <- next 4:address:duplex-list:character + 9:character <- first 8:address:duplex-list:character + 10:address:duplex-list:character <- next 8:address:duplex-list:character + 11:address:duplex-list:character <- prev 8:address:duplex-list:character + 4:address:duplex-list:character <- prev 4:address:duplex-list:character + 12:character <- first 4:address:duplex-list:character + 4:address:duplex-list:character <- prev 4:address:duplex-list:character + 13:character <- first 4:address:duplex-list:character 14:boolean <- equal 3:address:duplex-list:character, 4:address:duplex-list:character ] memory-should-contain [ @@ -118,7 +117,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] # Inserts 'x' after 'in'. Returns some pointer into the list. -recipe insert-duplex x:_elem, in:address:duplex-list:_elem -> new-node:address:duplex-list:_elem [ +recipe insert x:_elem, in:address:duplex-list:_elem -> new-node:address:duplex-list:_elem [ local-scope load-ingredients new-node <- new {(duplex-list _elem): type} @@ -144,27 +143,26 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario inserting-into-duplex-list [ run [ - 1:address:duplex-list:character <- copy 0 # 1 points to head of list - 1:address:duplex-list:character <- push-duplex 3, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 4, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 5, 1:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 1:address:duplex-list:character # 2 points inside list - 2:address:duplex-list:character <- insert-duplex 6, 2:address:duplex-list:character + 1:address:duplex-list:character <- push 3, 0 + 1:address:duplex-list:character <- push 4, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 5, 1:address:duplex-list:character + 2:address:duplex-list:character <- next 1:address:duplex-list:character # 2 points inside list + 2:address:duplex-list:character <- insert 6, 2:address:duplex-list:character # check structure like before 2:address:duplex-list:character <- copy 1:address:duplex-list:character - 3:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 4:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 5:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 6:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 7:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 8:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 9:character <- first-duplex 2:address:duplex-list:character + 3:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 4:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 5:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 6:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 7:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 8:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 9:character <- first 2:address:duplex-list:character 10:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character ] memory-should-contain [ @@ -181,28 +179,27 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario inserting-at-end-of-duplex-list [ run [ - 1:address:duplex-list:character <- copy 0 # 1 points to head of list - 1:address:duplex-list:character <- push-duplex 3, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 4, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 5, 1:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 1:address:duplex-list:character # 2 points inside list - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character # now at end of list - 2:address:duplex-list:character <- insert-duplex 6, 2:address:duplex-list:character + 1:address:duplex-list:character <- push 3, 0 + 1:address:duplex-list:character <- push 4, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 5, 1:address:duplex-list:character + 2:address:duplex-list:character <- next 1:address:duplex-list:character # 2 points inside list + 2:address:duplex-list:character <- next 2:address:duplex-list:character # now at end of list + 2:address:duplex-list:character <- insert 6, 2:address:duplex-list:character # check structure like before 2:address:duplex-list:character <- copy 1:address:duplex-list:character - 3:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 4:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 5:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 6:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 7:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 8:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 9:character <- first-duplex 2:address:duplex-list:character + 3:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 4:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 5:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 6:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 7:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 8:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 9:character <- first 2:address:duplex-list:character 10:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character ] memory-should-contain [ @@ -219,26 +216,25 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario inserting-after-start-of-duplex-list [ run [ - 1:address:duplex-list:character <- copy 0 # 1 points to head of list - 1:address:duplex-list:character <- push-duplex 3, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 4, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 5, 1:address:duplex-list:character - 2:address:duplex-list:character <- insert-duplex 6, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 3, 0 + 1:address:duplex-list:character <- push 4, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 5, 1:address:duplex-list:character + 2:address:duplex-list:character <- insert 6, 1:address:duplex-list:character # check structure like before 2:address:duplex-list:character <- copy 1:address:duplex-list:character - 3:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 4:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 5:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 6:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 7:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 8:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 9:character <- first-duplex 2:address:duplex-list:character + 3:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 4:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 5:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 6:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 7:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 8:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 9:character <- first 2:address:duplex-list:character 10:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character ] memory-should-contain [ @@ -258,7 +254,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } # # Returns null if and only if list is empty. Beware: in that case any pointers # to the head are now invalid. -recipe remove-duplex in:address:duplex-list:_elem -> next-node:address:duplex-list:_elem [ +recipe remove in:address:duplex-list:_elem -> next-node:address:duplex-list:_elem [ local-scope load-ingredients # if 'in' is null, return @@ -290,21 +286,20 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario removing-from-duplex-list [ run [ - 1:address:duplex-list:character <- copy 0 # 1 points to head of list - 1:address:duplex-list:character <- push-duplex 3, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 4, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 5, 1:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 1:address:duplex-list:character # 2 points at second element - 2:address:duplex-list:character <- remove-duplex 2:address:duplex-list:character + 1:address:duplex-list:character <- push 3, 0 + 1:address:duplex-list:character <- push 4, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 5, 1:address:duplex-list:character + 2:address:duplex-list:character <- next 1:address:duplex-list:character # 2 points at second element + 2:address:duplex-list:character <- remove 2:address:duplex-list:character 3:boolean <- equal 2:address:duplex-list:character, 0 # check structure like before 2:address:duplex-list:character <- copy 1:address:duplex-list:character - 4:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 5:character <- first-duplex 2:address:duplex-list:character - 6:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 7:character <- first-duplex 2:address:duplex-list:character + 4:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 5:character <- first 2:address:duplex-list:character + 6:address:duplex-list:character <- next 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 7:character <- first 2:address:duplex-list:character 8:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character ] memory-should-contain [ @@ -319,20 +314,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario removing-from-start-of-duplex-list [ run [ - 1:address:duplex-list:character <- copy 0 # 1 points to head of list - 1:address:duplex-list:character <- push-duplex 3, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 4, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 5, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 3, 0 + 1:address:duplex-list:character <- push 4, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 5, 1:address:duplex-list:character # removing from head? return value matters. - 1:address:duplex-list:character <- remove-duplex 1:address:duplex-list:character + 1:address:duplex-list:character <- remove 1:address:duplex-list:character # check structure like before 2:address:duplex-list:character <- copy 1:address:duplex-list:character - 3:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 4:character <- first-duplex 2:address:duplex-list:character - 5:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 6:character <- first-duplex 2:address:duplex-list:character + 3:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 4:character <- first 2:address:duplex-list:character + 5:address:duplex-list:character <- next 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 6:character <- first 2:address:duplex-list:character 7:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character ] memory-should-contain [ @@ -346,23 +340,22 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario removing-from-end-of-duplex-list [ run [ - 1:address:duplex-list:character <- copy 0 # 1 points to head of list - 1:address:duplex-list:character <- push-duplex 3, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 4, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 5, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 3, 0 + 1:address:duplex-list:character <- push 4, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 5, 1:address:duplex-list:character # delete last element - 2:address:duplex-list:character <- next-duplex 1:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- remove-duplex 2:address:duplex-list:character + 2:address:duplex-list:character <- next 1:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 2:address:duplex-list:character <- remove 2:address:duplex-list:character 3:boolean <- equal 2:address:duplex-list:character, 0 # check structure like before 2:address:duplex-list:character <- copy 1:address:duplex-list:character - 4:character <- first-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 5:character <- first-duplex 2:address:duplex-list:character - 6:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- prev-duplex 2:address:duplex-list:character - 7:character <- first-duplex 2:address:duplex-list:character + 4:character <- first 2:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 5:character <- first 2:address:duplex-list:character + 6:address:duplex-list:character <- next 2:address:duplex-list:character + 2:address:duplex-list:character <- prev 2:address:duplex-list:character + 7:character <- first 2:address:duplex-list:character 8:boolean <- equal 1:address:duplex-list:character, 2:address:duplex-list:character ] memory-should-contain [ @@ -377,9 +370,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario removing-from-singleton-list [ run [ - 1:address:duplex-list:character <- copy 0 # 1 points to singleton list - 1:address:duplex-list:character <- push-duplex 3, 1:address:duplex-list:character - 2:address:duplex-list:character <- remove-duplex 1:address:duplex-list:character + 1:address:duplex-list:character <- push 3, 0 + 2:address:duplex-list:character <- remove 1:address:duplex-list:character 3:address:duplex-list:character <- get *1:address:duplex-list:character, next:offset 4:address:duplex-list:character <- get *1:address:duplex-list:character, prev:offset ] @@ -390,11 +382,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] ] -# l:address:duplex-list <- remove-duplex-between start:address:duplex-list, end:address:duplex-list -# Remove values between 'start' and 'end' (both exclusive). Returns some valid -# pointer into the rest of the list. -# Also clear pointers back out from start/end for hygiene. -recipe remove-duplex-between start:address:duplex-list:_elem, end:address:duplex-list:_elem -> start:address:duplex-list:_elem [ +# remove values between 'start' and 'end' (both exclusive) +# also clear pointers back out from start/end for hygiene +recipe remove-between start:address:duplex-list:_elem, end:address:duplex-list:_elem -> start:address:duplex-list:_elem [ local-scope load-ingredients reply-unless start @@ -417,26 +407,25 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario remove-range [ # construct a duplex list with six elements [13, 14, 15, 16, 17, 18] - 1:address:duplex-list:character <- copy 0 # 1 points to singleton list - 1:address:duplex-list:character <- push-duplex 18, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 17, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 16, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 15, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 14, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 13, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 18, 0 + 1:address:duplex-list:character <- push 17, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 16, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 15, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 14, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 13, 1:address:duplex-list:character run [ # delete 16 onwards # first pointer: to the third element - 2:address:duplex-list:character <- next-duplex 1:address:duplex-list:character - 2:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 2:address:duplex-list:character <- remove-duplex-between 2:address:duplex-list:character, 0 + 2:address:duplex-list:character <- next 1:address:duplex-list:character + 2:address:duplex-list:character <- next 2:address:duplex-list:character + 2:address:duplex-list:character <- remove-between 2:address:duplex-list:character, 0 # now check the list 4:character <- get *1:address:duplex-list:character, value:offset - 5:address:duplex-list:character <- next-duplex 1:address:duplex-list:character + 5:address:duplex-list:character <- next 1:address:duplex-list:character 6:character <- get *5:address:duplex-list:character, value:offset - 7:address:duplex-list:character <- next-duplex 5:address:duplex-list:character + 7:address:duplex-list:character <- next 5:address:duplex-list:character 8:character <- get *7:address:duplex-list:character, value:offset - 9:address:duplex-list:character <- next-duplex 7:address:duplex-list:character + 9:address:duplex-list:character <- next 7:address:duplex-list:character ] memory-should-contain [ 4 <- 13 @@ -448,30 +437,29 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario remove-range-to-end [ # construct a duplex list with six elements [13, 14, 15, 16, 17, 18] - 1:address:duplex-list:character <- copy 0 # 1 points to singleton list - 1:address:duplex-list:character <- push-duplex 18, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 17, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 16, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 15, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 14, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 13, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 18, 0 + 1:address:duplex-list:character <- push 17, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 16, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 15, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 14, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 13, 1:address:duplex-list:character run [ # delete 15, 16 and 17 # first pointer: to the third element - 2:address:duplex-list:character <- next-duplex 1:address:duplex-list:character + 2:address:duplex-list:character <- next 1:address:duplex-list:character # second pointer: to the fifth element - 3:address:duplex-list:character <- next-duplex 2:address:duplex-list:character - 3:address:duplex-list:character <- next-duplex 3:address:duplex-list:character - 3:address:duplex-list:character <- next-duplex 3:address:duplex-list:character - 3:address:duplex-list:character <- next-duplex 3:address:duplex-list:character - remove-duplex-between 2:address:duplex-list:character, 3:address:duplex-list:character + 3:address:duplex-list:character <- next 2:address:duplex-list:character + 3:address:duplex-list:character <- next 3:address:duplex-list:character + 3:address:duplex-list:character <- next 3:address:duplex-list:character + 3:address:duplex-list:character <- next 3:address:duplex-list:character + remove-between 2:address:duplex-list:character, 3:address:duplex-list:character # now check the list 4:character <- get *1:address:duplex-list:character, value:offset - 5:address:duplex-list:character <- next-duplex 1:address:duplex-list:character + 5:address:duplex-list:character <- next 1:address:duplex-list:character 6:character <- get *5:address:duplex-list:character, value:offset - 7:address:duplex-list:character <- next-duplex 5:address:duplex-list:character + 7:address:duplex-list:character <- next 5:address:duplex-list:character 8:character <- get *7:address:duplex-list:character, value:offset - 9:address:duplex-list:character <- next-duplex 7:address:duplex-list:character + 9:address:duplex-list:character <- next 7:address:duplex-list:character ] memory-should-contain [ 4 <- 13 @@ -483,19 +471,18 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } scenario remove-range-empty [ # construct a duplex list with six elements [13, 14, 15, 16, 17, 18] - 1:address:duplex-list:character <- copy 0 # 1 points to singleton list - 1:address:duplex-list:character <- push-duplex 14, 1:address:duplex-list:character - 1:address:duplex-list:character <- push-duplex 13, 1:address:duplex-list:character + 1:address:duplex-list:character <- push 14, 0 + 1:address:duplex-list:character <- push 13, 1:address:duplex-list:character run [ # delete 16 onwards # first pointer: to the third element - 2:address:duplex-list:character <- next-duplex 1:address:duplex-list:character - remove-duplex-between 1:address:duplex-list:character, 2:address:duplex-list:character + 2:address:duplex-list:character <- next 1:address:duplex-list:character + remove-between 1:address:duplex-list:character, 2:address:duplex-list:character # now check the list 4:character <- get *1:address:duplex-list:character, value:offset - 5:address:duplex-list:character <- next-duplex 1:address:duplex-list:character + 5:address:duplex-list:character <- next 1:address:duplex-list:character 6:character <- get *5:address:duplex-list:character, value:offset - 7:address:duplex-list:character <- next-duplex 5:address:duplex-list:character + 7:address:duplex-list:character <- next 5:address:duplex-list:character ] memory-should-contain [ 4 <- 13 @@ -505,19 +492,19 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] # Inserts list beginning at 'new' after 'in'. Returns some pointer into the list. -recipe insert-duplex-range in:address:duplex-list:_elem, start:address:duplex-list:_elem -> in:address:duplex-list:_elem [ +recipe insert-range in:address:duplex-list:_elem, start:address:duplex-list:_elem -> in:address:duplex-list:_elem [ local-scope load-ingredients reply-unless in reply-unless start end:address:duplex-list:_elem <- copy start { - next:address:duplex-list:_elem <- next-duplex end/insert-range + next:address:duplex-list:_elem <- next end/insert-range break-unless next end <- copy next loop } - next:address:duplex-list:_elem <- next-duplex in + next:address:duplex-list:_elem <- next in dest:address:address:duplex-list:_elem <- get-address *end, next:offset *dest <- copy next { @@ -531,10 +518,10 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *dest <- copy in ] -recipe append-duplex in:address:duplex-list:_elem, new:address:duplex-list:_elem -> in:address:duplex-list:_elem [ +recipe append in:address:duplex-list:_elem, new:address:duplex-list:_elem -> in:address:duplex-list:_elem [ local-scope load-ingredients - last:address:duplex-list:_elem <- last-duplex in + last:address:duplex-list:_elem <- last in dest:address:address:duplex-list:_elem <- get-address *last, next:offset *dest <- copy new reply-unless new @@ -542,12 +529,12 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *dest <- copy last ] -recipe last-duplex in:address:duplex-list:_elem -> result:address:duplex-list:_elem [ +recipe last in:address:duplex-list:_elem -> result:address:duplex-list:_elem [ local-scope load-ingredients result <- copy in { - next:address:duplex-list:_elem <- next-duplex result + next:address:duplex-list:_elem <- next result break-unless next result <- copy next loop @@ -555,7 +542,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } ] # helper for debugging -recipe dump-duplex-from x:address:duplex-list:_elem [ +recipe dump-from x:address:duplex-list:_elem [ local-scope load-ingredients $print x, [: ] @@ -563,7 +550,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } break-unless x c:_elem <- get *x, value:offset $print c, [ ] - x <- next-duplex x + x <- next x { is-newline?:boolean <- equal c, 10/newline break-unless is-newline? @@ -574,19 +561,6 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } } $print 10/newline, [---], 10/newline ] - -recipe force-specialization-duplex-list-character [ - 1:address:duplex-list:character <- push-duplex 2:character, 1:address:duplex-list:character - 2:character <- first-duplex 1:address:duplex-list:character - 1:address:duplex-list:character <- next-duplex 1:address:duplex-list:character - 1:address:duplex-list:character <- prev-duplex 1:address:duplex-list:character - 1:address:duplex-list:character <- insert-duplex 2:character, 1:address:duplex-list:character - 1:address:duplex-list:character <- remove-duplex 1:address:duplex-list:character - 1:address:duplex-list:character <- remove-duplex-between 1:address:duplex-list:character, 1:address:duplex-list:character - 1:address:duplex-list:character <- insert-duplex-range 1:address:duplex-list:character, 1:address:duplex-list:character - 1:address:duplex-list:character <- append-duplex 1:address:duplex-list:character, 1:address:duplex-list:character - 1:address:duplex-list:character <- last-duplex 1:address:duplex-list:character -] diff --git a/html/091run_interactive.cc.html b/html/091run_interactive.cc.html index 30490309..b96eeb50 100644 --- a/html/091run_interactive.cc.html +++ b/html/091run_interactive.cc.html @@ -111,14 +111,13 @@ bool run_interactive(long long int address} string command = trim(strip_comments(read_mu_string(address))); if (command.empty()) return false; - Recipe.erase(get(Recipe_ordinal, "interactive")); Name[get(Recipe_ordinal, "interactive")].clear(); run_code_begin(); // don't kill the current routine on parse errors routine* save_current_routine = Current_routine; Current_routine = NULL; // call run(string) but without the scheduling - load(string("recipe interactive [\n") + + load(string("recipe! interactive [\n") + "local-scope\n" + "screen:address:screen <- next-ingredient\n" + "$start-tracking-products\n" + diff --git a/html/edit/001-editor.mu.html b/html/edit/001-editor.mu.html index 916e93c6..cf10dc6c 100644 --- a/html/edit/001-editor.mu.html +++ b/html/edit/001-editor.mu.html @@ -99,7 +99,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } x <- get-address *result, cursor-column:offset *x <- copy left init:address:address:duplex-list:character <- get-address *result, data:offset - *init <- push-duplex 167/§, 0/tail + *init <- push 167/§, 0/tail top-of-screen:address:address:duplex-list:character <- get-address *result, top-of-screen:offset *top-of-screen <- copy *init y:address:address:duplex-list:character <- get-address *result, before-cursor:offset @@ -127,9 +127,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } done?:boolean <- greater-or-equal idx, len break-if done? c:character <- index *text, idx - insert-duplex c, curr + insert c, curr # next iter - curr <- next-duplex curr + curr <- next curr idx <- add idx, 1 loop } @@ -171,8 +171,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } right:number <- get *editor, right:offset # traversing editor curr:address:duplex-list:character <- get *editor, top-of-screen:offset - prev:address:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev-duplex - curr <- next-duplex curr + prev:address:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev + curr <- next curr # traversing screen +render-loop-initialization color:number <- copy 7/white @@ -210,7 +210,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } left-of-cursor?:boolean <- lesser-than column, *cursor-column break-unless left-of-cursor? *cursor-column <- copy column - *before-cursor <- prev-duplex curr + *before-cursor <- prev curr } # clear rest of line in this window clear-line-delimited screen, column, right @@ -218,8 +218,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } row <- add row, 1 column <- copy left screen <- move-cursor screen, row, column - curr <- next-duplex curr - prev <- next-duplex prev + curr <- next curr + prev <- next prev loop +next-character:label } { @@ -236,8 +236,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } loop +next-character:label } print-character screen, c, color - curr <- next-duplex curr - prev <- next-duplex prev + curr <- next curr + prev <- next prev column <- add column, 1 loop } diff --git a/html/edit/002-typing.mu.html b/html/edit/002-typing.mu.html index c1f1128f..538bbf5d 100644 --- a/html/edit/002-typing.mu.html +++ b/html/edit/002-typing.mu.html @@ -114,8 +114,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } screen-height:number <- screen-height screen # count newlines until screen row curr:address:duplex-list:character <- get *editor, top-of-screen:offset - prev:address:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev-duplex - curr <- next-duplex curr + prev:address:duplex-list:character <- copy curr # just in case curr becomes null and we can't compute prev + curr <- next curr row:number <- copy 1/top column:number <- copy left cursor-row:address:number <- get-address *editor, cursor-row:offset @@ -155,8 +155,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } # skip to next line row <- add row, 1 column <- copy left - curr <- next-duplex curr - prev <- next-duplex prev + curr <- next curr + prev <- next prev loop +next-character:label } { @@ -169,8 +169,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } # don't increment curr/prev loop +next-character:label } - curr <- next-duplex curr - prev <- next-duplex prev + curr <- next curr + prev <- next prev column <- add column, 1 loop } @@ -234,8 +234,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } local-scope load-ingredients before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset - insert-duplex c, *before-cursor - *before-cursor <- next-duplex *before-cursor + insert c, *before-cursor + *before-cursor <- next *before-cursor cursor-row:address:number <- get-address *editor, cursor-row:offset cursor-column:address:number <- get-address *editor, cursor-column:offset left:number <- get *editor, left:offset @@ -248,7 +248,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } <insert-character-special-case> # but mostly we'll just move the cursor right *cursor-column <- add *cursor-column, 1 - next:address:duplex-list:character <- next-duplex *before-cursor + next:address:duplex-list:character <- next *before-cursor { # at end of all text? no need to scroll? just print the character and leave at-end?:boolean <- equal next, 0/null @@ -283,7 +283,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } break-if at-newline? print-character screen, currc curr-column <- add curr-column, 1 - curr <- next-duplex curr + curr <- next curr loop } go-render? <- copy 0/false @@ -867,8 +867,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } right:number <- get *editor, right:offset screen-height:number <- screen-height screen # insert newline - insert-duplex 10/newline, *before-cursor - *before-cursor <- next-duplex *before-cursor + insert 10/newline, *before-cursor + *before-cursor <- next *before-cursor *cursor-row <- add *cursor-row, 1 *cursor-column <- copy left # maybe scroll @@ -883,7 +883,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } indent?:boolean <- get *editor, indent?:offset reply-unless indent? d:address:duplex-list:character <- get *editor, data:offset - end-of-previous-line:address:duplex-list:character <- prev-duplex *before-cursor + end-of-previous-line:address:duplex-list:character <- prev *before-cursor indent:number <- line-indent end-of-previous-line, d i:number <- copy 0 { @@ -905,7 +905,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } at-start?:boolean <- equal curr, start reply-if at-start? { - curr <- prev-duplex curr + curr <- prev curr break-unless curr at-start?:boolean <- equal curr, start break-if at-start? diff --git a/html/edit/003-shortcuts.mu.html b/html/edit/003-shortcuts.mu.html index 023f8448..aabe23e0 100644 --- a/html/edit/003-shortcuts.mu.html +++ b/html/edit/003-shortcuts.mu.html @@ -119,14 +119,14 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } load-ingredients before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset # if at start of text (before-cursor at § sentinel), return - prev:address:duplex-list:character <- prev-duplex *before-cursor + prev:address:duplex-list:character <- prev *before-cursor go-render?, backspaced-cell <- copy 0/no-more-render, 0/nothing-deleted reply-unless prev trace 10, [app], [delete-before-cursor] original-row:number <- get *editor, cursor-row:offset editor, scroll?:boolean <- move-cursor-coordinates-left editor backspaced-cell:address:duplex-list:character <- copy *before-cursor - remove-duplex *before-cursor # will also neatly trim next/prev pointers in backspaced-cell/*before-cursor + remove *before-cursor # will also neatly trim next/prev pointers in backspaced-cell/*before-cursor *before-cursor <- copy prev go-render? <- copy 1/true reply-if scroll? @@ -139,7 +139,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } reply-unless same-row? left:number <- get *editor, left:offset right:number <- get *editor, right:offset - curr:address:duplex-list:character <- next-duplex *before-cursor + curr:address:duplex-list:character <- next *before-cursor screen <- move-cursor screen, cursor-row, cursor-column curr-column:number <- copy cursor-column { @@ -154,7 +154,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } break-if at-newline? screen <- print-character screen, currc curr-column <- add curr-column, 1 - curr <- next-duplex curr + curr <- next curr loop } # we're guaranteed not to be at the right margin @@ -218,7 +218,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } at-start?:boolean <- equal curr, start reply-if at-start? { - curr <- prev-duplex curr + curr <- prev curr break-unless curr at-start?:boolean <- equal curr, start break-if at-start? @@ -367,16 +367,16 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } local-scope load-ingredients before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset - deleted-cell:address:duplex-list:character <- next-duplex *before-cursor + deleted-cell:address:duplex-list:character <- next *before-cursor go-render? <- copy 0/false reply-unless deleted-cell currc:character <- get *deleted-cell, value:offset - remove-duplex deleted-cell + remove deleted-cell deleted-newline?:boolean <- equal currc, 10/newline go-render? <- copy 1/true reply-if deleted-newline? # wasn't a newline? render rest of line - curr:address:duplex-list:character <- next-duplex *before-cursor # refresh after remove-duplex above + curr:address:duplex-list:character <- next *before-cursor # refresh after remove above cursor-row:address:number <- get-address *editor, cursor-row:offset cursor-column:address:number <- get-address *editor, cursor-column:offset screen <- move-cursor screen, *cursor-row, *cursor-column @@ -394,7 +394,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } break-if at-newline? screen <- print-character screen, currc curr-column <- add curr-column, 1 - curr <- next-duplex curr + curr <- next curr loop } # we're guaranteed not to be at the right margin @@ -431,7 +431,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } move-to-next-character?:boolean <- equal *k, 65514/right-arrow break-unless move-to-next-character? # if not at end of text - next-cursor:address:duplex-list:character <- next-duplex *before-cursor + next-cursor:address:duplex-list:character <- next *before-cursor break-unless next-cursor # scan to next character <move-cursor-begin> @@ -474,7 +474,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } at-wrap?:boolean <- equal *cursor-column, wrap-column break-unless at-wrap? # and if next character isn't newline - next:address:duplex-list:character <- next-duplex before-cursor + next:address:duplex-list:character <- next before-cursor break-unless next next-character:character <- get *next, value:offset newline?:boolean <- equal next-character, 10/newline @@ -708,7 +708,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } break-unless move-to-previous-character? trace 10, [app], [left arrow] # if not at start of text (before-cursor at § sentinel) - prev:address:duplex-list:character <- prev-duplex *before-cursor + prev:address:duplex-list:character <- prev *before-cursor go-render? <- copy 0/false reply-unless prev <move-cursor-begin> @@ -954,7 +954,7 @@ d] { done?:boolean <- greater-or-equal *cursor-column, target-column break-if done? - curr:address:duplex-list:character <- next-duplex *before-cursor + curr:address:duplex-list:character <- next *before-cursor break-unless curr currc:character <- get *curr, value:offset at-newline?:boolean <- equal currc, 10/newline @@ -1171,7 +1171,7 @@ def] { done?:boolean <- greater-or-equal *cursor-column, target-column break-if done? - curr:address:duplex-list:character <- next-duplex *before-cursor + curr:address:duplex-list:character <- next *before-cursor break-unless curr currc:character <- get *curr, value:offset at-newline?:boolean <- equal currc, 10/newline @@ -1295,7 +1295,7 @@ def] prev:character <- get **before-cursor, value:offset at-start-of-line?:boolean <- equal prev, 10/newline break-if at-start-of-line? - *before-cursor <- prev-duplex *before-cursor + *before-cursor <- prev *before-cursor assert *before-cursor, [move-to-start-of-line tried to move before start of text] loop } @@ -1456,7 +1456,7 @@ def] cursor-column:address:number <- get-address *editor, cursor-column:offset # while not at start of line, move { - next:address:duplex-list:character <- next-duplex *before-cursor + next:address:duplex-list:character <- next *before-cursor break-unless next # end of text nextc:character <- get *next, value:offset at-end-of-line?:boolean <- equal nextc, 10/newline @@ -1586,20 +1586,20 @@ def] init:address:duplex-list:character <- get *editor, data:offset before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset start:address:duplex-list:character <- copy *before-cursor - end:address:duplex-list:character <- next-duplex *before-cursor + end:address:duplex-list:character <- next *before-cursor { at-start-of-text?:boolean <- equal start, init break-if at-start-of-text? curr:character <- get *start, value:offset at-start-of-line?:boolean <- equal curr, 10/newline break-if at-start-of-line? - start <- prev-duplex start + start <- prev start assert start, [delete-to-start-of-line tried to move before start of text] loop } # snip it out - result:address:duplex-list:character <- next-duplex start - remove-duplex-between start, end + result:address:duplex-list:character <- next start + remove-between start, end # adjust cursor *before-cursor <- copy start left:number <- get *editor, left:offset @@ -1718,19 +1718,19 @@ def] load-ingredients # compute range to delete start:address:duplex-list:character <- get *editor, before-cursor:offset - end:address:duplex-list:character <- next-duplex start + end:address:duplex-list:character <- next start { at-end-of-text?:boolean <- equal end, 0/null break-if at-end-of-text? curr:character <- get *end, value:offset at-end-of-line?:boolean <- equal curr, 10/newline break-if at-end-of-line? - end <- next-duplex end + end <- next end loop } # snip it out - result <- next-duplex start - remove-duplex-between start, end + result <- next start + remove-between start, end ] scenario editor-deletes-to-end-of-line-with-ctrl-k-2 [ @@ -1908,7 +1908,7 @@ def] c:character <- get *curr, value:offset at-newline?:boolean <- equal c, 10/newline break-unless at-newline? - curr <- next-duplex curr + curr <- next curr count <- add count, 1 } { @@ -1918,7 +1918,7 @@ def] c:character <- get *curr, value:offset at-newline?:boolean <- equal c, 10/newline break-if at-newline? - curr <- next-duplex curr + curr <- next curr count <- add count, 1 loop } @@ -2280,7 +2280,7 @@ def] { break-if len # empty line; just skip this newline - prev:address:duplex-list:character <- prev-duplex curr + prev:address:duplex-list:character <- prev curr reply-unless prev, curr reply prev } @@ -2296,7 +2296,7 @@ def] { done?:boolean <- greater-or-equal count, max break-if done? - prev:address:duplex-list:character <- prev-duplex curr + prev:address:duplex-list:character <- prev curr break-unless prev curr <- copy prev count <- add count, 1 @@ -2682,13 +2682,13 @@ e] reply-unless bottom-of-screen # if not, position cursor at final character before-cursor:address:address:duplex-list:character <- get-address *editor, before-cursor:offset - *before-cursor <- prev-duplex bottom-of-screen + *before-cursor <- prev bottom-of-screen # keep one line in common with previous page { last:character <- get **before-cursor, value:offset newline?:boolean <- equal last, 10/newline break-unless newline?:boolean - *before-cursor <- prev-duplex *before-cursor + *before-cursor <- prev *before-cursor } # move cursor and top-of-screen to start of that line move-to-start-of-line editor diff --git a/html/edit/005-sandbox.mu.html b/html/edit/005-sandbox.mu.html index 3fdab8a0..85fdf7da 100644 --- a/html/edit/005-sandbox.mu.html +++ b/html/edit/005-sandbox.mu.html @@ -186,7 +186,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } *dest <- copy new-sandbox # clear sandbox editor init:address:address:duplex-list:character <- get-address *current-sandbox, data:offset - *init <- push-duplex 167/§, 0/tail + *init <- push 167/§, 0/tail top-of-screen:address:address:duplex-list:character <- get-address *current-sandbox, top-of-screen:offset *top-of-screen <- copy *init } @@ -509,13 +509,13 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } curr:address:duplex-list:character <- get *editor, data:offset # skip § sentinel assert curr, [editor without data is illegal; must have at least a sentinel] - curr <- next-duplex curr + curr <- next curr reply-unless curr, 0 { break-unless curr c:character <- get *curr, value:offset buffer-append buf, c - curr <- next-duplex curr + curr <- next curr loop } result <- buffer-to-array buf diff --git a/html/edit/006-sandbox-edit.mu.html b/html/edit/006-sandbox-edit.mu.html index 2381b4bd..2381ec45 100644 --- a/html/edit/006-sandbox-edit.mu.html +++ b/html/edit/006-sandbox-edit.mu.html @@ -127,7 +127,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } local-scope load-ingredients head:address:duplex-list:character <- get *editor, data:offset - first:address:duplex-list:character <- next-duplex head + first:address:duplex-list:character <- next head result <- not first ] diff --git a/html/edit/011-editor-undo.mu.html b/html/edit/011-editor-undo.mu.html index b50f0063..5a3f537e 100644 --- a/html/edit/011-editor-undo.mu.html +++ b/html/edit/011-editor-undo.mu.html @@ -185,7 +185,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } previous-coalesce-tag:number <- get *typing, tag:offset break-unless previous-coalesce-tag insert-until:address:address:duplex-list:character <- get-address *typing, insert-until:offset - *insert-until <- next-duplex *before-cursor + *insert-until <- next *before-cursor after-row:address:number <- get-address *typing, after-row:offset *after-row <- copy *cursor-row after-column:address:number <- get-address *typing, after-column:offset @@ -195,8 +195,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } break +done-adding-insert-operation:label } # if not, create a new operation - insert-from:address:duplex-list:character <- next-duplex cursor-before - insert-to:address:duplex-list:character <- next-duplex insert-from + insert-from:address:duplex-list:character <- next cursor-before + insert-to:address:duplex-list:character <- next insert-from op:address:operation <- new operation:type *op <- merge 0/insert-operation, save-row/before, save-column/before, top-before, *cursor-row/after, *cursor-column/after, top-after, insert-from, insert-to, 1/coalesce editor <- add-operation editor, op @@ -213,8 +213,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } before <insert-enter-end> [ top-after:address:duplex-list:character <- get *editor, top-of-screen:offset # never coalesce - insert-from:address:duplex-list:character <- next-duplex cursor-before - insert-to:address:duplex-list:character <- next-duplex *before-cursor + insert-from:address:duplex-list:character <- next cursor-before + insert-to:address:duplex-list:character <- next *before-cursor op:address:operation <- new operation:type *op <- merge 0/insert-operation, cursor-row-before, cursor-column-before, top-before, *cursor-row/after, *cursor-column/after, top-after, insert-from, insert-to, 0/never-coalesce editor <- add-operation editor, op @@ -241,8 +241,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } start:address:duplex-list:character <- get *typing, insert-from:offset end:address:duplex-list:character <- get *typing, insert-until:offset # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen - *before-cursor <- prev-duplex start - remove-duplex-between *before-cursor, end + *before-cursor <- prev start + remove-between *before-cursor, end *cursor-row <- get *typing, before-row:offset *cursor-column <- get *typing, before-column:offset top:address:address:duplex-list:character <- get-address *editor, top-of-screen:offset @@ -436,8 +436,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } typing:address:insert-operation <- maybe-convert *op, typing:variant break-unless typing insert-from:address:duplex-list:character <- get *typing, insert-from:offset # ignore insert-to because it's already been spliced away - # assert insert-to matches next-duplex(*before-cursor) - insert-duplex-range *before-cursor, insert-from + # assert insert-to matches next(*before-cursor) + insert-range *before-cursor, insert-from # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen *cursor-row <- get *typing, after-row:offset *cursor-column <- get *typing, after-column:offset @@ -1643,7 +1643,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } delete-from:address:address:duplex-list:character <- get-address *deletion, delete-from:offset *delete-from <- copy *before-cursor backspaced-so-far:address:address:duplex-list:character <- get-address *deletion, deleted-text:offset - insert-duplex-range backspaced-cell, *backspaced-so-far + insert-range backspaced-cell, *backspaced-so-far *backspaced-so-far <- copy backspaced-cell after-row:address:number <- get-address *deletion, after-row:offset *after-row <- copy *cursor-row @@ -1655,7 +1655,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } } # if not, create a new operation op:address:operation <- new operation:type - deleted-until:address:duplex-list:character <- next-duplex *before-cursor + deleted-until:address:duplex-list:character <- next *before-cursor *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, *cursor-row/after, *cursor-column/after, top-after, backspaced-cell/deleted, *before-cursor/delete-from, deleted-until, 1/coalesce-backspace editor <- add-operation editor, op +done-adding-backspace-operation @@ -1670,8 +1670,8 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } anchor:address:duplex-list:character <- get *deletion, delete-from:offset break-unless anchor deleted:address:duplex-list:character <- get *deletion, deleted-text:offset - old-cursor:address:duplex-list:character <- last-duplex deleted - insert-duplex-range anchor, deleted + old-cursor:address:duplex-list:character <- last deleted + insert-range anchor, deleted # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen *before-cursor <- copy old-cursor *cursor-row <- get *deletion, before-row:offset @@ -1687,7 +1687,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } break-unless deletion start:address:duplex-list:character <- get *deletion, delete-from:offset end:address:duplex-list:character <- get *deletion, delete-until:offset - remove-duplex-between start, end + remove-between start, end # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen *cursor-row <- get *deletion, after-row:offset *cursor-column <- get *deletion, after-column:offset @@ -1863,9 +1863,9 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } coalesce?:boolean <- equal previous-coalesce-tag, 2/coalesce-delete break-unless coalesce? delete-until:address:address:duplex-list:character <- get-address *deletion, delete-until:offset - *delete-until <- next-duplex *before-cursor + *delete-until <- next *before-cursor deleted-so-far:address:address:duplex-list:character <- get-address *deletion, deleted-text:offset - *deleted-so-far <- append-duplex *deleted-so-far, deleted-cell + *deleted-so-far <- append *deleted-so-far, deleted-cell after-row:address:number <- get-address *deletion, after-row:offset *after-row <- copy *cursor-row after-column:address:number <- get-address *deletion, after-column:offset @@ -1876,7 +1876,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } } # if not, create a new operation op:address:operation <- new operation:type - deleted-until:address:duplex-list:character <- next-duplex *before-cursor + deleted-until:address:duplex-list:character <- next *before-cursor *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, *cursor-row/after, *cursor-column/after, top-after, deleted-cell/deleted, *before-cursor/delete-from, deleted-until, 2/coalesce-delete editor <- add-operation editor, op +done-adding-delete-operation @@ -1977,7 +1977,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } top-after:address:duplex-list:character <- get *editor, top-of-screen:offset undo:address:address:list:address:operation <- get-address *editor, undo:offset op:address:operation <- new operation:type - deleted-until:address:duplex-list:character <- next-duplex *before-cursor + deleted-until:address:duplex-list:character <- next *before-cursor *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, *cursor-row/after, *cursor-column/after, top-after, deleted-cells/deleted, *before-cursor/delete-from, deleted-until, 0/never-coalesce editor <- add-operation editor, op +done-adding-delete-operation @@ -2078,7 +2078,7 @@ body { font-family: monospace; color: #eeeeee; background-color: #080808; } top-after:address:duplex-list:character <- get *editor, top-of-screen:offset undo:address:address:list:address:operation <- get-address *editor, undo:offset op:address:operation <- new operation:type - deleted-until:address:duplex-list:character <- next-duplex *before-cursor + deleted-until:address:duplex-list:character <- next *before-cursor *op <- merge 2/delete-operation, save-row/before, save-column/before, top-before, *cursor-row/after, *cursor-column/after, top-after, deleted-cells/deleted, *before-cursor/delete-from, deleted-until, 0/never-coalesce editor <- add-operation editor, op +done-adding-delete-operation -- cgit 1.4.1-2-gfad0