about summary refs log tree commit diff stats
path: root/070text.mu
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-01-19 23:18:03 -0800
committerKartik K. Agaram <vc@akkartik.com>2016-01-19 23:18:03 -0800
commit455fbac64f101b05f7eaca89b84470569e4df3fd (patch)
tree32cfd5b092ad86086e4d15992bb10fd06a12bf13 /070text.mu
parent7163e18a774781c62f0c0542e4cb9037f6a71d22 (diff)
downloadmu-455fbac64f101b05f7eaca89b84470569e4df3fd.tar.gz
2576 - distinguish allocated addresses from others
This is the one major refinement on the C programming model I'm planning
to introduce in mu. Instead of Rust's menagerie of pointer types and
static checking, I want to introduce just one new type, and use it to
perform ref-counting at runtime.

So far all we're doing is updating new's interface. The actual
ref-counting implementation is next.

One implication: I might sometimes need duplicate implementations for a
recipe with allocated vs vanilla addresses of the same type. So far it
seems I can get away with just always passing in allocated addresses;
the situations when you want to pass an unallocated address to a recipe
should be few and far between.
Diffstat (limited to '070text.mu')
-rw-r--r--070text.mu456
1 files changed, 228 insertions, 228 deletions
diff --git a/070text.mu b/070text.mu
index 37acdfd5..4dc138a7 100644
--- a/070text.mu
+++ b/070text.mu
@@ -2,21 +2,21 @@
 
 # to-text-line gets called implicitly in various places
 # define it to be identical to 'to-text' by default
