The kcats Programming Language Lexicon

Table of Contents

1. Standard library source and documentation

1.1. Comparison

Words that help compare one item to another, with concepts of equal, greater, less etc.

[= [[spec [[item item] [boolean]]]
    [doc "Test two items for equality"]
    [examples [[[1 2 =] [🔳] "Different Numbers are not equal"]
               [[1 1 =] [] "Same numbers are equal"]
               [[1 1.0 =] [] "Same value integer and float are equal"]
               [[[1] 🔳 =]  [🔳] "Number and Nothing are unequal"]
               [[[1 [🔳]] [1 [🔳]] =] [] "Same nested list with numbers are equal"]
               [[[1.0 ["foo"]] [1.0 ["foo"]] =] [] "Same nested list with string are equal"]
               [["hi" "hi" =] [] "Same strings are equal"]
               [["hi" "there" =] [🔳] "Different strings are unequal"]
               [[\h \h =] [] "Same characters are equal"]
               [[\h \i =] [🔳] "Different characters are unequal"]
               [["hi" encode "hi" encode =] [] "Same bytes are equal"]
               [["hi" encode "there" encode =] [🔳] "Different bytes are unequal"]
               [[🔳 ✅ =] [🔳] "Different booleans unequal"]
               [[[1.0 ["foo"]] [1.0 ["bar"]] =]  [🔳] "Nested lists with different strings are unequal"]
               [[🔳 🔳 =] [] "'Nothing' is equal to itself"]
               [[🔳 🔳 association =] [] "List/Association empty container types are equal"]
               [[🔳 🔳 set =] [] "List/Set empty container types are equal"]
               [[[[a b]] [[a b]] association =] [🔳] "Nonempty List/Association types are unequal"]
               [[[1 2 3] set [3 1 2] set =] [] "Sets constructed from different lists are equal"]
               [[["foo" =] [🗑️ "Needs 2 items"] 🩹 ▶️] ["Needs 2 items"] "Less than 2 stack items results in an error"]]]]]

[compare [[spec [[item item] [word]]]
          [doc "Compare 2nd stack item to 1st, returning word `equal`, `greater`, or `less`"]
          [examples [[["a" "b" compare] [[less] 🍫] "string lexicographical order with single character inequality"]
                     [["a" "a" compare] [[equal] 🍫] "string lexicographical order with single character equality"]
                     [[1 1 compare] [[equal] 🍫] "Same integer compares equal"]
                     [[2 1 compare] [[greater] 🍫] "Integer order inequality"]
                     [[1 [foo] 🍫 compare] [[less] 🍫] "Integer/list order inequality"]
                     [[1 "foo" encode compare] [[less] 🍫] "Integer/byte order inequality"]
                     [[[foo] 🍫 "foo" encode compare] [[less] 🍫] "Word/string order inequality"]
                     [["foo" encode "foo" compare] [[less] 🍫] "String order equaltiy"]
                     [[🔳 [🔳] 🍫 compare] [[equal] 🍫] "Unwrapped Nothing value equality"]
                     [[🔳 [1] rest compare] [[equal] 🍫] "Nothing/emptied container equality"]
                     [[["foo" compare] [🗑️ "Needs 2 items"] 🩹 ▶️] ["Needs 2 items"] "Less than 2 stack items results in an error"]

                     ;; Length comparisons
                     [["ab" "a" compare] [[greater] 🍫] "Longer string is greater"]
                     [["" "" compare] [[equal] 🍫] "Empty strings are equal"]
                     [["" "a" compare] [[less] 🍫] "Empty string is less than non-empty"]

                     ;; List comparisons
                     [[[1 2] [1 2] compare] [[equal] 🍫] "Equal lists compare equal"]
                     [[[1 2] [1 3] compare] [[less] 🍫] "Lists compared element by element"]
                     [[[1 2 3] [1 2] compare] [[greater] 🍫] "Longer list is greater"]
                     [[🔳 🔳 compare] [[equal] 🍫] "Empty lists are equal"]
                     [[🔳 [1] compare] [[less] 🍫] "Empty list is less than non-empty"]

                     ;; Mixed type edge cases
                     [[🔳 "" compare] [[greater] 🍫] "Empty list vs empty string"]
                     [[[🔳] 🔳 compare] [[greater] 🍫] "Nothing in list vs bare Nothing"]
                     [[[""] 🔳 compare] [[greater] 🍫] "List with empty string vs empty list"]

                     ;; Number edge cases
                     [[0 -0 compare] [[equal] 🍫] "Zero equals negative zero"]
                     [[42 42.0 compare] [[equal] 🍫] "Integer equals float representation"]
                     [[-1 1 compare] [[less] 🍫] "Negative less than positive"]

                     ;; Unicode string comparisons
                     [["é" "e" compare] [[greater] 🍫] "Accented character comparison"]
                     [["a" "A" compare] [[greater] 🍫] "Case-sensitive comparison"]
                     [["🍫" "a" compare] [[greater] 🍫] "Emoji vs ASCII"]

                     ;; Nested structure comparisons
                     [[[1 [2]] [1 [2]] compare] [[equal] 🍫] "Nested structure equality"]
                     [[[1 [2]] [1 [3]] compare] [[less] 🍫] "Nested structure inequality"]
                     [[[🔳 🔳] [🔳 🔳] compare] [[equal] 🍫] "Different arrangements of Nothing and empty list"]]]]]

[< [[spec [[[item a] [item b]] [boolean]]]
    [doc "Is the 2nd stack item less than the first"]
    [definition [🔳 both compare [less] 🍫 =]]
    [examples [[[1 2 <] [] "Integer is less"]
               [[2.2 1.1 <] [🔳] "Float is not less"]
               [[1 2.2 <] [] "Integer/float is less"]
               [[-3 2.2 <] [] "Negative integer/float is less"]
               [[0 2.2 <] [] "Zero Integer/float is less"]
               [[1.1 1.1 <] [🔳] "Equal floats is not less"]
               [[-1.1 -1.1 <] [🔳] "Negative equal floats is not less"]
               [["a" "b" <] [] "String is less than other string"]
               [[["a" "b"] ["a" "c"] <] [] "List is less than other list"]]]]]

[> [[spec [[[item a] [item b]] [boolean]]]
    [doc "Is the 2nd stack item greater than the first"]
    [definition [🔳 both compare [greater] 🍫 =]]
    [examples [[[2 1 >] [] "Integer is greater"]
               [[1.1 2.2 >] [🔳] "Float is not greater"]
               [[2.2 1 >] [] "Integer/float is greater"]
               [[-1 -2.2 >] [] "Negative integer/float is greater"]
               [[0 -2.2 >] [] "Zero Integer/float is greater"]
               [[1.1 1.1 >] [🔳] "Equal floats is not greater"]
               [[-1.1 -1.1 >] [🔳] "Negative equal floats is not greater"]]]]]

[<= [[spec [[[item a] [item b]] [boolean]]]
     [doc "Is the 2nd stack item less than or equal to the first"]
     [definition [> ☯️]]
     [examples [[[1 2 <=] [] "Integer is less/equal"]
                [[2.2 1.1 <=] [🔳] "Float is not less/equal"]
                [[1 2.2 <=] [] "Integer/float is less/equal"]
                [[1.1 1.1 <=] [] "Equal floats is less/equal"]]]]]

[>= [[spec [[[item a] [item b]] [boolean]]]
     [doc "Is the 2nd stack item greater than or equal to the first"]
     [definition [< ☯️]]
     [examples [[[2 1 >=] [] "Integer is greater/equal"]
                [[1.1 2.2 >=] [🔳] "Float is not greater/equal"]
                [[2.2 1 >=] [] "Integer/float is greater/equal"]
                [[1.1 1.1 >=] [] "Equal floats is greater/equal"]]]]]

[max-by [[spec [[program [item a] [item b]] [item]]]
         [doc "Runs program on top two stack items, and returns the result that compares `greater`"]
         [definition [[both compare 🎁] •🛡️ ▶️ [less] =
                      [🗑️ •🗑️] [🗑️] ↔️]]
         [examples [[[[[price 25] [name bar]]
                      [[price 15] [name foo]]
                      [[price] 🔍] max-by] [[[price 25] [name bar]]]]]]]]

[min-by [[spec [[program [item a] [item b]] [item]]]
         [doc "Runs program on top two stack items, and returns the result that compares `less`"]
         [definition [[both compare 🎁] •🛡️ ▶️ [greater] =
                      [🗑️ •🗑️] [🗑️] ↔️]]
         [examples [[[[[price 25] [name bar]]
                      [[price 15] [name foo]]
                      [[price] 🔍] min-by] [[[price 15] [name foo]]]]]]]]

[min [[spec [[number number] [number]]]
      [doc "Compares the top two stack items and returns the one that compares `less`"]
      [definition [[<] 🛡️ [🗑️] [🔀] ⚖️ ▶️ 🗑️]]
      [examples [[[2 3 min] [2] "Smaller of two positive integers"]
                 [[-5 -3 min] [-5] "Smaller of two negative integers"]
                 [[0.3 0.2 min] [0.2] "Smaller of two floats <1"]]]]]

[max [[spec [[number number] [number]]]
      [doc "Compares the top two stack items and returns the one that compares `greater`"]
      [definition [[>] 🛡️ [🗑️] [🔀] ⚖️ ▶️ 🗑️]]
      [examples [[[2 3 max] [3] "Larger of two positive integers"]
                 [[-5 -3 max] [-3] "Larger of two positive integers"]
                 [[0.3 0.2 max] [0.3] "Larger of two floats <1"]]]]]

[between? [[spec [[[number exclusive-upper-bound] [number inclusive-lower-bound] number]]]
         [doc "Is number between inclusive-lower-bound and exclusive-upper-bound?"]
         [definition [[>=] •🛡️ 🪄 🔀 [<] 🪄 and]]
         [examples [[[9 2 10 between?] [] "Number is between other numbers"]
                    [[10 2 10 between?] [🔳] "Number exactly at upper bound, thus is not between"]
                    [[1 2 10 between?] [🔳] "Number below lower bound is not between"]
                    [[11 2 10 between?] [🔳] "Number above upper bound is not between"]
                    [["b" "a" "c" between?] [] "String is between other strings"]]]]]

1.2. Stack Ops

[🗑️ [[spec [[item] 🔳]]
    [names ["trash can" "drop"]]
    [doc "Throws away the top stack item"]
    [examples [[[1 2 3 🗑️] [1 2] "Drop integer on ToS"]
               [[1 2 3 [a b c] 🗑️] [1 2 3] "Drop list on ToS"]

               ;; Different types of values
               [[🔳 🗑️] 🔳 "Drop Nothing value"]
               [["hello" 🗑️] 🔳 "Drop string"]
               [[42.5 🗑️] 🔳 "Drop float"]
               [[✅ 🗑️] 🔳 "Drop boolean"]

               ;; Nested structures
               [[[1 [2 3] 4] 🗑️] 🔳 "Drop complex nested structure"]
               [[[[🔳]] 🗑️] 🔳 "Drop deeply nested empty lists"]

               ;; Multiple operations
               [[1 2 3 🗑️ 🗑️] [1] "Drop multiple times"]
               [[1 2 3 🗑️ 4 🗑️] [1 2] "Interleaved drops with pushes"]

               ;; Edge cases
               [[🔳 🗑️] 🔳 "Drop empty list"]
               [["" 🗑️] 🔳 "Drop empty string"]
               [[1 2 [🗑️] 🗑️] [1 2] "Drop list containing trash symbol"]

               ;; Error cases
               [[[🗑️] [🗑️ "Nothing to drop"] 🩹 ▶️] ["Nothing to drop"] "Empty stack results in error"]
               [[[1 🗑️ 🗑️] [🗑️ "Nothing to drop"] 🩹 ▶️] ["Nothing to drop"] "Multiple drops on nonempty stack"]]]]]

[👥 [[spec [[[item a]]
            [[item a] [item a]]]]
     [names ["twins" "busts in silhouette" "copy"]]
     [doc "Copy the top stack item"]
     [examples [[[1 2 3 👥] [1 2 3 3] "Copy integer on ToS"]
                [["foo" "bar" "baz" 👥] ["foo" "bar" "baz" "baz"] "Copy string on ToS"]
                [[[👥] [🗑️ "Nothing to clone"] 🩹 ▶️] ["Nothing to clone"] "Empty stack results in error"]

                ;; Different types of values
                [[🔳 👥] [🔳 🔳] "Copy Nothing value"]
                [[✅ 👥] [✅ ✅] "Copy boolean"]
                [[42.5 👥] [42.5 42.5] "Copy float"]
                [[🔳 👥] [🔳 🔳] "Copy empty list"]

                ;; Nested structures
                [[[1 2 3] 👥] [[1 2 3] [1 2 3]] "Copy list"]
                [[[1 [2 [3]]] 👥] [[1 [2 [3]]] [1 [2 [3]]]] "Copy nested structure"]
                [[[👥] 👥] [[👥] [👥]] "Copy list containing clone symbol"]

                ;; Multiple operations
                [[1 👥 👥] [1 1 1] "Multiple consecutive clones"]
                [[1 2 👥 3 👥] [1 2 2 3 3] "Interleaved clones with pushes"]
                [[1 👥 🗑️] [1] "Copy then trash"]
                [[1 2 👥 👥 🗑️] [1 2 2] "Multiple clones then trash"]

                ;; Edge cases
                [["" 👥] ["" ""] "Copy empty string"]
                [[[🔳 🔳] 👥] [[🔳 🔳] [🔳 🔳]] "Copy complex structure with Nothing"]
                [[[[🔳]] 👥] [[[🔳]] [[🔳]]] "Copy nested empty lists"]

                ;; Error cases
                [[[👥 👥] [🗑️ "Nothing to clone"] 🩹 ▶️] ["Nothing to clone"] "Copy on empty stack"]
                [[1 🗑️ [👥] [🗑️ "Nothing to clone"] 🩹 ▶️] ["Nothing to clone" ] "Copy after emptying stack"]]]]]

[📸 [[spec [🔳 [list]]]
     [names ["camera" "snapshot"]]
     [doc "Copy the whole stack as a list, onto the top of the stack"]
     [examples [[[1 2 3 📸] [1 2 3 [3 2 1]] "Copy the stack to ToS"]
                [[📸] [🔳] "Copy stack to ToS when stack is empty"]]]]]

