diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-03-14 01:00:48 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-03-14 01:00:48 -0700 |
commit | 2badd89a58b9666563746d71069abf16f05709ea (patch) | |
tree | 779c9feb243fc8d0f33051cd8323fd23f912f373 /074list.mu | |
parent | 8b095f802129f8c328a3a4dc3de4443890d34d59 (diff) | |
download | mu-2badd89a58b9666563746d71069abf16f05709ea.tar.gz |
2778 - fix all layers
Diffstat (limited to '074list.mu')
-rw-r--r-- | 074list.mu | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/074list.mu b/074list.mu new file mode 100644 index 00000000..856c5e9c --- /dev/null +++ b/074list.mu @@ -0,0 +1,133 @@ +# 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:shared:list:_elem +] + +def push x:_elem, in:address:shared:list:_elem -> in:address:shared:list:_elem [ + local-scope + load-ingredients + result:address:shared:list:_elem <- new {(list _elem): type} + val:address:_elem <- get-address *result, value:offset + *val <- copy x + next:address:address:shared:list:_elem <- get-address *result, next:offset + *next <- copy in + return result # needed explicitly because we need to replace 'in' with 'result' +] + +def first in:address:shared:list:_elem -> result:_elem [ + local-scope + load-ingredients + result <- get *in, value:offset +] + +def rest in:address:shared:list:_elem -> result:address:shared:list:_elem/contained-in:in [ + local-scope + load-ingredients + result <- get *in, next:offset +] + +scenario list-handling [ + run [ + 1:address:shared:list:number <- push 3, 0 + 1:address:shared:list:number <- push 4, 1:address:shared:list:number + 1:address:shared:list:number <- push 5, 1:address:shared:list:number + 2:number <- first 1:address:shared:list:number + 1:address:shared:list:number <- rest 1:address:shared:list:number + 3:number <- first 1:address:shared:list:number + 1:address:shared:list:number <- rest 1:address:shared:list:number + 4:number <- first 1:address:shared:list:number + 1:address:shared:list:number <- rest 1:address:shared:list:number + ] + memory-should-contain [ + 1 <- 0 # empty to empty, dust to dust.. + 2 <- 5 + 3 <- 4 + 4 <- 3 + ] +] + +def to-text in:address:shared:list:_elem -> result:address:shared:array:character [ + local-scope + load-ingredients + buf:address:shared: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:shared:list:_elem -> result:address:shared:array:character [ + local-scope + load-ingredients + buf:address:shared:buffer <- new-buffer 80 + buf <- to-buffer in, buf, 6 # max elements to display + result <- buffer-to-array buf +] + +def to-buffer in:address:shared:list:_elem, buf:address:shared:buffer -> buf:address:shared: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:shared:list:_elem <- rest in + nextn:number <- copy next + return-unless next + space:character <- copy 32/space + buf <- append buf, space:character + s:address:shared:array:character <- new [-> ] + n:number <- length *s + buf <- append buf, s + # 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 + s:address:shared:array:character <- new [...] + append buf, s +] + +scenario stash-on-list-converts-to-text [ + run [ + x:address:shared:list:number <- push 4, 0 + x <- push 5, x + x <- push 6, x + stash [foo foo], x + ] + trace-should-contain [ + app: foo foo 6 -> 5 -> 4 + ] +] + +scenario stash-handles-list-with-cycle [ + run [ + x:address:shared:list:number <- push 4, 0 + y:address:address:shared:list:number <- get-address *x, next:offset + *y <- copy x + stash [foo foo], x + ] + trace-should-contain [ + app: foo foo 4 -> 4 -> 4 -> 4 -> 4 -> 4 -> 4 -> ... + ] +] |