12// 1 :: A noun is an atom or a cell.
13// 2 :: An atom is a natural number.
14// 3 :: A cell is an ordered pair of nouns.
17// 6 :: [a b c] [a [b c]]
30// 19 :: /[(a + a) b] /[2 /[a b]]
31// 20 :: /[(a + a + 1) b] /[3 /[a b]]
34// 23 :: *[a [b c] d] [*[a b c] *[a d]]
36// 25 :: *[a 0 b] /[b a]
38// 27 :: *[a 2 b c] *[*[a b] *[a c]]
39// 28 :: *[a 3 b] ?*[a b]
40// 29 :: *[a 4 b] +*[a b]
41// 30 :: *[a 5 b] =*[a b]
43// 32 :: *[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]
44// 33 :: *[a 7 b c] *[a 2 b 1 c]
45// 34 :: *[a 8 b c] *[a 7 [[7 [0 1] b] 0 1] c]
46// 35 :: *[a 9 b c] *[a 7 c 2 [0 1] 0 b]
47// 36 :: *[a 10 [b c] d] *[a 8 c 7 [0 3] d]
48// 37 :: *[a 10 b c] *[a c]
52// 1 :: A noun is an atom or a cell.
53public indirect enum Noun: IntegerLiteralConvertible, ArrayLiteralConvertible, Equatable, Hashable, CustomStringConvertible
55 // 2 :: An atom is a natural number.
56 public typealias ATOM = UIntMax
59 // 3 :: A cell is an ordered pair of nouns.
63 public static var YES: Noun { return .Atom(0) }
64 public static var NO: Noun { return .Atom(1) }
66 public init(_ noun: Noun) { self = noun }
68 // 6 :: [a b c] [a [b c]]
69 public init(_ nouns: [Noun]) {
72 var reverse = nouns.reverse().generate()
73 self = reverse.next()!
74 while let n = reverse.next() {
80 // protocol IntegerLiteralConvertible
81 public typealias IntegerLiteralType = ATOM
82 public init(integerLiteral value: IntegerLiteralType) {
86 // protocol ArrayLiteralConvertible
87 public typealias Element = Noun
88 public init(arrayLiteral elements: Element...) {
93 public subscript(axis: ATOM) -> Noun {
94 return fas(.Cell(.Atom(axis), self))
98 public var hashValue: Int {
99 //return self.description.hashValue
103 case let .Cell(a, b):
104 return (5381 + 31 &* a.hashValue) &+ b.hashValue
110 // protocol CustomStringConvertible
111 public var description: String {
115 private func describe(depth: Int = 0) -> String {
121 case let .Atom(atom):
123 case let .Cell(.Cell(a, b), c):
124 sub = "[\(a.describe(next)) \(b.describe(next))] \(c.describe(next))"
125 case let .Cell(a, b):
126 sub = "\(a.describe(next)) \(b.describe(next))"
128 return depth == 0 ? "[\(sub)]" : sub
133public func == (left: Noun, right: Noun) -> Bool
135 switch (left, right) {
136 case let (.Atom(lhs), .Atom(rhs)): return lhs == rhs
137 case let (.Cell(lp, lq), .Cell(rp, rq)): return lp == rp && lq == rq
138 case (.Invalid, .Invalid): return true
139 default: return false
143public func wut(noun: Noun) -> Noun
158public func lus(noun: Noun) -> Noun
160 if case let .Atom(a) = noun {
164 // 10 :: +[a b] +[a b]
169public func tis(noun: Noun) -> Noun
171 if case let .Cell(a, b) = noun {
174 return (a == b) ? Noun.YES : Noun.NO
181public func fas(noun: Noun) -> Noun
185 case let .Cell(1, a):
188 case let .Cell(2, .Cell(a, _)):
191 case let .Cell(3, .Cell(_, b)):
193 // 19 :: /[(a + a) b] /[2 /[a b]]
194 // 20 :: /[(a + a + 1) b] /[3 /[a b]]
195 case let .Cell(.Atom(axis), tree):
196 let inner = Noun.Atom(axis / 2)
197 let outer = Noun.Atom(2 + (axis % 2))
198 return fas(.Cell(outer, fas(.Cell(inner, tree))))
206public func tar(noun: Noun) -> Noun
209 case let .Cell(a, formula):
211 // 23 :: *[a [b c] d] [*[a b c] *[a d]]
212 case let .Cell(.Cell(b, c), d):
213 return .Cell(tar([a, b, c]), tar([a, d]))
215 // 25 :: *[a 0 b] /[b a]
216 case let .Cell(0, b):
220 case let .Cell(1, b):
223 // 27 :: *[a 2 b c] *[*[a b] *[a c]]
224 case let .Cell(2, .Cell(b, c)):
225 return tar([tar([a, b]), tar([a, c])])
227 // 28 :: *[a 3 b] ?*[a b]
228 case let .Cell(3, b):
229 return wut(tar([a, b]))
231 // 29 :: *[a 4 b] +*[a b]
232 case let .Cell(4, b):
233 return lus(tar([a, b]))
235 // 30 :: *[a 5 b] =*[a b]
236 case let .Cell(5, b):
237 return tis(tar([a, b]))
239 // 32 :: *[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]
240 case let .Cell(6, .Cell(b, .Cell(c, d))):
241 return tar([a, 2, [0, 1], 2, [1, c, d], [1, 0], 2, [1, 2, 3], [1, 0], 4, 4, b])
243 // 33 :: *[a 7 b c] *[a 2 b 1 c]
244 case let .Cell(7, .Cell(b, c)):
245 return tar([a, 2, b, 1, c])
247 // 34 :: *[a 8 b c] *[a 7 [[7 [0 1] b] 0 1] c]
248 case let .Cell(8, .Cell(b, c)):
249 return tar([a, 7, [[7, [0, 1], b], 0, 1], c])
251 // 35 :: *[a 9 b c] *[a 7 c 2 [0 1] 0 b]
252 case let .Cell(9, .Cell(b, c)):
253 return tar([a, 7, c, 2, [0, 1], 0, b])
255 // 36 :: *[a 10 [b c] d] *[a 8 c 7 [0 3] d]
256 case let .Cell(10, .Cell(.Cell(_, c), d)):
257 return tar([a, 8, c, 7, [0, 3], d])
259 // 37 :: *[a 10 b c] *[a c]
260 case let .Cell(10, .Cell(_, c)):
274public var nock_functions = Dictionary<Noun, Noun -> Noun>()
276public func dao(formula: Noun) -> Noun->Noun
278 if let cached = nock_functions[formula] {
282 let compiler = { () -> Noun -> Noun in
284 case let .Cell(.Cell(b, c), d): // Distribution
285 let (p, q) = (dao(.Cell(b, c)), dao(d))
286 return { a in .Cell(p(a), q(a)) }
288 case let .Cell(0, b): // Axis
289 return { a in fas(.Cell(b, a)) }
291 case let .Cell(1, b): // Just
294 case let .Cell(2, .Cell(b, c)): // Fire
295 let (f, g) = (dao(b), dao(c))
296 return { a in dao(g(a))(f(a)) }
298 case let .Cell(3, b): // Depth
300 return { a in wut(f(a)) }
302 case let .Cell(4, b): // Bump
304 return { a in lus(f(a)) }
306 case let .Cell(5, b): // Same
308 return { a in tis(f(a)) }
310 case let .Cell(6, .Cell(b, .Cell(c, d))): // If
311 let (p, q, r) = (dao(b), dao(c), dao(d))
319 return tar(.Cell(a, formula))
323 case let .Cell(7, .Cell(b, c)): // Compose
324 let (f, g) = (dao(b), dao(c))
325 return { a in g(f(a)) }
327 case let .Cell(8, .Cell(b, c)): // Push
328 let (f, g) = (dao(b), dao(c))
329 return { a in g(.Cell(f(a), a)) }
331 case let .Cell(9, .Cell(b, c)): // Call
335 let arm = dao(fas(.Cell(b, core)))
339 case let .Cell(10, .Cell(.Cell(_, c), d)): // Hint
342 return { a in ignore(a); return f(a) }
344 case let .Cell(10, .Cell(_, c)): // Hint
349 return { a in tar(.Cell(a, formula)) }
354 nock_functions[formula] = r
358public func nock(n: Noun) -> Noun
360 if case let .Cell(a, b) = n {
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list