[🧦 [[spec [[list] [list *]]]
     [names ["socks" "evert"]]
     [doc "Turn inside-out: Takes a list on ToS, makes it the new
           stack, and takes what had previously been the rest of the
           stack, and makes it a list on top of the new stack. Used
           for context switching."]
     [examples [[[1 2 3 [4 5 6] 🧦] [6 5 4 [3 2 1]] "Swap a list of integers with the rest of the stack"]
                [[1 [2] 3 [4 foo "bar"] 🧦] ["bar" [foo] 🍫 4 [3 [2] 1]] "Swap a list of items with the rest of the stack"]
                [[[4 5 6] 🧦] [6 5 4 🔳] "Swap a list of integers with an empty stack"]
                [[["a" "b" "c"] 🧦] ["c" "b" "a" 🔳] "Swap a list of strings with an empty stack"]
                [[[1 2 3 4 🧦] [🗑️ "List is required"] 🩹 ▶️] ["List is required"] "Non-list item result in an error"]
                [[[🧦] [🗑️ "Nothing to evert"] 🩹 ▶️] ["Nothing to evert"] "Empty stack results in error"]

                ;; Empty and single-item cases
                [[🔳 🧦] [🔳] "Evert empty list"]
                [[[1] 🧦] [1 🔳] "Evert single-item list"]
                [[2 [1] 🧦] [1 [2]] "Evert single-item list with one item below"]

                ;; Nested structures
                [[[1 [2 3] 4] 🧦] [4 [2 3] 1 🔳] "Evert list containing nested list"]
                [[[1 🔳 2] 🧦] [2 🔳 1 🔳] "Evert list containing empty list"]
                [[1 2 [[3 4] 5] 🧦] [5 [3 4] [2 1]] "Evert nested list with items below"]

                ;; Mixed types
                [[[✅ 🔳 "hello" 42] 🧦] [42 "hello" 🔳 ✅ 🔳] "Evert list of mixed types"]
                [[🔳 ["a" 1 ✅] 🧦] [✅ 1 "a" [🔳]] "Evert with Nothing below"]

                ;; Multiple operations
                [[1 [2 3] 🧦 [4 5] 🧦] [5 4 [[1] 2 3]] "Sequential everts"]
                [[1 [2 3] 🧦 👥] [3 2 [1] [1]] "Evert then clone"]
                [[1 2 [3 4] 🧦 🗑️] [4 3] "Evert then trash"]

                ;; Complex structures
                [[[1 [2 [3]] [4 [5]]] 🧦] [[4 [5]] [2 [3]] 1 🔳] "Evert deeply nested structure"]
                [[1 2 [🔳 🔳 [foo]] 🧦] [[foo] 🔳 🔳 [2 1]] "Evert list containing Nothing and empty list"]

                ;; Error cases
                [[1 2 3 [🧦] [🗑️ "List is required"] 🩹 ▶️] [1 2 3 "List is required"] "Try to evert non-list ToS"]
                [["hello" [🧦] [🗑️ "List is required"] 🩹 ▶️] ["hello" "List is required"] "Try to evert string"]
                [[1 2 3 [4 5] 🧦 🧦] [1 2 3 [4 5]] "Evert undoes itself"]]]]]
[•👥  [[spec [[[item a] [item b]]
              [[item a] [item b] [item b]]]]
       [names ["twins with dot"]]
       [doc "Copy, one stack position down (copy the 2nd item and place it between the original and the top item)"]
       [definition [[👥] 🪄]]
       [examples [[[1 2 3 •👥] [1 2 2 3] "Clone the 2nd item on the stack"]]]]]


[••👥 [[spec [[[item a] [item b] [item c]]
              [[item a] [item b] [item c] [item c]]]]
       [names ["twins with dots"]]
       [doc "Copy, two stack positions down (copy the 3rd item)"]
       [definition [[👥] •🪄]]
       [examples [[[1 2 3 4 ••👥] [1 2 2 3 4] "Clone the 3rd item on the stack"]]]]]

[over [[spec [[[item a] [item b]]
              [[item b] [item a] [item b]]]]
       [doc "Copy the 2nd stack item, placing the copy on top"]
       [definition [•👥 🔀]]
       [examples [[[1 2 3 over] [1 2 3 2] "Copy the 2nd item to ToS"]]]]]

[under [[spec [[[item a] [item b]]
               [[item a] [item b] [item a]]]]
        [doc "Copy the top stack item, placing the copy beneath the 2nd item"]
        [definition [👥 •🔀]]
        [examples [[[1 2 3 under] [1 3 2 3] "Copy the ToS to the 2nd item"]]]]]

[•🗑️ [[spec [[[item a] [item b]] [[item b]]]]
     [names ["trash can with dot" "dropdown"]]
     [doc "Drop the second stack item"]
     [definition [🔀 🗑️]]
     [examples [[[1 2 3 •🗑️] [1 3] "Drop the 2nd item"]]]]]

[••🗑️ [[spec [[[item a] [item b] [item c]] [[item a] [item b]]]]
      [names ["trash can with dots" "dropdeep"]]
      [doc "Drop the third stack item"]
      [definition [🛟 🗑️]]
      [examples [[[1 2 3 ••🗑️] [2 3] "Drop the 3rd item"]]]]]

[restore [[spec [[list] [*]]]
          [doc "Replace the entire stack with the list on top of stack"]
          [definition [🧦 🗑️]]
          [examples [[["x" "y" [1 2 3] restore] [3 2 1] "Replace stack with list"]
                     [[🔳 restore] 🔳 "Replace stack with empty list"]]]]]

1.2.1. Motion

These words change the order of items on the stack.

[🔀 [[spec [[[item a] [item b]]
            [[item b] [item a]]]]
     [names ["crossing arrows" "swap"]]
     [doc "Swap the top two stack items"]
     [examples [[[1 2 3 🔀] [1 3 2] "Swap top two items"]
                ;; Basic types
                [[🔳 ✅ 🔀] [✅ 🔳] "Swap boolean values"]
                [[42 "hello" 🔀] ["hello" 42] "Swap number and string"]
                [[🔳 "" 🔀] ["" 🔳] "Swap Nothing and empty string"]
                [["a" "b" 🔀] ["b" "a"] "Swap strings"]

                ;; Lists and nested structures
                [[[1 2] [3 4] 🔀] [[3 4] [1 2]] "Swap lists"]
                [[[1 [2]] [3 [4]] 🔀] [[3 [4]] [1 [2]]] "Swap nested lists"]
                [[[[🔳]] 🔳 🔀] [🔳 [[🔳]]] "Swap deeply nested empty list with empty list"]

                ;; Multiple operations
                [[1 2 3 🔀 🔀] [1 2 3] "Double swap"]
                [[1 2 🔀 3 🔀] [2 3 1] "Interleaved swaps"]
                [[1 2 🔀 🗑️] [2] "Swap then trash"]

                ;; With identical items
                [[42 42 🔀] [42 42] "Swap identical numbers"]
                [[🔳 🔳 🔀] [🔳 🔳] "Swap identical empty lists"]
                [[[1 2] [1 2] 🔀] [[1 2] [1 2]] "Swap identical complex lists"]

                ;; Error cases
                [[[🔀] [🗑️ "Need 2 items to swap"] 🩹 ▶️] ["Need 2 items to swap"] "Empty stack"]
                [[[1 🔀] [🗑️ "Need 2 items to swap"] 🩹 ▶️] ["Need 2 items to swap"] "Only one item on stack"]]]]]

[•🔀 [[spec [[[item a] [item b] [item c]]
             [[item a] [item c] [item b]]]]
      [names ["crossing arrows with dot" "swapdown"]]
      [doc "Swap the second and third stack items"]
      [examples [[[1 2 3 •🔀] [2 1 3] "Swap 2nd and 3rd items"]]]]]

[🛟 [[spec [[[item a] [item b] [item c]]
            [[item c] [item a] [item b]]]]
     [names ["ring buoy" "float"]]
     [doc "Floats the third stack item to the top"]     
     [examples [[[1 2 3 🛟] [2 3 1] "Move 3rd item to ToS"]]]]]

[[[spec [[[item a] [item b] [item c]]
            [[item b] [item c] [item a]]]]
     [names ["anchor" "sink"]]
     [doc "Sinks the top stack item to the third position"]
     [examples [[[1 2 3 ⚓] [3 1 2] "Move ToS to 3rd item"]]]]]
[flip [[spec [[[item a] [item b] [item c]]
              [[item c] [item b] [item a]]]]
       [doc "Swaps the first and third stack items"]
       [definition [🛟 •🔀]]
       [examples [[[1 2 3 flip] [3 2 1] "Swap ToS and 3rd item"]]]]]

1.3. Program execution

;; Input spec is item because builtins can be executed directly too
[▶️ [[spec [[item] [*]]]
    [names ["play arrow" "right-pointing triangle" "execute"]]
    [doc "Execute a program on top of stack"]
    [examples [[[[1 2 +] ▶️] [3] "Execute a program"]
               [[1 2 🔳 ▶️] [1 2] "Execute an empty program"]

               ;; Nested execution
               [[1 2 [[+] ▶️] ▶️] [3] "Nested execution"]
               [[[1 [2 👥] ▶️ 3] ▶️] [1 2 2 3] "Execute nested program with clone"]

               ;; Multiple executions
               [[[1] ▶️ [2] ▶️] [1 2] "Sequential execution"]
               [[[[1] ▶️ [2 +] ▶️] ▶️] [3] "Nested sequential execution"]

               ;; Empty and Nothing cases
               [[🔳 ▶️] 🔳 "Execute empty program"]
               [[🔳 ▶️] 🔳 "Execute Nothing"]
               [[[🔳 [1] ▶️] ▶️] [🔳 1] "Execute Nothing then program"]

               ;; Complex programs
               [[[1 [2 +] ▶️ [3 +] ▶️] ▶️] [6] "Chained arithmetic operations"]
               [[[1 2 +] [3 4 *] 🔀 ▶️] [[3 4 *] 3] "Execute programs after swapping"]

               ;; Error handling
               [[[▶️] [🗑️ "Nothing to execute"] 🩹 ▶️] ["Nothing to execute"] "Try to execute with nothing on stack"]
               [[[1 ▶️] [🗑️ "Type error"] 🩹 ▶️] ["Type error"] "Try to execute a non program"]]]]]

[↔️ [[spec [[[program no-branch]
            [program yes-branch]
            [item condition]]
           [*]]]
    [names ["left-right arrow" "branch"]]
    [doc "Logical branch: if the top of stack is an affirmative value, execute the second item, otherwise the third item"]
    [examples [[[5 ✅ [🗑️ 3 *] [4 +] ↔️] [15] "Branch on true condition"]
               [[5 "hi" [🗑️ 3 *] [4 +] ↔️] [15] "Branch on truthy condition"]
               [[6 🔳 [3 *] [4 +] ↔️] [10] "Branch on false condition"]
               [[6 "" [3 *] [4 +] ↔️] [10] "Branch on falsey condition"]
               [[6 "hi" 🔳 [4 +] ↔️] [6 "hi"] "Branch with empty 'yes' program"]
               [[6 "" 🔳 🔳 ↔️] [6] "Branch with empty 'no' program"]]]]]

[🪄 [[spec [[program [item a]] [[item a] *]]]
     [names ["magic wand" "dip"]]
     [doc "Make top stack item disappear while program runs, then reappear on top of stack."]
     [examples [[[1 8 [inc] 🪄] [2 8] "Dipping a program under ToS"]
                [[1 2 [dec] 🍫
                  [+] 🪄] [3 [dec] 🍫] "A bare word on stack is left intact and not executed"]]]]]
[🪆 [[spec [[[program combinator]
             [program exit]
             [program body]
             [program pred]]
            [*]]]
     [names ["nesting dolls" "russian dolls" "recurrence"]]
     
     [doc "Construct a recursive program.  Takes 4 component programs
           as input: predicate, body, exit, and combinator. The
           recursive program, when executed will: run predicate, if
           result is false, the exit program runs and the recursive
           program is finished. If true, the body program runs, a copy
           of the whole recursive program is put on the stack, and the
           combinator is run."]

   [definition [[✂️4️⃣
                 [✂️3️⃣ 4️⃣ 3️⃣ 2️⃣ 1️⃣ 🪆 ✂️1️⃣]
                   2️⃣ ↔️] 🎒]]
     [examples [[[5
                  [2 >] 🛡️
                  [🗑️ 👥 dec] 🔳 [▶️ *]
                  🪆 ▶️]
                 [120]
                 "Recur with reduction"]]]]]

[🌀 [[spec [[program [item flag]] [*]]]
     [names ["swirl" "loop"]]
     
     [doc "Create a loop program with binary exit condition. Takes a
     program and a boolean value, if the value is affirmative, run
     the program and repeat. If negative, drop the value and the loop
     is finished."]
     
     [definition [🔳 🔀 🔳 [▶️] 🪆]]
     [examples [[[10 ✅ [🗑️ -2 * 👥 50 <] 🌀 ▶️] [160] "Looping"]
                [[10 🔳 [🗑️ -2 * 👥 50 <] 🌀 ▶️] [10] "Looping with false initial condition is no-op"]]]]]


[decide [[spec [[[list test-expr-pairs]] [*]]]
         [doc "Takes a list of choices (pairs of test, program) and executes the first
               choice whose test passes. If none pass, it's a no-op. Stack is reset
               between testing conditions."]
         [definition [📤
                      [🍫 ;; break up the pair
                       🔀 
                       🛡️
                       ;; 🪆 
                       flip [1️⃣ decide] 🎒 ⚖️ ▶️]
                      [🗑️] ;; the empty container
                      ↔️]]
         [examples [[[5 [[[3 =] [🗑️ "three"]]
                         [[5 =] [🗑️ "five"]]
                         [[7 =] [🗑️ "seven"]]
                         [[] [🗑️ "something else"]]]
                      decide]
                     [5 "five"] "Decide with matching condition"]

                    [[9 [[[3 =] [🗑️ "three"]]
                         [[5 =] [🗑️ "five"]]
                         [[7 =] [🗑️ "seven"]]
                         [[] [🗑️ "something else"]]]
                      decide]

                     [9 "something else"] "Decide with matching default condition"]

                    [[9 [[[3 =] [🗑️ "three"]]
                         [[5 =] [🗑️ "five"]]
                         [[7 =] [🗑️ "seven"]]]
                      decide]
                     [9] "Decide with no matching condition"]]]]]

;; TODO: implement as axiom (which would depend on 'restore' which should also be axiom?)
[🛡️ [[spec [[program] [program]]]
    [names ["shield"]]
    [doc "Run a program, protecting existing stack items from being consumed. Places the resulting top stack item on top of the original stack."]
    [definition [💉 [📸 ✂️1️⃣ first] 🎒]]
    [examples [[[1 2 3 [=] 🛡️ ▶️] [1 2 3 🔳] "Execute a program shielding the stack from consumption"]]]]]

[•🛡️ [[spec [[program] [program]]]
     [names ["shield with dot" "shielddown"]]
     [doc "Run a program, protecting all but the top stack item from being consumed."]
     [definition [💉 [📸 ✂️1️⃣ •🗑️ first] 🎒]]
     [examples [[[1 2 3 [=] •🛡️ ▶️] [1 2 🔳] "Execute a program consuming only the original ToS"]]]]]

[••🛡️ [[spec [[program] [program]]]
      [names ["shield with dots" "shielddeep"]]
      [doc "Run a program, protecting all but the top two stack items from being consumed."]
      [definition [💉 [📸 ✂️1️⃣ •🗑️ •🗑️ first] 🎒]]
      [examples [[[1 2 3 [+ +] ••🛡️ ▶️] [1 6] "Execute a program consuming only the original top 2 items"]]]]]

[⚖️ [[spec [[[program no-branch]
            [program yes-branch]
            [program condition]]
           [program]]]
    [names ["scales" "if"]]
    [doc "Create a logical branch program from 3 component programs. When executed, runs condition program. If its result is affirmative, runs yes-branch, otherwise runs no-branch"]
    [definition [[✂️3️⃣ ;; the condition
                  2️⃣ 1️⃣ ↔️] 🎒]]
    [examples [[[5 [👥 5 =] [🗑️ 3 *] [4 +] ⚖️ ▶️] [15] "Conditional with true predicate"]
               [[6 [👥 5 =] [🗑️ 3 *] [4 +] ⚖️ ▶️] [10] "Conditional with false predicate"]]]]]

[when [[spec [[[program yes-branch]
               [program condition]]
              [program]]]
       [doc "Creates a logical branchh program from 2 component programs.  When executed, runs condition program. If its result is affirmative, runs yes-branch, otherwise no-op."]
       [definition [🔳 ⚖️]]
       [examples [[[3 [👥 odd?] [🗑️ inc] when ▶️] [4] "Conditional with no false branch and true predicate"]
                  [[3 [👥 even?] [🗑️ inc] when ▶️] [3] "Conditional with no false branch and false predicate"]]]]]

[dipped [[spec [program program]]
         [doc "Creates a version of program that runs with 🪄."]
         [definition [[1️⃣ 🪄] 🎒]]]]

[•🪄 [[spec [[program
              [item a]
              [item b]]
             [[item a] [item b] *]]]
      [names ["magic wand with dot" "dipdown"]]
      [doc "Run a program, hiding the top two items and then making
            them reappear after the program is finished"]
      [definition [dipped dipped ▶️]]
      [examples [[[1 2 3 [inc] •🪄] [2 2 3] "Dip program under top two items"]]]]]

[••🪄 [[spec [[program
               [item a]
               [item b]
               [item c]]
              [[item a] [item b] [item c] *]]]
       [names ["magic wand with dots" "dipdeep"]]
       [doc "Run a program, hiding the top three items and then making
             them reappear after the program is finished"]
       [definition [dipped dipped dipped ▶️]]
       [examples [[[1 2 3 4 [inc] ••🪄] [2 2 3 4] "Dip program under top 3 items"]]]]]

[🪜 [[spec [[program] [program]]]
     [names ["ladder" "step"]]
     
     [doc "Create a stepping program from a body program. When run,
           iterates over a list and executes the body once per
           item. The rest of the list is hidden while the body runs."]

     [definition [[[📤 🔀 
                    1️⃣ 👥 •🪄
                    🪜 ▶️]
                   🔳 ↔️]
                  🎒]]
     [examples [[[1 [2 3 4] [*] 🪜 ▶️] [24] "Step through numbers doing arithmetic"]
                [[[1 2 3] [inc] 🪜 ▶️] [2 3 4] "Step through items"]
                [[1 🔳 [*] 🪜 ▶️] [1] "Stepping through empty list is no-op"]

                ;; Simple transformations
                [[[1 2 3] [👥] 🪜 ▶️] [1 1 2 2 3 3] "Double each item"]
                [[[1 2 3] [🗑️] 🪜 ▶️] 🔳 "Delete all items"]
                [[[1 2 3] 🔳 🪜 ▶️] [1 2 3] "No-op body"]
                [[[1 2 3] [🗑️ 🔳] 🪜 ▶️] [🔳 🔳 🔳] "Replace each item with Nothing"]

                ;; Different input types
                [[["a" "b" "c"] [encode] 🪜 ▶️] ["a" encode "b" encode "c" encode] "Convert each string to bytes"]
                [[[🔳 ✅ 🔳] [☯️] 🪜 ▶️] [✅ 🔳 ✅] "Step through list of booleans"]

                ;; Empty and single item cases
                [[[1] [👥] 🪜 ▶️] [1 1] "Step through single-item list"]
                [[[🔳] [👥] 🪜 ▶️] [🔳 🔳] "Step through list containing empty list"]

                ;; Nested lists
                [[[1 [2 3] 4] [🗑️] 🪜 ▶️] 🔳 "Step through list with nested structure"]
                [[[[1] [2] [3]] [first] 🪜 ▶️] [1 2 3] "Extract first item from each sublist"]

                ;; Stack manipulation within body
                [[[1 2 3] [42 🔀] 🪜 ▶️] [42 1 42 2 42 3] "Step and swap each item with constant"]
                [[[1 2 3] [👥 🔀] 🪜 ▶️] [1 1 2 2 3 3] "Clone and swap each item"]
                [[[1 2 3] [🗑️ 99] 🪜 ▶️] [99 99 99] "Remove and replace each item"]

                ;; Error cases
                [[[1 2 3] [🔀] [🪜 ▶️] [🗑️ "Error in body"] 🩹 ▶️] [[1 2 3] [🔀] "Error in body"] "Step body program causes error"]
                [[🔳 [1 0 /] 🪜 ▶️] 🔳 "Empty list with erroring body"]]]]]

[🐋 [[spec [[program [item a]] [item [item a] *]]]
     [names ["whale" "dive"]]
     [doc "Run a program 'below' the ToS (with the ToS hidden from the
           program), and then surfacing the result up to the top of
           the stack"]
     [definition [🪄 🔀]]
     [examples [[[4 5 6 [+] 🐋] [6 9] "Dip program and move result to ToS"]]]]]

[•🐋 [[spec [[program [item a] [item b]]
             [item [item a] [item b] *]]]
      [names ["whale with dot" "divedown"]]
      [doc "Run a program beneath the top two items, and then floating
            the result back to the ToS."]
      [definition [•🪄 🛟]]
      [examples [[[5 6 7 8 [+] •🐋] [7 8 11] "Dip under top 2 items and move result to ToS"]]]]]

[••🐋 [[spec [[program [item a] [item b] [item c]]
              [item [item a] [item b] [item c] *]]]
       [names ["whale with dots" "divedeep"]]
       [doc "Run a program beneath the top three items, and then
             floating the result back to the ToS."]
       [definition [🎁 [•🐋] 🔗 🪄 🔀]]
       [examples [[[4 5 6 7 8 [+] ••🐋] [6 7 8 9] "Dip under top 3 items and move result to ToS"]]]]]

[💉 [[spec [[program] [program]]]
     [names ["syringe" "needle" "injection"]]
     [doc "Creates an program that when executed, injects the given
           program into the list below it (runs the program with the
           list as its stack).  Does not affect the rest of the
           stack. Used for context switching."]
     [definition [dipped [🧦 ✂️1️⃣ 🧦] 🎒]]
     [examples [[[1 2 3 [4 5 6] [* +] 💉 ▶️] [1 2 3 [26]] "Inject program into list as if it's the stack"]]]]]

[[[spec [[[program body]
             [program pred]]
            [*]]]
     [names ["hourglass" "while"]]
     
     [doc "Create a 'while' loop: run predicate program. If it
           produces logical true, run the body and repeat, otherwise
           stop."]

     [definition [🔳 [▶️] 🪆]]
     [examples [[[3 [0 >] 🛡️ [🗑️ 👥 dec] ⏳ ▶️] [3 2 1 0] "While loop"]]]]]

[until [[spec [[[program body]
                [program pred]]
               [*]]]
        
        [doc "Create an 'until' loop: Run body once, then
              predicate. if predicate produces logical true,
              stop. Otherwise repeat."]

        [definition [[🎭] 🪄 ;; reverse logic of pred
                     ;; run body once, with dummy pred result
                     👥 [[🔳] 🔀 🔗 🪄] 🪄 ⏳]]
        [examples [[[2 [even?] 🛡️ [🗑️ inc] until ▶️] [4] "Until loop"]]]]]

[times [[spec [[[integer howmany]
                [program body]]
               [program]]]

        [doc "Create a repeater program. Given an integer n and a body
              program, return another program that runs the body n
              times. Non-positive values of n result in a no-op
              program."]

        [definition [[1️⃣ [positive?] 🛡️
                      [🗑️ dec [2️⃣ 👥 🪄] 🪄 times ▶️]
                      [🗑️] ⚖️
                      ▶️]
                     🎒]]
        [examples [[[[5] 3 times ▶️] [5 5 5] "Create an item a specific number of times"]
                   [[[5] 0 times ▶️] 🔳 "0 times is a no-op"]
                   [[[5] -3 times ▶️] 🔳 "negative times is a no-op"]
                   [[1 1 [inc 🔀] 3 times ▶️] [3 2] "Run a program a specific number of times"]]]]]

[primrec [[spec [[[program rec1]
                  [program exit]
                  [number n]]
                 [*]]]

          [doc "Create a countdown recurrence: given a combinator
                program, an exit program and a positive integer n,
                create a recurrence where each iteration decrements n
                and runs the combinator."]

          [definition [[▶️ ✂️1️⃣] 🎒  ;; add execute to rec1 to be recurs rec2
                       [[🗑️ ✂️1️⃣] 🎒] 🪄  ;; add drop to exit condition
                       [zero? ☯️] 🛡️ ⚓ ;; put the condition check on bottom
                       [🗑️ 👥 dec];; add the r1
                       🪆]]  ;; now its generic recur
          [examples [[[5 [1] [*] primrec ▶️] [120] "Simple countup loop"]]]]]

[bail [[spec [[program] [*]]]
       
       [doc "Short circuit primitive. If the top of stack is
             affirmative, run the program, otherwise no-op."]

       [definition [[🔳] ↔️]]
       [examples [[[🔳 [inc] bail] [🔳] "Can bail on invalid input"]
                  [[1 [inc] bail] [2] "Valid input doesn't bail"]]]]]

[bailer [[spec [[list] [program]]]

         [doc "Short circuit a chain of programs. Takes a list of
               programs to run, returns a new program. That program
               only runs each component program, if there is an
               affirmative value on the top of the stack right before
               it's due to run."]

         [definition [[and] •🛡️ [📤 🪄]]]
         [examples [[[1
                      [[👥 odd?] [🗑️ inc] [👥 odd?] [🗑️ inc]]
                      bailer ▶️]
                     [2 🔳]
                    "Short circuit when an empty value is produced"]]]]]

1.4. Collections

[🔗 [[spec [[sized sized] [sized]]]
     [names ["link" "join"]]
     [doc "Join two containers together"]
     [examples [[[["a" "b"] ["c" "d"] 🔗] [["a" "b" "c" "d"]] "Join two collections of strings"]
                [["ab" "cd" 🔗] ["abcd"] "Join two strings"]
                [["ab" encode "cd" encode 🔗 "abcd" encode =] [] "Two joined byte seqs are equal to the combined literal"]
                [[[[a b] [c d]] association [[e f] [a g]] 🔗] [[[a g] [c d] [e f]] association] "Joining list+assoc -> assoc, 2nd arg keys take priority"]
                [[[[e f] [a g]] [[a b] [c d]] association  🔗] [[[a b] [e f] [c d]] association] "Joining assoc+list -> assoc, 2nd arg keys take priority"]
                [[[a b c d] set [a e] 🔗] [[a b c d e] set] "Join set with list -> set"]
                [[[a e] [a b c d] set 🔗] [[a b c d e] set] "Join list with set -> set"]
                [["" "" 🔗] [""] "Join two empty strings -> empty string"]
                [["" [foo bar baz] 🔗] [[foo bar baz]] "Join empty string + list -> list (identity)"]
                [["a" [\b \c 100 101] 🔗] ["abcde"] "Join a string with a list of chars -> string"]
                [[[\b \c 100 101] "a" 🔗] ["bcdea"] "Join a list of chars with string -> string"]
                [["" [\b \c 100 101] 🔗] [[\b \c 100 101]] "Join an empty string with list of chars -> list of chars"]
                [["abc" [\d 101 "not-char" -1.1] 🔗] [[\a \b \c \d 101 "not-char" -1.1]] "Join a string with (non-char) list -> list"]
                [["abc" 🔳 🔗] ["abc"] "Join a string with empty list -> string"]
                [["" 🔳 🔗] [""] "Join empty string with empty list -> string"]
                [[[1 2 3] set [4 4 4] 🔗] [[1 2 3 4] set] "Join set with list -> set"]]]]]

[📤 [[spec [[dispenser] [item dispenser]]]
     [names ["outbox" "take"]]
     
     [doc "Take an item from a container, leaving the item on top and
           then the modified container."]

     [examples [[[["a" "b" "c"] 📤] [["b" "c"] "a"] "Take a string from a list"]
                [[[1 2 3] 📤] [[2 3] 1] "Take a number from a list"]
                [[[[a "foo"] [b "foo"] [c "foo"]] 📤 •🗑️ second] ["foo"] "Take an entry from association is nondeterministic"]
                [[[1 3 5 7 9] set 📤 •🗑️ odd?] [] "Take item from set is nondeterministic"]]]]]

[📮 [[spec [[item receptacle] [receptacle]]]
     [names ["postbox" "put"]]
     [doc "Put an item into a container, leaving the modified container on top"]
     [examples [[[🔳 1 📮] [[1]] "Put integer into empty list"]
                [[[1 2 3] 4 📮] [[1 2 3 4]] "Put integer into list"]
                [["foo" \d 📮] ["food"] "Put character into string"]
                [["foo" encode 32 📮 string] ["foo "] "Put byte into byte array"]]]]]

[📏 [[spec [[sized]
            [number]]]
     [names ["ruler" "count"]]
     [doc "Get the number of items in a container"]
     [examples [[[["a" "b" "cd"] 📏] [3] "Count list of strings"]
                [["abcd" 📏] [4] "Count chars in string"]
                [["abcd" encode 📏] [4] "Count bytes in byte array"]
                [[[[a b] [c d]] association 📏] [2] "Count entries in association"]]]]]

[second [[spec [[ordered] [item]]]
         [doc "Get the second item in a container"]
         [examples [[[[4 5 6] second] [5] "Get second item of list"]
                    [["foo" second [\o]] "Get second item of string"]
                    [[🔳 second] [🔳] "Get second item of empty list -> Nothing"]]]]]

[last [[spec [[ordered] [item]]]
       [doc "Get the last item in a container"]
       [examples [[[[3 4 5 6] last] [6] "Get last item of list"]
                  [["foo" last [\o]] "Get last item of string"]
                  [[🔳 last] [🔳] "Get last item of empty list -> Nothing"]]]]]

[pop [[spec [[ordered] [item ordered]]]
      [doc "Take the last item from a container, leaving the item on top and the modified container beneath."]
      [examples [[[["a" "b" "c"] pop] [["a" "b"] "c"] "Pop last string from list"]
                 [[[1 2 3] pop] [[1 2] 3] "Pop last number from list"]]]]]

[🎁 [[spec [[item] [list]]]
     [names ["wrapped present" "gift" "wrap"]]
     [doc "Wrap an item in a list container."]
     [examples [[[1 🎁] [[1]] "Wrap a number"]
                [[[1 2] 🎁] [[[1 2]]] "Wrap a list"]
                [[[] 🎁] [[[]]] "Wrap an empty list"]]]]]

[🍫 [[spec [[list] [*]]]
     [names ["chocolate bar" "unwrap"]]
     [doc "Unwrap a container, placing all the items inside onto the stack, in order."]
     [examples [[[[1] 🍫] [1] "Unwrap a list of one item"]
                [["foo" ["bar" "baz"] 🍫] ["foo" "bar" "baz"] "Unwrap a list of strings with existing stack items"]
                [["foo" 🔳 🍫] ["foo"] "Unwrap an empty list is a no-op"]
                [[[1 2 3] 🍫] [1 2 3] "Unwrap a list of multiple items"]]]]]

[reverse [[spec [[ordered] [ordered]]]
          [doc "Reverse the order of items in a container."]
          [examples [[[[1 2 3] reverse] [[3 2 1]] "Reverse a list"]
                     [["123" reverse] ["321"] "Reverse a string"]
                     [[["foo" "bar" "baz"] reverse] [["baz" "bar" "foo"]] "Reverse a list of string"]]]]]

[remove [[spec [[item [sized container]] [[sized container]]]]
         [doc "Remove an item from a container. If there are multiple occurences, removes first occurrence only."]
         [examples [[[[a b c] [b] 🍫 remove] [[a c]] "Remove item from a list (inefficient)"]
                    [[[a b c b d] [b] 🍫 remove] [[a c b d]] "Remove item from a list that occurs more than once"]
                    [[[a b c] set [b] 🍫 remove] [[a c] set] "Remove item from a set"]]]]]

[slice [[spec [[[integer start] [integer end] ordered] [ordered]]]
        
        [doc "Slices a container by taking indices from start
              (inclusive) to end (exclusive), returning a new
              container. Negative indices mean 'from the end'. Returns
              error if indices are out of bounds."]

        [examples [[["foobar" 0 3 slice] ["foo"] "Slice a string with valid indices"]
                   [[["foobar" 0 7 slice] [🗑️ "outofbounds"] 🩹 ▶️] ["outofbounds"] "Slice a string with index past end -> error"]
                   [[["foobar" -4 1 slice] [🗑️ "outofbounds"] 🩹 ▶️] ["outofbounds"] "Slice a string with index before beginning (or start > end) -> error"]
                   [["foobarbazquux" 0 -4 slice] ["foobarbaz"] "Slice a string from start to distance from end"]
                   [["foobarbazquux" -7 0 slice] ["bazquux"] "Slice a string from distance from end to end"]
                   [["foobarbazquux" -7 -4 slice] ["baz"] "Slice a string from distance from end to distance from end"]
                   
                   [["foobar" encode 0 3 slice] ["foo" encode] "Slice a byte array with valid indices"]
                   [[[a b c d e] 0 3 slice] [[a b c]] "Slice a list with valid indices"]]]]]

[cut [[spec [[integer sized] [list]]]
      [doc "Divide a container at a given index, leaving 2 containers on stack (beginning on top)"]
      [definition [[[[📏] 🛡️ 🐋 slice]
                    [0 🔀 slice]]
                   [▶️] 🚜 ▶️ 
                   [🗑️ 🗑️] 🪄 🍫]]
      [examples [[["abcdefghijklmnopqrstuvwxyz" 5 cut] ["fghijklmnopqrstuvwxyz" "abcde"] "Cut string at index"]
                 [["abcde" 0 cut] ["abcde" ""] "Cut string before start"]
                 [["abcde" 5 cut] ["" "abcde"] "Cut string after end"]
                 [[[a b c d e] 3 cut] [[d e] [a b c]] "Cut list at index"]]]]]

[empty [[spec [[sized] [sized]]]
        [doc "Empty out the given container"]
        [examples [[["foo" empty] [""] "Create empty container from string"]
                   [["foo" encode empty] ["" encode] "Create empty container from byte array"]
                   [[[1 2 3] empty] [🔳] "Create empty container from list"]
                   [[[[a b] [c d]] association empty] [🔳 association] "Create empty container from association"]
                   [[[1 2 3] set empty] [🔳 set] "Create empty container from set"]]]]]

[range [[spec [[[integer start]
                [integer end]
                [integer step]]

               [list]]]
        [doc "Create a range of numbers from `start` (inclusive) to `end` (noninclusive) increasing by `step`"]
        [examples [[[1 5 1 range] [[1 2 3 4]] "Create integer range with step of 1"]
                   [[3 13 3 range] [[3 6 9 12]] "Create integer range with step greater than 1"]
                   [[-10 -4 2 range] [[-10 -8 -6]] "Create negative integer range"]
                   [[10 4 -2 range] [[10 8 6]] "Create decreasing integer range"]]]]]

[empty? [[spec [[item] [boolean]]]
         [doc "Is item on ToS an empty container?"]
         [examples [[[🔳 empty?] [] "Empty list is empty"]
                    [[1 empty?] [🔳] "Number is not empty"]
                    [["" empty?] [] "Empty string is empty"]
                    [[[foo] empty?] [🔳] "Non-empty list is not empty"]]]]]

[list? [[spec [[item] [boolean]]]
        [doc "Is item on ToS a list?"]
        [examples [[[[1] list?] [] "A list is a list"]
                   [[🔳 list?] [] "An empty list is a list"]
                   [[5 list?] [🔳] "A number is not a list"]
                   [["foo" list?] [🔳] "A string is not a list"]
                   [[[[foo bar] [baz quux]] association list?] [🔳] "An association is not a list"]
                   [[🔳 association list?] [🔳] "An empty association is not a list"]]]]]

[🎒 [[spec [[[list template]] [list]]]
     [names ["backpack" "knapsack" "pack"]]
     
     [doc "Fill in a template, with items from the stack. Use 1️⃣, 2️⃣ etc
           to insert the first, second etc items from the stack. You
           can also splice a container item into the template, with
           ✂️1️⃣, ✂️2️⃣ etc. The number of stack items consumed is whatever
           is the highest index placeholder. So a 'backpack' of [1️⃣ 4️⃣]
           consumes 4 items even though 2️⃣ and 3️⃣ are not used."]

     [examples [[["x" [foo] [bar] 🍫
                  [2️⃣ [ 1️⃣ x ✂️2️⃣] c d 1 2 3] 🎒]
                 ["x" [[foo] [bar x foo] c d 1 2 3]]
                 "Packing values from the stack, into a template"]]]]]

[⛏️ [[spec [[[sized pattern] [sized data]] [associative list]]]
     [names ["pick" "unpack"]]
    
     [doc "Unpack values from a nested structure (aka
           destructuring). Takes a pattern and data to match
           against. The pattern is a nested structure containing
           placeholders that can be either an index (1️⃣, 2️⃣ etc) or a
           named value (named values start with 🏷️, eg
           `🏷️foo`). Traverses pattern and data simultaneously, looking
           for matches. To match against an association, the pattern
           must also be an association (see `assocify` which
           recursively converts lists of pairs to associations). The
           underscore word `_` represents a wildcard, which will match
           any value at that location. Returns two values: an
           association of named values, and a list of indexed
           values. The indexed values will stop at the highest index
           used in the pattern, any skipped indices will be assigned a 🔳 value."]
    
     [examples [[[[a b c d e]
                  [a b 1️⃣ d 2️⃣] ⛏️]

                 [[c e] []]

                 "Unpack values by index"]

                [[[a b c d e]
                  [a b 1️⃣ _ 2️⃣] ⛏️]

                 [[c e] []]

                 "Unpack values by index with wildcard"]

                [[[a b c d e]
                  [a 1️⃣ ✂️2️⃣] ⛏️]

                 [[b [c d e]] []]

                 "Unpacking values by index with catch-all at end"]
                
                [[[anything
                   [foo [this is a] 12]
                   [5 [this is b] 5]
                   []
                   thisisc]
                  [_ [_ 🏷️a 12]
                   [5 🏷️b 5]
                   []
                   🏷️c] 
                  ⛏️]

                 [[]
                  [[a [this is a]]
                   [b [this is b]]
                   [c thisisc]] association]

                "Unpack nested values by name"]

                [[[[a [[b 12]
                       [c 15]]]
                   [d [[e []]
                       [f [5 4 3 2 1]]]]] assocify
                  [[a 🏷️a]
                   [d [[f [_ _ 🏷️b _ _]]]]] assocify
                  ⛏️]
                 [[]
                  [[a [[b 12]
                       [c 15]]]
                   [b 3]] assocify]]]]]]

[🏷️⛏️ [[spec [[[sized pattern] [sized data]] [associative]]]
       [definition [⛏️ •🗑️]]]]

[#️⃣⛏️ [[spec [[[sized pattern] [sized data]] [*]]]
       [doc "Picks values from a nested structure and places them on the
     stack. Use 1️⃣, 2️⃣ etc for the first, second etc items to place on
     the stack (with 1️⃣ being on top)."]
       [definition [⛏️ 🗑️ reverse 🍫]]]]

[🧤 [[spec [[[[list patterns]] [program]]]]

     [doc "Creates a matcher program. Takes a list of pattern/program
           pairs. Returns a program that will match data below
           it. When that program runs, the first pattern that matches
           the data, its corresponding program will be executed. If
           no patterns match, then an error will be raised."]

     [definition [[🍫 ;; break up pair 
                   [[2️⃣
                     [⛏️ 🗑️ ✅ or] ;; use dummy value if no placeholders
                     [🗑️ []] 🩹 ▶️] ;; recover from failed destructure to try next
                    [[✅ =] 🛡️
                     [🗑️ 🗑️] ;; drop dummy value 
                     [•🗑️ 🍫] ;; unwrap the destructured elements onto the stack
                     ⚖️ ▶️ ✂️1️⃣]] 🎒] ;; rebuild pair with new condition and program
                  🚜 ▶️
                  ;; now add a clause to fail if no match
                  [[] [🗑️ [🧤] "No patterns match" [reason asked actual] label fail]] 📮
                  [1️⃣ decide] 🎒]]
     [examples [[[[foo bar [5 6]]
                  [[[foo nomatch [1️⃣ 2️⃣]] ["shouldn't match"]]
                   [[nomatch bar [1️⃣ quux]] ["also shouldn't match"]]
                   [[foo _ [1️⃣ 2️⃣]] [+]]] 🧤 ▶️]
                 [11] "Simple pattern matching"]

                [[[foo]
                  [[[bar] ["shouldn't match"]]
                   [[nomatch bar [1️⃣ quux]] ["also shouldn't match"]]
                   [[foo] ["match"]]] 🧤 ▶️]
                 [[foo] "match"] "Matching with no placeholders (equality test)"]
                
                [[[foo bar [5 6]]
                  [[[foo nomatch [1️⃣ 2️⃣]] ["shouldn't match"]]
                   [[nomatch bar [1️⃣ quux]] ["also shouldn't match"]]] 🧤
                  [🗑️ 🗑️ "no match"] 🩹 ▶️]
                 ["no match"] "Error when no patterns match"]]]]]

[🪗 [[spec [[[program reducer] dispenser] [item]]]
     [definition [[📤 🔀] 🪄 ;; get the first item as the initial value
                      🪜]]
     [examples [[[[1 2 3 4] [+] 🪗 ▶️] [10]]]]]]

[🚜🔗 [[spec [[[program transform]] [program]]] [doc "Like 🚜, but the
       expectation is that the `transform` program will return a sized
       container, and the final result will 🔗 the containers
       together. Like `flatMap` in other languages."]
       [definition [🚜 ▶️ [🔗] 🪗]]]]
;; DEPRECATE - this is redundant, all logical operators can take the item directly
[something? [[spec [[item] [boolean]]] 
             [definition [empty? ☯️]]
             [examples [[[1 something?] [] "A number is something"]
                        [[🔳 something?] [🔳] "Empty list is not something"]
                        [["" something?] [🔳] "Empty string is not something"]]]]]

[•📮 [[spec [[[item target] [item skip] receptacle] [[item skip] receptacle]]]
      [doc "Puts target into a container skipping over an intervening item"]
      [definition [•🔀 📮 🔀]]
      [examples [[[["a" "b" "c"] "foo" "d" •📮] [["a" "b" "c" "d"] "foo"]]]]]]

[••📮 [[spec [[[item target] [item skip1] [item skip2] receptacle]
              [[item skip1] [item skip2]  receptacle]]]
       [doc "Puts target into a container skipping over two intervening items"]
       [definition [[📮] •🪄]]
       [examples [[[["a" "b" "c"] "foo" "bar" "d" ••📮] [["a" "b" "c" "d"] "foo" "bar"]]]]]]

[first [[spec [[ordered] [item]]]
        [definition [📤 •🗑️]]
        [examples [[[[4 5 6] first] [4] "Get the first item of a list"]
                   [["foo" first] [\f] "The first item of a string is the first character"]
                   [[🔳 first] [🔳] "The first item of an empty list is Nothing"]]]]]

[rest [[spec [[sized] [sized]]]
       [definition [📤 🗑️]]
       [examples [[[[1 2 3] rest] [[2 3]] "Take rest of list"]
                  [["foo" rest] ["oo"] "Take rest of string"]]]]]

[butlast [[spec [[sized] [sized]]]
          [definition [pop 🗑️]]
          [examples [[[[1 2 3] butlast] [[1 2]] "Take all but last of list"]]]]]

[prepend [[spec [[item sized]
                 [sized]]]
          [definition [🎁 🔀 🔗]]
          [examples [[[[1 2] 3 prepend] [[3 1 2]] "Prepend to list"]
                     [["oo" \f prepend] ["foo"] "Prepend to string"]]]]]

[💯 [[spec [[program sized] [program]]]
     [doc "The '100' (percent) denotes creating a consensus program from a predicate program. The returned program will check whether all the items in the container match the predicate program. Each item is placed on the stack (with remaining items hidden), and the predicate program is run. If it returns logical true, repeat with the next item, otherwise stop and return logical false."]
     [definition [•🛡️ ;; protect the rest of stack
                  [[📤 🔀 1️⃣ 🐋 👥] ;; more items
                   [🔳 ✅ 🔳] ;; empty list, return ✅
                   ↔️] 🎒
                  [🗑️ 🗑️]
                  [•🗑️]
                  [▶️] 🪆]]
     [examples [[[[2 4 6] [even?] 💯 ▶️] [] "Every number matches predicate"]
                [[[2 4 5] [even?] 💯 ▶️] [🔳] "Not every number matches predicate"]
                [[🔳 [🔳] 💯 ▶️] [] "Every item in empty list matches any predicate"]
                [[[2 4 6] 🔳 💯 ▶️] [] "Every item in list matches empty predicate"]
                [[11 [2 4 6] [+ odd?] •🛡️ 💯 ▶️] [11 ✅] "Can shield stack from predicate"]
                [[12 [[even?] [positive?] [3 mod 0 =]] [▶️] •🛡️ 💯 ▶️] [12 ✅] "Can check list of predicates with execute predicate"]]]]]

[📣 [[spec [[program sized] boolean]]
     [doc "The megaphone denotes creating a existence program from a predicate program. (The megaphone represents amplifying from a single element to the whole). The returned program will check whether any of the items in the container match the predicate program. Each item is placed on the stack (with remaining items hidden), and the predicate program is run. If it returns logical false, repeat with the next item, otherwise stop and return logical true."]
     [definition [[[📤 🔀 1️⃣ 🐋 👥 ☯️] ;; more items
                   [🔳 🔳 🔳] ;; empty list, return 🔳
                   ↔️] 🎒
                  [🗑️ 🗑️]
                  [•🗑️]
                  [▶️] 🪆]]
     [examples [[[[2 4 6] [even?] 📣 ▶️] [] "Any number matches predicate"]
                [[[3 5 7] [even?] 📣 ▶️] [🔳] "No number matches predicate"]
                [[🔳 [] 📣 ▶️] [🔳] "No item in empty list matches any predicate"]
                [[[🔳 2 4 6] 🔳 📣 ▶️] [2] "Empty predicate returns first truthy item"]
                [[11 [3 5 6] [+ odd?] •🛡️ 📣 ▶️] [11 ✅] "Stack is shielded from predicate"]
                [[-15 [[even?] [positive?] [3 mod 0 =]] [🛡️ ▶️] 📣 ▶️] [-15 ✅] "Can check list of predicates with execute predicate"]]]]]

[🎭 [[spec [[program] [program]]]
     [doc "The performing arts masks denote logically complementing a program: create a new program that returns the logical opposite of what the original program did."]
     [definition [[1️⃣ ▶️ ☯️] 🎒]]
     [examples [[[4 [odd?] 🎭 [🗑️ "even"] ["odd"] ⚖️ ▶️]
                 ["even"]]]]]]

[🚜 [[spec [[[program transform]] [program]]]
     [doc "The tractor denotes creating an item-by-item transformation. The returned program will run the transform on each item in the container on ToS. Each item is placed on the stack with remaining items hidden, and the transform program is run. Its stack effects are erased for the next item."]
     [definition [[[🔀 1️⃣ •🛡️ 🪄 🔀 📮] 🪜
                   🔳 ⚓ ;; put empty results below list
                   ▶️]
                  🎒]]
     [examples [[[[1 2 3] [inc] 🚜 ▶️] [[2 3 4]] "Pass each item through a program"]

                [[1 [1 2 3] [+] 🚜 ▶️] [1 [2 3 4]] "Program has access to rest of stack"]
                [[7 9 [1 2 3] [+ *] 🚜 ▶️] [7 9 [70 77 84]] "Stack is shielded from mapping program"]
                [[7 9 [1 2 3] [🗑️ 🗑️] 🚜 ▶️] [7 9 [7 7 7]] "Result of program can be lower stack items"]

                [[7 9 [+] 🔳 🚜 ▶️] [7 9 [+]] "Empty program is a no-op"]
                [[[+] 🚜 [7 9 [1 2 3]] 🪄 ▶️] [7 9 [10 11 12]] "Create a map program and use later"]]]]]

[🧲 [[spec [[[program predicate] sized] [list]]]
     [doc "The magnet denotes a filtering. The returned program will filter a list on ToS and leave only those items for which the predicate returns logical true."]
     [definition [🛡️ ;; run the predicate with no stack effect
                  [1️⃣ •🔀 🐋] 🎒  ;; dive the predicate under the result
                  [🗑️ 🔀 📮] [•🗑️] ⚖️ ;; if match, drop the pred result and put the original item in result list
                  ;; if not, just drop the original
                  🪜 
                  [1️⃣ 🔳 ⚓ ▶️] 🎒]]  ;; place the empty result container beneath
     [examples [[[[1 2 3] [odd?] 🧲 ▶️] [[1 3]] "Filter a list with predicate"]
                [[[2 4 6] [odd?] 🧲 ▶️] [🔳] "Filter with predicate that matches no items"]
                [[33 [1 2 3] [+ odd?] 🧲 ▶️] [33 [2]] "Filter predicate uses existing stack items"]]]]]

[sort [[spec [[program sized] [list]]]
       [definition [[👥 ✂️1️⃣ pair] 🎒
                    🚜 ▶️ sort-indexed]]
       [examples [[[[1 3 2] 🔳 sort] [[1 2 3]] "Sort a list of numbers"]
                  [[["Carol" "Alice" "bob"] 🔳 sort] [["Alice" "Bob" "Carol"]] "Sort a list of strings"]
                  [[["Charlie" "Alice" "bob"] [📏] sort] [["Bob" "Alice" "Charlie"]] "Sort list of strings by length"]]]]]

[repetition [[spec [[[integer howmany]
                     item]
                    [list]]]
             [definition [🔳 ⚓ [🎁 [📮] 🔗] 🪄 times]]
             [examples [[["hi" 3 repetition ▶️] [["hi" "hi" "hi"]] "Create a list of repeated items"]]]]]

[indexed [[spec [[list] [list]]]
          [definition [[📏] 🛡️ ▶️ 0 🔀 1 range 🔀 zip]]
          [examples [[[[a b c] indexed] [[[0 a] [1 b] [2 c]]] "Index a list"]]]]]

[indexer [[spec [🔳 [program]]]
          [definition [0 [[▶️] 🐋
                          [[pair] •🛡️ ▶️ [inc] 🪄] bail]
                       🔳 [🗑️ 🔳] [🔀] 🪆]]
          [examples [[[[a b c] [indexer collect] assemble] [[[0 a] [1 b] [2 c]]] "Index a generator"]]]]]

[indexof [[spec [[item list] [item]]]
          [definition [[[second 🎁 [1️⃣] = ☯️] skipper
                        [indexer] •🪄
                        ▶️ first] 🎒 
                       assemble]]
          [examples [[[[a b c] [c] 🍫 indexof] [2] "Get the index of first matching item"]
                     [[[a b c] [d] 🍫 indexof] [🔳] "No matching item -> Nothing"]
                     [[[a b c d c e] [c] 🍫 indexof] [2] "Multiple matches returns index of first match"]]]]]

[interpose [[spec [[item ordered] [ordered]]]
            [definition [🔳 flip
                         [🔀 pair 🔗 [pop] 🛡️ ▶️] 🪜 ▶️ 
                         🗑️ pop 🗑️]]
            [examples [[[[foo bar baz] "hi" interpose] [[foo "hi" bar "hi" baz]] "Interpose string between words"]
                       [[🔳 "hi" interpose] [🔳] "Empty list is a no-op"]
                       [[[foo] "hi" interpose] [[foo]] "Single item list is a no-op"]]]]]

[starts? [[spec [[[ordered prefix] [ordered target]] [boolean]]]
          [definition [[[zip [🍫 =] 💯 ▶️] ;; the items at matching indexes are equal
                        [[📏] both >=]] ;; the prefix is shorter than the target
                       [▶️] •🛡️ 💯 ▶️
                       •🗑️ •🗑️]] ;; drop the originals
          [examples [[["abcd" "ab" starts?] [] "String starts with matching string"]
                     [["abcd" "" starts?] [] "String starts with empty string"]
                     [["" "ab" starts?] [🔳] "Empty string doesn't start with a string"]
                     [["abcd" "bb" starts?] [🔳] "String doesn't start with non-matching string"]
                     [[[1 2 3 4] [1 2] starts?] [] "List starts with matching list"]]]]]

[ends? [[spec [[ordered ordered] [boolean]]]
        [definition [[reverse] both starts?]]
        [examples [[["abcd" "cd" ends?] [] "String ends with matching string"]
                   [["abcd" "" ends?] [] "String ends with empty string"]
                   [["abcd" "bb" ends?] [🔳] "String doesn't end with non-matching string"]
                   [[[1 2 3 4] [3 4] ends?] [] "List ends with matching list"]]]]]

[pair [[spec [[item item] [list]]]
       [definition [[🎁] 🪄 📮]]
       [examples [[[1 2 pair] [[1 2]] "Pair up two numbers into a list"]
                  [[["hi"] ["there" "foo"] pair] [[["hi"] ["there" "foo"]]] "Pair up two lists into a new list"]]]]]

[pair? [[spec [[item] [boolean]]]
        [definition [[📏 2 =]
                     [[actual 0 0] 🔍 [sized] 🍫 =]
                     [🗑️ 🗑️ 🔳]
                     [🔳] ⚖️ 🩹 ▶️] ]
        [examples [[["ab" pair?] [] "2-character string is a pair"]
                   [[[a b] pair?] [] "2-item list is a pair"]
                   [["abc" pair?] [🔳] "3-character string is not a pair"]
                   [[🔳 pair?] [🔳] "Nothing is not a pair"]
                   [[7 pair?] [🔳] "Number is not a pair"]]]]]

[triplet [[spec [[item item] [list]]]
          [definition [[pair] 🪄 📮]]
          [examples [[[1 2 3 triplet] [[1 2 3]] "Make a 3-item list from 3 stack items"]
                     [[["hi"] ["there" "foo"] ["bar"] triplet] [[["hi"] ["there" "foo"] ["bar"]]] "Make a 3-item list from smaller lists"]]]]]

[both? [[spec [[program item item] [boolean]]]
        [definition [⚓ pair 🔀 💯 ▶️]]
        [examples [[[1 2 [odd?] both?] [🔳] "Test two items for predicate when not all match"]
                   [[1 3 [odd?] both?] [] "Test two items for predicate when all match"]]]]]

[both [[spec [[program [item a] [item b]] [item item]]]
       [definition [[pair] 🪄 🪜 ▶️]]
       [examples [[[1 2 [inc] both] [2 3] "Run program on two stack items"]]]]]

[walk [[spec [[[program item-transform] list] [list]]]
       [definition [[✂️1️⃣] 🎒 ;; the negative branch
                    [list?] 🛡️ ;; pred
                    [🗑️ 🔳 🔀] 🛟 ;; affirmative branch
                    [[✂️1️⃣ 🔗] 🎒 🪜 ▶️ 🎁] ;; recur into each subitem and wrap
                    🪆 [✂️1️⃣ 🍫] 🎒]] ;; unwrap at the end
       [examples [[[[1 2 [3 [4 5] 6]] [inc 🎁] walk ▶️] [[2 3 [4 [5 6] 7]]] "Walk a nested list"]
                  [[[1 2 [3 [4 5] 6]] [👥 inc pair] walk ▶️] [[1 2 2 3 [3 4 [4 5 5 6] 6 7]]] "Walk a nested list and splice results"]]]]]

[flatten [[spec [[list] [list]]]
          [definition [🔳 🔀 [list?] 🛡️ [🗑️] [📮] [🪜 ▶️] 🪆 ▶️]]
          [examples [[[[a b [c [d e] f] g] flatten] [[a b c d e f g]] "Flatten a nested list"]]]]]

[pad [[spec [[[item padding] [integer newsize] sized] [sized]]]
      [definition [[[[📏] 🛡️ ▶️] 🐋
                    [[abs] 🪄 -] 🛡️ ▶️ ;; negative means pad on left
                    •🗑️] 🪄
                   🔀 repetition ▶️
                   🔀
                   [positive?] [🗑️] [🔀] ⚖️ ▶️ 
                   🔗]]
      [examples [[[[1 2 3] -5 0 pad] [[0 0 1 2 3]] "Pad a list at start with negative argument, to given size"]
                 [[[1 2 3] 5 0 pad] [[1 2 3 0 0]] "Pad a list at end with positive argument, to given size"]
                 [[[1 2 3 4 5 6] -5 0 pad] [[1 2 3 4 5 6]] "Padding a list to smaller than original size, is a no-op"]]]]]

1.4.1. Associations

[get [[spec [[item sized] [item]]]
      [examples [[[[[a 3] [c 2]] [a] 🍫 get] [3] "Get a key from an association"]
                 [[[10 11 12 13] 1 get] [11] "Get an item by index from a list"]
                 [["foobar" 3 get] [\b] "Get a character by index from a string"]
                 [["foobar" encode 3 get] [98] "Get an integer by index from a byte array"]
                 [[[[a 3] [c 2]] [b] 🍫 get] [🔳] "Get a nonexistent key -> Nothing"]]]]]

[assign [[spec [[[item value]
                 [list keys]
                 sized]
                [association]]]
         [examples [[[[[a b] [c d]] [a] 5 assign]
                     [[[a 5] [c d]] association] "Assign a new value to an existing key"]

                    [[[[a b] [c d]] [e] 5 assign]
                     [[[a b] [c d] [e 5]] association] "Assign a new value to a new key"]

                    [[[[a b] [c [[d e]]]] [c d] 5 assign]
                     [[[a b] [c 🔳]] [c] [[d 5]] association assign] "Assign a new nested key, promoting to nested association"]

                    [[[[a b] [c [[d e]]]] [1 1 0] 5 assign]
                     [[[a b] [c [5]]]] "Assign a new index in a nested list"]

                    [[[1 2 3] [1 0 0] "foo" assign]
                     [[1 [["foo"]] 3]] "Assign a new index in a nested list"]

                    [[[[a [1 2 3]]] [a 0] 10 assign]
                     [[[a [10 2 3]]] association] "Assign a nested key in a mixed structure of association and list"]

                    [[[1 2 3] [1 2] "foo" assign]
                     [[1 [🔳 🔳 "foo"] 3]] "Assign an index creating placeholders for missing list items"]]]]]

[unassign [[spec [[[item key] [sized into-association]] [association]]]
           [examples [[[[[a b] [c d]] [a] unassign]
                       [[[c d]] association] "Unassign a key from an association, promoting from list"]

                      [[[[a b] [c d]] [e] unassign]
                       [[[a b] [c d]] association] "Unassign a key that doesn't exist, only promotes"]

                      [[[[a b] [c d]] [e f] unassign]
                       [[[a b] [c d]] association] "Unassign multiple keys that don't exist only promotes"]

                      [[[[a b] [c [[d e] [f g]]]] [c x] unassign]
                       [[[a b]] [c] [[d e] [f g]] association assign] "Unassign multiple keys where last doesn't exist, only promotes"]

                      [[[[a [[b c] [d e]]]] [a d] unassign]
                       [🔳 association [a b] [c] 🍫 assign] "Unassign associative keylist from nested structure, promoted to association"]

                      [[[0 1 2 [[a b] [c d]]] [3 c] unassign]
                       [[0 1 2] [[a b]] association 📮] "Unassign mixed keylist from nested structure, inner only is promoted to association"]]]]]

[association? [[spec [[item] [boolean]]]
               [examples [[[[[a b] [c d]] association association?] [] "Association is an association"]
                          [[[[a b] [c d]] association?] [🔳] "A list is not an association, even if it's possible to promote"]
                          [[1 association?] [🔳] "A number is not an association"]
                          [[🔳 association?] [🔳] "An empty list is not an association"]
                          [[🔳 association association?] [] "An empty association is an association"]
                          [[🔳 [a] 1 assign association?] [] "A list promoted to association by assignment, is an association"]]]]]

[association [[spec [[item] [association]]]
              [examples [[[[[a b] [c d]] association
                           [[c d] [a b]] association =]
                          [] "A list can be promoted to association"]

                         [[[[a b] [c d]]
                           [[c d] [a b]] association =]
                          [🔳] "An association and list are not the same, even if keys/vals are the same"]

                         [[[[a b] [c d]]
                           [[a b] [c d]] association =] [🔳] "An association is not the same as the list it was promoted from"]]]]]
;; Associative words
[update [[spec [[program [list keys] [sized into-association]]
                [association]]]
         [definition  [•🛡️ 
                       [🔍] 🛡️ 🪄
                       🛟 [🛟] 🪄 
                       [▶️] •🪄 🛟 assign]]
         [examples [[[[[a 1] [b 2]] [b] [inc] update]
                     [[[a 1] [b 3]] association] "Update a value in an association"]

                    [[[[a [[c 3] [d 5]]] [b 2]]
                      [a c] [inc] update
                      [a c] 🔍]
                     [4] "Update a value in a nested association"]

                    [[[[a [1 3 5 7]] [b 2]]
                      [a 2] [inc] update]
                     [[[a [1 3 6 7]] [b 2]] association] "Update a value in a mixed association/list structure"]

                    [["hi"
                      [[a [[c 3] [d 5]]] [b 2]]
                      [a c] [🗑️ 🗑️ 10 15] update
                      [a c] 🔍]
                     ["hi" 15] "Update function can't destroy stack items"]

                    [[[[a 1] [b 2]] [d] [5] update]
                     [[[a 1] [b 2] [d 5]] association] "Update creates new key when it doesn't exist"]

                    [[[[a [[c 3] [d 5]]] [b 2]]
                      [a e] [5 6 +] update
                      [a e] 🔍]
                     [11] "Update function can ignore previous value"]]]]]

[🔍 [[spec [[[list keys] sized] [item]]]
         [definition [🔳 ;; keylist not empty
                      [📤 🔀 [get] 🪄] ;; extract the first key and 🔍
                      ⏳ ▶️]]
         [examples [[[[[a b] [c d]] association [a] 🔍] [[b] 🍫] "Lookup the value of a key in an association"]
                    [[[[a b] [c d]] [a] 🔍] [[b] 🍫] "Lookup the value of a key, promoting a list to association"]
                    [[[[a b] [c d]] [e] 🔍] [🔳] "Looking up a key that doesn't exist returns Nothing"]
                    [[[[outer [[a b] [c d]]]] [outer c] 🔍] [[d] 🍫] "Lookup in a nested structure, with promotion"]]]]]

;; TODO: fix the case where you just want a value [[type foo]] - only
;; one item but you want the value, not key
[type [[spec [[item] [item]]]
       [definition [[[[empty?] [[nothing]]]
                     [[word?] [[word]]]
                     [[number?] [[number]]]
                     [[string?] [[string]]]
                     [[bytes?] [[bytes]]]
                     [[pipe?] [[pipe]]]
                     [[error?] [[error]]]
                     [[environment?] [[environment]]]
                     [[set?] [[set]]]
                     [[association?] [🗑️ [[[📏 1 =] [🗑️
                                                    [first first [type] 🍫 =] 🛡️
                                                    [🗑️ first second]
                                                    [first first]
                                                    ⚖️ ▶️]]
                                         [[[type] 🔍] [•🗑️]]
                                         [[] [[association] 🍫 •🗑️ •🗑️]]] decide
                                      🎁 🔳 🔳 🛟]]
                     [[list?] [[list]]]
                     [[] [[item]]]]
                    decide 🍫 •🗑️ •🗑️]]
       [examples [[[[[foo 1]] association type] [[foo] 🍫] "An association with one key assumes it is its type"]
                  [[1 type] [[number] 🍫] "Integers are of type number"]
                  [[1.0 type] [[number] 🍫] "Floats are of type number"]
                  [[🔳 type] [[nothing] 🍫] "Empty list is of type nothing"]
                  [["foo" encode type] [[bytes] 🍫] "A byte array is of type bytes"]
                  [["foo" type] [[string] 🍫] "A string is of type string"]
                  [[[1 2 3] set type] [[set] 🍫] "A set is of type set"]
                  [[🔳 environment type] [[environment] 🍫] "An environment is of type environment"]
                  [[[[type foo]] association type] [[foo] 🍫] "An association with a single type key, the value is its type"]
                  [[[[type foo] [attr "blah"]] association type] [[foo] 🍫] "An association with a single type key, the value is its type"]
                  [[[[attr1 foo] [attr2 "blah"]] association type] [[association] 🍫] "An association with multiple keys and no type key, is of type association"]
                  [[[[type url] [value "http://foo.com"]] association type] [[url] 🍫] "An association with type/value keys, uses the type key for its type"]]]]]

[value [[spec [[[sized into-association]] [item]]]
        [definition [[📏 1 =] 🛡️ ;; if it's a single item
                     [🗑️ first second] ;; the value is the value of that first item
                     [[value] 🔍] ;; otherwise look up the key 'value'
                     ⚖️ ▶️]]
        [examples [[[[[foo 1]] value] [1] "The value of a single-entry association is the value of the key-value pair"]

                   [[[[type url] [value "http://foo.com"]] value]
                    ["http://foo.com"] "The value of an object is the value key"]]]]]

[zip [[spec [[[dispenser values] [dispenser keys]] [list]]]
      [definition [🔳 ⚓ ;; save accumulator below args
                   [🔳 both?] 🛡️ ;; stop when either list is empty
                   [🗑️ [📤] both •🔀 pair ;; take from each list and pair them up
[📮] •🪄] ;; put them into the accumulator
                   ⏳ ▶️
                   🗑️ 🗑️]] ;; drop the empty containers
      [examples [[[[a b c] [1 2 3] zip] [[[a 1] [b 2] [c 3]]] "Zip two lists together into a single list of pairs"]
                 [[[a b c d] [1 2 3] zip] [[[a 1] [b 2] [c 3]]] "Zip two lists of unequal size pads with Nothing values"]]]]]

[label [[spec [[[sized labels]] [association]]]
        [definition [🔳 🔀 ;; labels acc
                     [🎁 🛟 assign] 🪜 ▶️]]
        [examples [[["Alice" 23 "123 Main St" [address age name] label]
                    [[[address "123 Main St"]
                      [age 23]
                      [name "Alice"]] association]
                    "Label values on the stack as an association"]]]]]

[assocify [[spec [[list] [item]]]
           [doc "Recursively converts association-shaped lists into
           actual associations, leaving non-convertiable values
           as-is. Useful for literal lists that are intended as
           nested associations."]
           [definition [[list?] 🛡️
                        [🗑️]
                        []
                        [🚜 [association] [🗑️] 🩹 🔗 ▶️]
                        🪆 ▶️]]
           [examples [[[[1 2] assocify] [[1 2]] "assocify a non-assoc-shaped list is a no-op"]
                      [[[[a b]] assocify] [[[a b]] association] "assocify an assoc-shaped list converts to association"]
                      [[[foo [[a b]] bar] assocify] [[[a b]] association [foo 1️⃣ bar] 🎒] "assocify an non-assoc-shaped list converts inner values to association where appropriate"]]]]]

1.4.2. Sets

;; TODO add 'set' type for spec?
[set [[spec [[item] [item]]]
      [examples [[[[1 2 3 1 2 3] set] [[1 2 3] set] "Promote a list to a set"]
                 [["hello" set] ["helo" set] "Promote a string to a set"]]]]]

[set? [[spec [[item] [boolean]]]
       [examples [[[[1 2 3] set set?] [] "A set is a set"]
                  [[[1 2 3] set?] [🔳] "A list is not a set"]]]]]

[contains? [[spec [[item [item container]] [boolean]]]
            [examples [[[[1 2 3] 3 contains?] [] "List contains a number"]
                       [[[1 2 3 3 5] set 3 contains?] [] "A set contains a number"]
                       [[[1 2 3] 4 contains?] [🔳] "A list doesn't contain a number"]
                       [[5 3 contains?] [🔳] "A number is atomic and doesn't contain anything"]
                       [[[foo] 🍫 \o contains?] [🔳] "A word is atomic and doesn't contain anything"]
                       [["food" "foo" contains?] [] "A string contains a sub-string"]
                       [[[a b c d] [b c] contains?] [🔳] "A list doesn't contain a sub-list (due to ambiguity with what 'contains' means with lists)"]
                       [[[a [b c] d] [b c] contains?] [] "A list contains another list"]
                       [[[a [b c] d] set [b c] contains?] [] "A set contains a list"]
                       [["food" \o contains?] [] "A string contains a character"]]]]]

[intersection [[spec [[sized sized] [sized]]]
               [examples [[[[1 2 3] [2 3 4] intersection] [[2 3] set] "Intersection of two lists expressed as set"]]]]]

[difference [[spec [[sized sized] [sized]]]
             [examples [[[[1 2 3] [2 3 4] difference] [[1] set] "Difference of two lists expressed as set"]]]]]

1.4.3. Generators

;; infinite sequence (generators) functions

[[generator [[spec [program program]]
             [definition [🔳 [🔳] [🔀] 🪆]]]]

 [liberator [[spec [🔳 [program]]]
             [definition [[📤] generator]]]]

 [extractor [[spec [program program]]
             [doc "Turns a wrapped generator into a regular one."]
             [definition [[[▶️] 💉 ▶️ 📤]
                          []
                          [[]]
                          [🔀] 🪆]]
             [examples []]]]

 [reap [[spec [[[program generator]] [item]]]
         [doc "Generates a value from a wrapped generator (stacked generator inside a list)"]
         [definition [🔳 🔀 💉 ▶️ first]] ;; the now-empty dispenser
         [examples [[[[integers generator 5 taker collect] reap] [[0 1 2 3 4]]]]]]]

 [assemble [[spec [[program dispenser] [list]]]
            [definition [[liberator ✂️1️⃣] 🎒
                         [🎁] 🪄 💉 ▶️ first]]
            [examples [[[[1 2 3 4 5]
                         [[odd?] keep
                          collect] assemble]
                        [[1 3 5]]]]]]]

 [produce [[spec [[[list wrapped-generator]] [list item]]]
           [definition [[▶️] 💉 ▶️ 📤]]
           [examples [[[integers generator
                        [👥 *] each
                        10 dropper
                        🔳 🧦 
                        produce •🗑️] [100]]]]]]

 [🧹 [[spec [[sized program] [program]]]
      [doc "The broom denotes a gathering - the returned program will repeatedly call the given program to generate items, and put them into the container below it."]
      [definition [[[▶️] 🐋] [📮]]]
      [examples [[[[\a \b \c \d] liberator "" 🧹 ▶️]
                  [🔳 "abcd"] "Sweep into an empty string"]
                 [[0 10 1 range liberator
                   5 dropper
                   [10 *] each
                   🔳 🧹 ▶️]
                  [🔳 [50 60 70 80 90]] "Generate a sequence and put it into the given container"]]]]]

 [drain [[spec [[sized program] [program]]]
         [doc "Returns a program that drains the generator below it,
               and doesn't save anything in memory. Should be used
               only for generators that have side effects, when you
               want to drive the side effects forward, without
               producing any values."]
         [definition [[▶️] [🗑️]]]
         [examples []]]]

 [collect [[spec [[program] [list]]]
           [definition [🔳 🧹 ▶️]]
           [examples [[[[[1 2 3 4] liberator collect] 🛡️ ▶️]
                       [[1 2 3 4]]]
                      [[[0 10 1 range liberator
                         5 dropper
                         [10 *] each
                         collect]
                        🛡️ ▶️]
                       [[50 60 70 80 90]] "Collect from a generator into an empty list"]]]]]

 [each [[spec [[program] [program]]]
        [definition [•🛡️ ;; prevent mapping program from overwriting stack
                     [▶️ 1️⃣ bail] 🎒 ;; only execute the mapping program if parent produces value
                     🔳 [🔳] [🔀] 🪆]] 
        [examples [[[[1 2 3 4] liberator
                     [👥 *] each
                     collect]

                    [🔳 [1 4 9 16]] "Generate a sequence transforming each value"]]]]]

 [taker [[spec [[[integer howmany]] [program]]]
         [definition [[positive?] 🛡️ ;; counter still positive?
                      [🗑️ [▶️] 🐋 ;; run the parent generator
                       🔳 [🔳 🔳] ↔️] ;; add padding to drop later
                      [🔳] ⚖️ ;; otherwise return nothing
                      [[dec] 🪄] ;; decrement counter
                      [🗑️ 🔳] ;; discard the counter but keep parent, all done
                      [🔀] 🪆]]
         [examples [[[[1 2 3 4 5] [3 taker collect] assemble]
                     [[1 2 3]] "Taker takes given number of items from the parent"]

                    [[[1 2 3 4 5] [6 taker collect] assemble]
                     [[1 2 3 4 5]] "Taker stops when parent ends before given number of items"]

                    [[[1 2 3 4 5 6] liberator
                      3 taker collect
                      [2 taker collect] 🐋
                      pair restore] ;; just keep the top 2 items
                     [[4 5] [1 2 3]] "Taker leaves parent intact so it can be reused"]]]]]

 [catcher [[spec [🔳 [program]]]
           [definition [[[▶️] 🐋 ;; get value from parent
                         [🔀 [▶️] 🛡️ ▶️] bail ;; only check pred iff we get a value, preserve pred
                         🔳
                         [🔳 🔳 🔳] ↔️] ;; place some dummy values to drop if we didn't get a value
                        [🗑️ 🔀] ;; iff pred matches drop the pred result 
                        [🗑️ 🗑️ 🗑️ 🔳] ;; otherwise drop all the stuff we no longer need
                        ⚖️ 🔳
                        [[🔳] 🔳] [🔀] 🪆]]
           [examples [[[[1 2 3 -4 5]
                        [[positive?] catcher collect]
                        assemble]

                       [[1 2 3]]]

                      [[[1 2 3 4 5]
                        [[positive?] catcher collect]
                        assemble]

                       [[1 2 3 4 5]]]]]]]

 [dropper [[spec [🔳 [program]]]
           [definition [[positive?] 🛡️ ;; condition
                        [🗑️ [▶️] 🐋 ;; call parent 
                         🔳 ;; if we get something, we're done
                         [🗑️ 🔳 🔳] ;; otherwise signal stop with empty generator
                         ↔️]
                        [🗑️ ▶️ 🔳] ⚖️ ;; if counter reaches zero we're done dropping 
                        [🗑️ dec] ⏳
                        🔳 [🔳] [🗑️] 🪆]]
           [examples [[[[1 2 3 4 5] [3 dropper collect]
                        assemble]
                       [[4 5]]]
                      [[[1 2 3 4 5] [6 dropper collect]
                        assemble]
                       [🔳]]]]]]

 [skipper [[spec [🔳 [program]]]
           [definition [[[▶️] 🐋] ;; get the item from parent
                        [🔀 [▶️] 🛡️ ▶️] ;; run the pred on it, keep the pred
                        [🗑️ 🔳 🔳] ⚖️ ;; when parent is empty, leave negative on the stack
                        [🗑️ •🗑️];; keep consuming items while they match pred
                        🔳 [🔳] [🗑️ 🗑️] 🪆]]
           [examples [[[[1 2 -3 4 5]
                        [[positive?] skipper collect]
                        assemble]

                       [[-3 4 5]]]]]]]

 [keep [[spec [[program] [program]]]
        [definition [[▶️  ;; exec the generator below to get value v
                      [1️⃣ 🛡️ ▶️ ☯️] ;; check if v does NOT match given pred, 
                      [🔳 🔳] ;; if generator below is finished, return 2 empty values 
                      ↔️] 🎒
                     [🗑️ 🗑️] ;; drop both the value v and the result of pred
;; repeat until generator below is finished
                     🔳 [🔳] [🔀] 🪆]]
        [examples [[[[1 2 3 4 5] liberator
                     [odd?] keep
                     collect]

                    [🔳 [1 3 5]]]]]]]

 [group [[spec [[[program group-by]] [association]]]
         [definition [🛡️
                      [1️⃣ ▶️ ;; k v state
                       🎁 🔀   ;;  v k state
                       🎁 [📮] 🔗 update] 🎒
                      🔳 association ;; state f
                      🔀 cram]]
         [examples [[[[1 2 3 4] liberator [odd?] group]
                     [🔳 [[[1 3]] [🔳 [2 4]]] association]]]]]]

 [splitter [[spec [[sized] [program sized sized]]]
            [definition [[[👥 [📮 1️⃣] 🪄  ;; add new value to input buffer
                           [☯️] ;; the input was empty
                           [ends?] 🛡️ ;; the input buffer ends in the delimiter
                           pair ;; user both these as conditions
                           [▶️] 📣 
                           [🗑️ ;; the bool
                            📏 ;; the delim 
                            0 🔀 - 0 🔀 slice] ;; chop the length of the divider 
                           [🗑️ 🔳]
                           ⚖️ ▶️] 🪄 ;; under the output
                          🔀 ;; put possible new output on top
                          [👥 empty [📮] 🪄 🔀] 🔳 ↔️]
                         over empty ;; starting empty container for parse
                         [🎒] 🪄]]
            [examples [[["abcabc" ["b" splitter parse collect] assemble]
                        [["a" "ca" "c"]]]
                       [[[1 2 3 4 2 5] [[2] splitter parse collect] assemble]
                        [[[1] [3 4] [5]]]]]]]]

 [parse [[spec [[[program partial-parser] [[program parser]]]]]

         [doc "A stream parser. On the stack should be: 1) an input
               buffer that receives chunks of input from upstream
               (usually an empty string or byte array or list
               depending on what type of data is being produced), 2)
               program that takes 3 args: parsed object output buffer
               (on top), a new input item, and an unparsed input
               buffer. The function should return new input and
               output buffers. If there is enough input to create a
               new output, the program should do so, otherwise it only
               needs to combine the new input with the existing input
               buffer. An empty input should signal an end-of-stream
               condition and it's up to the program how to interpret
               that."]

         [definition [🔳 ;; state - parsed object output buffer (on top), unparsed input 
                      🔳 ;; there's output?
                      [🔳]  ;; leave an empty value to be consumed by outer ⏳ exiting
                      [🔳 [▶️] ••🐋] ;; exec parent generator 
                      ⚖️ 
                      [🔀 [👥] ••🐋 ▶️] ;; exec a copy of parser program: output input parser
[📤] [[🔳] 🔀] ;; leave empty generator if we hit end of stream
                      [🔀] 🪆]]
         [examples [[[[[[104 101 108 108 111]              ;; "hello" (all ASCII)
                        [228 189 160 229 165 189]          ;; "你好" (two complete Chinese chars)
                        [104 105 226]                      ;; "hi" + start of "€"
                        [130 172]                          ;; completion of "€"
                        [240 159 145]                      ;; start of "👑"
                        [145]                              ;; completion of "👑"
                        [97 98 99 240]                     ;; "abc" + start of "🌈"
                        [159 140 136]]                     ;; completion of "🌈"

                       liberator
                       [#b64 "" 🔀 [📮] 🪜 ▶️] each ;; convert lists of ints to byte arrays
                       [parse-utf8] #b64 ""
                       parse "" 🧹 ▶️] reap]
                     ["hello你好hi€👑abc🌈"]]

                    [[[["[foo] [bar] [ba"
                        "z] [quux"
                        "] [[this] "
                        "[that]]"
                        "[foo" "]"] liberator
                       [parse-edn] "" parse collect]
                      reap]
                     [[[foo] [bar] [baz] [quux] [[this] [that]]
                       [foo]]]]]]]]

 [combinations [[spec [🔳 [program]]]
                [definition [[📏] 🛡️ -1 ;; l idx i
                             [[[🔀 📏 =] 🐋] [🗑️ 🗑️ 📤 0 🔀] when
                              [[🎁 🔍] 🐋 [pair] bail] 🛡️ [inc] •🪄]]]
                [examples [[[[1 2 3] [combinations] assemble] [[[1 2] [1 3] [2 3]]]]]]]]

 [frequencies [[spec [🔳 [association]]]
               [definition [🔳 association
                            [🎁 [🔳 [inc] [1] ⚖️ ▶️ ] update]
                            cram]]
               [examples [[["Hello there!" [frequencies] assemble]
                           [[[\space 1]
                             [\! 1]
                             [\H 1]
                             [\e 3]
                             [\h 1]
                             [\l 2]
                             [\o 1]
                             [\r 1]
                             [\t 1]] association]]]]]]

 [fold [[spec [[[program reducing-function] [program generator]] [item]]]
        [definition [[▶️] 🪄 ;; generate the first item below the reducer
                     cram]]
        [examples [[[[integers generator
                      1 dropper
                      10 taker
                      [+] fold] reap] [55]]]]]]

 [cram [[spec [[[program reducing-function]
                [item initial-value]
                [program generator]] [item]]]
        [definition [[[▶️] •🐋] ;; check that we generated another item
                     [🔀 [▶️] 🛡️ ▶️ ⚓ •🗑️ ••🗑️] ;; if so, run the reducer shielded and drop component items
                     🔳 ;; otherwise stop
                     [▶️] 🪆
                     ▶️ 🗑️]]
        [examples [[[[integers generator
                      1 dropper
                      10 taker
                      0 [+] cram]
                     reap] [55]]]]]]

 [integers [[spec [🔳 [program]]]
            [definition [-1 [inc 👥]]]]]

 [partition [[spec [[[number partition-size] [program generator]] [program]]]
             [definition [[flip [📏] 🛡️ ▶️ 1️⃣ >=] 🎒
                          [🗑️ •🔀 📮 [🎁] 🪄]
                          [🔀 📮 🔀]
                          ⚖️ 🔳 parse]]
             [examples [[[[1 2 3 4 5 6 7] [2 partition collect] assemble]
                         [[[1 2] [3 4] [5 6] [7]]]]]]]]

 [evaluator [[spec [[environment [program input-generator]] [program]]]
             [definition [[[▶️] 🐋]
                          [[program] 🔀 assign evaluate]
                          [🗑️ []]
                          [over] 🪆]]
             [examples []]]]]
🔗

1.5. Dictionary modules

[dictionary [[spec [🔳 [list]]]]]

[cache [[spec [[item bytes] [bytes]]]]]

[decache [[spec [[item] [bytes]]]]]

[hashbytes [[spec [[bytes] [bytes]]]
            [examples [[[["foo" encode hashbytes] 2 times ▶️ =] []]
                       [["foo" encode hashbytes
                         "fop" encode hashbytes
                         =]
                        [🔳]]]]]]

[resolve [[spec [[word] [word]]]
          [examples [[[[+] 🍫 resolve] [[core/+] 🍫]]]]]]

[namespace [[spec [[bytes word] [word]]]
            [examples [[[[foo] 🍫 #b64 "quux" namespace] [[quux/foo] 🍫]]]]]]

[unnamespace [[spec [[word] [bytes word]]]
              [examples [[[[quux/foo] 🍫 unnamespace] [[foo #b64 "quux"] 🍫]]]]]]

[dictmerge [[spec [[[dictionary module] [dictionary original] [bytes hash]] [dictionary]]]]]

[lingo [[spec [[dictionary] [association]]]]]
[updates [[spec [[[sized word-updates]] [[program single-update]]]]
          [definition [[[📤]
                        [[0] [🎁] update ;; wrap the word name to get a path to update
                         [update] 🔗] each
                        joiner generate] •🛡️]]]]

[entry [[spec [[[program definition]] [[association full-entry]]]]
        [definition [[definition] label]]]]

[words [[spec [🔳 [association]]]
        [definition [dictionary [words] 🔍]]]]

[lingo [[spec [🔳 [association]]]
        [definition [dictionary [lingo] 🔍]]]]

[module [[spec [[[item wrapped-module-alias-or-hash]] [program]]]
         [doc "reads a cached module from disk and puts it on the stack as a program"]
         [definition [decache string read]]
         [examples [
          ;;[["123" encode [crypto] module [hash] confine]
          ;; [#b64 "_1vRbfFezlcTCUfQCjC1FKukWLoOAeBuvxNXUDbFKSk"]]
          ]]]]

[inscribe [[spec [[[bytes raw-module] dictionary] [dictionary]]]
           [definition [[[hashbytes] ;; calculate module hash
                         [string read [words] 🔀 update]] ;; install the module in the dictionary
                        [▶️] 🚜 ▶️ ;; fork 
                        •🗑️ 🍫 •🔀 dictmerge]]]]

[draft [[spec [[[sized definitions]] [[program dictionary-updater]]]]
        [definition [[[1] [entry] update] 🚜 ▶️ ;; create full entries for each definition
                    [1️⃣ 🔗] 🎒]]]]  ;; add 'join' to join the entries with the existing dictionary

[let [[spec [[program [sized entries]] [*]]]
      [definition [[draft ;; build full entries
                    dictionary 🔀 
                    [emit encode hashbytes] 🛡️ ▶️ ;; get the hash of the entries
                    [[[words] 🔀 update] 🛡️ ▶️ •🗑️] 🪄 ;; update the dictionary
[dictmerge] ••🛡️ ▶️] 🪄 ;; merge it 
                   🛟 🎁 [📮] 🔗
                   •🔀 [modules] 🔀 update
                   [dictionary program] label environment
                   ;; TODO try using confine here
                   [1️⃣ capture evaluate [stack] 🔍 restore] 🎒]] 
      [examples [[[[[times5 [5 *]]
                    [doubledec [dec dec]]]
                   [3 times5 doubledec] let ▶️] [13]]
                 [[[[🔀 [5]]]
                   ["a" "b" "c" 🔀]
                   let ▶️]
                  ["a" "b" "c" 5]]
                 [[[[foo ["outer"]]]
                   ["inner"] let
                   [foo] label
                   [foo] let ▶️] ["inner"]]]]]]

[definition [[spec [[list] [program]]]
             [definition [[✂️1️⃣ definition] 🎒 dictionary lingo 🔀 🔍]]
             [examples [[[1 2 3 [🔀] definition ▶️] [1 3 2] "Fetch the definition of a builtin word and use it"]
                        [[1 2 3 [flip] definition ▶️] [3 2 1] "Fetch the definition of a word and use it"]]]]]

1.6. Math

[+ [[spec [[number number] [number]]]
    [examples [[[1 2 +] [3]]
               [[1.1 2.2 + 3.3 0.001 within?] []]
               [[1 2.2 +] [3.2]]]]]]

[- [[spec [[number number] [number]]]
    [examples [[[2 1 -] [1]]
               [[1.1 2.2 - -1.1 0.00001 within?] []]
               [[2.2 1 - 1.2 0.00001 within?] []]]]]]

[* [[spec [[number number] [number]]]
    [examples [[[4 3 *] [12]]
               [[10 1.5 * 15 0.0001 within?] []]
               [[5 0 *] [0]]
               [[5 -1 *] [-5]]]]]]

[/ [[spec [[number number] [number]]]
    [examples [[[12 3 /] [4]]
               [[15 1.5 /] [10.0]]
               [[0 1 /] [0]]
               [[1 0 / handle [reason] 🔍] [1 0 "division by zero"]]]]]]

[quot [[spec [[number number] [number]]]
       [examples [[[16 5 quot] [3]]]]]]

[rem [[spec [[number number] [number]]]
      [examples [[[17 5 rem] [2]]]]]]

[mod [[spec [[number number] [number]]]
      [examples [[[17 5 mod] [2]]]]]]

[exp [[spec [[number number] [number]]]
      [examples [[[2 5 exp] [32]]
                 [[2 2.5 exp 5.656854 0.00001 within?] []]]]]]

[log [[spec [[number number] [number]]]
      [examples [[[32 2 log] [5]]]]]]

[floor [[spec [[number] [number]]]
        [examples [[[2.1 floor] [2]]]]]]

[ceiling [[spec [[number] [number]]]
          [examples [[[2.1 ceiling] [3]]]]]]

[round [[spec [[number] [number]]]
        [examples [[[2.1 round] [2]]]]]]

[sqrt [[spec [[number] [number]]]
       [examples [[[9 sqrt] [3]]
                  [[81 sqrt] [9]]]]]]

[inc [[spec [[number] [number]]]
      [examples [[[1 inc] [2]]
                 [[-1 inc] [0]]
                 [[99 inc] [100]]]]]]

[dec [[spec [[number] [number]]]
      [examples [[[2 dec] [1]]
                 [[0 dec] [-1]]
                 [[100 dec] [99]]]]]]

[abs [[spec [[number] [integer]]]
      [examples [[[2.1 abs] [2.1]]
                 [[-0.2 abs] [0.2]]
                 [[-2 abs] [2]]
                 [[0 abs] [0]]]]]]

[odd? [[spec [[number] [boolean]]]
       [examples [[[1 odd?] []]
                  [[-1 odd?] []]
                  [[4 odd?] [🔳]]]]]]

[even? [[spec [[number] [boolean]]]
        [examples [[[2 even?] []]
                   [[-2 even?] []]
                   [[3 even?] [🔳]]]]]]

[zero? [[spec [[number] [boolean]]]
        [examples [[[0 zero?] []]
                   [[0.0 zero?] []]
                   [[-0.00001 zero?] [🔳]]
                   [[1.1 zero?] [🔳]]]]]]

[number? [[spec [[item] [boolean]]]
          [examples [[[[1] number?] [🔳]]
                     [[🔳 number?] [🔳]]
                     [[5 number?] []]
                     [[5.01 number?] []]]]]]

[integer? [[spec [[item] [boolean]]]
          [examples [[[[1] integer?] [🔳]]
                     [[🔳 integer?] [🔳]]
                     [[5 integer?] []]
                     [[-5 integer?] []]
                     [[0 integer?] []]
                     [[5.01 integer?] [🔳]]
                     [[5.00 integer?] [🔳]]]]]]
[number [[spec [[item] [number]]]
         [examples [[["12" number] [12]]
                    [["-11.1" number] [-11.1]]
                    [["a" first number] [97]]]]]]
[positive? [[spec [[number] [boolean]]]
            [definition [0 >]]]]

[negative? [[spec [[number] [boolean]]]
            [definition [0 <]]]]

[within? [[spec [[number number] [boolean]]]
          [definition [[- abs] 🪄 <]]
          [examples [[[1.0 2.0 + 3 0.001 within?] []]]]]]
[[fibonacci [[definition [1 0 ;; starting state
                          [[+] •🛡️ ▶️ ;; add and preserve the first addend
                           🔀 👥]]]]]] ;; make the result the new state item
🔗 

1.7. Serialization

[read [[spec [[string] [item]]]
       [examples [[["[1 [2] 3]" read] [[1 [2] 3]]]]]]]

[emit [[spec [[item] [string]]]
       [examples [[[[1 [2] 3] emit] ["1 [2] 3"]]]]]]

[parse-edn [[spec [[[list current-output-sequence] [string input] [string input-buffer]]
                   [[list updated-output-sequence] [string remaining-input]]]]
            [examples [[["" "[foo] [ba" 🔳 parse-edn] [" [ba" [[foo]]]]]]]]

[autoformat [[spec [[string] [string]]]
             [examples [[["[[foo bar] [baz [[quux floop] [toop zoop]]]]" autoformat]
                         ["[[foo bar]\n [baz [[quux floop]\n       [toop zoop]]]]"]]]]]]

1.8. Boolean logic

[[[spec [🔳 [word]]]]] ;; self-inserts

[and [[spec [[item item] [item]]]
      [examples [[[1 odd? 2 even? and] []]
                 [[2 3 and] [3]]
                 [[🔳 3 and] [🔳]]
                 [["" 3 and] [🔳]]]]]]

[or [[spec [[item item] [item]]]
     [examples [[[1 odd? 3 even? or] []]
                [[1 2 or] [1]]
                [[🔳 2 or] [2]]
                [[🔳 🔳 or] [🔳]]]]]]

[☯️ [[spec [[item] [boolean]]]
    [examples [[[1 even? ☯️] []]
               [[🔳 ☯️] []]
               [[✅ ☯️] [🔳]]
               [[🔳 ☯️] []]]]]]

1.9. Byte encoding and decoding

[character [[spec [[item] [character]]]
            [examples [[[97 character] [\a]]
                       [[128526 character] [\😎]]]]]]

[encodeitem [[spec [[item] [bytes]]]
             [examples [[["foo" encodeitem] [#b64 "Zm9v"]]
                        [["" encodeitem] [#b64 ""]]
                        [[12 encodeitem] [#b64 "AAAAAAAAAAw"]]
                        [[12.3 encodeitem] [#b64 "QCiZmZmZmZo"]]]]]]

[decodejson [[spec [[string] [item]]]
             [examples [[["12" decodejson] [12]]
                        [["12.01" decodejson] [12.01]]
                        [["\"foo\"" decodejson] ["foo"]]
                        [["{\"foo\": 12, \"bar\": \"baz\"}" decodejson] [[["foo" 12] ["bar" "baz"]] association]]
                        [["[1,\"foo\"]" decodejson] [[1 "foo"]]]]]]]

[encodejson [[spec [[item] [string]]]
             [examples [[[12 encodejson] ["12"]]
                        [[12.01 encodejson] ["12.01"]]
                        [["foo" encodejson] ["\"foo\""]]
                        [[[["foo" 12] ["bar" "baz"]] association encodejson decodejson] [[["foo" 12] ["bar" "baz"]] association]]
                        [[[1 "foo"] encodejson] ["[1,\"foo\"]"]]]]]]

[bytes? [[spec [[item] [boolean]]]
         [examples [[["foo" bytes?] [🔳]]
                    [[#b64 "Zm9v" bytes?] []]
                    [[[#b64 "Zm9v"] bytes?] [🔳]]
                    [["foo" encode bytes?] []]]]]]

[xor [[spec [[item] [item]]]
      [examples [[[10 12 xor] [6]] ;; 10 = 01010, 12 = 01100, 00110, 6
                  [["foo" encode "bar" encode xor] [#b64 "BA4d"]]]]]]

[bits [[spec [[item] [sized]]]
       [definition [encode [[2 radix -8 0 pad] each [🔗] fold] assemble]]
       [examples [[["foo" bits] [[0 1 1 0 0 1 1 0 0 1 1 0 1 1 1 1 0 1 1 0 1 1 1 1]]]]]]]
[[encode [[spec [[item] [bytes]]]
          [definition [[[[] [🗑️ encodeitem]]]
                       decide]]
          [examples [[[12 encode] [#b64 "AAAAAAAAAAw"]]
                     [["foo" encode] [#b64 "Zm9v"]]
                     [["foo" encode encode] [#b64 "Zm9v"]]
                     [["" encode] [#b64 ""]]]]]]

 [radix [[spec [[integer integer] [list]]]
         [definition [[🗑️ 1️⃣ [/] 🛡️ ▶️ 🔀 
                       [*] •🛡️ ▶️
                       •🔀 -
                       🔀 [prepend] 🪄] 🎒
                      [🔳 🔀 [positive?] 🛡️] 🪄
                      ⏳ ▶️ 🗑️]]
         [examples [[[7 2 radix] [[1 1 1]]]
                    [[9 3 radix] [[1 0 0]]]
                    [[255 16 radix] [[15 15]]]]]]]]
🔗

1.10. Strings

[string [[spec [[item] [string]]]
         [examples [[[1 string] ["1"]]
                    [[[97 98 99] string] ["abc"]]
                    [[🔳 string] [""]]]]]]

[format [[spec [[string list] [string]]]
         [examples [[[["abc" "def"] "foo {} bar {} baz" format] ["foo abc bar def baz"]]]]]]

[parse-utf8 [[spec [[[sized current-output] [bytes input] [bytes input-buffer]]
                    [[string updated-output-sequence] [bytes remaining-input]]]]
             [examples [[["hi" encode [226] encode "" parse-utf8] [#b64 "4g" "hi"]]
                        [["hell" encode \o encode "" parse-utf8] [#b64 "" "hello"]]]]]]

[string? [[spec [[item] [boolean]]]
          [examples [[["hi" string?] []]
                     [["" string?] []]
                     [[["hi"] string?] [🔳]]
                     [[✅ string?] [🔳]]]]]]

;; Don't really belong here but good enough for now
[word? [[spec [[item] [boolean]]]
        [examples [[[[foo] 🍫 word?] []]
                   [[✅ word?] []]
                   [[1 word?] [🔳]]
                   [["✅" word?] [🔳]]]]]]

[word [[spec [[item] [word]]]
       [examples [[["foo" word] [[foo] 🍫]]]]]]

[inspect [[spec [[item] [string]]]]]

1.11. Error handling

[error? [[spec [[item] [boolean]]]]]

;; handle is a special word only used to unwind the program on
;; error, if there's no error and we end up reaching this word, we
;; ignore it.
[handle [[spec [🔳 🔳]]
         [definition 🔳]]]

[fail [[spec [[sized] [*]]]]]
[[assert [[spec [[program]
                 [*]]]
          [definition [📸 ;; save stack to print in err message
                       [🛡️] 🐋 ;; run the assertion under the saved stack
                       [🗑️] ;; if passes, drop the saved stack, dont need
                       [string ["assertion failed "] 🪄 🔗 fail]]]]] ;; else throw err

 [🩹 [[spec [[[program error-handler] [program to-attempt]] [program]]]
      [doc "The bandage denotes a recovery, it takes an error-handler
            program, and a program to attempt that may cause an
            error. If the to-attempt program succeeds, the
            error-handler is dropped. Iff the to-attempt program fails
            with an error, the error-handler is invoked on a snapshot
            of the stack when the to-attempt program began."]
      [definition [[📸 [✂️2️⃣ handle] 💉 ▶️
                    [first error?] 🛡️
                    [🗑️ first ✂️1️⃣]
                    [🧦 🗑️]
                    ⚖️ ▶️] 🎒]]
      [examples [[[[+]
                   [🗑️ 1
                    [+] [🗑️ 2 +]
                    🩹 ▶️]
                   🩹 ▶️]
                  [3] "Simple recovery"]

                 [[[1 2 "oh fudge"]
                   [5 +]
                   [🗑️ 5]
                   🩹 🚜 ▶️]
                  [[6 7 5]] "Recover as part of mapping function"]]]]]

 [retry [[spec [[error] [*]]]
         [definition [[unwound] 🔍 ▶️]]
         [examples [[[2 3 "four" * + handle [🗑️ 4] 🪄 retry] [14]]]]]]]
🔗

1.12. Methods

We want a way of adding methods to a word that's already set up as a simple 'decide' form. This will add the method at the beginning - adding it at the end is not good because often there's a catchall condition at the end, and adding beyond that means the new condition is unreachable. Adding at the beginning is not always what the user wants either, though. So maybe this could be improved by taking another argument: a program to combine the item and the existing list (that defaults to prepend here).

[[addmethod [[spec [[[program method] [program condition] [program definition]]
                    [[program newdefinition]]]]
             [definition [[[2️⃣ 1️⃣] prepend] 🎒
                          [0] 🔀 update]]
             [examples [[[[[[[📏 3 >] ["foo" 📮]]
                            [[☯️] ["bar" 📮]]] decide]
                          [📏 1 =] [rest] addmethod]

                         [[[[[📏 1 =] [rest]]
                            [[📏 3 >] ["foo" 📮]]
                            [[☯️] ["bar" 📮]]]
                           decide]]]]]]]

 [method? [[spec [[program] [boolean]]]
           [definition [[[first [[pair?]
                                 [[list?] every?]] every?]
                         [second [decide] unwrap =]]
                        every?]]]]]
🔗

1.13. Database

[[[list selection] [list constraints]]
 [string]]

[[fork [[▶️] 🚜]]
 [triangle [[🔳 [[📤] 🪄 🔀 [[📮] 🛡️ ⚓ 🔀 pair] bail] collect] •🛡️]]
 [indexed-as-property [🔀 indexed
                       [🍫 ⚓ assign] 🚜 •🗑️]]
 [join-all [[first empty] 🛡️ 🔀 [🔗] 🪜]]
 [selectkeys [set [1️⃣ [first] 🐋 contains?] 🎒 🧲]]
 [invert [[reverse] 🚜 association]]

 ;; datalog variables
 [variable? [[[word?]
              [string last \? =]] [▶️] 💯]]
 [variable= [[[pair [variable?] 💯] [=]] [▶️] 💯]] 

 ;; datalog constraints
 [slots [[entity attribute value]]]
 [slot-combos [slots [slots [pair] 🚜] 🚜 join-all]]
 [constraint [🍫 slots reverse label]] 

 ;; links between datalog constraints
 [links [slot-combos
         [[🎁] 🚜 🍫 •🔀 
          [[[🔍] 💉] both] pairwise 
          variable=]
         🧲    
         [🍫 pair ⚓ pair
          [[index] 🔍] 🚜 🔀 zip]
         🚜]]
 [all-links [🔳 ⚓
             [[[[index] 🔍] 🛡️] both ;; lookup the indices of both constraints
              [•🔀] 🪄 ⚓ ;; move the indices under the constraints
              [links] •🛡️
              🔀 [•🗑️ •🗑️ 🔗] 🪄] 

             🪜 🗑️]]
 [format-link [[🔗] 💉 🍫 [string] 🚜
               "c{0}.{1} = c{2}.{3}" format]] 

 ;; formatting pieces of query data into text
 [anded-together [" AND " interpose join-all]]

 ;; where clause data processing
 [where-data [[[index] 🔍] 🛡️ 🔀 
              [[[second variable? ☯️]
                [first [index] 🍫 = ☯️]] [▶️] 💯] 🧲 
              [🔀 prepend] 🚜 •🗑️]]
 [format-where [[string] 🚜 
                "c{0}.{1} = :c{0}{1}" format]]
 [make-where [first [where] 🔍 anded-together]]
 [format-join [[[[on] 🔍]
                [[where] 🔍]
                [[index] 🔍 string]] [▶️] 🚜
               [🔗 anded-together] 💉 
               "JOIN EAV c{1} ON {0}" format]]
 [make-query [rest [[on]
                    [[format-link] 🚜] update
                    [format-join] 🛡️ [🔗] 🔀 assign] 🚜]]

 ;; SQL parameters for rusqlite
 [param-name [[string] 🚜 ":c{0}{1}" format]]
 [extract-params [🔳 association 🔀 [[params] 🔍 🔗] 🪜]]


 ;; SELECT clause
 [wordval? [second word?]]
 [invert [[reverse] 🚜 association]]
 [validate [[[second ☯️]
             [first "All selected query variables must appear somewhere in constraints"
              [reason variable] label fail]
             when] 🚜]]
 [select-data [🔀
               [[slots selectkeys invert] 🛡️
                [wordval?] 🧲 🔗 association] 🚜
               🔀
               [[[[index 1️⃣] selectkeys] 🎒 ;; make the program to cut down 
                 🚜 
                 [📏 2 =] 🧲 first [second] 🚜
                 [first number?] [reverse] when] ;; items are in random order due to coming from association, fix the order
                🚜]
               🛡️ ••🗑️ zip
               validate]]

 ;; query 
 [extract-data [[[[🍫 all-links]
                  [first where-data   ; [🔗] 💉 🍫
                   ;; build the query param 🚜
                   [[🔳 🔀
                     [[param-name] 🛡️ [last] 🪄 🎁 🔀 assign]
                     🪜]
                    ;; build the actual query where clauses
                    [[format-where] 🚜]]
                   fork]]
                 fork] 🛡️
                ;; combine extracted items

                [first] 🪄 ;; keep the original constraint to add properties to
                🍫 🍫 [where params on] label 🔗]]
 [format-select [[🍫 🔀
                  string butlast ;; remove the ? from the variable name for result column
                  📮
                  [string] 🚜 %
                  "c{1}.{0} as {2}" format] 🚜 ", " interpose join-all]]]

;; This is the program we need to modify that is `query`

[🔀
 ;; expand all combinations of constraints
 [constraint] 🚜
 ;;🔳 prepend ;; an empty constraint to represent the orignal EAV table we're joining with
 [index] indexed-as-property
 triangle
 ;; for each pair of constraints, build the "ON" clause data for the JOIN
 [extract-data] 🚜
 [[extract-params]
  [make-query]
  [make-where]
  [🔀 select-data]] fork 
 •🗑️ ;; don't need original anymore
 🍫 🛟
 [[🔗] 🔍] 🚜  
 format-select 
 [" " interpose join-all] 🪄 triplet reverse
 "SELECT {0} from EAV as c0 {1} WHERE {2}" format
 🔀 ••🗑️]

let
[definition spec] label
[query] 🔀 assign

1.14. Pipes

[pipe? [[spec [[item] [boolean]]]
        [examples [[[timestamps pipe?] []]
                   [[standard pipe?] []]
                   [[[1 2 3] pipe?] [🔳]]
                   [[5 pipe?] [🔳]]]]]]

[animate [[spec [[environment] 🔳]]]]

[attend [[spec [[list] [list]]]]]

[file-in [[spec [[string] [pipe]]]]]

[file-out [[spec [[string] [pipe]]]]]

[handoff [[spec [🔳 [pipe]]]]]

[receiver [[spec [[pipe] [pipe]]]]]

[select [[spec [[[list pipes]] [item pipe [list pipes]]]]]]

[sender [[spec [[pipe] [pipe]]]]]

[serversocket [[spec [[integer string] [pipe]]]]]

[socket [[spec [[integer string] [pipe]]]]]

[standard [[spec [🔳 [pipe]]]]]

[timer [[spec [[integer] [pipe]]]]]

[timestamps [[spec [🔳 [pipe]]]]]

[database [[spec [[[sized params] string] 🔳]]]]

[persist [[spec [[sized] 🔳]]]]
[[pipe-in [[spec [[item] [pipe]]]
           [definition [association
                        [[[type [file] 🍫 =]
                          [🗑️ value file-in]]
                         [[type [stdout] 🍫 =]
                          [🗑️ stdout]]]
                        decide]]]]

 [tunnel [[spec [[item] [pipe]]]
          [definition [association
                       [[[type [ip-host] 🍫 =]
                         [🗑️ 👥
                          [port] 🔍
                          [[address] 🔍] 🪄
                          serversocket]]
                        [[type [ip-client] 🍫 =]
                         [🗑️ 👥
                          [port] 🔍
                          [[address] 🔍] 🪄
                          socket]]]
                       decide]]]]

 [pipe-out [[spec [[item] [pipe]]]
            [definition [association
                         [[[type [file] 🍫 =] 
                           [🗑️ value file-out]]
                          [[type [ip-host] 🍫 =]
                           [🗑️ 👥
                            [port] 🔍
                            [[address] 🔍] 🪄
                            serversocket]]]
                         decide]]]]

 [spit [[spec [[item [item target]] 🔳]]
        [definition [[pipe-in] 🪄 encode 📮 🗑️]]]]

 [slurp [[spec [[pipe] [item]]]
         [definition [[📤] [🔗] fold string [🗑️ 🗑️] 🪄]]]]

 [print [[spec [[string] 🔳]]
         [definition [[standard] 🪄 "\n" 🔗 encodeitem 📮 🗑️]]]]

 ;;[slurp [[spec [[[item target]] [item pipe]]]]]

 [sleep [[spec [[integer] 🔳]]
         [definition [timer 📤 🗑️ 🗑️]]]]

 [future [[spec [[program] [pipe]]]
          [definition [handoff 🔀
                       [[✂️1️⃣ 📸] ;; return entire stack
                        🐋 📮 🗑️] 🎒
                       dictionary 🔀 spawn animate]]
          [examples [[[1 [2 +] future 📤 •🗑️] [1 [3]]]]]]]

 [close [[spec [[pipe] 🔳]]
         [definition [🗑️]]]]]
🔗

1.15. Crypto

[random [[spec [[integer] [bytes]]]]]

[key [[spec [[bytes] [bytes]]]
      [examples [[[["foo" encode key] 2 times =] []]]]]]

[sign [[spec [[[bytes message] [association key]] [bytes]]]]]

[verify [[spec [[[bytes signature]
                 [bytes message]
                 [sized key]]

                [boolean]]]
         [examples [[["foo" encode key "we attack at dawn" encode [sign] 🛡️ verify] []]]]]]
[[delegated [[spec [[[association pubkey]] [program]]]
             [definition [[[;; css cs pk
                            [[hash] [🛡️ 🪄] decorated ;; css csh cs pk
                             🛟 ;; cs css csh pk
                             [verify] 🪄
                             [🔳]  ;; the program to run if the child script isn't authorized
                             ↔️] ;; runs the child script if the sig on its hash is verified
                            [🗑️ 🗑️ ;; the sig and (empty) child script -> pk sig msg
;; sig msg pk
                             verify]
                            [👥] •🪄 ↔️]
                           [🔳] 🩹]
                          🔀 prepend]]]] ;; prepend the pubkey

 [hash [[spec [[item] [bytes]]]
        [definition [[[[bytes?] [🗑️ hashbytes]]
                      [[] [🗑️ encode hash]]]
                     decide]]]]]
🔗

1.16. Time and date

[[milliseconds [[spec [[integer] [integer]]]
                [definition 🔳]]]

 [seconds [[spec [[integer] [integer]]]
           [definition [1000 *]]]]

 [minutes [[spec [[integer] [integer]]]
           [definition [seconds 60 *]]]]

 [hours [[spec [[integer] [integer]]]
         [definition [minutes 60 *]]]]

 [days [[spec [[integer] [integer]]]
        [definition [hours 24 *]]]]]
🔗

1.17. Nested Environments

[environment [[spec [[sized] [environment]]]
              [examples [[[[[program [1 2 3]]] environment eval-step [stack] 🔍] [[1]]]]]]]

[environment? [[spec [[item] [boolean]]]
               [examples [[[[[program [1 inc]]] environment environment?] []]
                          [[[[program [1 inc]]] environment?] [🔳]]]]]]

[eval-step [[spec [[environment] [environment]]]
            [examples [[[[[program [1 inc]]] environment
                         eval-step eval-step
                         [stack] 🔍]
                        [[2]]]]]]]

[evaluate [[spec [[item] [environment]]]
           [examples [[[[[program [1 2 3 4 + *]]] environment
                        evaluate
                        [stack] 🔍]
                       [[14 1]]]]]]]

[finished? [[spec [[environment] [boolean]]]
            [examples [[[[[program [1 2 3 4 + *]]] environment
                        finished?]
                       [🔳]]
                      [[[[program [1 2 3 4 + *]]] environment
                        evaluate
                        finished?]
                       []]]]]]

[using [[spec [[[list hash-bool-pairs] dictionary] [dictionary]]]
        [definition [[🍫 [[decache] 🛡️ ▶️ •🔀 inscribe] 🪄 •🔀 
                      [🗑️ [1️⃣ 📮] 🎒 [modules] 🔀 update  ] ;; use the newly loaded module if checked
                      [🗑️ ] ↔️] 🪜 ▶️]]
        [examples [[[dictionary
                     [[#b64 "DzKwIM_7C7bQOxEBEwS2HShK-QF_n_dVMleH2iFfcRw"]
                      [#b64 "IXce0iyf1NJA-aART0yr1FsjJvpm5l92asEWl0X3Eew"]
                      [#b64 "mUBaz5wtBlKaV5UqwpiRJKjq50l96qUBpC7OgMhfTPo" []]]
                     using [foo bar mUBaz5wtBlKaV5UqwpiRJKjq50l96qUBpC7OgMhfTPo/baz] confine]
                    ["this is foo" "this is bar" "this is baz"]]]]]]

[use [[spec [[[program [list modules]] [*]]]]
      [definition [[[1️⃣ 🔗] 🎒 [modules] 🔀 update] 🪄 ;; d p
                   confine]]]]

[depend [[spec [[[list hash-bool-pairs] program] [*]]]
         [definition [dictionary ⚓
                      [using] 🪄
                      confine]]]]
[tos [[spec [[sized] [item]]]
      [definition [[stack] 🔍 first]]
      [examples [[[[[stack [1 2 3]]
                    [program [[+] 🪜]]]
                   tos]
                  [1]]]]]]

[top [[spec [[sized] [item]]]
      [definition [[program] 🔍 first]]
      [examples [[[[[stack [1 2 3]]
                    [program [[+] 🪜]]]
                   top]
                  [[+]]]]]]]

[stage [[spec [[program] [environment]]]
        [definition [[program] label environment]]]]

[capture [[spec [[environment] [environment]]]
          [doc "Capture the outer stack and assign it to the inner env's stack"]
          [definition [[stack]
                       [📸] •🐋
                       assign]]]]

[spawn [[spec [[program dictionary] [environment]]]
        [definition [[📸] •🪄 ;; p d s
                     [program dictionary stack] label
                     environment]]
        [examples [[[1 2 3 dictionary [🔀 👥] spawn]
                    [1 2 3 [[program [🔀 👥]] [stack [3 2 1]]] environment]]]]]]

[confine [[spec [[[program module] dictionary] [*]]]
          [definition [spawn evaluate [stack] 🔍 restore]]]]

1.17.1. Debugging

[[break [[spec [[[program condition] environment]
                [[program condition] environment]]]
         [definition [[[[🔀 something?] ;; still running
                        [▶️ ☯️]] ;; check condition not true yet
                       [▶️]
                       every?] ;; break?
                      [[eval-step] 🪄]  ;; evaluate the environment one step
]]]]

 [breakpoint [[spec [🔳 🔳]]
              [definition 🔳]]]

 [sprint [[spec [[environment]
                 [environment]]]
          [definition [[[program 0] 🔍 🎁 [breakpoint] =] break
                       🗑️ ;; the condition
                       🔳 [eval-step] when]]]] ;; advance past the breakpoint word if the program isn't complete


 [advance [[spec [[environment] [environment]]]
           [definition [👥 [program] 🔍 📏 🔀 ;; count up the program length, we'll run until it's smaller than this
                        [[program] 🔍 📏 ;; only stop if env's program empty or shorter than we started off
                         [[positive?] [<=]] [🛡️ ▶️] 💯 ▶️] 🛡️ 
                        [🗑️ eval-step] ;; evaluate the environment one step
                        ⏳ ▶️
                        •🗑️]]]] ;; drop the program length item

 [stepper [[spec [🔳 [program]]]
           [definition [[eval-step 👥]]]]]

 [tracer [[spec [[program] [[program generator]]]]
          [definition [stage stepper]]]]

 [dump [[spec [🔳 🔳]]
        [definition [📸 🎁 emit autoformat print]]]]

 [heatmap [[spec [[program] [association]]]
           [definition [[tracer
                         ;; what item is being ▶️d
                         [[program] 🔍 [first]
                          ;; don't emit 🔳 or the execution stops, use 0 instead
                          bail 0 or]
                         each 
                         [word?] keep ;; count only words, which filters out the 0's from above
                         frequencies] •🛡️]]]]]


🔗
[[evaluating? [[program] 🔍 [evaluate] starts?]]
 [with-innermost [[🔳 🔀
                   [[evaluating?]
                    [[stack 0] 👥 [🔍] 🪄 🔀 [🔗] 🪄 ] ;; append the next part of the path to the accumulator
                    ⏳ 🔀] 🛡️ ••🗑️]
                  🪄 ;; under the stepping prog
                  [update] •🛡️ flip 🗑️

                  ;; find which envs are finished and remove
                  ;; 'evaluate' from parent
                  [0 -2 slice 👥] [collect] ••🛡️ 
                  [[[[[evaluating?]
                      [[stack 0] 🔍 finished?]]
                     [▶️] 💯]
                    [[program] [rest] update]
                    when]
                   [update] •🛡️ flip 🗑️ 🗑️]
                  🪜]]]
🔗

1.18. Test modules

[[foo [[definition ["this is foo"]]]]]
🔗
[[bar [[definition ["this is bar"]]]]]
🔗
[[baz [[definition ["this is baz"]]]]]
🔗

2. Issues

2.1. DONE Get rid of platform-specific definitions

2.2. DONE fix evaluate

[[program [1 1 +]]] environment evaluate [stack] 🔍

[[2]]

2.3. TODO merkle tree functions

"foo" "bar" join hash "foobar" hash =
yes

First let's figure out how to represent a tree:

;[5 [[3 [[1c 🔳]
;        [2c 🔳]]]
;    [4 [[3c 🔳]]]]]
[[hash 🔳]
 [children [second]]
 [data [first]]
 [node [🔳 pair]]
 [empty-node [#b64 "" hash node]]
 [child [[children] 🪄 get]]
 [addchild [[pop] 🪄 📮 📮]]
 [rawpath [1 [interpose] 🛡️ 🔀 prepend •🗑️]]
 [siblings [🔳 node ⚓ [addchild] 🪄 addchild]]
 ;[path [🔳 [📤 🔀 [child] 🪄 path] [drop] ⚖️]]
 [path [dec 2 radix rawpath]]
 [parent [butlast butlast]]
 [rehash [[children [data] 🚜] 🛡️
          [first] 🛡️ empty 🔀 [join] 🪜
          hash wrap [0] 🔀 update]]
 ;; lopsidedtree n
 [balance 🔳]
 ;; node tree cur-ct
 [add [[👥 path [pop zero?] [parent] when] •🪄  ;; node tree path ct
       •🔀 ;; node path tree ct
       🔳]]
 [add [[odd?]
       ;; insert an unbalanced node (empty sibling)
       [empty-node siblings [path parent]]
       ;; otherwise replace the empty sibling
       🔳
      ]]]
; ["" drop
;  ;[0 🔳] 1 node addchild 2 node 3 node addchild addchild
;  ;[1 0]  1 [interpose] shield 🔀 📮 •🗑️ 🔍
;  "foo"  hash node "bar"  hash node siblings
;  ;; update the root node
;  rehash
;  ; now add a new sibling
;  "baz"  hash node siblings
;  rehash
;  3 path [pop zero?] [butlast butlast] 🔳 ⚖️
;  ;dump
;  ["quux" hash node siblings rehash ] update
; ]
[["foo" "bar" "baz" "quux"] [node] 🚜 🔳
let
[["foo" 🔳]
 ["bar" 🔳]
 ["baz" 🔳]
 ["quux" 🔳]]
  • 1234

    • 12
      • 1
      • 2
    • 34
      • 3
      • 4
    • 5
    • 6
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              ["bazquux" [["baz" 🔳]
                          ["quux" 🔳]]]]]
["" 🔳]

interpose impl

[1 3 4] [foo] unwrap interpose
[1 foo 3 foo 4]
[0 [[1 🔳]
    [2 [[3 🔳]]]]]
  [1 0] 1 [interpose] 🛡️ 🔀 prepend 0 📮 •🗑️ [inc] update
[0 [[1 🔳]
    [2 [[4 🔳]]]]]

We need a function that, given a number n, gives the path in the merkle tree. eg, 8 would be 1 1 1. Is it just n-1 in binary? 6 would be 1 0 1. Ok so just write a function to expand binary digits:

8 dec 2 radix
[1 1 1]
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              ["baz" 🔳]]] [1 1] [🗑️ 🗑️ "hi" "there"] update
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              "there"]]
[[hash 🔳]
 [children [second]]
 [data [first]]
 [node [🔳 pair]]
 [child [[children] 🪄 get]]
 [addchild [[pop] 🪄 📮 📮]]
 [siblings [🔳 node ⚓ [addchild] 🪄 addchild]]
 ;[path [🔳 [📤 🔀 [child] 🪄 path] [🗑️] ⚖️]]
 [path [dec 2 radix nodepath]]
 [rehash [[children [data] 🚜] 🛡️ [first] 🛡️ empty 🔀 [join] 🪜 hash wrap [0] 🔀 update]]]
[["foobarbaz" [["foobar" [["foo" 🔳]
                          ["bar" 🔳]]]
               ["baz" 🔳]]]
 [1 1]

 ["bazquux" [["baz" 🔳]
             ["quux" 🔳]]]
 assign]
let
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              ["bazquux" [["baz" 🔳]
                          ["quux" 🔳]]]]]
[["bazquux" [["baz" 🔳]
             ["quux" 🔳]]]
 [1 1]
 ["foobarbaz" [["foobar" [["foo" 🔳]
                          ["bar" 🔳]]]
               ["baz" 🔳]]]]
reverse unwrap assign
["foobarbaz" [["foobar" [["foo" 🔳]
                         ["bar" 🔳]]]
              ["bazquux" [["baz" 🔳]
                          ["quux" 🔳]]]]]
[
 [children [second]]
 [data [first]]
 [node [🔳 pair]]
 [addchild [[pop] 🪄 📮 📮]]
 [siblings [🔳 node ⚓ [addchild] 🪄 addchild]]
 [nodepath [1 [interpose] 🛡️ 🔀 prepend •🗑️]]
 [padded [[[[📏] 🛡️] 🐋 -] 🪄
          🔀 repetition
          🔀 join]]
 [path [[dec 2 radix] 🪄 2 log ceiling 0 padded nodepath]] ;; item-ct index
 [depth 🔳]

 [rehash [[children [data] 🚜] 🛡️
          [first] 🛡️ empty 🔀
          [join] 🪜
          hash
          wrap [0] 🔀 update]]
 [joiner [[2 2 partition
           [[📏 1 =] [🔳 📮] when
            unwrap siblings] each]
          assemble [rehash] 🚜]]
 [merkle [[hash node] 🚜
          [📏 1 >] [joiner]]]]
[["a" "b" "c" "d" "e"]
 📏
 5 ;; 2nd item
 🔀 path ]
let
[1 1 1 0 1 0]
[[#b64 "FO3l6Ol62TcjJ3KPUJm5VgSjlZPKw704o0OtdiBSE+c=" [[#b64 "5aAf7hTg7VxIcU8iGA8lrYNltT+XefedxKPX6Tlj+Uo="
                                                        [[#b64 "ypeBEsobvcr6wjGzmiPcTaeG7/gUfE5yuYB3ha/uSLs=" 🔳]
                                                         [#b64 "PiPoFgA5WUoziU9lZOGxNIu9egCI1CxKy3PurtWcAJ0=" 🔳]]]
                                                       [#b64 "v/4LNNuha8b6wXwIusVdZ2ze1aSt5B/iyZJKXd6PPls=" [[#b64 "Ln0sA6lQeuJl7PW1NWiFpTOTogKdJBOUmXJloaJa78Y="
                                                                                                              🔳]
                                                                                                             [#b64 "GKw+c0PwFokMUQ6T+TUmEWnZ4/VlQ2Qpgw+vCTT0+OQ=" 🔳]]]]]]
[1 1 1] 5 0 [[[📏] 🛡️] 🐋 -] 🪄
        🔀 repetition
        🔀 join
[0 0 1 1 1]

2.4. CANCELED Make taker/dropper more flexible

Goal: implement drop and drop-while with the same logic

Canceled - the commonality between drop and drop-while are too small to be worth trying to factor out.

[1 2 3 4 5] [📤]
3
[[[positive?]
  [[generate 🗑️] 🪄 dec]
  while
  [generate 🔀] 🪄 🛟]
 bail]
collect
[4 5]
[[[positive?] [[generate 🗑️]
               🪄 dec]
  while [generate 🔀]
  🪄 🛟]
 bail]
0 [📤] 🔳

This is what drop-while looks like

🔳 [📤]
[positive?]
🔳 ;; the state (whether threshold reached)
[🔳 ;; condition - whether we've finished dropping or not 
 [[generate] •🐋] ;; true - pass everything else through
 [[[generate] •🐋] ;; prime init
  [[[👥] •🐋 execute] bail] ;; bring pred up and exec it
  [🗑️] ;; if pred passes drop the value
  prime ;; after this should have value on top
  [🗑️ true] 🪄 ;; set flag
 ] ;; false - generate, check pred, repeat
 ⚖️]
collect
🔳 [🔳 [[generate] •🐋]
    [[[generate] •🐋]
     [[[👥] •🐋 execute] bail]
     [🗑️] prime [🗑️ yes]
     🪄]
    ⚖️]
yes [positive?] [📤] 🔳

Author: Skyrod Vactai

Created: 2025-08-02 Sat 13:35

Validate