about summary refs log tree commit diff stats
path: root/064list.mu
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-06-13 16:25:45 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-06-13 16:25:45 -0700
commit5e15a74f06e19e75954547cadc8bc73f9034727e (patch)
tree865531ced05be722a67dd874338c791eb4da9622 /064list.mu
parent29cc15d6b3559221e1147f1a822e10dcb22678e6 (diff)
downloadmu-5e15a74f06e19e75954547cadc8bc73f9034727e.tar.gz
3055
Diffstat (limited to '064list.mu')
-rw-r--r--064list.mu110
1 files changed, 110 insertions, 0 deletions
diff --git a/064list.mu b/064list.mu
new file mode 100644
index 00000000..80613694
--- /dev/null
+++ b/064list.mu
@@ -0,0 +1,110 @@
+# A list links up multiple objects together to make them easier to manage.
+#
+# The objects must be of the same type. If you want to store multiple types in
+# a single list, use an exclusive-container.
+
+container list:_elem [
+  value:_elem
+  next:address:list:_elem
+]
+
+def push x:_elem, in:address:list:_elem -> result:address:list:_elem [
+  local-scope
+  load-ingredients
+  result <- new {(list _elem): type}
+  *result <- merge x, in
+]
+
+def first in:address:list:_elem -> result:_elem [
+  local-scope
+  load-ingredients
+  result <- get *in, value:offset
+]
+
+def rest in:address:list:_elem -> result:address:list:_elem/contained-in:in [
+  local-scope
+  load-ingredients
+  result <- get *in, next:offset
+]
+
+scenario list-handling [
+  run [
+    local-scope
+    x:address:list:number <- push 3, 0
+    x <- push 4, x
+    x <- push 5, x
+    10:number/raw <- first x
+    x <- rest x
+    11:number/raw <- first x
+    x <- rest x
+    12:number/raw <- first x
+    20:address:list:number/raw <- rest x
+  ]
+  memory-should-contain [
+    10 <- 5
+    11 <- 4
+    12 <- 3
+    20 <- 0  # nothing left
+  ]
+]
+
+def length l:address:list:_elem -> result:number [
+  local-scope
+  load-ingredients
+  return-unless l, 0
+  rest:address:list:_elem <- rest l
+  length-of-rest:number <- length rest
+  result <- add length-of-rest, 1
+]
+
+def to-text in:address:list:_elem -> result:address:array:character [
+  local-scope
+  load-ingredients
+  buf:address:buffer <- new-buffer 80
+  buf <- to-buffer in, buf
+  result <- buffer-to-array buf
+]
+
+# variant of 'to-text' which stops printing after a few elements (and so is robust to cycles)
+def to-text-line in:address:list:_elem -> result:address:array:character [
+  local-scope
+  load-ingredients
+  buf:address:buffer <- new-buffer 80
+  buf <- to-buffer in, buf, 6  # max elements to display
+  result <- buffer-to-array buf
+]
+
+def to-buffer in:address:list:_elem, buf:address:buffer -> buf:address:buffer [
+  local-scope
+  load-ingredients
+  {
+    break-if in
+    buf <- append buf, 48/0
+    return
+  }
+  # append in.value to buf
+  val:_elem <- get *in, value:offset
+  buf <- append buf, val
+  # now prepare next
+  next:address:list:_elem <- rest in
+  nextn:number <- copy next
+  return-unless next
+  buf <- append buf, [ -> ]
+  # and recurse
+  remaining:number, optional-ingredient-found?:boolean <- next-ingredient
+  {
+    break-if optional-ingredient-found?
+    # unlimited recursion
+    buf <- to-buffer next, buf
+    return
+  }
+  {
+    break-unless remaining
+    # limited recursion
+    remaining <- subtract remaining, 1
+    buf <- to-buffer next, buf, remaining
+    return
+  }
+  # past recursion depth; insert ellipses and stop
+  append buf, [...]
+]