about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-06-18 11:16:37 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-06-18 11:16:43 -0700
commit9e86933229e6d6d45f0192a23e618557540d21d9 (patch)
tree491e8745b0e7f87f7045da68f00c212459145dcb
parent28c52ee125769488d790e8524095ca27f0f18795 (diff)
downloadmu-9e86933229e6d6d45f0192a23e618557540d21d9.tar.gz
1593
-rw-r--r--030container.cc3
-rw-r--r--065duplex_list.mu75
2 files changed, 77 insertions, 1 deletions
diff --git a/030container.cc b/030container.cc
index a1bb2290..9f337251 100644
--- a/030container.cc
+++ b/030container.cc
@@ -107,7 +107,8 @@ case GET: {
   reagent base = current_instruction().ingredients.at(0);
   long long int base_address = base.value;
   type_number base_type = base.types.at(0);
-  assert(Type[base_type].kind == container);
+  if (Type[base_type].kind != container)
+    raise << "'get' on a non-container in " << current_recipe_name () << ": " << current_instruction().to_string() << '\n' << die();
   assert(is_literal(current_instruction().ingredients.at(1)));
   assert(scalar(ingredients.at(1)));
   long long int offset = ingredients.at(1).at(0);
diff --git a/065duplex_list.mu b/065duplex_list.mu
index 9caf21d3..8334066c 100644
--- a/065duplex_list.mu
+++ b/065duplex_list.mu
@@ -210,3 +210,78 @@ scenario inserting-after-start-of-duplex-list [
     10 <- 1  # list back at start
   ]
 ]
+
+# l:address:duplex-list <- remove-duplex in:address:duplex-list
+# Removes 'in' from its surrounding list. Returns some valid pointer into the
+# rest of the list. Returns null if and only if list is empty.
+recipe remove-duplex [
+  default-space:address:array:location <- new location:type, 30:literal
+  in:address:duplex-list <- next-ingredient
+  # if 'in' is null, return
+  reply-unless in:address:duplex-list, in:address:duplex-list
+  next-node:address:duplex-list <- get in:address:duplex-list/deref, next:offset
+  prev-node:address:duplex-list <- get in:address:duplex-list/deref, prev:offset
+  # null in's pointers
+  x:address:address:duplex-list <- get-address in:address:duplex-list/deref, next:offset
+  x:address:address:duplex-list/deref <- copy 0:literal
+  x:address:address:duplex-list <- get-address in:address:duplex-list/deref, prev:offset
+  x:address:address:duplex-list/deref <- copy 0:literal
+  {
+    # if next-node is not null
+    break-unless next-node:address:duplex-list
+    # next-node.prev = prev-node
+    x:address:address:duplex-list <- get-address next-node:address:duplex-list/deref, prev:offset
+    x:address:address:duplex-list/deref <- copy prev-node:address:duplex-list
+  }
+  {
+    # if prev-node is not null
+    break-unless prev-node:address:duplex-list
+    # prev-node.next = next-node
+    x:address:address:duplex-list <- get-address prev-node:address:duplex-list/deref, next:offset
+    x:address:address:duplex-list/deref <- copy next-node:address:duplex-list
+    reply prev-node:address:duplex-list
+  }
+  reply next-node:address:duplex-list
+]
+
+scenario removing-from-duplex-list [
+  run [
+    1:address:duplex-list <- copy 0:literal  # 1 points to head of list
+    1:address:duplex-list <- push-duplex 3:literal, 1:address:duplex-list
+    1:address:duplex-list <- push-duplex 4:literal, 1:address:duplex-list
+    1:address:duplex-list <- push-duplex 5:literal, 1:address:duplex-list
+    2:address:duplex-list <- next-duplex 1:address:duplex-list  # 2 points at second element
+    2:address:duplex-list <- remove-duplex 2:address:duplex-list
+    # check structure like before
+    2:address:duplex-list <- copy 1:address:duplex-list
+    3:number <- first 2:address:duplex-list
+    2:address:duplex-list <- next-duplex 2:address:duplex-list
+    4:number <- first 2:address:duplex-list
+    5:address:duplex-list <- next-duplex 2:address:duplex-list
+    2:address:duplex-list <- prev-duplex 2:address:duplex-list
+    6:number <- first 2:address:duplex-list
+    7:boolean <- equal 1:address:duplex-list, 2:address:duplex-list
+  ]
+  memory-should-contain [
+    3 <- 5  # scanning next, skipping deleted element
+    4 <- 3
+    5 <- 0  # no more elements
+    6 <- 5  # prev of final element
+    7 <- 1  # list back at start
+  ]
+]
+
+scenario removing-from-singleton-list [
+  run [
+    1:address:duplex-list <- copy 0:literal  # 1 points to singleton list
+    1:address:duplex-list <- push-duplex 3:literal, 1:address:duplex-list
+    2:address:duplex-list <- remove-duplex 1:address:duplex-list
+    3:address:duplex-list <- get 1:address:duplex-list/deref, next:offset
+    4:address:duplex-list <- get 1:address:duplex-list/deref, prev:offset
+  ]
+  memory-should-contain [
+    2 <- 0  # list is now empty
+    3 <- 0  # removed node is also detached
+    4 <- 0
+  ]
+]