on 6d45ede help sign in
366 lines 11 kB history raw
1---
2navhome: /docs
3title: Swift
4sort: 10
5next: true
6---
8# Swift
10```swift
11import Foundation
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.
15// 4
16// 5 :: nock(a) *a
17// 6 :: [a b c] [a [b c]]
18// 7
19// 8 :: ?[a b] 0
20// 9 :: ?a 1
21// 10 :: +[a b] +[a b]
22// 11 :: +a 1 + a
23// 12 :: =[a a] 0
24// 13 :: =[a b] 1
25// 14 :: =a =a
26// 15
27// 16 :: /[1 a] a
28// 17 :: /[2 a b] a
29// 18 :: /[3 a b] b
30// 19 :: /[(a + a) b] /[2 /[a b]]
31// 20 :: /[(a + a + 1) b] /[3 /[a b]]
32// 21 :: /a /a
33// 22
34// 23 :: *[a [b c] d] [*[a b c] *[a d]]
35// 24
36// 25 :: *[a 0 b] /[b a]
37// 26 :: *[a 1 b] b
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]
42// 31
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]
49// 38
50// 39 :: *a *a
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
58 case Atom(ATOM)
59 // 3 :: A cell is an ordered pair of nouns.
60 case Cell(Noun, Noun)
61 case Invalid
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]) {
70 self = .Invalid
71 if nouns.count > 0 {
72 var reverse = nouns.reverse().generate()
73 self = reverse.next()!
74 while let n = reverse.next() {
75 self = .Cell(n, self)
76 }
77 }
78 }
80 // protocol IntegerLiteralConvertible
81 public typealias IntegerLiteralType = ATOM
82 public init(integerLiteral value: IntegerLiteralType) {
83 self = .Atom(value)
84 }
86 // protocol ArrayLiteralConvertible
87 public typealias Element = Noun
88 public init(arrayLiteral elements: Element...) {
89 self = Noun(elements)
90 }
92 // Array subscript
93 public subscript(axis: ATOM) -> Noun {
94 return fas(.Cell(.Atom(axis), self))
95 }
97 // protocol Hashable
98 public var hashValue: Int {
99 //return self.description.hashValue
100 switch self {
101 case let .Atom(a):
102 return a.hashValue
103 case let .Cell(a, b):
104 return (5381 + 31 &* a.hashValue) &+ b.hashValue
105 default:
106 abort()
107 }
108 }
110 // protocol CustomStringConvertible
111 public var description: String {
112 return describe()
113 }
115 private func describe(depth: Int = 0) -> String {
116 var sub = ""
117 let next = depth+1
118 switch self {
119 case .Invalid:
120 return "[%INVALID%]"
121 case let .Atom(atom):
122 return "\(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))"
127 }
128 return depth == 0 ? "[\(sub)]" : sub
129 }
132// protocol Equatable
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
140 }
143public func wut(noun: Noun) -> Noun
145 switch noun {
146 // 8 :: ?[a b] 0
147 case .Cell:
148 return Noun.YES
149 case .Atom:
150 // 9 :: ?a 1
151 return Noun.NO
152 default:
153 //return wut(noun)
154 abort()
155 }
158public func lus(noun: Noun) -> Noun
160 if case let .Atom(a) = noun {
161 // 11 :: +a 1 + a
162 return .Atom(1+a)
163 }
164 // 10 :: +[a b] +[a b]
165 //return lus(noun)
166 abort()
169public func tis(noun: Noun) -> Noun
171 if case let .Cell(a, b) = noun {
172 // 12 :: =[a a] 0
173 // 13 :: =[a b] 1
174 return (a == b) ? Noun.YES : Noun.NO
175 }
176 // 14 :: =a =a
177 //return tis(noun)
178 abort()
181public func fas(noun: Noun) -> Noun
183 switch noun {
184 // 16 :: /[1 a] a
185 case let .Cell(1, a):
186 return a
187 // 17 :: /[2 a b] a
188 case let .Cell(2, .Cell(a, _)):
189 return a
190 // 18 :: /[3 a b] b
191 case let .Cell(3, .Cell(_, b)):
192 return 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))))
199 default:
200 // 21 :: /a /a
201 //return fas(noun)
202 abort()
203 }
206public func tar(noun: Noun) -> Noun
208 switch noun {
209 case let .Cell(a, formula):
210 switch 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):
217 return fas([b, a])
219 // 26 :: *[a 1 b] b
220 case let .Cell(1, b):
221 return 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)):
261 return tar([a, c]);
263 default:
264 //return tar(noun)
265 abort()
266 }
267 default:
268 //return tar(noun)
269 abort()
270 }
274public var nock_functions = Dictionary<Noun, Noun -> Noun>()
276public func dao(formula: Noun) -> Noun->Noun
278 if let cached = nock_functions[formula] {
279 return cached
280 }
282 let compiler = { () -> Noun -> Noun in
283 switch formula {
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
292 return { _ in b }
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
299 let f = dao(b)
300 return { a in wut(f(a)) }
302 case let .Cell(4, b): // Bump
303 let f = dao(b)
304 return { a in lus(f(a)) }
306 case let .Cell(5, b): // Same
307 let f = dao(b)
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))
312 return { a in
313 switch p(a) {
314 case Noun.self.YES:
315 return q(a)
316 case Noun.self.NO:
317 return r(a)
318 default:
319 return tar(.Cell(a, formula))
320 }
321 }
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
332 let f = dao(c)
333 return { a in
334 let core = f(a)
335 let arm = dao(fas(.Cell(b, core)))
336 return arm(core)
337 }
339 case let .Cell(10, .Cell(.Cell(_, c), d)): // Hint
340 let ignore = dao(c)
341 let f = dao(d)
342 return { a in ignore(a); return f(a) }
344 case let .Cell(10, .Cell(_, c)): // Hint
345 let f = dao(c)
346 return { a in f(a) }
348 default:
349 return { a in tar(.Cell(a, formula)) }
350 }
351 }
353 let r = compiler()
354 nock_functions[formula] = r
355 return r
358public func nock(n: Noun) -> Noun
360 if case let .Cell(a, b) = n {
361 let f = dao(b)
362 return f(a)
363 }
364 return nock(n)
366```