-recipe to-text-line x:_elem -> y:address:array:character [
+recipe to-text-line x:_elem -> y:address:shared:array:character [
   local-scope
   load-ingredients
   y <- to-text x
 ]
 
 # to-text on text is just the identity function
-recipe to-text x:address:array:character -> y:address:array:character [
+recipe to-text x:address:shared:array:character -> y:address:shared:array:character [
   local-scope
   load-ingredients
 #?   $print [to-text text], 10/newline
   reply x
 ]
 
-recipe equal a:address:array:character, b:address:array:character -> result:boolean [
+recipe equal a:address:shared:array:character, b:address:shared:array:character -> result:boolean [
   local-scope
   load-ingredients
   a-len:number <- length *a
@@ -49,8 +49,8 @@ recipe equal a:address:array:character, b:address:array:character -> result:bool
 
 scenario text-equal-reflexive [
   run [
-    default-space:address:array:location <- new location:type, 30
-    x:address:array:character <- new [abc]
+    default-space:address:shared:array:location <- new location:type, 30
+    x:address:shared:array:character <- new [abc]
     3:boolean/raw <- equal x, x
   ]
   memory-should-contain [
@@ -60,9 +60,9 @@ scenario text-equal-reflexive [
 
 scenario text-equal-identical [
   run [
-    default-space:address:array:location <- new location:type, 30
-    x:address:array:character <- new [abc]
-    y:address:array:character <- new [abc]
+    default-space:address:shared:array:location <- new location:type, 30
+    x:address:shared:array:character <- new [abc]
+    y:address:shared:array:character <- new [abc]
     3:boolean/raw <- equal x, y
   ]
   memory-should-contain [
@@ -72,9 +72,9 @@ scenario text-equal-identical [
 
 scenario text-equal-distinct-lengths [
   run [
-    default-space:address:array:location <- new location:type, 30
-    x:address:array:character <- new [abc]
-    y:address:array:character <- new [abcd]
+    default-space:address:shared:array:location <- new location:type, 30
+    x:address:shared:array:character <- new [abc]
+    y:address:shared:array:character <- new [abcd]
     3:boolean/raw <- equal x, y
   ]
   memory-should-contain [
@@ -90,9 +90,9 @@ scenario text-equal-distinct-lengths [
 
 scenario text-equal-with-empty [
   run [
-    default-space:address:array:location <- new location:type, 30
-    x:address:array:character <- new []
-    y:address:array:character <- new [abcd]
+    default-space:address:shared:array:location <- new location:type, 30
+    x:address:shared:array:character <- new []
+    y:address:shared:array:character <- new [abcd]
     3:boolean/raw <- equal x, y
   ]
   memory-should-contain [
@@ -102,9 +102,9 @@ scenario text-equal-with-empty [
 
 scenario text-equal-common-lengths-but-distinct [
   run [
-    default-space:address:array:location <- new location:type, 30
-    x:address:array:character <- new [abc]
-    y:address:array:character <- new [abd]
+    default-space:address:shared:array:location <- new location:type, 30
+    x:address:shared:array:character <- new [abc]
+    y:address:shared:array:character <- new [abd]
     3:boolean/raw <- equal x, y
   ]
   memory-should-contain [
@@ -115,28 +115,28 @@ scenario text-equal-common-lengths-but-distinct [
 # A new type to help incrementally construct texts.
 container buffer [
   length:number
-  data:address:array:character
+  data:address:shared:array:character
 ]
 
-recipe new-buffer capacity:number -> result:address:buffer [
+recipe new-buffer capacity:number -> result:address:shared:buffer [
   local-scope
   load-ingredients
   result <- new buffer:type
   len:address:number <- get-address *result, length:offset
   *len:address:number <- copy 0
-  s:address:address:array:character <- get-address *result, data:offset
+  s:address:address:shared:array:character <- get-address *result, data:offset
   *s <- new character:type, capacity
   reply result
 ]
 
-recipe grow-buffer in:address:buffer -> in:address:buffer [
+recipe grow-buffer in:address:shared:buffer -> in:address:shared:buffer [
   local-scope
   load-ingredients
   # double buffer size
-  x:address:address:array:character <- get-address *in, data:offset
+  x:address:address:shared:array:character <- get-address *in, data:offset
   oldlen:number <- length **x
   newlen:number <- multiply oldlen, 2
-  olddata:address:array:character <- copy *x
+  olddata:address:shared:array:character <- copy *x
   *x <- new character:type, newlen
   # copy old contents
   i:number <- copy 0
@@ -151,21 +151,21 @@ recipe grow-buffer in:address:buffer -> in:address:buffer [
   }
 ]
 
-recipe buffer-full? in:address:buffer -> result:boolean [
+recipe buffer-full? in:address:shared:buffer -> result:boolean [
   local-scope
   load-ingredients
   len:number <- get *in, length:offset
-  s:address:array:character <- get *in, data:offset
+  s:address:shared:array:character <- get *in, data:offset
   capacity:number <- length *s
   result <- greater-or-equal len, capacity
 ]
 
 # most broadly applicable definition of append to a buffer: just call to-text
-recipe append buf:address:buffer, x:_elem -> buf:address:buffer [
+recipe append buf:address:shared:buffer, x:_elem -> buf:address:shared:buffer [
   local-scope
 #?   $print [append _elem to buffer], 10/newline
   load-ingredients
-  text:address:array:character <- to-text x
+  text:address:shared:array:character <- to-text x
   len:number <- length *text
   i:number <- copy 0
   {
@@ -178,7 +178,7 @@ recipe append buf:address:buffer, x:_elem -> buf:address:buffer [
   }
 ]
 
-recipe append in:address:buffer, c:character -> in:address:buffer [
+recipe append in:address:shared:buffer, c:character -> in:address:shared:buffer [
   local-scope
 #?   $print [append character to buffer], 10/newline
   load-ingredients
@@ -198,7 +198,7 @@ recipe append in:address:buffer, c:character -> in:address:buffer [
     break-unless full?
     in <- grow-buffer in
   }
-  s:address:array:character <- get *in, data:offset
+  s:address:shared:array:character <- get *in, data:offset
   dest:address:character <- index-address *s, *len
   *dest <- copy c
   *len <- add *len, 1
@@ -207,20 +207,20 @@ recipe append in:address:buffer, c:character -> in:address:buffer [
 scenario buffer-append-works [
   run [
     local-scope
-    x:address:buffer <- new-buffer 3
-    s1:address:array:character <- get *x:address:buffer, data:offset
-    x:address:buffer <- append x:address:buffer, 97  # 'a'
-    x:address:buffer <- append x:address:buffer, 98  # 'b'
-    x:address:buffer <- append x:address:buffer, 99  # 'c'
-    s2:address:array:character <- get *x:address:buffer, data:offset
-    1:boolean/raw <- equal s1:address:array:character, s2:address:array:character
-    2:array:character/raw <- copy *s2:address:array:character
+    x:address:shared:buffer <- new-buffer 3
+    s1:address:shared:array:character <- get *x, data:offset
+    x <- append x, 97  # 'a'
+    x <- append x, 98  # 'b'
+    x <- append x, 99  # 'c'
+    s2:address:shared:array:character <- get *x, data:offset
+    1:boolean/raw <- equal s1, s2
+    2:array:character/raw <- copy *s2
     +buffer-filled
-    x:address:buffer <- append x:address:buffer, 100  # 'd'
-    s3:address:array:character <- get *x:address:buffer, data:offset
-    10:boolean/raw <- equal s1:address:array:character, s3:address:array:character
-    11:number/raw <- get *x:address:buffer, length:offset
-    12:array:character/raw <- copy *s3:address:array:character
+    x <- append x, 100  # 'd'
+    s3:address:shared:array:character <- get *x, data:offset
+    10:boolean/raw <- equal s1, s3
+    11:number/raw <- get *x, length:offset
+    12:array:character/raw <- copy *s3
   ]
   memory-should-contain [
     # before +buffer-filled
@@ -245,11 +245,11 @@ scenario buffer-append-works [
 scenario buffer-append-handles-backspace [
   run [
     local-scope
-    x:address:buffer <- new-buffer 3
+    x:address:shared:buffer <- new-buffer 3
     x <- append x, 97  # 'a'
     x <- append x, 98  # 'b'
     x <- append x, 8/backspace
-    s:address:array:character <- buffer-to-array x
+    s:address:shared:array:character <- buffer-to-array x
     1:array:character/raw <- copy *s
   ]
   memory-should-contain [
@@ -259,7 +259,7 @@ scenario buffer-append-handles-backspace [
   ]
 ]
 
-recipe to-text n:number -> result:address:array:character [
+recipe to-text n:number -> result:address:shared:array:character [
   local-scope
   load-ingredients
   # is n zero?
@@ -277,14 +277,14 @@ recipe to-text n:number -> result:address:array:character [
     n <- multiply n, -1
   }
   # add digits from right to left into intermediate buffer
-  tmp:address:buffer <- new-buffer 30
+  tmp:address:shared:buffer <- new-buffer 30
   digit-base:number <- copy 48  # '0'
   {
     done?:boolean <- equal n, 0
     break-if done?
     n, digit:number <- divide-with-remainder n, 10
     c:character <- add digit-base, digit
-    tmp:address:buffer <- append tmp, c
+    tmp:address:shared:buffer <- append tmp, c
     loop
   }
   # add sign
@@ -294,7 +294,7 @@ recipe to-text n:number -> result:address:array:character [
   }
   # reverse buffer into text result
   len:number <- get *tmp, length:offset
-  buf:address:array:character <- get *tmp, data:offset
+  buf:address:shared:array:character <- get *tmp, data:offset
   result <- new character:type, len
   i:number <- subtract len, 1  # source index, decreasing
   j:number <- copy 0  # destination index, increasing
@@ -312,7 +312,7 @@ recipe to-text n:number -> result:address:array:character [
   }
 ]
 
-recipe buffer-to-array in:address:buffer -> result:address:array:character [
+recipe buffer-to-array in:address:shared:buffer -> result:address:shared:array:character [
   local-scope
   load-ingredients
   {
@@ -321,7 +321,7 @@ recipe buffer-to-array in:address:buffer -> result:address:array:character [
     reply 0
   }
   len:number <- get *in, length:offset
-  s:address:array:character <- get *in, data:offset
+  s:address:shared:array:character <- get *in, data:offset
   # we can't just return s because it is usually the wrong length
   result <- new character:type, len
   i:number <- copy 0
@@ -338,8 +338,8 @@ recipe buffer-to-array in:address:buffer -> result:address:array:character [
 
 scenario integer-to-decimal-digit-zero [
   run [
-    1:address:array:character/raw <- to-text 0
-    2:array:character/raw <- copy *1:address:array:character/raw
+    1:address:shared:array:character/raw <- to-text 0
+    2:array:character/raw <- copy *1:address:shared:array:character/raw
   ]
   memory-should-contain [
     2:array:character <- [0]
@@ -348,8 +348,8 @@ scenario integer-to-decimal-digit-zero [
 
 scenario integer-to-decimal-digit-positive [
   run [
-    1:address:array:character/raw <- to-text 234
-    2:array:character/raw <- copy *1:address:array:character/raw
+    1:address:shared:array:character/raw <- to-text 234
+    2:array:character/raw <- copy *1:address:shared:array:character/raw
   ]
   memory-should-contain [
     2:array:character <- [234]
@@ -358,8 +358,8 @@ scenario integer-to-decimal-digit-positive [
 
 scenario integer-to-decimal-digit-negative [
   run [
-    1:address:array:character/raw <- to-text -1
-    2:array:character/raw <- copy *1:address:array:character/raw
+    1:address:shared:array:character/raw <- to-text -1
+    2:array:character/raw <- copy *1:address:shared:array:character/raw
   ]
   memory-should-contain [
     2 <- 2
@@ -368,7 +368,7 @@ scenario integer-to-decimal-digit-negative [
   ]
 ]
 
-recipe append a:address:array:character, b:address:array:character -> result:address:array:character [
+recipe append a:address:shared:array:character, b:address:shared:array:character -> result:address:shared:array:character [
   local-scope
 #?   $print [append text to text], 10/newline
   load-ingredients
@@ -410,10 +410,10 @@ recipe append a:address:array:character, b:address:array:character -> result:add
 
 scenario text-append-1 [
   run [
-    1:address:array:character/raw <- new [hello,]
-    2:address:array:character/raw <- new [ world!]
-    3:address:array:character/raw <- append 1:address:array:character/raw, 2:address:array:character/raw
-    4:array:character/raw <- copy *3:address:array:character/raw
+    1:address:shared:array:character/raw <- new [hello,]
+    2:address:shared:array:character/raw <- new [ world!]
+    3:address:shared:array:character/raw <- append 1:address:shared:array:character/raw, 2:address:shared:array:character/raw
+    4:array:character/raw <- copy *3:address:shared:array:character/raw
   ]
   memory-should-contain [
     4:array:character <- [hello, world!]
@@ -422,16 +422,16 @@ scenario text-append-1 [
 
 scenario replace-character-in-text [
   run [
-    1:address:array:character/raw <- new [abc]
-    1:address:array:character/raw <- replace 1:address:array:character/raw, 98/b, 122/z
-    2:array:character/raw <- copy *1:address:array:character/raw
+    1:address:shared:array:character/raw <- new [abc]
+    1:address:shared:array:character/raw <- replace 1:address:shared:array:character/raw, 98/b, 122/z
+    2:array:character/raw <- copy *1:address:shared:array:character/raw
   ]
   memory-should-contain [
     2:array:character <- [azc]
   ]
 ]
 
-recipe replace s:address:array:character, oldc:character, newc:character, from:number/optional -> s:address:array:character [
+recipe replace s:address:shared:array:character, oldc:character, newc:character, from:number/optional -> s:address:shared:array:character [
   local-scope
   load-ingredients
   len:number <- length *s
@@ -446,9 +446,9 @@ recipe replace s:address:array:character, oldc:character, newc:character, from:n
 
 scenario replace-character-at-start [
   run [
-    1:address:array:character/raw <- new [abc]
-    1:address:array:character/raw <- replace 1:address:array:character/raw, 97/a, 122/z
-    2:array:character/raw <- copy *1:address:array:character/raw
+    1:address:shared:array:character/raw <- new [abc]
+    1:address:shared:array:character/raw <- replace 1:address:shared:array:character/raw, 97/a, 122/z
+    2:array:character/raw <- copy *1:address:shared:array:character/raw
   ]
   memory-should-contain [
     2:array:character <- [zbc]
@@ -457,9 +457,9 @@ scenario replace-character-at-start [
 
 scenario replace-character-at-end [
   run [
-    1:address:array:character/raw <- new [abc]
-    1:address:array:character/raw <- replace 1:address:array:character/raw, 99/c, 122/z
-    2:array:character/raw <- copy *1:address:array:character/raw
+    1:address:shared:array:character/raw <- new [abc]
+    1:address:shared:array:character/raw <- replace 1:address:shared:array:character/raw, 99/c, 122/z
+    2:array:character/raw <- copy *1:address:shared:array:character/raw
   ]
   memory-should-contain [
     2:array:character <- [abz]
@@ -468,9 +468,9 @@ scenario replace-character-at-end [
 
 scenario replace-character-missing [
   run [
-    1:address:array:character/raw <- new [abc]
-    1:address:array:character/raw <- replace 1:address:array:character/raw, 100/d, 122/z
-    2:array:character/raw <- copy *1:address:array:character/raw
+    1:address:shared:array:character/raw <- new [abc]
+    1:address:shared:array:character/raw <- replace 1:address:shared:array:character/raw, 100/d, 122/z
+    2:array:character/raw <- copy *1:address:shared:array:character/raw
   ]
   memory-should-contain [
     2:array:character <- [abc]
@@ -479,9 +479,9 @@ scenario replace-character-missing [
 
 scenario replace-all-characters [
   run [
-    1:address:array:character/raw <- new [banana]
-    1:address:array:character/raw <- replace 1:address:array:character/raw, 97/a, 122/z
-    2:array:character/raw <- copy *1:address:array:character/raw
+    1:address:shared:array:character/raw <- new [banana]
+    1:address:shared:array:character/raw <- replace 1:address:shared:array:character/raw, 97/a, 122/z
+    2:array:character/raw <- copy *1:address:shared:array:character/raw
   ]
   memory-should-contain [
     2:array:character <- [bznznz]
@@ -489,7 +489,7 @@ scenario replace-all-characters [
 ]
 
 # replace underscores in first with remaining args
-recipe interpolate template:address:array:character -> result:address:array:character [
+recipe interpolate template:address:shared:array:character -> result:address:shared:array:character [
   local-scope
   load-ingredients  # consume just the template
   # compute result-len, space to allocate for result
@@ -497,7 +497,7 @@ recipe interpolate template:address:array:character -> result:address:array:char
   result-len:number <- copy tem-len
   {
     # while ingredients remain
-    a:address:array:character, arg-received?:boolean <- next-ingredient
+    a:address:shared:array:character, arg-received?:boolean <- next-ingredient
     break-unless arg-received?
     # result-len = result-len + arg.length - 1 (for the 'underscore' being replaced)
     a-len:number <- length *a
@@ -507,13 +507,13 @@ recipe interpolate template:address:array:character -> result:address:array:char
   }
   rewind-ingredients
   _ <- next-ingredient  # skip template
-  result:address:array:character <- new character:type, result-len
+  result <- new character:type, result-len
   # repeatedly copy sections of template and 'holes' into result
   result-idx:number <- copy 0
   i:number <- copy 0
   {
     # while arg received
-    a:address:array:character, arg-received?:boolean <- next-ingredient
+    a:address:shared:array:character, arg-received?:boolean <- next-ingredient
     break-unless arg-received?
     # copy template into result until '_'
     {
@@ -567,10 +567,10 @@ recipe interpolate template:address:array:character -> result:address:array:char
 
 scenario interpolate-works [
   run [
-    1:address:array:character/raw <- new [abc _]
-    2:address:array:character/raw <- new [def]
-    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
-    4:array:character/raw <- copy *3:address:array:character/raw
+    1:address:shared:array:character/raw <- new [abc _]
+    2:address:shared:array:character/raw <- new [def]
+    3:address:shared:array:character/raw <- interpolate 1:address:shared:array:character/raw, 2:address:shared:array:character/raw
+    4:array:character/raw <- copy *3:address:shared:array:character/raw
   ]
   memory-should-contain [
     4:array:character <- [abc def]
@@ -579,10 +579,10 @@ scenario interpolate-works [
 
 scenario interpolate-at-start [
   run [
-    1:address:array:character/raw <- new [_, hello!]
-    2:address:array:character/raw <- new [abc]
-    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
-    4:array:character/raw <- copy *3:address:array:character/raw
+    1:address:shared:array:character/raw <- new [_, hello!]
+    2:address:shared:array:character/raw <- new [abc]
+    3:address:shared:array:character/raw <- interpolate 1:address:shared:array:character/raw, 2:address:shared:array:character/raw
+    4:array:character/raw <- copy *3:address:shared:array:character/raw
   ]
   memory-should-contain [
     4:array:character <- [abc, hello!]
@@ -592,10 +592,10 @@ scenario interpolate-at-start [
 
 scenario interpolate-at-end [
   run [
-    1:address:array:character/raw <- new [hello, _]
-    2:address:array:character/raw <- new [abc]
-    3:address:array:character/raw <- interpolate 1:address:array:character/raw, 2:address:array:character/raw
-    4:array:character/raw <- copy *3:address:array:character/raw
+    1:address:shared:array:character/raw <- new [hello, _]
+    2:address:shared:array:character/raw <- new [abc]
+    3:address:shared:array:character/raw <- interpolate 1:address:shared:array:character/raw, 2:address:shared:array:character/raw
+    4:array:character/raw <- copy *3:address:shared:array:character/raw
   ]
   memory-should-contain [
     4:array:character <- [hello, abc]
@@ -664,7 +664,7 @@ recipe space? c:character -> result:boolean [
   result <- equal c, 12288/ideographic-space
 ]
 
-recipe trim s:address:array:character -> result:address:array:character [
+recipe trim s:address:shared:array:character -> result:address:shared:array:character [
   local-scope
   load-ingredients
   len:number <- length *s
@@ -696,7 +696,7 @@ recipe trim s:address:array:character -> result:address:array:character [
   }
   # result = new character[end+1 - start]
   new-len:number <- subtract end, start, -1
-  result:address:array:character <- new character:type, new-len
+  result:address:shared:array:character <- new character:type, new-len
   # copy the untrimmed parts between start and end
   i:number <- copy start
   j:number <- copy 0
@@ -716,9 +716,9 @@ recipe trim s:address:array:character -> result:address:array:character [
 
 scenario trim-unmodified [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- trim 1:address:array:character
-    3:array:character <- copy *2:address:array:character
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- trim 1:address:shared:array:character
+    3:array:character <- copy *2:address:shared:array:character
   ]
   memory-should-contain [
     3:array:character <- [abc]
@@ -727,9 +727,9 @@ scenario trim-unmodified [
 
 scenario trim-left [
   run [
-    1:address:array:character <- new [  abc]
-    2:address:array:character <- trim 1:address:array:character
-    3:array:character <- copy *2:address:array:character
+    1:address:shared:array:character <- new [  abc]
+    2:address:shared:array:character <- trim 1:address:shared:array:character
+    3:array:character <- copy *2:address:shared:array:character
   ]
   memory-should-contain [
     3:array:character <- [abc]
@@ -738,9 +738,9 @@ scenario trim-left [
 
 scenario trim-right [
   run [
-    1:address:array:character <- new [abc  ]
-    2:address:array:character <- trim 1:address:array:character
-    3:array:character <- copy *2:address:array:character
+    1:address:shared:array:character <- new [abc  ]
+    2:address:shared:array:character <- trim 1:address:shared:array:character
+    3:array:character <- copy *2:address:shared:array:character
   ]
   memory-should-contain [
     3:array:character <- [abc]
@@ -749,9 +749,9 @@ scenario trim-right [
 
 scenario trim-left-right [
   run [
-    1:address:array:character <- new [  abc   ]
-    2:address:array:character <- trim 1:address:array:character
-    3:array:character <- copy *2:address:array:character
+    1:address:shared:array:character <- new [  abc   ]
+    2:address:shared:array:character <- trim 1:address:shared:array:character
+    3:array:character <- copy *2:address:shared:array:character
   ]
   memory-should-contain [
     3:array:character <- [abc]
@@ -760,17 +760,17 @@ scenario trim-left-right [
 
 scenario trim-newline-tab [
   run [
-    1:address:array:character <- new [	abc
+    1:address:shared:array:character <- new [	abc
 ]
-    2:address:array:character <- trim 1:address:array:character
-    3:array:character <- copy *2:address:array:character
+    2:address:shared:array:character <- trim 1:address:shared:array:character
+    3:array:character <- copy *2:address:shared:array:character
   ]
   memory-should-contain [
     3:array:character <- [abc]
   ]
 ]
 
-recipe find-next text:address:array:character, pattern:character, idx:number -> next-index:number [
+recipe find-next text:address:shared:array:character, pattern:character, idx:number -> next-index:number [
   local-scope
   load-ingredients
   len:number <- length *text
@@ -788,8 +788,8 @@ recipe find-next text:address:array:character, pattern:character, idx:number ->
 
 scenario text-find-next [
   run [
-    1:address:array:character <- new [a/b]
-    2:number <- find-next 1:address:array:character, 47/slash, 0/start-index
+    1:address:shared:array:character <- new [a/b]
+    2:number <- find-next 1:address:shared:array:character, 47/slash, 0/start-index
   ]
   memory-should-contain [
     2 <- 1
@@ -798,8 +798,8 @@ scenario text-find-next [
 
 scenario text-find-next-empty [
   run [
-    1:address:array:character <- new []
-    2:number <- find-next 1:address:array:character, 47/slash, 0/start-index
+    1:address:shared:array:character <- new []
+    2:number <- find-next 1:address:shared:array:character, 47/slash, 0/start-index
   ]
   memory-should-contain [
     2 <- 0
@@ -808,8 +808,8 @@ scenario text-find-next-empty [
 
 scenario text-find-next-initial [
   run [
-    1:address:array:character <- new [/abc]
-    2:number <- find-next 1:address:array:character, 47/slash, 0/start-index
+    1:address:shared:array:character <- new [/abc]
+    2:number <- find-next 1:address:shared:array:character, 47/slash, 0/start-index
   ]
   memory-should-contain [
     2 <- 0  # prefix match
@@ -818,8 +818,8 @@ scenario text-find-next-initial [
 
 scenario text-find-next-final [
   run [
-    1:address:array:character <- new [abc/]
-    2:number <- find-next 1:address:array:character, 47/slash, 0/start-index
+    1:address:shared:array:character <- new [abc/]
+    2:number <- find-next 1:address:shared:array:character, 47/slash, 0/start-index
   ]
   memory-should-contain [
     2 <- 3  # suffix match
@@ -828,8 +828,8 @@ scenario text-find-next-final [
 
 scenario text-find-next-missing [
   run [
-    1:address:array:character <- new [abc]
-    2:number <- find-next 1:address:array:character, 47/slash, 0/start-index
+    1:address:shared:array:character <- new [abc]
+    2:number <- find-next 1:address:shared:array:character, 47/slash, 0/start-index
   ]
   memory-should-contain [
     2 <- 3  # no match
@@ -838,8 +838,8 @@ scenario text-find-next-missing [
 
 scenario text-find-next-invalid-index [
   run [
-    1:address:array:character <- new [abc]
-    2:number <- find-next 1:address:array:character, 47/slash, 4/start-index
+    1:address:shared:array:character <- new [abc]
+    2:number <- find-next 1:address:shared:array:character, 47/slash, 4/start-index
   ]
   memory-should-contain [
     2 <- 4  # no change
@@ -848,8 +848,8 @@ scenario text-find-next-invalid-index [
 
 scenario text-find-next-first [
   run [
-    1:address:array:character <- new [ab/c/]
-    2:number <- find-next 1:address:array:character, 47/slash, 0/start-index
+    1:address:shared:array:character <- new [ab/c/]
+    2:number <- find-next 1:address:shared:array:character, 47/slash, 0/start-index
   ]
   memory-should-contain [
     2 <- 2  # first '/' of multiple
@@ -858,8 +858,8 @@ scenario text-find-next-first [
 
 scenario text-find-next-second [
   run [
-    1:address:array:character <- new [ab/c/]
-    2:number <- find-next 1:address:array:character, 47/slash, 3/start-index
+    1:address:shared:array:character <- new [ab/c/]
+    2:number <- find-next 1:address:shared:array:character, 47/slash, 3/start-index
   ]
   memory-should-contain [
     2 <- 4  # second '/' of multiple
@@ -868,7 +868,7 @@ scenario text-find-next-second [
 
 # search for a pattern of multiple characters
 # fairly dumb algorithm
-recipe find-next text:address:array:character, pattern:address:array:character, idx:number -> next-index:number [
+recipe find-next text:address:shared:array:character, pattern:address:shared:array:character, idx:number -> next-index:number [
   local-scope
   load-ingredients
   first:character <- index *pattern, 0
@@ -890,9 +890,9 @@ recipe find-next text:address:array:character, pattern:address:array:character,
 
 scenario find-next-text-1 [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- new [bc]
-    3:number <- find-next 1:address:array:character, 2:address:array:character, 0
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- new [bc]
+    3:number <- find-next 1:address:shared:array:character, 2:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 1
@@ -901,9 +901,9 @@ scenario find-next-text-1 [
 
 scenario find-next-text-2 [
   run [
-    1:address:array:character <- new [abcd]
-    2:address:array:character <- new [bc]
-    3:number <- find-next 1:address:array:character, 2:address:array:character, 1
+    1:address:shared:array:character <- new [abcd]
+    2:address:shared:array:character <- new [bc]
+    3:number <- find-next 1:address:shared:array:character, 2:address:shared:array:character, 1
   ]
   memory-should-contain [
     3 <- 1
@@ -912,9 +912,9 @@ scenario find-next-text-2 [
 
 scenario find-next-no-match [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- new [bd]
-    3:number <- find-next 1:address:array:character, 2:address:array:character, 0
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- new [bd]
+    3:number <- find-next 1:address:shared:array:character, 2:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 3  # not found
@@ -923,9 +923,9 @@ scenario find-next-no-match [
 
 scenario find-next-suffix-match [
   run [
-    1:address:array:character <- new [abcd]
-    2:address:array:character <- new [cd]
-    3:number <- find-next 1:address:array:character, 2:address:array:character, 0
+    1:address:shared:array:character <- new [abcd]
+    2:address:shared:array:character <- new [cd]
+    3:number <- find-next 1:address:shared:array:character, 2:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 2
@@ -934,9 +934,9 @@ scenario find-next-suffix-match [
 
 scenario find-next-suffix-match-2 [
   run [
-    1:address:array:character <- new [abcd]
-    2:address:array:character <- new [cde]
-    3:number <- find-next 1:address:array:character, 2:address:array:character, 0
+    1:address:shared:array:character <- new [abcd]
+    2:address:shared:array:character <- new [cde]
+    3:number <- find-next 1:address:shared:array:character, 2:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 4  # not found
@@ -944,7 +944,7 @@ scenario find-next-suffix-match-2 [
 ]
 
 # checks if pattern matches at index 'idx'
-recipe match-at text:address:array:character, pattern:address:array:character, idx:number -> result:boolean [
+recipe match-at text:address:shared:array:character, pattern:address:shared:array:character, idx:number -> result:boolean [
   local-scope
   load-ingredients
   pattern-len:number <- length *pattern
@@ -977,9 +977,9 @@ recipe match-at text:address:array:character, pattern:address:array:character, i
 
 scenario match-at-checks-pattern-at-index [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- new [ab]
-    3:boolean <- match-at 1:address:array:character, 2:address:array:character, 0
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- new [ab]
+    3:boolean <- match-at 1:address:shared:array:character, 2:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 1  # match found
@@ -988,8 +988,8 @@ scenario match-at-checks-pattern-at-index [
 
 scenario match-at-reflexive [
   run [
-    1:address:array:character <- new [abc]
-    3:boolean <- match-at 1:address:array:character, 1:address:array:character, 0
+    1:address:shared:array:character <- new [abc]
+    3:boolean <- match-at 1:address:shared:array:character, 1:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 1  # match found
@@ -998,9 +998,9 @@ scenario match-at-reflexive [
 
 scenario match-at-outside-bounds [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- new [a]
-    3:boolean <- match-at 1:address:array:character, 2:address:array:character, 4
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- new [a]
+    3:boolean <- match-at 1:address:shared:array:character, 2:address:shared:array:character, 4
   ]
   memory-should-contain [
     3 <- 0  # never matches
@@ -1009,9 +1009,9 @@ scenario match-at-outside-bounds [
 
 scenario match-at-empty-pattern [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- new []
-    3:boolean <- match-at 1:address:array:character, 2:address:array:character, 0
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- new []
+    3:boolean <- match-at 1:address:shared:array:character, 2:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 1  # always matches empty pattern given a valid index
@@ -1020,9 +1020,9 @@ scenario match-at-empty-pattern [
 
 scenario match-at-empty-pattern-outside-bound [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- new []
-    3:boolean <- match-at 1:address:array:character, 2:address:array:character, 4
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- new []
+    3:boolean <- match-at 1:address:shared:array:character, 2:address:shared:array:character, 4
   ]
   memory-should-contain [
     3 <- 0  # no match
@@ -1031,9 +1031,9 @@ scenario match-at-empty-pattern-outside-bound [
 
 scenario match-at-empty-text [
   run [
-    1:address:array:character <- new []
-    2:address:array:character <- new [abc]
-    3:boolean <- match-at 1:address:array:character, 2:address:array:character, 0
+    1:address:shared:array:character <- new []
+    2:address:shared:array:character <- new [abc]
+    3:boolean <- match-at 1:address:shared:array:character, 2:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 0  # no match
@@ -1042,8 +1042,8 @@ scenario match-at-empty-text [
 
 scenario match-at-empty-against-empty [
   run [
-    1:address:array:character <- new []
-    3:boolean <- match-at 1:address:array:character, 1:address:array:character, 0
+    1:address:shared:array:character <- new []
+    3:boolean <- match-at 1:address:shared:array:character, 1:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 1  # matches because pattern is also empty
@@ -1052,9 +1052,9 @@ scenario match-at-empty-against-empty [
 
 scenario match-at-inside-bounds [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- new [bc]
-    3:boolean <- match-at 1:address:array:character, 2:address:array:character, 1
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- new [bc]
+    3:boolean <- match-at 1:address:shared:array:character, 2:address:shared:array:character, 1
   ]
   memory-should-contain [
     3 <- 1  # match
@@ -1063,16 +1063,16 @@ scenario match-at-inside-bounds [
 
 scenario match-at-inside-bounds-2 [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- new [bc]
-    3:boolean <- match-at 1:address:array:character, 2:address:array:character, 0
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- new [bc]
+    3:boolean <- match-at 1:address:shared:array:character, 2:address:shared:array:character, 0
   ]
   memory-should-contain [
     3 <- 0  # no match
   ]
 ]
 
-recipe split s:address:array:character, delim:character -> result:address:array:address:array:character [
+recipe split s:address:shared:array:character, delim:character -> result:address:shared:array:address:shared:array:character [
   local-scope
   load-ingredients
   # empty text? return empty array
@@ -1080,7 +1080,7 @@ recipe split s:address:array:character, delim:character -> result:address:array:
   {
     empty?:boolean <- equal len, 0
     break-unless empty?
-    result <- new {(address array character): type}, 0
+    result <- new {(address shared array character): type}, 0
     reply
   }
   # count #pieces we need room for
@@ -1095,7 +1095,7 @@ recipe split s:address:array:character, delim:character -> result:address:array:
     loop
   }
   # allocate space
-  result <- new {(address array character): type}, count
+  result <- new {(address shared array character): type}, count
   # repeatedly copy slices start..end until delimiter into result[curr-result]
   curr-result:number <- copy 0
   start:number <- copy 0
@@ -1105,7 +1105,7 @@ recipe split s:address:array:character, delim:character -> result:address:array:
     break-if done?
     end:number <- find-next s, delim, start
     # copy start..end into result[curr-result]
-    dest:address:address:array:character <- index-address *result, curr-result
+    dest:address:address:shared:array:character <- index-address *result, curr-result
     *dest <- copy-range s, start, end
     # slide over to next slice
     start <- add end, 1
@@ -1116,13 +1116,13 @@ recipe split s:address:array:character, delim:character -> result:address:array:
 
 scenario text-split-1 [
   run [
-    1:address:array:character <- new [a/b]
-    2:address:array:address:array:character <- split 1:address:array:character, 47/slash
-    3:number <- length *2:address:array:address:array:character
-    4:address:array:character <- index *2:address:array:address:array:character, 0
-    5:address:array:character <- index *2:address:array:address:array:character, 1
-    10:array:character <- copy *4:address:array:character
-    20:array:character <- copy *5:address:array:character
+    1:address:shared:array:character <- new [a/b]
+    2:address:shared:array:address:shared:array:character <- split 1:address:shared:array:character, 47/slash
+    3:number <- length *2:address:shared:array:address:shared:array:character
+    4:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 0
+    5:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 1
+    10:array:character <- copy *4:address:shared:array:character
+    20:array:character <- copy *5:address:shared:array:character
   ]
   memory-should-contain [
     3 <- 2  # length of result
@@ -1133,15 +1133,15 @@ scenario text-split-1 [
 
 scenario text-split-2 [
   run [
-    1:address:array:character <- new [a/b/c]
-    2:address:array:address:array:character <- split 1:address:array:character, 47/slash
-    3:number <- length *2:address:array:address:array:character
-    4:address:array:character <- index *2:address:array:address:array:character, 0
-    5:address:array:character <- index *2:address:array:address:array:character, 1
-    6:address:array:character <- index *2:address:array:address:array:character, 2
-    10:array:character <- copy *4:address:array:character
-    20:array:character <- copy *5:address:array:character
-    30:array:character <- copy *6:address:array:character
+    1:address:shared:array:character <- new [a/b/c]
+    2:address:shared:array:address:shared:array:character <- split 1:address:shared:array:character, 47/slash
+    3:number <- length *2:address:shared:array:address:shared:array:character
+    4:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 0
+    5:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 1
+    6:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 2
+    10:array:character <- copy *4:address:shared:array:character
+    20:array:character <- copy *5:address:shared:array:character
+    30:array:character <- copy *6:address:shared:array:character
   ]
   memory-should-contain [
     3 <- 3  # length of result
@@ -1153,11 +1153,11 @@ scenario text-split-2 [
 
 scenario text-split-missing [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:address:array:character <- split 1:address:array:character, 47/slash
-    3:number <- length *2:address:array:address:array:character
-    4:address:array:character <- index *2:address:array:address:array:character, 0
-    10:array:character <- copy *4:address:array:character
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:address:shared:array:character <- split 1:address:shared:array:character, 47/slash
+    3:number <- length *2:address:shared:array:address:shared:array:character
+    4:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 0
+    10:array:character <- copy *4:address:shared:array:character
   ]
   memory-should-contain [
     3 <- 1  # length of result
@@ -1167,9 +1167,9 @@ scenario text-split-missing [
 
 scenario text-split-empty [
   run [
-    1:address:array:character <- new []
-    2:address:array:address:array:character <- split 1:address:array:character, 47/slash
-    3:number <- length *2:address:array:address:array:character
+    1:address:shared:array:character <- new []
+    2:address:shared:array:address:shared:array:character <- split 1:address:shared:array:character, 47/slash
+    3:number <- length *2:address:shared:array:address:shared:array:character
   ]
   memory-should-contain [
     3 <- 0  # empty result
@@ -1178,17 +1178,17 @@ scenario text-split-empty [
 
 scenario text-split-empty-piece [
   run [
-    1:address:array:character <- new [a/b//c]
-    2:address:array:address:array:character <- split 1:address:array:character, 47/slash
-    3:number <- length *2:address:array:address:array:character
-    4:address:array:character <- index *2:address:array:address:array:character, 0
-    5:address:array:character <- index *2:address:array:address:array:character, 1
-    6:address:array:character <- index *2:address:array:address:array:character, 2
-    7:address:array:character <- index *2:address:array:address:array:character, 3
-    10:array:character <- copy *4:address:array:character
-    20:array:character <- copy *5:address:array:character
-    30:array:character <- copy *6:address:array:character
-    40:array:character <- copy *7:address:array:character
+    1:address:shared:array:character <- new [a/b//c]
+    2:address:shared:array:address:shared:array:character <- split 1:address:shared:array:character, 47/slash
+    3:number <- length *2:address:shared:array:address:shared:array:character
+    4:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 0
+    5:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 1
+    6:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 2
+    7:address:shared:array:character <- index *2:address:shared:array:address:shared:array:character, 3
+    10:array:character <- copy *4:address:shared:array:character
+    20:array:character <- copy *5:address:shared:array:character
+    30:array:character <- copy *6:address:shared:array:character
+    40:array:character <- copy *7:address:shared:array:character
   ]
   memory-should-contain [
     3 <- 4  # length of result
@@ -1199,7 +1199,7 @@ scenario text-split-empty-piece [
   ]
 ]
 
-recipe split-first text:address:array:character, delim:character -> x:address:array:character, y:address:array:character [
+recipe split-first text:address:shared:array:character, delim:character -> x:address:shared:array:character, y:address:shared:array:character [
   local-scope
   load-ingredients
   # empty text? return empty texts
@@ -1207,22 +1207,22 @@ recipe split-first text:address:array:character, delim:character -> x:address:ar
   {
     empty?:boolean <- equal len, 0
     break-unless empty?
-    x:address:array:character <- new []
-    y:address:array:character <- new []
+    x:address:shared:array:character <- new []
+    y:address:shared:array:character <- new []
     reply
   }
   idx:number <- find-next text, delim, 0
-  x:address:array:character <- copy-range text, 0, idx
+  x:address:shared:array:character <- copy-range text, 0, idx
   idx <- add idx, 1
-  y:address:array:character <- copy-range text, idx, len
+  y:address:shared:array:character <- copy-range text, idx, len
 ]
 
 scenario text-split-first [
   run [
-    1:address:array:character <- new [a/b]
-    2:address:array:character, 3:address:array:character <- split-first 1:address:array:character, 47/slash
-    10:array:character <- copy *2:address:array:character
-    20:array:character <- copy *3:address:array:character
+    1:address:shared:array:character <- new [a/b]
+    2:address:shared:array:character, 3:address:shared:array:character <- split-first 1:address:shared:array:character, 47/slash
+    10:array:character <- copy *2:address:shared:array:character
+    20:array:character <- copy *3:address:shared:array:character
   ]
   memory-should-contain [
     10:array:character <- [a]
@@ -1230,7 +1230,7 @@ scenario text-split-first [
   ]
 ]
 
-recipe copy-range buf:address:array:character, start:number, end:number -> result:address:array:character [
+recipe copy-range buf:address:shared:array:character, start:number, end:number -> result:address:shared:array:character [
   local-scope
   load-ingredients
   # if end is out of bounds, trim it
@@ -1238,7 +1238,7 @@ recipe copy-range buf:address:array:character, start:number, end:number -> resul
   end:number <- min len, end
   # allocate space for result
   len <- subtract end, start
-  result:address:array:character <- new character:type, len
+  result:address:shared:array:character <- new character:type, len
   # copy start..end into result[curr-result]
   src-idx:number <- copy start
   dest-idx:number <- copy 0
@@ -1256,9 +1256,9 @@ recipe copy-range buf:address:array:character, start:number, end:number -> resul
 
 scenario text-copy-copies-partial-text [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- copy-range 1:address:array:character, 1, 3
-    3:array:character <- copy *2:address:array:character
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- copy-range 1:address:shared:array:character, 1, 3
+    3:array:character <- copy *2:address:shared:array:character
   ]
   memory-should-contain [
     3:array:character <- [bc]
@@ -1267,9 +1267,9 @@ scenario text-copy-copies-partial-text [
 
 scenario text-copy-out-of-bounds [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- copy-range 1:address:array:character, 2, 4
-    3:array:character <- copy *2:address:array:character
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- copy-range 1:address:shared:array:character, 2, 4
+    3:array:character <- copy *2:address:shared:array:character
   ]
   memory-should-contain [
     3:array:character <- [c]
@@ -1278,9 +1278,9 @@ scenario text-copy-out-of-bounds [
 
 scenario text-copy-out-of-bounds-2 [
   run [
-    1:address:array:character <- new [abc]
-    2:address:array:character <- copy-range 1:address:array:character, 3, 3
-    3:array:character <- copy *2:address:array:character
+    1:address:shared:array:character <- new [abc]
+    2:address:shared:array:character <- copy-range 1:address:shared:array:character, 3, 3
+    3:array:character <- copy *2:address:shared:array:character
   ]
   memory-should-contain [
     3:array:character <- []