From bd6134610c2ab2742f2fc4159b6e9a99e85d183f Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Wed, 20 Jan 2016 20:32:43 -0800 Subject: 2580 - check product type of 'maybe-convert' I had to undo some over-zealous changes in 2576. --- 033exclusive_container.cc | 50 +++++++++++++++++++++++++++++++--- edit/011-editor-undo.mu | 20 +++++++------- sandbox/004-programming-environment.mu | 8 +++--- sandbox/011-editor-undo.mu | 20 +++++++------- 4 files changed, 70 insertions(+), 28 deletions(-) diff --git a/033exclusive_container.cc b/033exclusive_container.cc index d481ccac..06f7ddec 100644 --- a/033exclusive_container.cc +++ b/033exclusive_container.cc @@ -69,7 +69,7 @@ recipe main [ 12:number <- copy 1 13:number <- copy 35 14:number <- copy 36 - 20:address:point <- maybe-convert 12:number-or-point/unsafe, 0:variant + 20:address:number <- maybe-convert 12:number-or-point/unsafe, 0:variant ] +mem: storing 0 in location 20 @@ -79,18 +79,36 @@ MAYBE_CONVERT, put(Recipe_ordinal, "maybe-convert", MAYBE_CONVERT); :(before "End Primitive Recipe Checks") case MAYBE_CONVERT: { + const recipe& caller = get(Recipe, r); if (SIZE(inst.ingredients) != 2) { - raise_error << maybe(get(Recipe, r).name) << "'maybe-convert' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); + raise_error << maybe(caller.name) << "'maybe-convert' expects exactly 2 ingredients in '" << inst.to_string() << "'\n" << end(); break; } reagent base = inst.ingredients.at(0); canonize_type(base); if (!base.type || !base.type->value || get(Type, base.type->value).kind != EXCLUSIVE_CONTAINER) { - raise_error << maybe(get(Recipe, r).name) << "first ingredient of 'maybe-convert' should be an exclusive-container, but got " << base.original_string << '\n' << end(); + raise_error << maybe(caller.name) << "first ingredient of 'maybe-convert' should be an exclusive-container, but got " << base.original_string << '\n' << end(); break; } if (!is_literal(inst.ingredients.at(1))) { - raise_error << maybe(get(Recipe, r).name) << "second ingredient of 'maybe-convert' should have type 'variant', but got " << inst.ingredients.at(1).original_string << '\n' << end(); + raise_error << maybe(caller.name) << "second ingredient of 'maybe-convert' should have type 'variant', but got " << inst.ingredients.at(1).original_string << '\n' << end(); + break; + } + if (inst.products.empty()) break; + reagent product = inst.products.at(0); + if (!canonize_type(product)) break; + const reagent& offset = inst.ingredients.at(1); + long long int tag = 0; + if (is_integer(offset.name)) { + tag = to_integer(offset.name); + } + else { + tag = offset.value; + } + reagent variant = variant_type(base, tag); + variant.type = new type_tree(get(Type_ordinal, "address"), variant.type); + if (!types_coercible(product, variant)) { + raise_error << maybe(caller.name) << "'maybe-convert " << base.original_string << ", " << inst.ingredients.at(1).original_string << "' should write to " << debug_string(variant.type) << " but " << product.name << " has type " << debug_string(product.type) << '\n' << end(); break; } break; @@ -117,6 +135,30 @@ case MAYBE_CONVERT: { break; } +:(code) +const reagent variant_type(const reagent& canonized_base, long long int tag) { + assert(tag >= 0); + assert(contains_key(Type, canonized_base.type->value)); + assert(!get(Type, canonized_base.type->value).name.empty()); + const type_info& info = get(Type, canonized_base.type->value); + assert(info.kind == EXCLUSIVE_CONTAINER); + reagent element; + element.type = new type_tree(*info.elements.at(tag)); + // End variant_type Special-cases + return element; +} + +:(scenario maybe_convert_product_type_mismatch) +% Hide_errors = true; +recipe main [ + 12:number <- copy 1 + 13:number <- copy 35 + 14:number <- copy 36 + 20:address:shared:point <- maybe-convert 12:number-or-point/unsafe, 1:variant +] ++error: main: 'maybe-convert 12:number-or-point/unsafe, 1:variant' should write to
>> but 20 has type
>>> + + //:: Allow exclusive containers to be defined in mu code. :(scenario exclusive_container) diff --git a/edit/011-editor-undo.mu b/edit/011-editor-undo.mu index 82362dd9..d79e056c 100644 --- a/edit/011-editor-undo.mu +++ b/edit/011-editor-undo.mu @@ -145,7 +145,7 @@ before [ # if previous operation was an insert, coalesce this operation with it break-unless *undo op:address:shared:operation <- first *undo - typing:address:shared:insert-operation <- maybe-convert *op, typing:variant + typing:address:insert-operation <- maybe-convert *op, typing:variant break-unless typing previous-coalesce-tag:number <- get *typing, tag:offset break-unless previous-coalesce-tag @@ -201,7 +201,7 @@ recipe add-operation editor:address:shared:editor-data, op:address:shared:operat after [ { - typing:address:shared:insert-operation <- maybe-convert *op, typing:variant + typing:address:insert-operation <- maybe-convert *op, typing:variant break-unless typing start:address:shared:duplex-list:character <- get *typing, insert-from:offset end:address:shared:duplex-list:character <- get *typing, insert-until:offset @@ -398,7 +398,7 @@ scenario editor-redo-typing [ after [ { - typing:address:shared:insert-operation <- maybe-convert *op, typing:variant + typing:address:insert-operation <- maybe-convert *op, typing:variant break-unless typing insert-from:address:shared:duplex-list:character <- get *typing, insert-from:offset # ignore insert-to because it's already been spliced away # assert insert-to matches next(*before-cursor) @@ -715,7 +715,7 @@ before [ undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset break-unless *undo op:address:shared:operation <- first *undo - move:address:shared:move-operation <- maybe-convert *op, move:variant + move:address:move-operation <- maybe-convert *op, move:variant break-unless move previous-coalesce-tag:number <- get *move, tag:offset coalesce?:boolean <- equal undo-coalesce-tag, previous-coalesce-tag @@ -736,7 +736,7 @@ before [ after [ { - move:address:shared:move-operation <- maybe-convert *op, move:variant + move:address:move-operation <- maybe-convert *op, move:variant break-unless move # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset @@ -1510,7 +1510,7 @@ ghi] after [ { - move:address:shared:move-operation <- maybe-convert *op, move:variant + move:address:move-operation <- maybe-convert *op, move:variant break-unless move # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen *cursor-row <- get *move, after-row:offset @@ -1600,7 +1600,7 @@ before [ # if previous operation was an insert, coalesce this operation with it break-unless *undo op:address:shared:operation <- first *undo - deletion:address:shared:delete-operation <- maybe-convert *op, delete:variant + deletion:address:delete-operation <- maybe-convert *op, delete:variant break-unless deletion previous-coalesce-tag:number <- get *deletion, tag:offset coalesce?:boolean <- equal previous-coalesce-tag, 1/coalesce-backspace @@ -1629,7 +1629,7 @@ before [ after [ { - deletion:address:shared:delete-operation <- maybe-convert *op, delete:variant + deletion:address:delete-operation <- maybe-convert *op, delete:variant break-unless deletion start2:address:address:shared:duplex-list:character <- get-address *editor, data:offset anchor:address:shared:duplex-list:character <- get *deletion, delete-from:offset @@ -1648,7 +1648,7 @@ after [ after [ { - deletion:address:shared:delete-operation <- maybe-convert *op, delete:variant + deletion:address:delete-operation <- maybe-convert *op, delete:variant break-unless deletion start:address:shared:duplex-list:character <- get *deletion, delete-from:offset end:address:shared:duplex-list:character <- get *deletion, delete-until:offset @@ -1822,7 +1822,7 @@ before [ # if previous operation was an insert, coalesce this operation with it break-unless *undo op:address:shared:operation <- first *undo - deletion:address:shared:delete-operation <- maybe-convert *op, delete:variant + deletion:address:delete-operation <- maybe-convert *op, delete:variant break-unless deletion previous-coalesce-tag:number <- get *deletion, tag:offset coalesce?:boolean <- equal previous-coalesce-tag, 2/coalesce-delete diff --git a/sandbox/004-programming-environment.mu b/sandbox/004-programming-environment.mu index 3e8922e5..b6c50fbf 100644 --- a/sandbox/004-programming-environment.mu +++ b/sandbox/004-programming-environment.mu @@ -56,18 +56,18 @@ recipe event-loop screen:address:shared:screen, console:address:shared:console, # check for global events that will trigger regardless of which editor has focus { - k:address:shared:number <- maybe-convert e:event, keycode:variant + k:address:number <- maybe-convert e:event, keycode:variant break-unless k } { - c:address:shared:character <- maybe-convert e:event, text:variant + c:address:character <- maybe-convert e:event, text:variant break-unless c } # 'touch' event { - t:address:shared:touch-event <- maybe-convert e:event, touch:variant + t:address:touch-event <- maybe-convert e:event, touch:variant break-unless t # ignore all but 'left-click' events for now # todo: test this @@ -83,7 +83,7 @@ recipe event-loop screen:address:shared:screen, console:address:shared:console, # 'resize' event - redraw editor # todo: test this after supporting resize in assume-console { - r:address:shared:resize-event <- maybe-convert e:event, resize:variant + r:address:resize-event <- maybe-convert e:event, resize:variant break-unless r # if more events, we're still resizing; wait until we stop more-events?:boolean <- has-more-events? console diff --git a/sandbox/011-editor-undo.mu b/sandbox/011-editor-undo.mu index 82362dd9..d79e056c 100644 --- a/sandbox/011-editor-undo.mu +++ b/sandbox/011-editor-undo.mu @@ -145,7 +145,7 @@ before [ # if previous operation was an insert, coalesce this operation with it break-unless *undo op:address:shared:operation <- first *undo - typing:address:shared:insert-operation <- maybe-convert *op, typing:variant + typing:address:insert-operation <- maybe-convert *op, typing:variant break-unless typing previous-coalesce-tag:number <- get *typing, tag:offset break-unless previous-coalesce-tag @@ -201,7 +201,7 @@ recipe add-operation editor:address:shared:editor-data, op:address:shared:operat after [ { - typing:address:shared:insert-operation <- maybe-convert *op, typing:variant + typing:address:insert-operation <- maybe-convert *op, typing:variant break-unless typing start:address:shared:duplex-list:character <- get *typing, insert-from:offset end:address:shared:duplex-list:character <- get *typing, insert-until:offset @@ -398,7 +398,7 @@ scenario editor-redo-typing [ after [ { - typing:address:shared:insert-operation <- maybe-convert *op, typing:variant + typing:address:insert-operation <- maybe-convert *op, typing:variant break-unless typing insert-from:address:shared:duplex-list:character <- get *typing, insert-from:offset # ignore insert-to because it's already been spliced away # assert insert-to matches next(*before-cursor) @@ -715,7 +715,7 @@ before [ undo:address:address:shared:list:address:shared:operation <- get-address *editor, undo:offset break-unless *undo op:address:shared:operation <- first *undo - move:address:shared:move-operation <- maybe-convert *op, move:variant + move:address:move-operation <- maybe-convert *op, move:variant break-unless move previous-coalesce-tag:number <- get *move, tag:offset coalesce?:boolean <- equal undo-coalesce-tag, previous-coalesce-tag @@ -736,7 +736,7 @@ before [ after [ { - move:address:shared:move-operation <- maybe-convert *op, move:variant + move:address:move-operation <- maybe-convert *op, move:variant break-unless move # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen top:address:address:shared:duplex-list:character <- get-address *editor, top-of-screen:offset @@ -1510,7 +1510,7 @@ ghi] after [ { - move:address:shared:move-operation <- maybe-convert *op, move:variant + move:address:move-operation <- maybe-convert *op, move:variant break-unless move # assert cursor-row/cursor-column/top-of-screen match after-row/after-column/after-top-of-screen *cursor-row <- get *move, after-row:offset @@ -1600,7 +1600,7 @@ before [ # if previous operation was an insert, coalesce this operation with it break-unless *undo op:address:shared:operation <- first *undo - deletion:address:shared:delete-operation <- maybe-convert *op, delete:variant + deletion:address:delete-operation <- maybe-convert *op, delete:variant break-unless deletion previous-coalesce-tag:number <- get *deletion, tag:offset coalesce?:boolean <- equal previous-coalesce-tag, 1/coalesce-backspace @@ -1629,7 +1629,7 @@ before [ after [ { - deletion:address:shared:delete-operation <- maybe-convert *op, delete:variant + deletion:address:delete-operation <- maybe-convert *op, delete:variant break-unless deletion start2:address:address:shared:duplex-list:character <- get-address *editor, data:offset anchor:address:shared:duplex-list:character <- get *deletion, delete-from:offset @@ -1648,7 +1648,7 @@ after [ after [ { - deletion:address:shared:delete-operation <- maybe-convert *op, delete:variant + deletion:address:delete-operation <- maybe-convert *op, delete:variant break-unless deletion start:address:shared:duplex-list:character <- get *deletion, delete-from:offset end:address:shared:duplex-list:character <- get *deletion, delete-until:offset @@ -1822,7 +1822,7 @@ before [ # if previous operation was an insert, coalesce this operation with it break-unless *undo op:address:shared:operation <- first *undo - deletion:address:shared:delete-operation <- maybe-convert *op, delete:variant + deletion:address:delete-operation <- maybe-convert *op, delete:variant break-unless deletion previous-coalesce-tag:number <- get *deletion, tag:offset coalesce?:boolean <- equal previous-coalesce-tag, 2/coalesce-delete -- cgit 1.4.1-2-gfad0