about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-01-20 20:32:43 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-01-20 20:32:43 -0800
commitbd6134610c2ab2742f2fc4159b6e9a99e85d183f (patch)
tree404e34f296eb00faf52d1f26fa53339f5c1b2d9e
parent2186422cded068a90ad4f6589e3307f74e82fcaf (diff)
downloadmu-bd6134610c2ab2742f2fc4159b6e9a99e85d183f.tar.gz
2580 - check product type of 'maybe-convert'
I had to undo some over-zealous changes in 2576.
-rw-r--r--033exclusive_container.cc50
-rw-r--r--edit/011-editor-undo.mu20
-rw-r--r--sandbox/004-programming-environment.mu8
-rw-r--r--sandbox/011-editor-undo.mu20
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 <address : <point : <>>> but 20 has type <address : <shared : <point : <>>>>
+
+
 //:: 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 <insert-character-end> [
     # 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 <handle-undo> [
   {
-    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 <handle-redo> [
   {
-    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 <move-cursor-end> [
     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 <move-cursor-end> [
 
 after <handle-undo> [
   {
-    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 <handle-redo> [
   {
-    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 <backspace-character-end> [
       # 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 <backspace-character-end> [
 
 after <handle-undo> [
   {
-    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 <handle-undo> [
 
 after <handle-redo> [
   {
-    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 <delete-character-end> [
       # 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,
     <handle-event>
     # 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
       <global-keypress>
     }
     {
-      c:address:shared:character <- maybe-convert e:event, text:variant
+      c:address:character <- maybe-convert e:event, text:variant
       break-unless c
       <global-type>
     }
     # '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 <insert-character-end> [
     # 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 <handle-undo> [
   {
-    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 <handle-redo> [
   {
-    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 <move-cursor-end> [
     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 <move-cursor-end> [
 
 after <handle-undo> [
   {
-    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 <handle-redo> [
   {
-    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 <backspace-character-end> [
       # 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 <backspace-character-end> [
 
 after <handle-undo> [
   {
-    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 <handle-undo> [
 
 after <handle-redo> [
   {
-    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 <delete-character-end> [
       # 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