on master help sign in
Various fixes and improvements.
3437290C. Guy Yarvin
docs/about/overview.md+4−2
@@ -5,7 +5,7 @@ title: System overview
5navhome: /main
5navhome: /main
6---
6---
7
7
8−# System Overview
8+# System overview
9
9
10<div class="row"><div class="col-md-8">
10<div class="row"><div class="col-md-8">
11
11
@@ -31,7 +31,9 @@ Instead, the top-level event function defines an I/O protocol.
31It maps an input event and the current state to a list of output
31It maps an input event and the current state to a list of output
32actions and the subsequent state. In Hoon:
32actions and the subsequent state. In Hoon:
33
33
34+```
34− $+([event state] [(list action) state])
35+$-([event state] [(list action) state])
36+```
35
37
36### Nock
38### Nock
37
39
docs/programming.md+4−4
@@ -4,9 +4,9 @@ sort: 3
4
4
5# Programming
5# Programming
6
6
7−Most people should start by learning Hoon. If you're a madman
7+Most people should start by [learning Hoon](programming/hoon). If you're a
8−and just want something fun fast, skim the Hoon docs, then go to
8+madman and just want something fun fast, skim the Hoon docs, then go to [Arvo
9−[Arvo systems programming](arvo/system). If you're interested in
9+systems programming](programming/arvo/system). If you're interested in the
10−the theory, learn Nock first; otherwise, learn it last.
10+theory, learn [Nock](programming/nock) first; otherwise, learn it last.
11
11
12<kids/>
12<kids/>
docs/programming/arvo.md+1−1
@@ -1,5 +1,5 @@
1---
1---
2−sort: 3
2+sort: 2
3title: Arvo
3title: Arvo
4---
4---
5
5
docs/programming/hoon.md+1−1
@@ -1,5 +1,5 @@
1---
1---
2−sort: 2
2+sort: 1
3title: Hoon
3title: Hoon
4---
4---
5
5
docs/programming/hoon/concepts.md+21−13
@@ -19,10 +19,9 @@ ones, which mean almost the same things. But why?
19Hoon has no close relatives. The normal jargon of programming
19Hoon has no close relatives. The normal jargon of programming
20maps poorly onto its semantics. For example, although Hoon is a
20maps poorly onto its semantics. For example, although Hoon is a
21typed language, the term "type" is not formally defined in Hoon.
21typed language, the term "type" is not formally defined in Hoon.
22−"Type" is a great word, but Hoon has three quite separate
22+"Type" is a great word, but Hoon has three separate concepts
23−concepts which could comfortably claim it. We say "type" all the
23+which could comfortably claim it. We say "type" all the time; we
24−time; we mean `span`, or `mold`, or `mark`, or possibly all
24+mean `span`, or `mold`, or `mark`, or possibly all three.
25−three.
26
25
27Other common programming concepts used only informally in Hoon
26Other common programming concepts used only informally in Hoon
28are "function," "object," "event," "expression," "variable,"
27are "function," "object," "event," "expression," "variable,"
@@ -30,17 +29,21 @@ are "function," "object," "event," "expression," "variable,"
30more. We do use these words informally, but we're always making
29more. We do use these words informally, but we're always making
31an analogy whose precision depends on context.
30an analogy whose precision depends on context.
32
31
33−## Overview
32+Hoon has concepts *like* all these abstractions, but they remain
33+*false cognates*. The closer an inexact cognate, the more
34+unsettling it feels when the abstractions don't match. Learning
35+a few new words is a small price for avoiding this pain point.
34
36
35−This document is a quick overview of Hoon, structured as a
37+## Concepts
38+
36−glossary of a few major concepts: `noun` (data), `nock`
39+A few major Hoon concepts: `noun` (data), `nock` (interpreter),
37−(interpreter), `mint` (compiler), `span` (type), `twig`
40+`mint` (compiler), `span` (type), `twig` (expression), `gate`
38−(expression), `gate` (function), `mold` (constructor), `core`
41+(function), `mold` (constructor), `core` (object), `mark`
39−(object), `mark` (protocol).
42+(protocol).
40
43
41### `noun` (data value)
44### `noun` (data value)
42
45
43−A value in Hoon is called a [`noun`](noun). A noun is either a
46+A value in Hoon is called a `noun`. A noun is either a
44unsigned integer of any size (`atom`), or an ordered pair of any
47unsigned integer of any size (`atom`), or an ordered pair of any
45two nouns (`cell`). Nouns are like Lisp S-expressions, but
48two nouns (`cell`). Nouns are like Lisp S-expressions, but
46simpler (Lisp atoms effectively have dynamic type bits).
49simpler (Lisp atoms effectively have dynamic type bits).
@@ -62,14 +65,19 @@ One common operation on nouns is `slot`, a tree addressing
62scheme which maps an atom to a subtree. The whole noun is slot
65scheme which maps an atom to a subtree. The whole noun is slot
63`1`; the left child of `n` is `2n`, the right child `2n+1`.
66`1`; the left child of `n` is `2n`, the right child `2n+1`.
64
67
68+Nothing in Nock, Hoon or Urbit can create cycles in a noun or
69+detect pointer equivalence. Nouns are generally implemented
70+with reference counting, and have a lazy short Merkle hash to
71+help with equality testing and associative containers.
72+
65### `nock` (interpreter)
73### `nock` (interpreter)
66
74
67−Hoon compiles itself to the [Nock](../nock) VM. Nock is a
75+Hoon compiles itself to the [Nock](../../nock) VM. Nock is a
68Turing-complete, non-lambda combinator function. The function
76Turing-complete, non-lambda combinator function. The function
69takes a cell `{subject formula}`, and produces a noun `product`.
77takes a cell `{subject formula}`, and produces a noun `product`.
70
78
71To program in Hoon, this is all you need to know about Nock. But
79To program in Hoon, this is all you need to know about Nock. But
72−it's still fun and useful to [learn more](../nock).
80+it's still bfun and useful to [learn more](../../nock).
73
81
74## Compilation concepts
82## Compilation concepts
75
83
docs/programming/hoon/demo.md+2−2
@@ -19,11 +19,11 @@ line is commented with its number:
19:cons :: 7
19:cons :: 7
20 :if =(0 (mod count 15)) :: 8
20 :if =(0 (mod count 15)) :: 8
21 "FizzBuzz" :: 9
21 "FizzBuzz" :: 9
22− :if =(0 (mod count 5)) :: 10
22+ :if =(0 (mod count 5)) :: 10
23 "Fizz" :: 11
23 "Fizz" :: 11
24 :if =(0 (mod count 3)) :: 12
24 :if =(0 (mod count 3)) :: 12
25 "Buzz" :: 13
25 "Buzz" :: 13
26− (text :wrap(count)) :: 14
26+ (pave :wrap(count)) :: 14
27:moar(count (add 1 count)) :: 15
27:moar(count (add 1 count)) :: 15
28```
28```
29
29
docs/programming/hoon/exercises.md+1−1
@@ -27,7 +27,7 @@ and they are intended to form a sort of primer to Hoon.
27 "Fizz"
27 "Fizz"
28 ?: =(0 (mod count 3))
28 ?: =(0 (mod count 3))
29 "Buzz"
29 "Buzz"
30− (text !>(count))
30+ (pave !>(count))
31 $(count (add 1 count))
31 $(count (add 1 count))
32 ```
32 ```
33
33
docs/programming/hoon/philosophy.md → docs/programming/hoon/mission.mdrenamed+13−15
@@ -1,13 +1,13 @@
1---
1---
2sort: 2
2sort: 2
3next: true
3next: true
4−title: Philosophy
4+title: Mission
5---
5---
6
6
7−# Mission statement
7+# Mission
8
8
9Hoon is a strict, typed functional language which compiles itself
9Hoon is a strict, typed functional language which compiles itself
10−to the Nock VM (whose spec fits on a T-shirt).
10+to Nock, a combinator interpreter whose spec fits on a T-shirt.
11
11
12Hoon's design goal is to support higher-order typed functional
12Hoon's design goal is to support higher-order typed functional
13programming without category theory, formal logic, or other
13programming without category theory, formal logic, or other
@@ -20,9 +20,8 @@ But good Hoon style isn't good Haskell style. Hoon encourages
20coders to use higher-order programming as little as possible --
20coders to use higher-order programming as little as possible --
21again, simply for UI reasons. For example, multiple arguments
21again, simply for UI reasons. For example, multiple arguments
22are curried by default in Haskell and tupled by default in Hoon.
22are curried by default in Haskell and tupled by default in Hoon.
23−The house style has been described as "procedural programming in
23+The Hoon style has been described as "procedural programming in
24−a functional language." The power of Haskell, or close, is there
24+a functional language."
25−when we really need it. But we try not to swat flies with it.
26
25
27Hoon is objectively simple: its complexity is bounded by the size
26Hoon is objectively simple: its complexity is bounded by the size
28of the compiler, about 3000 lines of Hoon. This is split evenly
27of the compiler, about 3000 lines of Hoon. This is split evenly
@@ -35,12 +34,11 @@ This ratio reflects the belief that our brains are better than
35everyone thinks at learning languages (symbols and/or grammars),
34everyone thinks at learning languages (symbols and/or grammars),
36and worse at learning abstractions (proofs and/or algorithms).
35and worse at learning abstractions (proofs and/or algorithms).
37At first glance, Hoon may look gnarly (though its squiggles are
36At first glance, Hoon may look gnarly (though its squiggles are
38−more structured than most ASCII-heavy languages). But there's
37+more structured than most ASCII-heavy languages). But under the
39−less than you might expect under the hood.
38+hood, there's much less complexity than you might expect.
40−
39+
41−Keeping the Hoon-to-Nock mapping straightforward is a priority.
40+Keeping the Hoon-to-Nock mapping simple and transparent is a
42−Very roughly, Hoon is to Haskell as C is to Pascal. Pascal tries
41+priority. In a sense, Hoon is to Haskell as C is to Pascal.
43−to conceal its implementation beneath a layer of abstract
42+There is no opaque high-level abstraction of Hoon's semantics;
44−concepts; C, an "advanced macro assembler," tries to provide a
43+the language is what the compiler does. This design only works
45−similar user experience with few abstract ideas as possible.
44+when the compilation process is trivial or nearly so.
46−
docs/programming/nock.md+1−1
@@ -1,5 +1,5 @@
1---
1---
2−sort: 1
2+sort: 3
3title: Nock
3title: Nock
4---
4---
5
5
docs/programming/nock/interpreter.md → docs/programming/nock/definition.mdrenamed+3−3
@@ -1,10 +1,10 @@
1---
1---
2sort: 1
2sort: 1
3next: true
3next: true
4−title: Interpreter
4+title: Definition
5---
5---
6
6
7−# Interpreter: `nock`
7+# Definition
8
8
9The Nock VM is a Turing-complete function that maps a cell
9The Nock VM is a Turing-complete function that maps a cell
10`{subject formula}` to a noun `product`, where `subject` is the
10`{subject formula}` to a noun `product`, where `subject` is the
@@ -128,7 +128,7 @@ true and `1` is false.
128`[8 b c]` produces the product of formula `c`, against
128`[8 b c]` produces the product of formula `c`, against
129a subject whose head is the product of formula `b` with the
129a subject whose head is the product of formula `b` with the
130original subject, and whose tail is the original subject. (Think
130original subject, and whose tail is the original subject. (Think
131−of `8` as a ``variable declaration'' or ``stack push.'')
131+of `8` as a "variable declaration" or "stack push.")
132
132
133`[9 b c]` computes the product of formula `c` with the current
133`[9 b c]` computes the product of formula `c` with the current
134subject; from that product `d` it extracts a formula `e` at tree
134subject; from that product `d` it extracts a formula `e` at tree
docs/programming/nock/implementations.mdnew file+8
@@ -0,0 +1,8 @@
1+---
2+sort: 4
3+title: Implementations
4+---
5+
6+# Implementations
7+
8+<list src="."></list>
docs/programming/nock/implementations/c.mdnew file+211
@@ -0,0 +1,211 @@
1+---
2+title: C
3+sort: 6
4+next: true
5+---
6+
7+# C
8+
9+The actual production interpreter. Note gotos for tail-call elimination,
10+and manual reference counting. More about the C environment can be found
11+in the [runtime system documentation](../../../runtime).
12+
13+```
14+/* nock(): produce .*(bus fol). Do not virtualize.
15+*/
16+static u3_noun
17+nock(u3_noun bus, u3_noun fol)
18+{
19+ u3_noun hib, gal;
20+
21+ while ( 1 ) {
22+ hib = u3h(fol);
23+ gal = u3t(fol);
24+
25+ if ( c3y == u3r_du(hib) ) {
26+ u3_noun poz, riv;
27+
28+ poz = nock(u3k(bus), u3k(hib));
29+ riv = nock(bus, u3k(gal));
30+
31+ u3a_lose(fol);
32+ return u3i_cell(poz, riv);
33+ }
34+ else switch ( hib ) {
35+ default: return u3m_bail(c3__exit);
36+
37+ case 0: {
38+ if ( c3n == u3r_ud(gal) ) {
39+ return u3m_bail(c3__exit);
40+ }
41+ else {
42+ u3_noun pro = u3k(u3at(gal, bus));
43+
44+ u3a_lose(bus); u3a_lose(fol);
45+ return pro;
46+ }
47+ }
48+ c3_assert(!"not reached");
49+
50+ case 1: {
51+ u3_noun pro = u3k(gal);
52+
53+ u3a_lose(bus); u3a_lose(fol);
54+ return pro;
55+ }
56+ c3_assert(!"not reached");
57+
58+ case 2: {
59+ u3_noun nex = nock(u3k(bus), u3k(u3t(gal)));
60+ u3_noun seb = nock(bus, u3k(u3h(gal)));
61+
62+ u3a_lose(fol);
63+ bus = seb;
64+ fol = nex;
65+ continue;
66+ }
67+ c3_assert(!"not reached");
68+
69+ case 3: {
70+ u3_noun gof, pro;
71+
72+ gof = nock(bus, u3k(gal));
73+ pro = u3r_du(gof);
74+
75+ u3a_lose(gof); u3a_lose(fol);
76+ return pro;
77+ }
78+ c3_assert(!"not reached");
79+
80+ case 4: {
81+ u3_noun gof, pro;
82+
83+ gof = nock(bus, u3k(gal));
84+ pro = u3i_vint(gof);
85+
86+ u3a_lose(fol);
87+ return pro;
88+ }
89+ c3_assert(!"not reached");
90+
91+ case 5: {
92+ u3_noun wim = nock(bus, u3k(gal));
93+ u3_noun pro = u3r_sing(u3h(wim), u3t(wim));
94+
95+ u3a_lose(wim); u3a_lose(fol);
96+ return pro;
97+ }
98+ c3_assert(!"not reached");
99+
100+ case 6: {
101+ u3_noun b_gal, c_gal, d_gal;
102+
103+ u3x_trel(gal, &b_gal, &c_gal, &d_gal);
104+ {
105+ u3_noun tys = nock(u3k(bus), u3k(b_gal));
106+ u3_noun nex;
107+
108+ if ( 0 == tys ) {
109+ nex = u3k(c_gal);
110+ } else if ( 1 == tys ) {
111+ nex = u3k(d_gal);
112+ } else return u3m_bail(c3__exit);
113+
114+ u3a_lose(fol);
115+ fol = nex;
116+ continue;
117+ }
118+ }
119+ c3_assert(!"not reached");
120+
121+ case 7: {
122+ u3_noun b_gal, c_gal;
123+
124+ u3x_cell(gal, &b_gal, &c_gal);
125+ {
126+ u3_noun bod = nock(bus, u3k(b_gal));
127+ u3_noun nex = u3k(c_gal);
128+
129+ u3a_lose(fol);
130+ bus = bod;
131+ fol = nex;
132+ continue;
133+ }
134+ }
135+ c3_assert(!"not reached");
136+
137+ case 8: {
138+ u3_noun b_gal, c_gal;
139+
140+ u3x_cell(gal, &b_gal, &c_gal);
141+ {
142+ u3_noun heb = nock(u3k(bus), u3k(b_gal));
143+ u3_noun bod = u3nc(heb, bus);
144+ u3_noun nex = u3k(c_gal);
145+
146+ u3a_lose(fol);
147+ bus = bod;
148+ fol = nex;
149+ continue;
150+ }
151+ }
152+ c3_assert(!"not reached");
153+
154+ case 9: {
155+ u3_noun b_gal, c_gal;
156+
157+ u3x_cell(gal, &b_gal, &c_gal);
158+ {
159+ u3_noun seb = nock(bus, u3k(c_gal));
160+
161+ if ( c3n == u3r_ud(b_gal) ) {
162+ return u3m_bail(c3__exit);
163+ }
164+ else {
165+ u3_noun nex = u3k(u3at(b_gal, seb));
166+
167+ u3a_lose(fol);
168+ bus = seb;
169+ fol = nex;
170+ continue;
171+ }
172+ }
173+ }
174+ c3_assert(!"not reached");
175+
176+ case 10: {
177+ u3_noun p_gal, q_gal;
178+
179+ u3x_cell(gal, &p_gal, &q_gal);
180+ {
181+ u3_noun zep, hod, nex;
182+
183+ if ( c3y == u3r_du(p_gal) ) {
184+ u3_noun b_gal = u3h(p_gal);
185+ u3_noun c_gal = u3t(p_gal);
186+ u3_noun d_gal = q_gal;
187+
188+ zep = u3k(b_gal);
189+ hod = nock(u3k(bus), u3k(c_gal));
190+ nex = u3k(d_gal);
191+ }
192+ else {
193+ u3_noun b_gal = p_gal;
194+ u3_noun c_gal = q_gal;
195+
196+ zep = u3k(b_gal);
197+ hod = u3_nul;
198+ nex = u3k(c_gal);
199+ }
200+
201+ u3a_lose(zep);
202+ u3a_lose(hod);
203+
204+ return nock(bus, nex);
205+ }
206+ }
207+ c3_assert(!"not reached");
208+ }
209+ }
210+}
211+```
docs/programming/nock/implementations/clojure.mdnew file+124
@@ -0,0 +1,124 @@
1+---
2+title: Clojure
3+sort: 5
4+next: true
5+---
6+
7+# Clojure
8+
9+From [Matt Earnshaw](https://github.com/mattearnshaw/anock/blob/master/src/anock/core.clj):
10+
11+```
12+(ns anock.core
13+ (:import anock.NockException))
14+
15+(declare atom? cell? cell)
16+
17+(defn noun?
18+ "A noun is an atom or a cell."
19+ [noun & ns]
20+ (if ns false
21+ (or (atom? noun) (cell? noun))))
22+
23+(defn atom?
24+ "An atom is a natural number."
25+ [noun & ns]
26+ (if ns false
27+ (and (integer? noun) (>= noun 0))))
28+
29+(defn cell?
30+ "A cell is an ordered pair of nouns."
31+ [noun]
32+ (cond
33+ (atom? noun) false
34+ (nil? noun) false
35+ (not= 2 (count noun)) false
36+ :else (and (noun? (first noun))
37+ (noun? (second noun)))))
38+
39+(defn tis
40+ "= (pronounced 'tis') tests a cell for equality."
41+ [noun]
42+ (if (atom? noun) (throw (anock.NockException. "Cannot tis an atom."))
43+ (let [[a b] noun]
44+ (if (= a b) 0 1))))
45+
46+(defn wut
47+ "? (pronounced 'wut') tests whether a noun is a cell."
48+ [noun]
49+ (cond
50+ (atom? noun) 1
51+ (cell? noun) 0
52+ :else (throw (anock.NockException. "Invalid noun."))))
53+
54+(defn lus
55+ "+ (pronounced 'lus') adds 1 to an atom."
56+ [noun]
57+ (if (atom? noun) (inc noun)
58+ (throw (anock.NockException. "Can only lus atoms."))))
59+
60+(defn fas
61+ "/ (pronounced 'fas') is a tree address function."
62+ [noun]
63+ (if (atom? noun) (throw (anock.NockException. "Cannot fas an atom."))
64+ (let [[a b] (cell noun)]
65+ (assert (and (pos? a) (atom? a)) "Subject of fas must be a positive atom.")
66+ (if (and (not (coll? b)) (or (= 2 a) (= 3 a)))
67+ (throw (anock.NockException. (str "Cannot fas noun: " noun))))
68+ (cond
69+ (= 1 a) b
70+ (= 2 a) (first b)
71+ (= 3 a) (second b)
72+ (even? a) (fas [2 (fas [(/ a 2) b])])
73+ (odd? a) (fas [3 (fas [(/ (dec a) 2) b])])))))
74+
75+(defn tar
76+ "* (pronounced 'tar') means Nock"
77+ [noun]
78+ (if (atom? noun) (throw (anock.NockException. "Cannot tar an atom."))
79+ (try
80+ (let [noun (cell noun) [x [y z]] noun]
81+ (cond
82+ (cell? y) (cell (tar [x y]) (tar [x z]))
83+ (zero? y) (fas [z x])
84+ (= 1 y) z
85+ (= 3 y) (wut (tar [x z]))
86+ (= 4 y) (lus (tar [x z]))
87+ (= 5 y) (tis (tar [x z]))
88+ :else (let [[p q] z]
89+ (cond
90+ (= 2 y) (tar [(tar [x p]) (tar [x q])])
91+ (= 6 y) (tar [x 2 [0 1] 2 [1 (first q) (second q)]
92+ [1 0] 2 [1 2 3] [1 0] 4 4 p])
93+ (= 7 y) (tar [x 2 p 1 q])
94+ (= 8 y) (tar [x 7 [[7 [0 1] p] 0 1] q])
95+ (= 9 y) (tar [x 7 q 2 [0 1] 0 p])
96+ (= 10 y) (if (cell? p)
97+ (tar [x 8 (second p) 7 [0 3] q])
98+ (tar [x q]))))))
99+ (catch RuntimeException e
100+ (throw (anock.NockException. (str "Cannot tar the noun " noun)))))))
101+
102+(def nock tar)
103+
104+; Some convenience functions
105+(defn apply* [f x]
106+ (if (and (= 1 (count x)) (coll? (first x)))
107+ (apply f x)
108+ (f x)))
109+
110+(defn bracket
111+ "[a b c] -> [a [b c]]"
112+ [[a & b :as c]]
113+ (let [b (vec b)]
114+ (cond
115+ (and (noun? a) (apply noun? b)) (vec c)
116+ (apply noun? b) (apply vector (bracket a) b)
117+ (noun? a) [a (apply* bracket b)]
118+ :else [(bracket a) (apply* bracket b)])))
119+
120+(defn cell [& nouns]
121+ (if (apply atom? nouns)
122+ (throw (anock.NockException. "Cannot convert atom to cell."))
123+ (apply* bracket nouns)))
124+```
docs/programming/nock/implementations/haskell.mdnew file+62
@@ -0,0 +1,62 @@
1+---
2+title: Haskell
3+sort: 3
4+next: true
5+---
6+
7+# Haskell
8+
9+From [Steve Dee](https://github.com/mrdomino/hsnock/blob/master/Language/Nock5K/Spec.hs):
10+
11+```
12+module Language.Nock5K.Spec where
13+import Control.Monad.Instances
14+
15+wut (a :- b) = return $ Atom 0
16+wut a = return $ Atom 1
17+
18+lus (a :- b) = Left "+[a b]"
19+lus (Atom a) = return $ Atom (1 + a)
20+
21+tis (a :- a') | a == a' = return $ Atom 0
22+tis (a :- b) = return $ Atom 1
23+tis a = Left "=a"
24+
25+fas (Atom 1 :- a) = return a
26+fas (Atom 2 :- a :- b) = return a
27+fas (Atom 3 :- a :- b) = return b
28+fas (Atom a :- b) | a > 3 = do x <- fas $ Atom (a `div` 2) :- b
29+ fas $ Atom (2 + (a `mod` 2)) :- x
30+fas a = Left "/a"
31+
32+tar (a :- (b :- c) :- d) = do x <- tar (a :- b :- c)
33+ y <- tar (a :- d)
34+ return $ x :- y
35+
36+tar (a :- Atom 0 :- b) = fas $ b :- a
37+tar (a :- Atom 1 :- b) = return b
38+tar (a :- Atom 2 :- b :- c) = do x <- tar (a :- b)
39+ y <- tar (a :- c)
40+ tar $ x :- y
41+tar (a :- Atom 3 :- b) = tar (a :- b) >>= wut
42+tar (a :- Atom 4 :- b) = tar (a :- b) >>= lus
43+tar (a :- Atom 5 :- b) = tar (a :- b) >>= tis
44+
45+tar (a :- Atom 6 :- b :- c :- d) = tar (a :- Atom 2 :- (Atom 0 :- Atom 1) :-
46+ Atom 2 :- (Atom 1 :- c :- d) :-
47+ (Atom 1 :- Atom 0) :- Atom 2 :-
48+ (Atom 1 :- Atom 2 :- Atom 3) :-
49+ (Atom 1 :- Atom 0) :- Atom 4 :-
50+ Atom 4 :- b)
51+tar (a :- Atom 7 :- b :- c) = tar (a :- Atom 2 :- b :- Atom 1 :- c)
52+tar (a :- Atom 8 :- b :- c) = tar (a :- Atom 7 :-
53+ ((Atom 7 :- (Atom 0 :- Atom 1) :- b) :-
54+ Atom 0 :- Atom 1) :- c)
55+tar (a :- Atom 9 :- b :- c) = tar (a :- Atom 7 :- c :- Atom 2 :-
56+ (Atom 0 :- Atom 1) :- Atom 0 :- b)
57+tar (a :- Atom 10 :- (b :- c) :- d) = tar (a :- Atom 8 :- c :- Atom 7 :-
58+ (Atom 0 :- Atom 3) :- d)
59+tar (a :- Atom 10 :- b :- c) = tar (a :- c)
60+
61+tar a = Left "*a"
62+```
docs/programming/nock/implementations/hoon.mdnew file+53
@@ -0,0 +1,53 @@
1+---
2+title: Hoon
3+sort: 7
4+---
5+
6+# Hoon
7+
8+```
9+|= {sub/* fol/*}
10+^- *
11+?< ?=(@ fol)
12+?: ?=(^ -.fol)
13+ [$(fol -.fol) $(fol +.fol)]
14+?+ fol
15+ !!
16+ {$0 b/@}
17+ ?< =(0 b.fol)
18+ ?: =(1 b.fol) sub
19+ ?< ?=(@ sub)
20+ =+ [now=(cap b.fol) lat=(mas b.fol)]
21+ $(b.fol lat, sub ?:(=(2 now) -.sub +.sub))
22+::
23+ {$1 b/*}
24+ b.fol
25+::
26+ {$2 b/{^ *}}
27+ =+ ben=$(fol b.fol)
28+ $(sub -.ben, fol +.ben)
29+::
30+ {$3 b/*}
31+ =+ ben=$(fol b.fol)
32+ .?(ben)
33+::
34+ {$4 b/*}
35+ =+ ben=$(fol b.fol)
36+ ?> ?=(@ ben)
37+ +(ben)
38+::
39+ {$5 b/*}
40+ =+ ben=$(fol b.fol)
41+ ?> ?=(^ ben)
42+ =(-.ben +.ben)
43+::
44+ {$6 b/* c/* d/*}
45+ $(fol =>(fol [2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]))
46+::
47+ {$7 b/* c/*} $(fol =>(fol [2 b 1 c]))
48+ {$8 b/* c/*} $(fol =>(fol [7 [[0 1] b] c]))
49+ {$9 b/* c/*} $(fol =>(fol [7 c 0 b]))
50+ {$10 @ c/*} $(fol c.fol)
51+ {$10 {b/* c/*} d/*} =+($(fol c.fol) $(fol d.fol))
52+==
53+```
docs/programming/nock/implementations/python.mdnew file+94
@@ -0,0 +1,94 @@
1+---
2+title: Python
3+sort: 1
4+next: true
5+---
6+
7+# Python
8+
9+From [James Tauber](https://github.com/jtauber/pynock/blob/master/nock.py):
10+
11+```
12+#!/usr/bin/env python3
13+
14+# []
15+def l(*lst):
16+ if len(lst) == 1:
17+ return(lst[0], 0)
18+ if len(lst) == 2:
19+ return lst
20+ else:
21+ return (lst[0], l(*lst[1:]))
22+
23+# *
24+def nock(noun):
25+ return tar(noun)
26+
27+# ?
28+def wut(noun):
29+ if isinstance(noun, int):
30+ return 1
31+ else:
32+ return 0
33+
34+
35+# +
36+def lus(noun):
37+ if isinstance(noun, int):
38+ return 1 + noun
39+ else:
40+ return noun
41+
42+
43+# =
44+def tis(noun):
45+ if noun[0] == noun[1]:
46+ return 0
47+ else:
48+ return 1
49+
50+
51+# /
52+def slot(noun):
53+ if noun[0] == 1:
54+ return noun[1]
55+ elif noun[0] == 2:
56+ return noun[1][0]
57+ elif noun[0] == 3:
58+ return noun[1][1]
59+ elif noun[0] % 2 == 0:
60+ return slot((2, slot((noun[0] // 2, noun[1]))))
61+ elif noun[0] % 2 == 1:
62+ return slot((3, slot(((noun[0] - 1) // 2, noun[1]))))
63+
64+
65+def tar(noun):
66+ if isinstance(noun[1][0], int):
67+ if noun[1][0] == 0:
68+ return slot((noun[1][1], noun[0]))
69+ elif noun[1][0] == 1:
70+ return noun[1][1]
71+ elif noun[1][0] == 2:
72+ return nock((nock((noun[0], noun[1][1][0])), nock((noun[0], noun[1][1][1]))))
73+ elif noun[1][0] == 3:
74+ return wut(nock((noun[0], noun[1][1])))
75+ elif noun[1][0] == 4:
76+ return lus(nock((noun[0], noun[1][1])))
77+ elif noun[1][0] == 5:
78+ return tis(nock((noun[0], noun[1][1])))
79+ elif noun[1][0] == 6:
80+ return nock(l(noun[0], 2, (0, 1), 2, l(1, noun[1][1][1][0], noun[1][1][1][1]), (1, 0), 2, l(1, 2, 3), (1, 0), 4, 4, noun[1][1][0]))
81+ elif noun[1][0] == 7:
82+ return nock(l(noun[0], 2, noun[1][1][0], 1, noun[1][1][1]))
83+ elif noun[1][0] == 8:
84+ return nock(l(noun[0], 7, l(l(7, (0, 1), noun[1][1][0]), 0, 1), noun[1][1][1]))
85+ elif noun[1][0] == 9:
86+ return nock(l(noun[0], 7, noun[1][1][1], l(2, (0, 1), (0, noun[1][1][0]))))
87+ elif noun[1][0] == 10:
88+ if isinstance(noun[1][1][0], int):
89+ return nock((noun[0], noun[1][1][1]))
90+ else:
91+ return nock(l(noun[0], 8, noun[1][1][0][1], 7, (0, 3), noun[1][1][1][0]))
92+ else:
93+ return (nock((noun[0], noun[1][0])), nock((noun[0], noun[1][1])))
94+```
docs/programming/nock/implementations/ruby.mdnew file+138
@@ -0,0 +1,138 @@
1+---
2+title: Ruby
3+sort: 2
4+next: true
5+---
6+
7+# Ruby
8+
9+From [T.J. Corcoran](https://github.com/TJamesCorcoran/nock/blob/master/nock.rb):
10+
11+```
12+def str_to_tree(str)
13+ arr = []
14+ str.scan(/\+|\=|\?|\/|\*|\[|\]|\d+/).each do |token|
15+ end
16+end
17+
18+def max_depth(arr)
19+ ret = arr.is_a?(Array) ? [max_depth(arr[0]), max_depth(arr[1])].max + 1 : 1
20+ ret
21+end
22+
23+def pp(arr)
24+ depth = max_depth(arr)
25+ space = 128
26+ 1.up_to(8) do |depth|
27+ space = space / 2
28+ min = 2 ** (depth - 1)
29+ max = (2 ** depth) - 1
30+ min.upto(max) { |axis|
31+ end
32+
33+end
34+
35+def norm(arr)
36+ return arr unless arr.is_a?(Array)
37+ while arr.size > 2
38+ size = arr.size
39+ arr[size - 2] = [ arr[size - 2], arr.pop ]
40+ end
41+ arr = arr.map { |x| norm(x) }
42+end
43+
44+def wut(arr)
45+ arr.is_a?(Array) ? YES : NO
46+end
47+
48+def lus(atom)
49+ raise "not an atom" unless atom.is_a?(Fixnum)
50+ atom + 1
51+end
52+
53+def tis(arr)
54+ raise "not pair" unless arr.is_a?(Array) && arr.size == 2
55+ ( arr[0] == arr[1] ) ? YES : NO
56+end
57+
58+def slot(axis, arr, allow_error = true)
59+ raise "axis on atom" unless arr.is_a?(Array)
60+ return arr if axis == 1
61+ return arr[0] if axis == 2
62+ return arr[1] if axis == 3
63+ return slot(2, slot(axis/2, arr)) if (axis %2) == 0
64+ return slot(3, slot(axis/2, arr))
65+end
66+
67+
68+def nock(arr)
69+ raise "error: nocking an atom" unless arr.is_a?(Array)
70+
71+ oper = slot(4, arr)
72+ a = slot(2, arr)
73+ b = slot(5, arr)
74+
75+ if oper.is_a?(Array)
76+ return [ nock( [ a, [b, c]]), nock( [a, d]) ]
77+ end
78+
79+
80+ case oper
81+ when 0 then
82+ slot(b,a )
83+
84+ when 1 then
85+ b
86+
87+ when 2 then
88+ b_prime = slot(2, b)
89+ c = slot(3,b)
90+ nock( [ nock([a, b_primce]), nock([a, c]) ])
91+
92+ when 3 then
93+ wut(nock([a, b]))
94+
95+ when 4 then
96+ lus(nock([a, b]))
97+
98+ when 5 then
99+ tis(nock([a, b]))
100+
101+ when 6 then
102+ b_prime = slot(2, b)
103+ c = slot(6,b)
104+ d = slot(7,b)
105+ nock( norm([a, 2, [0, 1], 2, [1, c, d], [1, 0], 2, [1, 2, 3], [1, 0], 4, 4, b]) )
106+
107+ when 7 then
108+ b_prime = slot(2, b)
109+ c = slot(3,b)
110+ nock( norm ([a, 2, b_prime, 1, c]))
111+
112+ when 8 then
113+ b_prime = slot(2, b)
114+ c = slot(3,b)
115+ nock( norm ([a, 7, [[7, [0, 1], b_prime], 0, 1], c]))
116+
117+ when 9 then
118+ b_prime = slot(2, b)
119+ c = slot(3,b)
120+ nock( norm ([a, 7, c, 2, [0, 1], 0, b_prime]))
121+
122+ when 10 then
123+ if wut(slot(2,b)) == TRUE
124+ b_prime = slot(4, b)
125+ c = slot(5, b)
126+ d = slot(3, b)
127+ c = slot(3,b)
128+ nock( norm ([a, 8, c, 7, [0, 3], d]))
129+ else
130+ b_prime = slot(2, b)
131+ c = slot(3, b)
132+ nock( norm ([a, 10, [b, c]]))
133+ end
134+ else
135+ raise "error: unknown opcode #{oper.inspect}"
136+ end
137+end
138+```
docs/programming/nock/implementations/scala.mdnew file+85
@@ -0,0 +1,85 @@
1+---
2+title: Scala
3+sort: 4
4+next: true
5+---
6+
7+# Scala
8+
9+From [Steve Randy Waldman](https://github.com/swaldman/nnnock/blob/master/src/main/scala/com/mchange/sc/v1/nnnock/package.scala):
10+
11+```
12+package object nnnock {
13+
14+ sealed trait Noun;
15+ case class Atom( value : Int ) extends Noun;
16+ case class Cell( head : Noun, tail : Noun ) extends Noun;
17+ implicit def toAtom( value : Int ) : Atom = Atom( value );
18+ implicit def toInt( atom : Atom ) : Int = atom.value;
19+
20+ def nock( a : Noun ) : Noun = *(a)
21+
22+ object Cell {
23+ private def apply( nl : List[Noun] ) : Cell = {
24+ nl match {
25+ case a :: b :: Nil => Cell(a, b);
26+ case a :: b :: c :: Nil => Cell(a, Cell(b, c));
27+ case a :: b :: c :: tail => Cell(a, this.apply( b :: c :: tail ) );
28+ }
29+ }
30+ def apply(a : Noun, b : Noun, tail : Noun*) : Cell = apply( a :: b :: tail.toList );
31+ }
32+
33+ def ?( noun : Noun ) : Noun = noun match {
34+ case _ : Cell => 0;
35+ case _ : Atom => 1;
36+ }
37+
38+ @tailrec def plus( noun : Noun ) : Noun = noun match {
39+ case a : Atom => 1 + a;
40+ case c : Cell => plus( c ); //intentional endless spin
41+ }
42+
43+ def heq( noun : Noun ) : Atom = noun match {
44+ case Cell( a : Atom, b : Atom ) => if ( a == b ) 0 else 1;
45+ case Cell( a : Cell, b : Atom ) => 1;
46+ case Cell( a : Atom, b : Cell ) => 1;
47+ case Cell( a : Cell, b : Cell ) => if ((heq( Cell( a.head, b.head ) ) | heq( Cell( a.tail, b.tail ) )) == 0) 0 else 1;
48+ case a : Atom => heq( a ); //intentional endless spin
49+ }
50+
51+ def /( noun : Noun ) : Noun = noun match {
52+ case Cell(Atom(1), a) => a;
53+ case Cell(Atom(2), Cell(a, b)) => a;
54+ case Cell(Atom(3), Cell(a, b)) => b;
55+ case Cell(Atom(value), b ) => {
56+ val a = value / 2;
57+ val num = if ( value % a == 0 ) 2 else 3;
58+ /(Cell(num, /(Cell(a, b))));
59+ }
60+ case a => /( a ); //intentional endless spin
61+ }
62+
63+ def *( noun : Noun ) : Noun = noun match {
64+ case Cell( a, Cell(Cell(b, c), d) ) => Cell( *(Cell(a,b,c)), *(Cell(a,d)) );
65+ case Cell( a, Cell(Atom(value), tail) ) => {
66+ (value, tail) match {
67+ case (0, b) => /( Cell(b, a) );
68+ case (1, b) => b;
69+ case (2, Cell(b, c)) => *( Cell( *( Cell(a,b) ), *( Cell(a,c) ) ) );
70+ case (3, b) => ?( *( Cell(a,b) ) );
71+ case (4, b) => plus( *( Cell(a,b) ) );
72+ case (5, b) => heq( *( Cell(a,b) ) );
73+ case (6, Cell(b, Cell(c, d))) => *( Cell(a,2,Cell(0,1),2,Cell(1,c,d),Cell(1,0),2,Cell(1,2,3),Cell(1,0),4,4,b) ); //wtf?
74+ case (7, Cell(b, c)) => *( Cell(a,2,b,1,c) );
75+ case (8, Cell(b, c)) => *( Cell(a,7,Cell(Cell(7,Cell(0,1),b),0,1),c) ); //wtf2
76+ case (9, Cell(b, c)) => *( Cell(a,7,c,2,Cell(0,1),0,b) );
77+ case (10, Cell(Cell(b,c),d)) => *( Cell(a,8,c,7,Cell(0,3),d) );
78+ case (10, Cell(b, c)) => *( Cell(a,c) );
79+ case _ => *( noun ); //intentional endless spin
80+ }
81+ }
82+ case a => *( a ); //intentional endless spin
83+ }
84+}
85+```
docs/programming/runtime.md+6−3
@@ -1,10 +1,13 @@
1---
1---
2sort: 4
2sort: 4
3−title: Runtime
3+title: Runtime system
4---
4---
5
5
6−## Runtime
6+## Runtime system
7
7
8−The C code
8+Nock, though a conceptually simple interpreter, is executed by a
9+fairly interesting noun-specific, single-threaded runtime system.
10+All functions in the noun system proper (`noun` in the
11+interpreter tree) start with the `u3_` prefix.
9
12
10<list src="."></list>
13<list src="."></list>