From 3317e8778b584f196b1951834301df7f1eedbd49 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 11:19:12 -0400 Subject: [PATCH 001/138] Doubt is testable. --- prototype/DoubtTests/DoubtTests.swift | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/prototype/DoubtTests/DoubtTests.swift b/prototype/DoubtTests/DoubtTests.swift index dc956aa09..ab38963f3 100644 --- a/prototype/DoubtTests/DoubtTests.swift +++ b/prototype/DoubtTests/DoubtTests.swift @@ -15,10 +15,5 @@ let sexpr: String -> State? = fix { sexpr in } -func fix(f: (T -> U) -> T -> U) -> T -> U { - return { f(fix(f))($0) } -} - - -import Doubt +@testable import Doubt import XCTest From 29cc2ed663d8adea3b985a557287c49fdeabe91f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 11:23:05 -0400 Subject: [PATCH 002/138] Character class from sequences of characters. --- prototype/Doubt/Parse.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prototype/Doubt/Parse.swift b/prototype/Doubt/Parse.swift index a60c4d5ec..5c2285f3f 100644 --- a/prototype/Doubt/Parse.swift +++ b/prototype/Doubt/Parse.swift @@ -17,6 +17,10 @@ public prefix func ^(strings: [String])(_ input: String) -> State? { } } +public prefix func ^(strings: S) -> String -> State? { + return ^strings.map { String($0) } +} + public func parseWhile(predicate: Character -> Bool)(_ input: String) -> State? { return input.characters.count > 0 && predicate(input.characters[input.startIndex]) ? parseWhile(predicate)(input.from(1)).map { State(rest: $0.rest, value: input.to(1) + $0.value) } ?? State(rest: input.from(1), value: input.to(1)) From 8cdb91b5c4175eceea760c7eee35b96f23e8a6d3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 11:23:47 -0400 Subject: [PATCH 003/138] Remove the lambda calculus parser. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 ---- prototype/Doubt/Lambda.swift | 9 --------- 2 files changed, 13 deletions(-) delete mode 100644 prototype/Doubt/Lambda.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index dedf615c1..a99e5da4d 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -16,7 +16,6 @@ D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; D4AAE5421B5AE2D0004E581F /* Doc.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5371B5AE2D0004E581F /* Doc.swift */; }; - D4AAE5441B5AE2D0004E581F /* Lambda.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5391B5AE2D0004E581F /* Lambda.swift */; }; D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53A1B5AE2D0004E581F /* Operators.swift */; }; D4AAE5461B5AE2D0004E581F /* Parse.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53B1B5AE2D0004E581F /* Parse.swift */; }; D4AAE5471B5AE2D0004E581F /* Prelude.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53C1B5AE2D0004E581F /* Prelude.swift */; }; @@ -49,7 +48,6 @@ D4AAE5351B5AE2D0004E581F /* Array.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = ""; }; D4AAE5361B5AE2D0004E581F /* Diff.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Diff.swift; sourceTree = ""; }; D4AAE5371B5AE2D0004E581F /* Doc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Doc.swift; sourceTree = ""; }; - D4AAE5391B5AE2D0004E581F /* Lambda.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lambda.swift; sourceTree = ""; }; D4AAE53A1B5AE2D0004E581F /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = ""; }; D4AAE53B1B5AE2D0004E581F /* Parse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parse.swift; sourceTree = ""; }; D4AAE53C1B5AE2D0004E581F /* Prelude.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prelude.swift; sourceTree = ""; }; @@ -102,7 +100,6 @@ D4AAE5351B5AE2D0004E581F /* Array.swift */, D4AAE5361B5AE2D0004E581F /* Diff.swift */, D4AAE5371B5AE2D0004E581F /* Doc.swift */, - D4AAE5391B5AE2D0004E581F /* Lambda.swift */, D4AAE53A1B5AE2D0004E581F /* Operators.swift */, D4AAE53B1B5AE2D0004E581F /* Parse.swift */, D4AAE53C1B5AE2D0004E581F /* Prelude.swift */, @@ -244,7 +241,6 @@ buildActionMask = 2147483647; files = ( D4AAE5471B5AE2D0004E581F /* Prelude.swift in Sources */, - D4AAE5441B5AE2D0004E581F /* Lambda.swift in Sources */, D4AAE5481B5AE2D0004E581F /* String.swift in Sources */, D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */, D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */, diff --git a/prototype/Doubt/Lambda.swift b/prototype/Doubt/Lambda.swift deleted file mode 100644 index 9e6f195a5..000000000 --- a/prototype/Doubt/Lambda.swift +++ /dev/null @@ -1,9 +0,0 @@ -let word = ^("abcdefghijklmnopqrstuvwxyz".characters.map { String($0) }) -let ws = ^" " - -let term: String -> State? = fix { term in - let variable = Syntax.Variable <^> word - let application = Syntax.Apply <^> (^"(" *> ws* *> term <*> (ws *> term)* <* ws* <* ^")") - let abstraction = Syntax.Abstract <^> (^"λ" *> ws* *> interpolate(term, ws) <*> (ws* *> ^"." *> term)) - return Term.init <^> (abstraction <|> application <|> variable) -} From ec190096140391f7b1e1c20274a5a1d1fadb6eb4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 11:24:05 -0400 Subject: [PATCH 004/138] Move the S-expression parser into the library. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 ++++ prototype/Doubt/Swift.swift | 7 +++++++ prototype/DoubtTests/DoubtTests.swift | 8 -------- 3 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 prototype/Doubt/Swift.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index a99e5da4d..26c69ac2a 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + D40024EC1BAC62BA00A110B8 /* Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40024EB1BAC62BA00A110B8 /* Swift.swift */; }; D432D4711BA9AC0B00F3FABC /* DiffTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4701BA9AC0B00F3FABC /* DiffTests.swift */; }; D432D4731BA9C55300F3FABC /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4721BA9C55300F3FABC /* Stream.swift */; }; D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4741BA9D6A400F3FABC /* Memo.swift */; }; @@ -36,6 +37,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + D40024EB1BAC62BA00A110B8 /* Swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Swift.swift; sourceTree = ""; }; D432D4701BA9AC0B00F3FABC /* DiffTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffTests.swift; sourceTree = ""; }; D432D4721BA9C55300F3FABC /* Stream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stream.swift; sourceTree = ""; }; D432D4741BA9D6A400F3FABC /* Memo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Memo.swift; sourceTree = ""; }; @@ -110,6 +112,7 @@ D432D4761BA9FE6A00F3FABC /* Comparable.swift */, D432D4721BA9C55300F3FABC /* Stream.swift */, D432D4741BA9D6A400F3FABC /* Memo.swift */, + D40024EB1BAC62BA00A110B8 /* Swift.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, ); path = Doubt; @@ -252,6 +255,7 @@ D4AAE5461B5AE2D0004E581F /* Parse.swift in Sources */, D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, + D40024EC1BAC62BA00A110B8 /* Swift.swift in Sources */, D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift new file mode 100644 index 000000000..58b8ae067 --- /dev/null +++ b/prototype/Doubt/Swift.swift @@ -0,0 +1,7 @@ +let atom = Syntax.Variable <^> ^("abcdefghijklmnopqrstuvwxyz".characters.map { String($0) }) +let ws = ^" \t\n".characters + +let sexpr: String -> State? = fix { sexpr in + let list = Syntax.Apply <^> (ws* *> ^"(" *> ws* *> sexpr <*> sexpr* <* ^")") + return Term.init <^> (atom <|> list) <* ws* +} diff --git a/prototype/DoubtTests/DoubtTests.swift b/prototype/DoubtTests/DoubtTests.swift index ab38963f3..a4efbcc1e 100644 --- a/prototype/DoubtTests/DoubtTests.swift +++ b/prototype/DoubtTests/DoubtTests.swift @@ -6,14 +6,6 @@ final class DoubtTests: XCTestCase { } } -let atom = Syntax.Variable <^> ^("abcdefghijklmnopqrstuvwxyz".characters.map { String($0) }) -let ws = ^(" \t\n".characters.map { String($0) }) - -let sexpr: String -> State? = fix { sexpr in - let list = Syntax.Apply <^> (ws* *> ^"(" *> ws* *> sexpr <*> sexpr* <* ^")") - return Term.init <^> (atom <|> list) <* ws* -} - @testable import Doubt import XCTest From 079518a3f4ceec0337df2b084ae79ad92a7c63c0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 13:39:08 -0400 Subject: [PATCH 005/138] Add words. --- prototype/Doubt/Swift.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 58b8ae067..12b1f3ae9 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -1,4 +1,6 @@ let atom = Syntax.Variable <^> ^("abcdefghijklmnopqrstuvwxyz".characters.map { String($0) }) +let alphabetic = ^"abcdefghijklmnopqrstuvwxyz".characters +let word = { $0.joinWithSeparator("") } <^> alphabetic* let ws = ^" \t\n".characters let sexpr: String -> State? = fix { sexpr in From 8191905eaf2c0546875e4bdb0802418ccd7a0923 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 13:39:28 -0400 Subject: [PATCH 006/138] Add a simple tree type representing Swift AST. --- prototype/Doubt/Swift.swift | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 12b1f3ae9..10dd67321 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -1,9 +1,18 @@ -let atom = Syntax.Variable <^> ^("abcdefghijklmnopqrstuvwxyz".characters.map { String($0) }) let alphabetic = ^"abcdefghijklmnopqrstuvwxyz".characters let word = { $0.joinWithSeparator("") } <^> alphabetic* let ws = ^" \t\n".characters -let sexpr: String -> State? = fix { sexpr in - let list = Syntax.Apply <^> (ws* *> ^"(" *> ws* *> sexpr <*> sexpr* <* ^")") - return Term.init <^> (atom <|> list) <* ws* +func never(_: String) -> State? { + return nil +} + +enum Swift { + case KeyValue(String, String) + case Branch(String, [Swift]) + + struct Parsers { + static let keyValue = KeyValue <^> (word <* ^"=" <*> word) + static let branch = Branch <^> (^"(" *> ws* *> word <*> sexpr* <* ^")") + static let sexpr: String -> State? = never + } } From cce9fe71b8f63db6b294c9288225cb28ebceb1b6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 13:43:08 -0400 Subject: [PATCH 007/138] Whitespace has some places it can be. --- prototype/Doubt/Swift.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 10dd67321..fbdab13c1 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -12,7 +12,7 @@ enum Swift { struct Parsers { static let keyValue = KeyValue <^> (word <* ^"=" <*> word) - static let branch = Branch <^> (^"(" *> ws* *> word <*> sexpr* <* ^")") - static let sexpr: String -> State? = never + static let branch = Branch <^> (^"(" *> ws* *> word <*> sexpr* <* ws* <* ^")") + static let sexpr: String -> State? = never <* ws* } } From 2edb3b60f17059facae5e08261fca28e1edb4c1a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 13:43:25 -0400 Subject: [PATCH 008/138] Move all the parsers into Swift.Parsers. --- prototype/Doubt/Swift.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index fbdab13c1..68b3fa7a4 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -1,7 +1,3 @@ -let alphabetic = ^"abcdefghijklmnopqrstuvwxyz".characters -let word = { $0.joinWithSeparator("") } <^> alphabetic* -let ws = ^" \t\n".characters - func never(_: String) -> State? { return nil } @@ -11,6 +7,9 @@ enum Swift { case Branch(String, [Swift]) struct Parsers { + static let alphabetic = ^"abcdefghijklmnopqrstuvwxyz".characters + static let word = { $0.joinWithSeparator("") } <^> alphabetic* + static let ws = ^" \t\n".characters static let keyValue = KeyValue <^> (word <* ^"=" <*> word) static let branch = Branch <^> (^"(" *> ws* *> word <*> sexpr* <* ws* <* ^")") static let sexpr: String -> State? = never <* ws* From c92dbc446beea400dfa5f9284ab0fca9390749fc Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 13:45:47 -0400 Subject: [PATCH 009/138] The Swift AST is Equatable. --- prototype/Doubt/Equatable.swift | 11 +++++++++++ prototype/Doubt/Swift.swift | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/Equatable.swift b/prototype/Doubt/Equatable.swift index 34cfd49e7..90dbeb3aa 100644 --- a/prototype/Doubt/Equatable.swift +++ b/prototype/Doubt/Equatable.swift @@ -60,3 +60,14 @@ public func == (left: Doc, right: Doc) -> Bool { return false } } + +func == (left: Swift, right: Swift) -> Bool { + switch (left, right) { + case let (.KeyValue(k1, v1), .KeyValue(k2, v2)): + return k1 == k2 && v1 == v2 + case let (.Branch(n1, b1), .Branch(n2, b2)): + return n1 == n2 && b1 == b2 + default: + return false + } +} diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 68b3fa7a4..3d9d5c976 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -2,7 +2,7 @@ func never(_: String) -> State? { return nil } -enum Swift { +enum Swift: Equatable { case KeyValue(String, String) case Branch(String, [Swift]) From 56c139cd0bbdd773d79a0126d448cc7e55784a5e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 13:46:52 -0400 Subject: [PATCH 010/138] Test that the key value parser accepts alphabetic keys & values. --- prototype/Doubt.xcodeproj/project.pbxproj | 8 ++++---- prototype/DoubtTests/DoubtTests.swift | 11 ----------- prototype/DoubtTests/SwiftTests.swift | 9 +++++++++ 3 files changed, 13 insertions(+), 15 deletions(-) delete mode 100644 prototype/DoubtTests/DoubtTests.swift create mode 100644 prototype/DoubtTests/SwiftTests.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 26c69ac2a..e86a0cd9b 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -8,12 +8,12 @@ /* Begin PBXBuildFile section */ D40024EC1BAC62BA00A110B8 /* Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40024EB1BAC62BA00A110B8 /* Swift.swift */; }; + D40024EE1BAC819000A110B8 /* SwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40024ED1BAC819000A110B8 /* SwiftTests.swift */; }; D432D4711BA9AC0B00F3FABC /* DiffTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4701BA9AC0B00F3FABC /* DiffTests.swift */; }; D432D4731BA9C55300F3FABC /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4721BA9C55300F3FABC /* Stream.swift */; }; D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4741BA9D6A400F3FABC /* Memo.swift */; }; D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4761BA9FE6A00F3FABC /* Comparable.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; - D4AAE5131B5AE22E004E581F /* DoubtTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5121B5AE22E004E581F /* DoubtTests.swift */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; D4AAE5421B5AE2D0004E581F /* Doc.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5371B5AE2D0004E581F /* Doc.swift */; }; @@ -38,6 +38,7 @@ /* Begin PBXFileReference section */ D40024EB1BAC62BA00A110B8 /* Swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Swift.swift; sourceTree = ""; }; + D40024ED1BAC819000A110B8 /* SwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftTests.swift; sourceTree = ""; }; D432D4701BA9AC0B00F3FABC /* DiffTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffTests.swift; sourceTree = ""; }; D432D4721BA9C55300F3FABC /* Stream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stream.swift; sourceTree = ""; }; D432D4741BA9D6A400F3FABC /* Memo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Memo.swift; sourceTree = ""; }; @@ -45,7 +46,6 @@ D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - D4AAE5121B5AE22E004E581F /* DoubtTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubtTests.swift; sourceTree = ""; }; D4AAE5141B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE5351B5AE2D0004E581F /* Array.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = ""; }; D4AAE5361B5AE2D0004E581F /* Diff.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Diff.swift; sourceTree = ""; }; @@ -129,8 +129,8 @@ D4AAE5111B5AE22E004E581F /* DoubtTests */ = { isa = PBXGroup; children = ( - D4AAE5121B5AE22E004E581F /* DoubtTests.swift */, D432D4701BA9AC0B00F3FABC /* DiffTests.swift */, + D40024ED1BAC819000A110B8 /* SwiftTests.swift */, D4AAE5141B5AE22E004E581F /* Info.plist */, ); path = DoubtTests; @@ -264,8 +264,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D40024EE1BAC819000A110B8 /* SwiftTests.swift in Sources */, D432D4711BA9AC0B00F3FABC /* DiffTests.swift in Sources */, - D4AAE5131B5AE22E004E581F /* DoubtTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/prototype/DoubtTests/DoubtTests.swift b/prototype/DoubtTests/DoubtTests.swift deleted file mode 100644 index a4efbcc1e..000000000 --- a/prototype/DoubtTests/DoubtTests.swift +++ /dev/null @@ -1,11 +0,0 @@ -final class DoubtTests: XCTestCase { - func testEqualSyntaxResultsInRecursivelyCopyingDiff() { - if let s = sexpr("\t(\n( a) \n)\t")?.value, t = sexpr("((a))")?.value { - XCTAssertEqual(Diff(s, t), Diff.Copy(.Apply(.Copy(.Apply(.Copy(.Variable("a")), [])), []))) - } - } -} - - -@testable import Doubt -import XCTest diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift new file mode 100644 index 000000000..f2e342908 --- /dev/null +++ b/prototype/DoubtTests/SwiftTests.swift @@ -0,0 +1,9 @@ +final class SwiftTests: XCTestCase { + func testKeyValueAcceptsAlphabeticKeysAndValues() { + XCTAssertEqual(Swift.Parsers.keyValue("key=value")?.value, .KeyValue("key", "value")) + } +} + + +@testable import Doubt +import XCTest From 0224ccc5c7fe9fe797d6e927ae3577a5b9b1ecc3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 13:53:12 -0400 Subject: [PATCH 011/138] Move `never` in with the other parsers. --- prototype/Doubt/Parse.swift | 7 +++++++ prototype/Doubt/Swift.swift | 4 ---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/prototype/Doubt/Parse.swift b/prototype/Doubt/Parse.swift index 5c2285f3f..379d1becf 100644 --- a/prototype/Doubt/Parse.swift +++ b/prototype/Doubt/Parse.swift @@ -21,6 +21,13 @@ public prefix func ^( return ^strings.map { String($0) } } + +/// A convenience for use while developing parsers. +public func never(_: String) -> State? { + return nil +} + + public func parseWhile(predicate: Character -> Bool)(_ input: String) -> State? { return input.characters.count > 0 && predicate(input.characters[input.startIndex]) ? parseWhile(predicate)(input.from(1)).map { State(rest: $0.rest, value: input.to(1) + $0.value) } ?? State(rest: input.from(1), value: input.to(1)) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 3d9d5c976..1ef928925 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -1,7 +1,3 @@ -func never(_: String) -> State? { - return nil -} - enum Swift: Equatable { case KeyValue(String, String) case Branch(String, [Swift]) From 37612e763a2765c22f41d78be2a1d230487ca1f5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:03:42 -0400 Subject: [PATCH 012/138] Combinator which matches a character when its argument does not. --- prototype/Doubt/Parse.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/prototype/Doubt/Parse.swift b/prototype/Doubt/Parse.swift index 379d1becf..368eb26b2 100644 --- a/prototype/Doubt/Parse.swift +++ b/prototype/Doubt/Parse.swift @@ -27,6 +27,11 @@ public func never(_: String) -> State? { return nil } +//// Matches a single character that is not matched by `parser`. +public func not(parser: String -> State?)(_ input: String) -> State? { + return parser(input).map(const(nil)) ?? State(rest: input.from(1), value: input.to(1)) +} + public func parseWhile(predicate: Character -> Bool)(_ input: String) -> State? { return input.characters.count > 0 && predicate(input.characters[input.startIndex]) From fbcd667a4c26e5d5320483cbdc0e0effc864972b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:03:50 -0400 Subject: [PATCH 013/138] Full parser. --- prototype/Doubt/Parse.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prototype/Doubt/Parse.swift b/prototype/Doubt/Parse.swift index 368eb26b2..bafae1e03 100644 --- a/prototype/Doubt/Parse.swift +++ b/prototype/Doubt/Parse.swift @@ -22,6 +22,12 @@ public prefix func ^( } +/// Parse the full string with parser or fail. +public func full(parser: String -> State?)(_ input: String) -> A? { + return parser(input).flatMap { $0.rest.isEmpty ? $0.value : nil } +} + + /// A convenience for use while developing parsers. public func never(_: String) -> State? { return nil From c46c35157a4cf664ff23313ef548d80632a5f0b9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:04:04 -0400 Subject: [PATCH 014/138] Values can be quoted. --- prototype/Doubt/Swift.swift | 15 +++++++++++++-- prototype/DoubtTests/SwiftTests.swift | 12 ++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 1ef928925..9fa39506c 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -4,10 +4,21 @@ enum Swift: Equatable { struct Parsers { static let alphabetic = ^"abcdefghijklmnopqrstuvwxyz".characters - static let word = { $0.joinWithSeparator("") } <^> alphabetic* static let ws = ^" \t\n".characters - static let keyValue = KeyValue <^> (word <* ^"=" <*> word) + + static let word = { $0.joinWithSeparator("") } <^> alphabetic+ + static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) + + static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> word)) static let branch = Branch <^> (^"(" *> ws* *> word <*> sexpr* <* ws* <* ^")") static let sexpr: String -> State? = never <* ws* } } + +private func join(a: String -> State?, _ b: String -> State?) -> String -> State? { + return (+) <^> (a <*> b) +} + +private func concat(strings: [String]) -> String { + return strings.joinWithSeparator("") +} diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index f2e342908..21dece0b0 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -1,6 +1,14 @@ final class SwiftTests: XCTestCase { - func testKeyValueAcceptsAlphabeticKeysAndValues() { - XCTAssertEqual(Swift.Parsers.keyValue("key=value")?.value, .KeyValue("key", "value")) + func testValuesCanBeAlphabetic() { + XCTAssertEqual(full(Swift.Parsers.keyValue)("key=value"), .KeyValue("key", "value")) + } + + func testKeyValueCanBeQuoted() { + XCTAssertEqual(full(Swift.Parsers.keyValue)("key='value'"), .KeyValue("key", "'value'")) + } + + func testQuotedMatchesQuotedStrings() { + XCTAssertEqual(full (Swift.Parsers.quoted)("'value'"), "'value'") } } From 73da6e2d32e61466ae227acc23d95e4af492834a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:08:24 -0400 Subject: [PATCH 015/138] No zero-width matches from `not`. --- prototype/Doubt/Parse.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/prototype/Doubt/Parse.swift b/prototype/Doubt/Parse.swift index bafae1e03..d4a6bb1fa 100644 --- a/prototype/Doubt/Parse.swift +++ b/prototype/Doubt/Parse.swift @@ -35,6 +35,7 @@ public func never(_: String) -> State? { //// Matches a single character that is not matched by `parser`. public func not(parser: String -> State?)(_ input: String) -> State? { + if input.isEmpty { return nil } return parser(input).map(const(nil)) ?? State(rest: input.from(1), value: input.to(1)) } From 08d07baef72daeee82c3c3839dbc34b6512a8c5f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:08:37 -0400 Subject: [PATCH 016/138] Allow values to be quoted or non-ws strings. --- prototype/Doubt/Swift.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 9fa39506c..10cbadb13 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -9,7 +9,7 @@ enum Swift: Equatable { static let word = { $0.joinWithSeparator("") } <^> alphabetic+ static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) - static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> word)) + static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> (concat <^> not(ws <|> ^")")*))) static let branch = Branch <^> (^"(" *> ws* *> word <*> sexpr* <* ws* <* ^")") static let sexpr: String -> State? = never <* ws* } From a918261abce9975c800647d209743db69f6b98ef Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:37:53 -0400 Subject: [PATCH 017/138] Use concat. --- prototype/Doubt/Swift.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 10cbadb13..10ef4816c 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -6,7 +6,7 @@ enum Swift: Equatable { static let alphabetic = ^"abcdefghijklmnopqrstuvwxyz".characters static let ws = ^" \t\n".characters - static let word = { $0.joinWithSeparator("") } <^> alphabetic+ + static let word = concat <^> alphabetic+ static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> (concat <^> not(ws <|> ^")")*))) From abb63b7c4d2913475671b248b308366a20ff76f9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:38:05 -0400 Subject: [PATCH 018/138] Words can contain _. --- prototype/Doubt/Swift.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 10ef4816c..169669bd8 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -6,7 +6,7 @@ enum Swift: Equatable { static let alphabetic = ^"abcdefghijklmnopqrstuvwxyz".characters static let ws = ^" \t\n".characters - static let word = concat <^> alphabetic+ + static let word = concat <^> (alphabetic <|> ^"_")+ static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> (concat <^> not(ws <|> ^")")*))) From 4f1181c51ee71bd229b7815fed80ac9a564611d2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:42:53 -0400 Subject: [PATCH 019/138] Add a delay combinator. --- prototype/Doubt/Parse.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prototype/Doubt/Parse.swift b/prototype/Doubt/Parse.swift index d4a6bb1fa..c7c28a9ff 100644 --- a/prototype/Doubt/Parse.swift +++ b/prototype/Doubt/Parse.swift @@ -40,6 +40,12 @@ public func not(parser: String -> State?)(_ input: String) -> State(thunk: () -> String -> State?) -> String -> State? { + return { thunk()($0) } +} + + public func parseWhile(predicate: Character -> Bool)(_ input: String) -> State? { return input.characters.count > 0 && predicate(input.characters[input.startIndex]) ? parseWhile(predicate)(input.from(1)).map { State(rest: $0.rest, value: input.to(1) + $0.value) } ?? State(rest: input.from(1), value: input.to(1)) From b5cdad9f32f8d2e161908a5978fd64e75102f0c2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:43:04 -0400 Subject: [PATCH 020/138] Remove a bogus space. --- prototype/DoubtTests/SwiftTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index 21dece0b0..d1c9b1bbc 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -8,7 +8,7 @@ final class SwiftTests: XCTestCase { } func testQuotedMatchesQuotedStrings() { - XCTAssertEqual(full (Swift.Parsers.quoted)("'value'"), "'value'") + XCTAssertEqual(full(Swift.Parsers.quoted)("'value'"), "'value'") } } From 23f8a99867e39c8351a274ca1e1b1043e1be7fde Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:43:23 -0400 Subject: [PATCH 021/138] S-expression parsing includes branches and key/value pairs. --- prototype/Doubt/Swift.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 169669bd8..9a11b8be9 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -10,8 +10,8 @@ enum Swift: Equatable { static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> (concat <^> not(ws <|> ^")")*))) - static let branch = Branch <^> (^"(" *> ws* *> word <*> sexpr* <* ws* <* ^")") - static let sexpr: String -> State? = never <* ws* + static let branch: String -> State? = Branch <^> (^"(" *> ws* *> word <* ws* <*> sexpr* <* ws* <* ^")") + static let sexpr = delay { (branch <|> keyValue) <* ws* } } } From 3b6838097f8bf55c102496cbc2a9459644c77722 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:44:11 -0400 Subject: [PATCH 022/138] Test branch parsing. --- prototype/DoubtTests/SwiftTests.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index d1c9b1bbc..bb6a24742 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -10,6 +10,10 @@ final class SwiftTests: XCTestCase { func testQuotedMatchesQuotedStrings() { XCTAssertEqual(full(Swift.Parsers.quoted)("'value'"), "'value'") } + + func testBranchesStartWithAnIdentifier() { + XCTAssertEqual(full(Swift.Parsers.branch)("(a b=c)"), .Branch("a", [ .KeyValue("b", "c") ])) + } } From b80e8cb527105fa4bab2112a58479ff361082691 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:56:53 -0400 Subject: [PATCH 023/138] Extract a parser for atoms. --- prototype/Doubt/Swift.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 9a11b8be9..5790b1cd5 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -7,9 +7,10 @@ enum Swift: Equatable { static let ws = ^" \t\n".characters static let word = concat <^> (alphabetic <|> ^"_")+ + static let atom = concat <^> not(ws <|> ^")")* static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) - static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> (concat <^> not(ws <|> ^")")*))) + static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> atom)) static let branch: String -> State? = Branch <^> (^"(" *> ws* *> word <* ws* <*> sexpr* <* ws* <* ^")") static let sexpr = delay { (branch <|> keyValue) <* ws* } } From bcec39379db870f628e5f9d68b9a08cb5e0215f3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 15:58:01 -0400 Subject: [PATCH 024/138] Allow atoms to occur in branches. --- prototype/Doubt/Swift.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 5790b1cd5..2ce8dcece 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -1,4 +1,5 @@ enum Swift: Equatable { + case Atom(String) case KeyValue(String, String) case Branch(String, [Swift]) @@ -12,7 +13,7 @@ enum Swift: Equatable { static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> atom)) static let branch: String -> State? = Branch <^> (^"(" *> ws* *> word <* ws* <*> sexpr* <* ws* <* ^")") - static let sexpr = delay { (branch <|> keyValue) <* ws* } + static let sexpr = delay { (branch <|> (Swift.Atom <^> atom) <|> keyValue) <* ws* } } } From 4b3ea05f8edb7cd2a1e16c980bf9d0388fe211b6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 16:02:41 -0400 Subject: [PATCH 025/138] This is just the worst test of alphabetic characters I can imagine. --- prototype/Doubt/Swift.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 2ce8dcece..8c3582918 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -4,7 +4,7 @@ enum Swift: Equatable { case Branch(String, [Swift]) struct Parsers { - static let alphabetic = ^"abcdefghijklmnopqrstuvwxyz".characters + static let alphabetic = ^"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".characters static let ws = ^" \t\n".characters static let word = concat <^> (alphabetic <|> ^"_")+ From 04a207f71b4c518a36c6ac38914c382c7ee5d539 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 16:03:58 -0400 Subject: [PATCH 026/138] Parse symbols. --- prototype/Doubt/Swift.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 8c3582918..4501cb113 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -1,5 +1,6 @@ enum Swift: Equatable { case Atom(String) + case Symbol(String, [String]) case KeyValue(String, String) case Branch(String, [Swift]) @@ -11,9 +12,10 @@ enum Swift: Equatable { static let atom = concat <^> not(ws <|> ^")")* static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) + static let symbol = Swift.Symbol <^> (join(^"\"", join((concat <^> not(^"\"")*), ^"\"")) <*> (^"<" *> interpolate(concat <^> alphabetic+, ^"," <* ws*) <* ^">")) static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> atom)) static let branch: String -> State? = Branch <^> (^"(" *> ws* *> word <* ws* <*> sexpr* <* ws* <* ^")") - static let sexpr = delay { (branch <|> (Swift.Atom <^> atom) <|> keyValue) <* ws* } + static let sexpr = delay { (branch <|> symbol <|> (Swift.Atom <^> atom) <|> keyValue) <* ws* } } } From 654492158ab14f395f30b49003587bb18274ed70 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 16:31:05 -0400 Subject: [PATCH 027/138] Symbol nodes can be equated. --- prototype/Doubt/Equatable.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prototype/Doubt/Equatable.swift b/prototype/Doubt/Equatable.swift index 90dbeb3aa..98dc36582 100644 --- a/prototype/Doubt/Equatable.swift +++ b/prototype/Doubt/Equatable.swift @@ -67,6 +67,8 @@ func == (left: Swift, right: Swift) -> Bool { return k1 == k2 && v1 == v2 case let (.Branch(n1, b1), .Branch(n2, b2)): return n1 == n2 && b1 == b2 + case let (.Symbol(s, u), .Symbol(t, v)): + return s == t && u == v default: return false } From b71b40bf6f38d95aba0b23dcc4ce4ac929343644 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 16:31:25 -0400 Subject: [PATCH 028/138] Atoms must be one or more character. --- prototype/Doubt/Swift.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index 4501cb113..e3cfd458b 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -9,7 +9,7 @@ enum Swift: Equatable { static let ws = ^" \t\n".characters static let word = concat <^> (alphabetic <|> ^"_")+ - static let atom = concat <^> not(ws <|> ^")")* + static let atom = concat <^> not(ws <|> ^")")+ static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) static let symbol = Swift.Symbol <^> (join(^"\"", join((concat <^> not(^"\"")*), ^"\"")) <*> (^"<" *> interpolate(concat <^> alphabetic+, ^"," <* ws*) <* ^">")) From dfde9f26b9edf8f3a7d72bef7357dc6c424abee4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 16:31:47 -0400 Subject: [PATCH 029/138] Prioritize key/value pairs ahead of atoms. --- prototype/Doubt/Swift.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index e3cfd458b..d80408df9 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -15,7 +15,7 @@ enum Swift: Equatable { static let symbol = Swift.Symbol <^> (join(^"\"", join((concat <^> not(^"\"")*), ^"\"")) <*> (^"<" *> interpolate(concat <^> alphabetic+, ^"," <* ws*) <* ^">")) static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> atom)) static let branch: String -> State? = Branch <^> (^"(" *> ws* *> word <* ws* <*> sexpr* <* ws* <* ^")") - static let sexpr = delay { (branch <|> symbol <|> (Swift.Atom <^> atom) <|> keyValue) <* ws* } + static let sexpr = delay { (branch <|> symbol <|> keyValue <|> (Swift.Atom <^> atom)) <* ws* } } } From 8b1afceaad52fb83998d90cb9a26841193c80a8a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 16:31:54 -0400 Subject: [PATCH 030/138] Atoms are equatable. --- prototype/Doubt/Equatable.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prototype/Doubt/Equatable.swift b/prototype/Doubt/Equatable.swift index 98dc36582..742dc5dba 100644 --- a/prototype/Doubt/Equatable.swift +++ b/prototype/Doubt/Equatable.swift @@ -67,6 +67,8 @@ func == (left: Swift, right: Swift) -> Bool { return k1 == k2 && v1 == v2 case let (.Branch(n1, b1), .Branch(n2, b2)): return n1 == n2 && b1 == b2 + case let (.Atom(a), .Atom(b)): + return a == b case let (.Symbol(s, u), .Symbol(t, v)): return s == t && u == v default: From ca5298da88b2c781f7c72cdd493caa923c63f05a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 16:32:07 -0400 Subject: [PATCH 031/138] Test that empty branches can be produced. --- prototype/DoubtTests/SwiftTests.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index bb6a24742..4209c86da 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -14,6 +14,10 @@ final class SwiftTests: XCTestCase { func testBranchesStartWithAnIdentifier() { XCTAssertEqual(full(Swift.Parsers.branch)("(a b=c)"), .Branch("a", [ .KeyValue("b", "c") ])) } + + func testBranchesDoNotRequireChildren() { + XCTAssertEqual(full(Swift.Parsers.branch)("(return_stmt)"), .Branch("return_stmt", [])) + } } From ab4ec9e0aac68cb0ccb266634f12557d9db9c888 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 18 Sep 2015 16:36:14 -0400 Subject: [PATCH 032/138] Add a root parser taking multiple sexprs. --- prototype/Doubt/Swift.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index d80408df9..b58f2324a 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -16,6 +16,8 @@ enum Swift: Equatable { static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> atom)) static let branch: String -> State? = Branch <^> (^"(" *> ws* *> word <* ws* <*> sexpr* <* ws* <* ^")") static let sexpr = delay { (branch <|> symbol <|> keyValue <|> (Swift.Atom <^> atom)) <* ws* } + + static let root = ws* *> sexpr* } } From de2c7f516900b79ab304caea50a2f78ce1b5e50e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 11:14:31 -0400 Subject: [PATCH 033/138] Add & link SourceKitten & dependencies. --- .gitmodules | 3 ++ prototype/Doubt.xcodeproj/project.pbxproj | 34 +++++++++++++++++++ .../contents.xcworkspacedata | 15 ++++++++ prototype/External/SourceKitten | 1 + 4 files changed, 53 insertions(+) create mode 100644 .gitmodules create mode 160000 prototype/External/SourceKitten diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..b5f60331c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "prototype/External/SourceKitten"] + path = prototype/External/SourceKitten + url = https://github.com/jpsim/SourceKitten.git diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index e86a0cd9b..943e45e07 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -13,6 +13,16 @@ D432D4731BA9C55300F3FABC /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4721BA9C55300F3FABC /* Stream.swift */; }; D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4741BA9D6A400F3FABC /* Memo.swift */; }; D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4761BA9FE6A00F3FABC /* Comparable.swift */; }; + D4413FD51BB052ED00E3C3C1 /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; + D4413FD71BB0531E00E3C3C1 /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; + D4413FD91BB0534000E3C3C1 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; + D4413FDB1BB0536700E3C3C1 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; }; + D4413FDD1BB0559400E3C3C1 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; }; + D4413FDE1BB0559400E3C3C1 /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; + D4413FE51BB055A600E3C3C1 /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; + D4413FE61BB055A800E3C3C1 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; + D4413FE81BB055AE00E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; + D4413FE91BB055B500E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; @@ -43,6 +53,11 @@ D432D4721BA9C55300F3FABC /* Stream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stream.swift; sourceTree = ""; }; D432D4741BA9D6A400F3FABC /* Memo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Memo.swift; sourceTree = ""; }; D432D4761BA9FE6A00F3FABC /* Comparable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Comparable.swift; sourceTree = ""; }; + D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SourceKittenFramework.framework; path = ../External/SourceKitten/build/Debug/SourceKittenFramework.framework; sourceTree = ""; }; + D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftXPC.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/SwiftXPC.framework"; sourceTree = ""; }; + D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SWXMLHash.framework; path = ../External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug/SWXMLHash.framework; sourceTree = ""; }; + D4413FDA1BB0536700E3C3C1 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Result.framework"; sourceTree = ""; }; + D4413FE71BB055AE00E3C3C1 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Commandant.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Commandant.framework"; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -64,6 +79,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D4413FE81BB055AE00E3C3C1 /* Commandant.framework in Frameworks */, + D4413FDB1BB0536700E3C3C1 /* Result.framework in Frameworks */, + D4413FD91BB0534000E3C3C1 /* SWXMLHash.framework in Frameworks */, + D4413FD71BB0531E00E3C3C1 /* SwiftXPC.framework in Frameworks */, + D4413FD51BB052ED00E3C3C1 /* SourceKittenFramework.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -71,7 +91,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D4413FE91BB055B500E3C3C1 /* Commandant.framework in Frameworks */, + D4413FDD1BB0559400E3C3C1 /* Result.framework in Frameworks */, + D4413FDE1BB0559400E3C3C1 /* SwiftXPC.framework in Frameworks */, D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */, + D4413FE61BB055A800E3C3C1 /* SWXMLHash.framework in Frameworks */, + D4413FE51BB055A600E3C3C1 /* SourceKittenFramework.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -121,6 +146,11 @@ D4AAE5001B5AE22E004E581F /* Supporting Files */ = { isa = PBXGroup; children = ( + D4413FE71BB055AE00E3C3C1 /* Commandant.framework */, + D4413FDA1BB0536700E3C3C1 /* Result.framework */, + D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */, + D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */, + D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */, D4AAE5011B5AE22E004E581F /* Info.plist */, ); name = "Supporting Files"; @@ -413,6 +443,8 @@ FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", + "$(PROJECT_DIR)/External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug", + "$(PROJECT_DIR)/External/SourceKitten/build/Debug", ); INFOPLIST_FILE = DoubtTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; @@ -429,6 +461,8 @@ FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", + "$(PROJECT_DIR)/External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug", + "$(PROJECT_DIR)/External/SourceKitten/build/Debug", ); INFOPLIST_FILE = DoubtTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; diff --git a/prototype/Doubt.xcworkspace/contents.xcworkspacedata b/prototype/Doubt.xcworkspace/contents.xcworkspacedata index e6ef37109..fc16a845f 100644 --- a/prototype/Doubt.xcworkspace/contents.xcworkspacedata +++ b/prototype/Doubt.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,19 @@ + + + + + + + + + + diff --git a/prototype/External/SourceKitten b/prototype/External/SourceKitten new file mode 160000 index 000000000..5981d19d5 --- /dev/null +++ b/prototype/External/SourceKitten @@ -0,0 +1 @@ +Subproject commit 5981d19d53cccff7ab3b5b9b7533a875d89e7875 From c1f9dd3dd76e7257de08b716e93ec05a1f074d41 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 11:17:19 -0400 Subject: [PATCH 034/138] Xcode loves breaking search paths. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 943e45e07..51bb421f0 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -443,8 +443,6 @@ FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", - "$(PROJECT_DIR)/External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug", - "$(PROJECT_DIR)/External/SourceKitten/build/Debug", ); INFOPLIST_FILE = DoubtTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; @@ -461,8 +459,6 @@ FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", - "$(PROJECT_DIR)/External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug", - "$(PROJECT_DIR)/External/SourceKitten/build/Debug", ); INFOPLIST_FILE = DoubtTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; From 3ff518ac46255390f67fe0a0fdf77a2a56b83461 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:19:42 -0400 Subject: [PATCH 035/138] Add a dictionary constructor over key/value pairs. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 ++++ prototype/Doubt/Dictionary.swift | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 prototype/Doubt/Dictionary.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 51bb421f0..cbe851264 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ D4413FE61BB055A800E3C3C1 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; D4413FE81BB055AE00E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; D4413FE91BB055B500E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; + D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; @@ -58,6 +59,7 @@ D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SWXMLHash.framework; path = ../External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug/SWXMLHash.framework; sourceTree = ""; }; D4413FDA1BB0536700E3C3C1 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Result.framework"; sourceTree = ""; }; D4413FE71BB055AE00E3C3C1 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Commandant.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Commandant.framework"; sourceTree = ""; }; + D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -138,6 +140,7 @@ D432D4721BA9C55300F3FABC /* Stream.swift */, D432D4741BA9D6A400F3FABC /* Memo.swift */, D40024EB1BAC62BA00A110B8 /* Swift.swift */, + D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, ); path = Doubt; @@ -274,6 +277,7 @@ buildActionMask = 2147483647; files = ( D4AAE5471B5AE2D0004E581F /* Prelude.swift in Sources */, + D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */, D4AAE5481B5AE2D0004E581F /* String.swift in Sources */, D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */, D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */, diff --git a/prototype/Doubt/Dictionary.swift b/prototype/Doubt/Dictionary.swift new file mode 100644 index 000000000..dd8f38c09 --- /dev/null +++ b/prototype/Doubt/Dictionary.swift @@ -0,0 +1,8 @@ +extension Dictionary { + init(elements: C) { + self.init(minimumCapacity: Int(elements.count.toIntMax())) + for (key, value) in elements { + self[key] = value + } + } +} From 8625c90aaa25d0f77a3cf916fbd15e33352a0f7a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:19:49 -0400 Subject: [PATCH 036/138] Add Prisms. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 ++++ prototype/Doubt/Prism.swift | 14 ++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 prototype/Doubt/Prism.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index cbe851264..645eeab48 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ D4413FE61BB055A800E3C3C1 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; D4413FE81BB055AE00E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; D4413FE91BB055B500E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; + D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEC1BB0652300E3C3C1 /* Prism.swift */; }; D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; @@ -59,6 +60,7 @@ D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SWXMLHash.framework; path = ../External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug/SWXMLHash.framework; sourceTree = ""; }; D4413FDA1BB0536700E3C3C1 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Result.framework"; sourceTree = ""; }; D4413FE71BB055AE00E3C3C1 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Commandant.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Commandant.framework"; sourceTree = ""; }; + D4413FEC1BB0652300E3C3C1 /* Prism.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prism.swift; sourceTree = ""; }; D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -140,6 +142,7 @@ D432D4721BA9C55300F3FABC /* Stream.swift */, D432D4741BA9D6A400F3FABC /* Memo.swift */, D40024EB1BAC62BA00A110B8 /* Swift.swift */, + D4413FEC1BB0652300E3C3C1 /* Prism.swift */, D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, ); @@ -286,6 +289,7 @@ D432D4731BA9C55300F3FABC /* Stream.swift in Sources */, D4AAE5421B5AE2D0004E581F /* Doc.swift in Sources */, D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */, + D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */, D4AAE5461B5AE2D0004E581F /* Parse.swift in Sources */, D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift new file mode 100644 index 000000000..f9d5ecd78 --- /dev/null +++ b/prototype/Doubt/Prism.swift @@ -0,0 +1,14 @@ +struct Prism { + let forward: From -> To? + let backward: To -> From +} + +extension Dictionary { + static func prism(key: Key) -> Prism<[Key:Value], Value> { + return Prism(forward: { $0[key] }, backward: { [key: $0] }) + } +} + +func >>> (left: Prism, right: Prism) -> Prism { + return Prism(forward: { left.forward($0).flatMap(right.forward) }, backward: right.backward >>> left.backward) +} From 700a7004c443faee118554f90930e4cd5e59fc3f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:20:33 -0400 Subject: [PATCH 037/138] Add a representation of JSON & prisms for encoding/casting. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 + prototype/Doubt/JSON.swift | 93 +++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 prototype/Doubt/JSON.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 645eeab48..0d461c6da 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ D4413FE91BB055B500E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEC1BB0652300E3C3C1 /* Prism.swift */; }; D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; + D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; @@ -62,6 +63,7 @@ D4413FE71BB055AE00E3C3C1 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Commandant.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Commandant.framework"; sourceTree = ""; }; D4413FEC1BB0652300E3C3C1 /* Prism.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prism.swift; sourceTree = ""; }; D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; + D4413FF01BB08FDC00E3C3C1 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -144,6 +146,7 @@ D40024EB1BAC62BA00A110B8 /* Swift.swift */, D4413FEC1BB0652300E3C3C1 /* Prism.swift */, D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, + D4413FF01BB08FDC00E3C3C1 /* JSON.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, ); path = Doubt; @@ -293,6 +296,7 @@ D4AAE5461B5AE2D0004E581F /* Parse.swift in Sources */, D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, + D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */, D40024EC1BAC62BA00A110B8 /* Swift.swift in Sources */, D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */, ); diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift new file mode 100644 index 000000000..ac113b4a9 --- /dev/null +++ b/prototype/Doubt/JSON.swift @@ -0,0 +1,93 @@ +enum JSON { + case Number(Double) + case Boolean(Bool) + case String(Swift.String) + case Array([JSON]) + case Dictionary([Swift.String:JSON]) + case Null + + var number: Double? { + if case let .Number(d) = self { return d } + return nil + } + + var boolean: Bool? { + if case let .Boolean(b) = self { return b } + return nil + } + + var string: Swift.String? { + if case let .String(s) = self { return s } + return nil + } + + var array: [JSON]? { + if case let .Array(a) = self { return a } + return nil + } + + var dictionary: [Swift.String:JSON]? { + if case let .Dictionary(d) = self { return d } + return nil + } + + var isNull: Bool { + if case .Null = self { return true } + return false + } + + enum Prisms { + static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) + + static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) + static let boolean: Prism = Prism(forward: { $0.boolean }, backward: { .Boolean($0) }) + static let string: Prism = Prism(forward: { $0.string }, backward: { .String($0) }) + static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) + static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) + } +} + +func toJSON(object: AnyObject) -> JSON? { + struct E: ErrorType {} + func die() throws -> T { + throw E() + } + do { + switch object { + case let n as Double: + return JSON.Number(n) + case let b as Bool: + return JSON.Boolean(b) + case let s as String: + return JSON.String(s) + case let a as [AnyObject]: + return JSON.Array(try a.map { try toJSON($0) ?? die() }) + case let d as [String:AnyObject]: + return JSON.Dictionary(Dictionary(elements: try d.map { ($0, try toJSON($1) ?? die()) })) + case is NSNull: + return JSON.Null + default: + return nil + } + } catch { return nil } +} + +func toAnyObject(json: JSON) -> AnyObject { + switch json { + case let .Number(n): + return n + case let .Boolean(b): + return b + case let .String(s): + return s + case let .Array(a): + return a.map(toAnyObject) + case let .Dictionary(d): + return Dictionary(elements: d.map { ($0, toAnyObject($1)) }) + case .Null: + return NSNull() + } +} + + +import Foundation From fb48f885759bfa2e2d4d9ebde37194732739f735 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:21:09 -0400 Subject: [PATCH 038/138] Move the prisms into the JSON namespace. --- prototype/Doubt/JSON.swift | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index ac113b4a9..b358ae6a6 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -2,8 +2,8 @@ enum JSON { case Number(Double) case Boolean(Bool) case String(Swift.String) - case Array([JSON]) - case Dictionary([Swift.String:JSON]) + case Array([Doubt.JSON]) + case Dictionary([Swift.String:Doubt.JSON]) case Null var number: Double? { @@ -21,12 +21,12 @@ enum JSON { return nil } - var array: [JSON]? { + var array: [Doubt.JSON]? { if case let .Array(a) = self { return a } return nil } - var dictionary: [Swift.String:JSON]? { + var dictionary: [Swift.String:Doubt.JSON]? { if case let .Dictionary(d) = self { return d } return nil } @@ -36,15 +36,13 @@ enum JSON { return false } - enum Prisms { - static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) + static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) - static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) - static let boolean: Prism = Prism(forward: { $0.boolean }, backward: { .Boolean($0) }) - static let string: Prism = Prism(forward: { $0.string }, backward: { .String($0) }) - static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) - static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) - } + static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) + static let boolean: Prism = Prism(forward: { $0.boolean }, backward: { .Boolean($0) }) + static let string: Prism = Prism(forward: { $0.string }, backward: { .String($0) }) + static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) + static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) } func toJSON(object: AnyObject) -> JSON? { From 21e1b7e3e903b345a5d07f1348eced008c77e114 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:21:31 -0400 Subject: [PATCH 039/138] toJSON/toAnyObject are private. --- prototype/Doubt/JSON.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index b358ae6a6..e17a1353f 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -45,7 +45,7 @@ enum JSON { static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) } -func toJSON(object: AnyObject) -> JSON? { +private func toJSON(object: AnyObject) -> JSON? { struct E: ErrorType {} func die() throws -> T { throw E() @@ -70,7 +70,7 @@ func toJSON(object: AnyObject) -> JSON? { } catch { return nil } } -func toAnyObject(json: JSON) -> AnyObject { +private func toAnyObject(json: JSON) -> AnyObject { switch json { case let .Number(n): return n From e989c8aac5d589ea0a8878b5b63db454a86687d5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:22:14 -0400 Subject: [PATCH 040/138] Prism & its concatenation are public. --- prototype/Doubt/Prism.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index f9d5ecd78..6d55468ec 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -1,4 +1,4 @@ -struct Prism { +public struct Prism { let forward: From -> To? let backward: To -> From } @@ -9,6 +9,6 @@ extension Dictionary { } } -func >>> (left: Prism, right: Prism) -> Prism { +public func >>> (left: Prism, right: Prism) -> Prism { return Prism(forward: { left.forward($0).flatMap(right.forward) }, backward: right.backward >>> left.backward) } From 78ae28a1ae024400e3c25912818506267c9ef6a3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:22:55 -0400 Subject: [PATCH 041/138] forward/backward are public. --- prototype/Doubt/Prism.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index 6d55468ec..9e5fefe57 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -1,6 +1,6 @@ public struct Prism { - let forward: From -> To? - let backward: To -> From + public let forward: From -> To? + public let backward: To -> From } extension Dictionary { From d82acf8b9fd886246bb412efa7283f49925cfd2e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:23:01 -0400 Subject: [PATCH 042/138] Add a public constructor. --- prototype/Doubt/Prism.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index 9e5fefe57..ec78cfe7e 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -1,4 +1,9 @@ public struct Prism { + public init(forward: From -> To?, backward: To -> From) { + self.forward = forward + self.backward = backward + } + public let forward: From -> To? public let backward: To -> From } From a787679652e46f76028f6445387a371a54c79c5c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:23:16 -0400 Subject: [PATCH 043/138] JSON is public. --- prototype/Doubt/JSON.swift | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index e17a1353f..a4c3c1230 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -1,4 +1,4 @@ -enum JSON { +public enum JSON { case Number(Double) case Boolean(Bool) case String(Swift.String) @@ -6,43 +6,43 @@ enum JSON { case Dictionary([Swift.String:Doubt.JSON]) case Null - var number: Double? { + public var number: Double? { if case let .Number(d) = self { return d } return nil } - var boolean: Bool? { + public var boolean: Bool? { if case let .Boolean(b) = self { return b } return nil } - var string: Swift.String? { + public var string: Swift.String? { if case let .String(s) = self { return s } return nil } - var array: [Doubt.JSON]? { + public var array: [Doubt.JSON]? { if case let .Array(a) = self { return a } return nil } - var dictionary: [Swift.String:Doubt.JSON]? { + public var dictionary: [Swift.String:Doubt.JSON]? { if case let .Dictionary(d) = self { return d } return nil } - var isNull: Bool { + public var isNull: Bool { if case .Null = self { return true } return false } - static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) + public static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) - static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) - static let boolean: Prism = Prism(forward: { $0.boolean }, backward: { .Boolean($0) }) - static let string: Prism = Prism(forward: { $0.string }, backward: { .String($0) }) - static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) - static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) + public static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) + public static let boolean: Prism = Prism(forward: { $0.boolean }, backward: { .Boolean($0) }) + public static let string: Prism = Prism(forward: { $0.string }, backward: { .String($0) }) + public static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) + public static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) } private func toJSON(object: AnyObject) -> JSON? { From c03c01f7263bc627e856f4bf8ca0097c4a9fad18 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:29:27 -0400 Subject: [PATCH 044/138] Typealiases for array/dictionary types. --- prototype/Doubt/JSON.swift | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index a4c3c1230..b7d30e528 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -1,11 +1,15 @@ public enum JSON { + public typealias ArrayType = [Doubt.JSON] + public typealias DictionaryType = [Swift.String:Doubt.JSON] + case Number(Double) case Boolean(Bool) case String(Swift.String) - case Array([Doubt.JSON]) - case Dictionary([Swift.String:Doubt.JSON]) + case Array(ArrayType) + case Dictionary(DictionaryType) case Null + public var number: Double? { if case let .Number(d) = self { return d } return nil @@ -21,12 +25,12 @@ public enum JSON { return nil } - public var array: [Doubt.JSON]? { + public var array: ArrayType? { if case let .Array(a) = self { return a } return nil } - public var dictionary: [Swift.String:Doubt.JSON]? { + public var dictionary: DictionaryType? { if case let .Dictionary(d) = self { return d } return nil } @@ -41,8 +45,8 @@ public enum JSON { public static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) public static let boolean: Prism = Prism(forward: { $0.boolean }, backward: { .Boolean($0) }) public static let string: Prism = Prism(forward: { $0.string }, backward: { .String($0) }) - public static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) - public static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) + public static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) + public static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) } private func toJSON(object: AnyObject) -> JSON? { From 4f97a6bc4a693c217a21df7fa374a75ecb8183d1 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:40:43 -0400 Subject: [PATCH 045/138] Subscripting Prism by K returns Prism. --- prototype/Doubt/JSON.swift | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index b7d30e528..0dc52dde5 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -49,6 +49,30 @@ public enum JSON { public static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) } +protocol DictionaryType { + typealias Key : Hashable + typealias Value + + init(dictionary: [Key:Value]) + var dictionary: [Key:Value] { get } +} + +extension Dictionary: DictionaryType { + init(dictionary: [Key:Value]) { + self = dictionary + } + + var dictionary: [Key:Value] { + return self + } +} + +extension Prism where To : DictionaryType { + subscript (key: To.Key) -> Prism { + return self >>> Prism(forward: { $0.dictionary[key] }, backward: { To(dictionary: [key: $0]) }) + } +} + private func toJSON(object: AnyObject) -> JSON? { struct E: ErrorType {} func die() throws -> T { From 0eca41946897c7fbf85aa3e38a160ffd427c6093 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:41:01 -0400 Subject: [PATCH 046/138] Subscripting Prism by Int produces Prism. --- prototype/Doubt/JSON.swift | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index 0dc52dde5..8d34e6fe2 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -73,6 +73,29 @@ extension Prism where To : DictionaryType { } } +protocol ArrayType { + typealias Element + + init(array: [Element]) + var array: [Element] { get } +} + +extension Array : ArrayType { + init(array: [Element]) { + self = array + } + + var array: [Element] { + return self + } +} + +extension Prism where To : ArrayType { + subscript (index: Int) -> Prism { + return self >>> Prism(forward: { $0.array[index] }, backward: { To(array: [ $0 ]) }) + } +} + private func toJSON(object: AnyObject) -> JSON? { struct E: ErrorType {} func die() throws -> T { From fda61501e1abdf61be41f15a7a5e02d21f59b7ff Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:42:07 -0400 Subject: [PATCH 047/138] Array Prism subscripting is safe. --- prototype/Doubt/JSON.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index 8d34e6fe2..ec35a8fb9 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -92,7 +92,12 @@ extension Array : ArrayType { extension Prism where To : ArrayType { subscript (index: Int) -> Prism { - return self >>> Prism(forward: { $0.array[index] }, backward: { To(array: [ $0 ]) }) + return self >>> Prism( + forward: { + let array = $0.array + return array.count > index ? array[index] : nil + }, + backward: { To(array: [ $0 ]) }) } } From 92482ddbaba6b8ec958f8730066e918e031502a6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:53:30 -0400 Subject: [PATCH 048/138] Replace (most of) the static Prisms with properties in a constrained extension on Prism. --- prototype/Doubt/JSON.swift | 41 +++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index ec35a8fb9..d6ca2807b 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -41,12 +41,43 @@ public enum JSON { } public static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) +} - public static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) - public static let boolean: Prism = Prism(forward: { $0.boolean }, backward: { .Boolean($0) }) - public static let string: Prism = Prism(forward: { $0.string }, backward: { .String($0) }) - public static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) - public static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) +protocol JSONConvertible { + init(JSON: Doubt.JSON) + var JSON: Doubt.JSON { get } +} + +extension JSON: JSONConvertible { + init(JSON: Doubt.JSON) { + self = JSON + } + + var JSON: Doubt.JSON { + return self + } +} + +extension Prism where To : JSONConvertible { + var number: Prism { + return self >>> Prism(forward: { $0.JSON.number }, backward: { To(JSON: .Number($0)) }) + } + + var boolean: Prism { + return self >>> Prism(forward: { $0.JSON.boolean }, backward: { To(JSON: .Boolean($0)) }) + } + + var string: Prism { + return self >>> Prism(forward: { $0.JSON.string }, backward: { To(JSON: .String($0)) }) + } + + var array: Prism { + return self >>> Prism(forward: { $0.JSON.array }, backward: { To(JSON: .Array($0)) }) + } + + var dictionary: Prism { + return self >>> Prism(forward: { $0.JSON.dictionary }, backward: { To(JSON: .Dictionary($0)) }) + } } protocol DictionaryType { From 20a75201815ee86b33819787288bb7854652124d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:59:17 -0400 Subject: [PATCH 049/138] Move dictionary/array extensions into Prism. --- prototype/Doubt/JSON.swift | 51 ----------------------------------- prototype/Doubt/Prism.swift | 53 +++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 51 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index d6ca2807b..8e3e1e36c 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -80,57 +80,6 @@ extension Prism where To : JSONConvertible { } } -protocol DictionaryType { - typealias Key : Hashable - typealias Value - - init(dictionary: [Key:Value]) - var dictionary: [Key:Value] { get } -} - -extension Dictionary: DictionaryType { - init(dictionary: [Key:Value]) { - self = dictionary - } - - var dictionary: [Key:Value] { - return self - } -} - -extension Prism where To : DictionaryType { - subscript (key: To.Key) -> Prism { - return self >>> Prism(forward: { $0.dictionary[key] }, backward: { To(dictionary: [key: $0]) }) - } -} - -protocol ArrayType { - typealias Element - - init(array: [Element]) - var array: [Element] { get } -} - -extension Array : ArrayType { - init(array: [Element]) { - self = array - } - - var array: [Element] { - return self - } -} - -extension Prism where To : ArrayType { - subscript (index: Int) -> Prism { - return self >>> Prism( - forward: { - let array = $0.array - return array.count > index ? array[index] : nil - }, - backward: { To(array: [ $0 ]) }) - } -} private func toJSON(object: AnyObject) -> JSON? { struct E: ErrorType {} diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index ec78cfe7e..9ea71439b 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -17,3 +17,56 @@ extension Dictionary { public func >>> (left: Prism, right: Prism) -> Prism { return Prism(forward: { left.forward($0).flatMap(right.forward) }, backward: right.backward >>> left.backward) } + + +protocol DictionaryType { + typealias Key : Hashable + typealias Value + + init(dictionary: [Key:Value]) + var dictionary: [Key:Value] { get } +} + +extension Dictionary: DictionaryType { + init(dictionary: [Key:Value]) { + self = dictionary + } + + var dictionary: [Key:Value] { + return self + } +} + +extension Prism where To : DictionaryType { + subscript (key: To.Key) -> Prism { + return self >>> Prism(forward: { $0.dictionary[key] }, backward: { To(dictionary: [key: $0]) }) + } +} + +protocol ArrayType { + typealias Element + + init(array: [Element]) + var array: [Element] { get } +} + +extension Array : ArrayType { + init(array: [Element]) { + self = array + } + + var array: [Element] { + return self + } +} + +extension Prism where To : ArrayType { + subscript (index: Int) -> Prism { + return self >>> Prism( + forward: { + let array = $0.array + return array.count > index ? array[index] : nil + }, + backward: { To(array: [ $0 ]) }) + } +} From 3efd234eea8b193f0ae4ba079911653175044918 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 15:59:52 -0400 Subject: [PATCH 050/138] Dictionary/array extensions are public. --- prototype/Doubt/Prism.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index 9ea71439b..5f2d96a64 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -19,7 +19,7 @@ public func >>> (left: Prism, right: Prism Prism { + public subscript (key: To.Key) -> Prism { return self >>> Prism(forward: { $0.dictionary[key] }, backward: { To(dictionary: [key: $0]) }) } } -protocol ArrayType { +public protocol ArrayType { typealias Element init(array: [Element]) @@ -51,17 +51,17 @@ protocol ArrayType { } extension Array : ArrayType { - init(array: [Element]) { + public init(array: [Element]) { self = array } - var array: [Element] { + public var array: [Element] { return self } } extension Prism where To : ArrayType { - subscript (index: Int) -> Prism { + public subscript (index: Int) -> Prism { return self >>> Prism( forward: { let array = $0.array From 1f3d05ae2313d13ce0f4b20a03e3fc43f705d857 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:05:29 -0400 Subject: [PATCH 051/138] Add Iso. --- prototype/Doubt/Prism.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index 5f2d96a64..661d5f1c9 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -70,3 +70,14 @@ extension Prism where To : ArrayType { backward: { To(array: [ $0 ]) }) } } + + +public struct Iso { + public init(forward: Here -> There, backward: There -> Here) { + self.forward = forward + self.backward = backward + } + + public let forward: Here -> There + public let backward: There -> Here +} From 7e40055294b4e0936fc09c79a578aa205a4f2d09 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:05:58 -0400 Subject: [PATCH 052/138] Add .map to Prisms taking an Iso. --- prototype/Doubt/Prism.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index 661d5f1c9..54ace8450 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -81,3 +81,12 @@ public struct Iso { public let forward: Here -> There public let backward: There -> Here } + + +extension Prism where To : ArrayType { + public func map(transform: Iso) -> Prism { + return Prism( + forward: { self.forward($0)?.array.map(transform.forward) }, + backward: { self.backward(To(array: $0.map(transform.backward))) }) + } +} From 0ca911e6037d9b2ba9e7366cba68c85b85e09e6e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:08:43 -0400 Subject: [PATCH 053/138] JSON/Prism extensions are public. --- prototype/Doubt/JSON.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index 8e3e1e36c..b45c7a2d7 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -43,39 +43,39 @@ public enum JSON { public static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) } -protocol JSONConvertible { +public protocol JSONConvertible { init(JSON: Doubt.JSON) var JSON: Doubt.JSON { get } } extension JSON: JSONConvertible { - init(JSON: Doubt.JSON) { + public init(JSON: Doubt.JSON) { self = JSON } - var JSON: Doubt.JSON { + public var JSON: Doubt.JSON { return self } } extension Prism where To : JSONConvertible { - var number: Prism { + public var number: Prism { return self >>> Prism(forward: { $0.JSON.number }, backward: { To(JSON: .Number($0)) }) } - var boolean: Prism { + public var boolean: Prism { return self >>> Prism(forward: { $0.JSON.boolean }, backward: { To(JSON: .Boolean($0)) }) } - var string: Prism { + public var string: Prism { return self >>> Prism(forward: { $0.JSON.string }, backward: { To(JSON: .String($0)) }) } - var array: Prism { + public var array: Prism { return self >>> Prism(forward: { $0.JSON.array }, backward: { To(JSON: .Array($0)) }) } - var dictionary: Prism { + public var dictionary: Prism { return self >>> Prism(forward: { $0.JSON.dictionary }, backward: { To(JSON: .Dictionary($0)) }) } } From b5efc49129e300512d9f3e83a345c24af128dc9f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:25:34 -0400 Subject: [PATCH 054/138] Restore the static prisms. --- prototype/Doubt/JSON.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index b45c7a2d7..5f7b9c56d 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -41,6 +41,12 @@ public enum JSON { } public static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) + + public static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) + public static let boolean: Prism = Prism(forward: { $0.boolean }, backward: { .Boolean($0) }) + public static let string: Prism = Prism(forward: { $0.string }, backward: { .String($0) }) + public static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) + public static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) } public protocol JSONConvertible { From 806ea1ea93adb773d726d2330fa72e0041ca9caf Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:27:45 -0400 Subject: [PATCH 055/138] Add a JSONConverter property to JSONConvertibles. --- prototype/Doubt/JSON.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index 5f7b9c56d..06ff192fb 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -64,6 +64,12 @@ extension JSON: JSONConvertible { } } +extension JSONConvertible { + static var JSONConverter: Prism { + return Prism(forward: { $0.JSON }, backward: { Self(JSON: $0) }) + } +} + extension Prism where To : JSONConvertible { public var number: Prism { return self >>> Prism(forward: { $0.JSON.number }, backward: { To(JSON: .Number($0)) }) From 1ec7e5b06c7d4ea6dc5fad0c551170d5a2c7bb47 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:28:04 -0400 Subject: [PATCH 056/138] Extension methods use the converter and wrap the static prisms. --- prototype/Doubt/JSON.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index 06ff192fb..6ebcd9922 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -72,23 +72,23 @@ extension JSONConvertible { extension Prism where To : JSONConvertible { public var number: Prism { - return self >>> Prism(forward: { $0.JSON.number }, backward: { To(JSON: .Number($0)) }) + return self >>> To.JSONConverter >>> Doubt.JSON.number } public var boolean: Prism { - return self >>> Prism(forward: { $0.JSON.boolean }, backward: { To(JSON: .Boolean($0)) }) + return self >>> To.JSONConverter >>> Doubt.JSON.boolean } public var string: Prism { - return self >>> Prism(forward: { $0.JSON.string }, backward: { To(JSON: .String($0)) }) + return self >>> To.JSONConverter >>> Doubt.JSON.string } public var array: Prism { - return self >>> Prism(forward: { $0.JSON.array }, backward: { To(JSON: .Array($0)) }) + return self >>> To.JSONConverter >>> Doubt.JSON.array } public var dictionary: Prism { - return self >>> Prism(forward: { $0.JSON.dictionary }, backward: { To(JSON: .Dictionary($0)) }) + return self >>> To.JSONConverter >>> Doubt.JSON.dictionary } } From 56569eeb73b7ddf281baddd5b9ea58eab80d6818 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:42:52 -0400 Subject: [PATCH 057/138] Move ArrayType to its own file. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 ++++ prototype/Doubt/ArrayType.swift | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 prototype/Doubt/ArrayType.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 0d461c6da..63b49e330 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEC1BB0652300E3C3C1 /* Prism.swift */; }; D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; + D4413FF31BB0A33600E3C3C1 /* ArrayType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF21BB0A33600E3C3C1 /* ArrayType.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; @@ -64,6 +65,7 @@ D4413FEC1BB0652300E3C3C1 /* Prism.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prism.swift; sourceTree = ""; }; D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4413FF01BB08FDC00E3C3C1 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; + D4413FF21BB0A33600E3C3C1 /* ArrayType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayType.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -147,6 +149,7 @@ D4413FEC1BB0652300E3C3C1 /* Prism.swift */, D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, D4413FF01BB08FDC00E3C3C1 /* JSON.swift */, + D4413FF21BB0A33600E3C3C1 /* ArrayType.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, ); path = Doubt; @@ -293,6 +296,7 @@ D4AAE5421B5AE2D0004E581F /* Doc.swift in Sources */, D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */, D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */, + D4413FF31BB0A33600E3C3C1 /* ArrayType.swift in Sources */, D4AAE5461B5AE2D0004E581F /* Parse.swift in Sources */, D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, diff --git a/prototype/Doubt/ArrayType.swift b/prototype/Doubt/ArrayType.swift new file mode 100644 index 000000000..f926ca084 --- /dev/null +++ b/prototype/Doubt/ArrayType.swift @@ -0,0 +1,16 @@ +public protocol ArrayType { + typealias Element + + init(array: [Element]) + var array: [Element] { get } +} + +extension Array : ArrayType { + public init(array: [Element]) { + self = array + } + + public var array: [Element] { + return self + } +} From 07d01dc79aa358ff269e9cc426b54c8e0fe23582 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:43:22 -0400 Subject: [PATCH 058/138] Move DictionaryType to its own file. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 ++++ prototype/Doubt/DictionaryType.swift | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 prototype/Doubt/DictionaryType.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 63b49e330..e9a5b3c50 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; D4413FF31BB0A33600E3C3C1 /* ArrayType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF21BB0A33600E3C3C1 /* ArrayType.swift */; }; + D4413FF51BB0A35F00E3C3C1 /* DictionaryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF41BB0A35F00E3C3C1 /* DictionaryType.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; @@ -66,6 +67,7 @@ D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4413FF01BB08FDC00E3C3C1 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; D4413FF21BB0A33600E3C3C1 /* ArrayType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayType.swift; sourceTree = ""; }; + D4413FF41BB0A35F00E3C3C1 /* DictionaryType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryType.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -150,6 +152,7 @@ D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, D4413FF01BB08FDC00E3C3C1 /* JSON.swift */, D4413FF21BB0A33600E3C3C1 /* ArrayType.swift */, + D4413FF41BB0A35F00E3C3C1 /* DictionaryType.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, ); path = Doubt; @@ -292,6 +295,7 @@ D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */, D4AAE54C1B5AE42D004E581F /* Equatable.swift in Sources */, D4AAE54A1B5AE2D0004E581F /* Syntax.swift in Sources */, + D4413FF51BB0A35F00E3C3C1 /* DictionaryType.swift in Sources */, D432D4731BA9C55300F3FABC /* Stream.swift in Sources */, D4AAE5421B5AE2D0004E581F /* Doc.swift in Sources */, D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */, diff --git a/prototype/Doubt/DictionaryType.swift b/prototype/Doubt/DictionaryType.swift new file mode 100644 index 000000000..3172a7bf0 --- /dev/null +++ b/prototype/Doubt/DictionaryType.swift @@ -0,0 +1,17 @@ +public protocol DictionaryType { + typealias Key : Hashable + typealias Value + + init(dictionary: [Key:Value]) + var dictionary: [Key:Value] { get } +} + +extension Dictionary: DictionaryType { + public init(dictionary: [Key:Value]) { + self = dictionary + } + + public var dictionary: [Key:Value] { + return self + } +} From ddc020c774eb9ec1540c457be0aeaa0e4a6f90c7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:44:24 -0400 Subject: [PATCH 059/138] Rename Array/DictionaryType to Array/DictionaryConvertible. --- prototype/Doubt.xcodeproj/project.pbxproj | 16 ++++---- ...ArrayType.swift => ArrayConvertible.swift} | 4 +- ...Type.swift => DictionaryConvertible.swift} | 4 +- prototype/Doubt/Prism.swift | 39 +------------------ 4 files changed, 14 insertions(+), 49 deletions(-) rename prototype/Doubt/{ArrayType.swift => ArrayConvertible.swift} (71%) rename prototype/Doubt/{DictionaryType.swift => DictionaryConvertible.swift} (73%) diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index e9a5b3c50..f7a6a1909 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -26,8 +26,8 @@ D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEC1BB0652300E3C3C1 /* Prism.swift */; }; D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; - D4413FF31BB0A33600E3C3C1 /* ArrayType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF21BB0A33600E3C3C1 /* ArrayType.swift */; }; - D4413FF51BB0A35F00E3C3C1 /* DictionaryType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF41BB0A35F00E3C3C1 /* DictionaryType.swift */; }; + D4413FF31BB0A33600E3C3C1 /* ArrayConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF21BB0A33600E3C3C1 /* ArrayConvertible.swift */; }; + D4413FF51BB0A35F00E3C3C1 /* DictionaryConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF41BB0A35F00E3C3C1 /* DictionaryConvertible.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; @@ -66,8 +66,8 @@ D4413FEC1BB0652300E3C3C1 /* Prism.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prism.swift; sourceTree = ""; }; D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4413FF01BB08FDC00E3C3C1 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; - D4413FF21BB0A33600E3C3C1 /* ArrayType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayType.swift; sourceTree = ""; }; - D4413FF41BB0A35F00E3C3C1 /* DictionaryType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryType.swift; sourceTree = ""; }; + D4413FF21BB0A33600E3C3C1 /* ArrayConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayConvertible.swift; sourceTree = ""; }; + D4413FF41BB0A35F00E3C3C1 /* DictionaryConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryConvertible.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -151,8 +151,8 @@ D4413FEC1BB0652300E3C3C1 /* Prism.swift */, D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, D4413FF01BB08FDC00E3C3C1 /* JSON.swift */, - D4413FF21BB0A33600E3C3C1 /* ArrayType.swift */, - D4413FF41BB0A35F00E3C3C1 /* DictionaryType.swift */, + D4413FF21BB0A33600E3C3C1 /* ArrayConvertible.swift */, + D4413FF41BB0A35F00E3C3C1 /* DictionaryConvertible.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, ); path = Doubt; @@ -295,12 +295,12 @@ D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */, D4AAE54C1B5AE42D004E581F /* Equatable.swift in Sources */, D4AAE54A1B5AE2D0004E581F /* Syntax.swift in Sources */, - D4413FF51BB0A35F00E3C3C1 /* DictionaryType.swift in Sources */, + D4413FF51BB0A35F00E3C3C1 /* DictionaryConvertible.swift in Sources */, D432D4731BA9C55300F3FABC /* Stream.swift in Sources */, D4AAE5421B5AE2D0004E581F /* Doc.swift in Sources */, D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */, D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */, - D4413FF31BB0A33600E3C3C1 /* ArrayType.swift in Sources */, + D4413FF31BB0A33600E3C3C1 /* ArrayConvertible.swift in Sources */, D4AAE5461B5AE2D0004E581F /* Parse.swift in Sources */, D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, diff --git a/prototype/Doubt/ArrayType.swift b/prototype/Doubt/ArrayConvertible.swift similarity index 71% rename from prototype/Doubt/ArrayType.swift rename to prototype/Doubt/ArrayConvertible.swift index f926ca084..be1281f5c 100644 --- a/prototype/Doubt/ArrayType.swift +++ b/prototype/Doubt/ArrayConvertible.swift @@ -1,11 +1,11 @@ -public protocol ArrayType { +public protocol ArrayConvertible { typealias Element init(array: [Element]) var array: [Element] { get } } -extension Array : ArrayType { +extension Array : ArrayConvertible { public init(array: [Element]) { self = array } diff --git a/prototype/Doubt/DictionaryType.swift b/prototype/Doubt/DictionaryConvertible.swift similarity index 73% rename from prototype/Doubt/DictionaryType.swift rename to prototype/Doubt/DictionaryConvertible.swift index 3172a7bf0..798147af2 100644 --- a/prototype/Doubt/DictionaryType.swift +++ b/prototype/Doubt/DictionaryConvertible.swift @@ -1,4 +1,4 @@ -public protocol DictionaryType { +public protocol DictionaryConvertible { typealias Key : Hashable typealias Value @@ -6,7 +6,7 @@ public protocol DictionaryType { var dictionary: [Key:Value] { get } } -extension Dictionary: DictionaryType { +extension Dictionary: DictionaryConvertible { public init(dictionary: [Key:Value]) { self = dictionary } diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index 54ace8450..3d831b408 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -19,48 +19,13 @@ public func >>> (left: Prism, right: Prism Prism { return self >>> Prism(forward: { $0.dictionary[key] }, backward: { To(dictionary: [key: $0]) }) } } -public protocol ArrayType { - typealias Element - - init(array: [Element]) - var array: [Element] { get } -} - -extension Array : ArrayType { - public init(array: [Element]) { - self = array - } - - public var array: [Element] { - return self - } -} - -extension Prism where To : ArrayType { +extension Prism where To : ArrayConvertible { public subscript (index: Int) -> Prism { return self >>> Prism( forward: { From 83e3c8e23220538ed33ece98d17ae17bf0a95f48 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:45:45 -0400 Subject: [PATCH 060/138] Missed a rename. --- prototype/Doubt/Prism.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index 3d831b408..15299821c 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -48,7 +48,7 @@ public struct Iso { } -extension Prism where To : ArrayType { +extension Prism where To : ArrayConvertible { public func map(transform: Iso) -> Prism { return Prism( forward: { self.forward($0)?.array.map(transform.forward) }, From 13f1d70071103825523b5c3967b25e9f8c0d0dd1 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:45:52 -0400 Subject: [PATCH 061/138] =?UTF-8?q?We=20really=20don=E2=80=99t=20need=20th?= =?UTF-8?q?is=20old=20thing.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prototype/Doubt/Prism.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index 15299821c..642fab688 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -8,12 +8,6 @@ public struct Prism { public let backward: To -> From } -extension Dictionary { - static func prism(key: Key) -> Prism<[Key:Value], Value> { - return Prism(forward: { $0[key] }, backward: { [key: $0] }) - } -} - public func >>> (left: Prism, right: Prism) -> Prism { return Prism(forward: { left.forward($0).flatMap(right.forward) }, backward: right.backward >>> left.backward) } From 5daa7d4398803cd2f07b7b6bcf29bcee2e0ad167 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:46:32 -0400 Subject: [PATCH 062/138] =?UTF-8?q?Don=E2=80=99t=20bother=20with=20Iso.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prototype/Doubt/Prism.swift | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index 642fab688..bfb445e71 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -28,24 +28,10 @@ extension Prism where To : ArrayConvertible { }, backward: { To(array: [ $0 ]) }) } -} - -public struct Iso { - public init(forward: Here -> There, backward: There -> Here) { - self.forward = forward - self.backward = backward - } - - public let forward: Here -> There - public let backward: There -> Here -} - - -extension Prism where To : ArrayConvertible { - public func map(transform: Iso) -> Prism { + public func map(transform: Prism) -> Prism { return Prism( - forward: { self.forward($0)?.array.map(transform.forward) }, + forward: { self.forward($0)?.array.flatMap(transform.forward) }, backward: { self.backward(To(array: $0.map(transform.backward))) }) } } From 514a863547f4918c0d1fc551a78b447017c6a892 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 16:46:48 -0400 Subject: [PATCH 063/138] Add a mapping convenience for constructed Prisms. --- prototype/Doubt/Prism.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index bfb445e71..e6738ad0f 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -34,4 +34,8 @@ extension Prism where To : ArrayConvertible { forward: { self.forward($0)?.array.flatMap(transform.forward) }, backward: { self.backward(To(array: $0.map(transform.backward))) }) } + + public func map(transform: Prism -> Prism) -> Prism { + return map(transform(Prism(forward: { $0 }, backward: { $0 }))) + } } From 1d0a54d62a484798323051a9695825cd86aa7ba3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 17:01:00 -0400 Subject: [PATCH 064/138] Rename Swift to SwiftAST. --- prototype/Doubt/Equatable.swift | 2 +- prototype/Doubt/Swift.swift | 10 +++++----- prototype/DoubtTests/SwiftTests.swift | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/prototype/Doubt/Equatable.swift b/prototype/Doubt/Equatable.swift index 742dc5dba..e256bd737 100644 --- a/prototype/Doubt/Equatable.swift +++ b/prototype/Doubt/Equatable.swift @@ -61,7 +61,7 @@ public func == (left: Doc, right: Doc) -> Bool { } } -func == (left: Swift, right: Swift) -> Bool { +func == (left: SwiftAST, right: SwiftAST) -> Bool { switch (left, right) { case let (.KeyValue(k1, v1), .KeyValue(k2, v2)): return k1 == k2 && v1 == v2 diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index b58f2324a..b03de203c 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -1,8 +1,8 @@ -enum Swift: Equatable { +enum SwiftAST: Equatable { case Atom(String) case Symbol(String, [String]) case KeyValue(String, String) - case Branch(String, [Swift]) + case Branch(String, [SwiftAST]) struct Parsers { static let alphabetic = ^"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".characters @@ -12,10 +12,10 @@ enum Swift: Equatable { static let atom = concat <^> not(ws <|> ^")")+ static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) - static let symbol = Swift.Symbol <^> (join(^"\"", join((concat <^> not(^"\"")*), ^"\"")) <*> (^"<" *> interpolate(concat <^> alphabetic+, ^"," <* ws*) <* ^">")) + static let symbol = SwiftAST.Symbol <^> (join(^"\"", join((concat <^> not(^"\"")*), ^"\"")) <*> (^"<" *> interpolate(concat <^> alphabetic+, ^"," <* ws*) <* ^">")) static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> atom)) - static let branch: String -> State? = Branch <^> (^"(" *> ws* *> word <* ws* <*> sexpr* <* ws* <* ^")") - static let sexpr = delay { (branch <|> symbol <|> keyValue <|> (Swift.Atom <^> atom)) <* ws* } + static let branch: String -> State? = Branch <^> (^"(" *> ws* *> word <* ws* <*> sexpr* <* ws* <* ^")") + static let sexpr = delay { (branch <|> symbol <|> keyValue <|> (SwiftAST.Atom <^> atom)) <* ws* } static let root = ws* *> sexpr* } diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index 4209c86da..24d3ce1ae 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -1,22 +1,22 @@ final class SwiftTests: XCTestCase { func testValuesCanBeAlphabetic() { - XCTAssertEqual(full(Swift.Parsers.keyValue)("key=value"), .KeyValue("key", "value")) + XCTAssertEqual(full(SwiftAST.Parsers.keyValue)("key=value"), .KeyValue("key", "value")) } func testKeyValueCanBeQuoted() { - XCTAssertEqual(full(Swift.Parsers.keyValue)("key='value'"), .KeyValue("key", "'value'")) + XCTAssertEqual(full(SwiftAST.Parsers.keyValue)("key='value'"), .KeyValue("key", "'value'")) } func testQuotedMatchesQuotedStrings() { - XCTAssertEqual(full(Swift.Parsers.quoted)("'value'"), "'value'") + XCTAssertEqual(full(SwiftAST.Parsers.quoted)("'value'"), "'value'") } func testBranchesStartWithAnIdentifier() { - XCTAssertEqual(full(Swift.Parsers.branch)("(a b=c)"), .Branch("a", [ .KeyValue("b", "c") ])) + XCTAssertEqual(full(SwiftAST.Parsers.branch)("(a b=c)"), .Branch("a", [ .KeyValue("b", "c") ])) } func testBranchesDoNotRequireChildren() { - XCTAssertEqual(full(Swift.Parsers.branch)("(return_stmt)"), .Branch("return_stmt", [])) + XCTAssertEqual(full(SwiftAST.Parsers.branch)("(return_stmt)"), .Branch("return_stmt", [])) } } From 1e9be8b9b0a9955bb6ebb2ee170cf66ae23627ea Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 17:23:29 -0400 Subject: [PATCH 065/138] Prism conjunction. --- prototype/Doubt/Operators.swift | 5 +++++ prototype/Doubt/Prism.swift | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/prototype/Doubt/Operators.swift b/prototype/Doubt/Operators.swift index 1b668919b..42588b6c2 100644 --- a/prototype/Doubt/Operators.swift +++ b/prototype/Doubt/Operators.swift @@ -28,6 +28,11 @@ infix operator >>- { precedence 100 } +infix operator &&& { + associativity left + precedence 120 +} + prefix operator ^ {} postfix operator * {} diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift index e6738ad0f..2ad645ecd 100644 --- a/prototype/Doubt/Prism.swift +++ b/prototype/Doubt/Prism.swift @@ -39,3 +39,16 @@ extension Prism where To : ArrayConvertible { return map(transform(Prism(forward: { $0 }, backward: { $0 }))) } } + +public func &&& (left: Prism, right: Prism) -> Prism { + return Prism( + forward: { + if let a = left.forward($0), b = right.forward($0) { + return (a, b) + } + return nil + }, + backward: { + (left.backward($0), right.backward($1)).1 + }) +} From e54bc56d13a0161249f81568c88a5a1cf2edb3b8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 17:32:41 -0400 Subject: [PATCH 066/138] Extract document structure with SourceKitten. --- prototype/DoubtTests/SwiftTests.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index 24d3ce1ae..f62aa2b63 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -18,8 +18,26 @@ final class SwiftTests: XCTestCase { func testBranchesDoNotRequireChildren() { XCTAssertEqual(full(SwiftAST.Parsers.branch)("(return_stmt)"), .Branch("return_stmt", [])) } + + func testParsingAFile() { + guard let file = File(path: __FILE__) else { + XCTFail("Could not make a File from \(__FILE__)") + return + } + + let structure = Structure(file: file) + print(toAnyObject(structure.dictionary)) + + let prism: Prism = JSON.JSON.dictionary["key.substructure"].array.map { + $0.dictionary["key.name"].string &&& $0.dictionary["key.substructure"].array.map { $0.dictionary["key.name"].string } + } + let focus = prism.forward(toAnyObject(structure.dictionary)) + XCTAssertEqual(focus?[0].0, "SwiftTests") + XCTAssertEqual(focus?[0].1 ?? [], ["testValuesCanBeAlphabetic()", "testKeyValueCanBeQuoted()", "testQuotedMatchesQuotedStrings()", "testBranchesStartWithAnIdentifier()", "testBranchesDoNotRequireChildren()", "testParsingAFile()"]) + } } @testable import Doubt +import SourceKittenFramework import XCTest From aa82ed1a2ba29997cd0ede9e782c2d9dc58f9cb4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 21 Sep 2015 17:35:38 -0400 Subject: [PATCH 067/138] Remove Swift AST parsing. --- prototype/Doubt/Swift.swift | 24 ------------------------ prototype/DoubtTests/SwiftTests.swift | 22 +--------------------- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift index b03de203c..bc12a997d 100644 --- a/prototype/Doubt/Swift.swift +++ b/prototype/Doubt/Swift.swift @@ -3,28 +3,4 @@ enum SwiftAST: Equatable { case Symbol(String, [String]) case KeyValue(String, String) case Branch(String, [SwiftAST]) - - struct Parsers { - static let alphabetic = ^"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".characters - static let ws = ^" \t\n".characters - - static let word = concat <^> (alphabetic <|> ^"_")+ - static let atom = concat <^> not(ws <|> ^")")+ - static let quoted = join(^"'", join((concat <^> not(^"'")*), ^"'")) - - static let symbol = SwiftAST.Symbol <^> (join(^"\"", join((concat <^> not(^"\"")*), ^"\"")) <*> (^"<" *> interpolate(concat <^> alphabetic+, ^"," <* ws*) <* ^">")) - static let keyValue = KeyValue <^> (word <* ^"=" <*> (quoted <|> atom)) - static let branch: String -> State? = Branch <^> (^"(" *> ws* *> word <* ws* <*> sexpr* <* ws* <* ^")") - static let sexpr = delay { (branch <|> symbol <|> keyValue <|> (SwiftAST.Atom <^> atom)) <* ws* } - - static let root = ws* *> sexpr* - } -} - -private func join(a: String -> State?, _ b: String -> State?) -> String -> State? { - return (+) <^> (a <*> b) -} - -private func concat(strings: [String]) -> String { - return strings.joinWithSeparator("") } diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index f62aa2b63..ab1dcceaf 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -1,24 +1,4 @@ final class SwiftTests: XCTestCase { - func testValuesCanBeAlphabetic() { - XCTAssertEqual(full(SwiftAST.Parsers.keyValue)("key=value"), .KeyValue("key", "value")) - } - - func testKeyValueCanBeQuoted() { - XCTAssertEqual(full(SwiftAST.Parsers.keyValue)("key='value'"), .KeyValue("key", "'value'")) - } - - func testQuotedMatchesQuotedStrings() { - XCTAssertEqual(full(SwiftAST.Parsers.quoted)("'value'"), "'value'") - } - - func testBranchesStartWithAnIdentifier() { - XCTAssertEqual(full(SwiftAST.Parsers.branch)("(a b=c)"), .Branch("a", [ .KeyValue("b", "c") ])) - } - - func testBranchesDoNotRequireChildren() { - XCTAssertEqual(full(SwiftAST.Parsers.branch)("(return_stmt)"), .Branch("return_stmt", [])) - } - func testParsingAFile() { guard let file = File(path: __FILE__) else { XCTFail("Could not make a File from \(__FILE__)") @@ -33,7 +13,7 @@ final class SwiftTests: XCTestCase { } let focus = prism.forward(toAnyObject(structure.dictionary)) XCTAssertEqual(focus?[0].0, "SwiftTests") - XCTAssertEqual(focus?[0].1 ?? [], ["testValuesCanBeAlphabetic()", "testKeyValueCanBeQuoted()", "testQuotedMatchesQuotedStrings()", "testBranchesStartWithAnIdentifier()", "testBranchesDoNotRequireChildren()", "testParsingAFile()"]) + XCTAssertEqual(focus?[0].1 ?? [], ["testParsingAFile()"]) } } From b1c8394a8f5451c4ed2a43ba208522396cabd69b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:15:55 -0400 Subject: [PATCH 068/138] Convenience constructor for JSON from AnyObject. --- prototype/Doubt/JSON.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index 6ebcd9922..bb6708f36 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -40,6 +40,11 @@ public enum JSON { return false } + init?(object: AnyObject) { + guard let result = Doubt.JSON.JSON.forward(object) else { return nil } + self = result + } + public static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) public static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) From 4a51b786d3c67f9734e141003d1c5dc9cbffa032 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:16:25 -0400 Subject: [PATCH 069/138] Capture the path in a temporary. --- prototype/DoubtTests/SwiftTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index ab1dcceaf..b73c1a9a9 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -1,6 +1,7 @@ final class SwiftTests: XCTestCase { func testParsingAFile() { - guard let file = File(path: __FILE__) else { + let path = __FILE__ + guard let file = File(path: path) else { XCTFail("Could not make a File from \(__FILE__)") return } From 401d0b4194dd375111ba943fcd3b4e85cd7289c7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:16:38 -0400 Subject: [PATCH 070/138] Capture the dictionary in a temporary. --- prototype/DoubtTests/SwiftTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index b73c1a9a9..7e29608e1 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -7,7 +7,8 @@ final class SwiftTests: XCTestCase { } let structure = Structure(file: file) - print(toAnyObject(structure.dictionary)) + let dictionary = toAnyObject(structure.dictionary) + print(dictionary) let prism: Prism = JSON.JSON.dictionary["key.substructure"].array.map { $0.dictionary["key.name"].string &&& $0.dictionary["key.substructure"].array.map { $0.dictionary["key.name"].string } From 9612325ea8a66996cde736a690ad157243b6f0c2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:16:58 -0400 Subject: [PATCH 071/138] Add an extension to Term constructing it from JSON. --- prototype/DoubtTests/SwiftTests.swift | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index 7e29608e1..83132b1d7 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -19,6 +19,28 @@ final class SwiftTests: XCTestCase { } } +extension Term { + init(path: String, JSON: Doubt.JSON) { + switch JSON.dictionary?["key.substructure"] { + case let .Some(.Array(a)): + self = .Roll(.Group(.Roll(.Literal(path)), a.map(Term.init))) + default: + self = .Empty + } + } + + init(JSON: Doubt.JSON) { + switch JSON.dictionary { + case let .Some(d) where d["key.name"] != nil && d["key.substructure"] != nil: + let name = d["key.name"]?.string ?? "" + let substructure = d["key.substructure"]?.array ?? [] + self = .Roll(.Group(.Roll(.Literal(name)), substructure.map(Term.init))) + default: + self = .Empty + } + } +} + @testable import Doubt import SourceKittenFramework From b7647a46edb5d4c84d0e07ec76b8470b5610afd4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:17:58 -0400 Subject: [PATCH 072/138] Use the temporary. --- prototype/DoubtTests/SwiftTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index 83132b1d7..7e17c5349 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -13,7 +13,7 @@ final class SwiftTests: XCTestCase { let prism: Prism = JSON.JSON.dictionary["key.substructure"].array.map { $0.dictionary["key.name"].string &&& $0.dictionary["key.substructure"].array.map { $0.dictionary["key.name"].string } } - let focus = prism.forward(toAnyObject(structure.dictionary)) + let focus = prism.forward(dictionary) XCTAssertEqual(focus?[0].0, "SwiftTests") XCTAssertEqual(focus?[0].1 ?? [], ["testParsingAFile()"]) } From 0c4e9a0b5802b9557a8d9fc02a4fbfdb2a11c29b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:18:22 -0400 Subject: [PATCH 073/138] Construct a Term from the JSON. --- prototype/DoubtTests/SwiftTests.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index 7e17c5349..beb55aca7 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -13,6 +13,9 @@ final class SwiftTests: XCTestCase { let prism: Prism = JSON.JSON.dictionary["key.substructure"].array.map { $0.dictionary["key.name"].string &&& $0.dictionary["key.substructure"].array.map { $0.dictionary["key.name"].string } } + + print(JSON(object: dictionary).map { Term(path: path, JSON: $0) }) + let focus = prism.forward(dictionary) XCTAssertEqual(focus?[0].0, "SwiftTests") XCTAssertEqual(focus?[0].1 ?? [], ["testParsingAFile()"]) From a6473b9effa74fac2c25be24093a4ade2d2fad65 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:23:48 -0400 Subject: [PATCH 074/138] Abstractions can have >1 elements in their body. --- prototype/Doubt/Diff.swift | 3 +-- prototype/Doubt/Syntax.swift | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/prototype/Doubt/Diff.swift b/prototype/Doubt/Diff.swift index 2a5d91943..906b624ca 100644 --- a/prototype/Doubt/Diff.swift +++ b/prototype/Doubt/Diff.swift @@ -64,11 +64,10 @@ public enum Diff: Comparable, CustomDebugStringConvertible, CustomDocConvertible case let (.Roll(a), .Roll(b)): switch (a, b) { case let (.Apply(a, aa), .Apply(b, bb)): - // fixme: SES self = .Copy(.Apply(Diff(a, b), Diff.diff(aa, bb))) case let (.Abstract(p1, b1), .Abstract(p2, b2)): - self = .Copy(.Abstract(Diff.diff(p1, p2), Diff(b1, b2))) + self = .Copy(.Abstract(Diff.diff(p1, p2), Diff.diff(b1, b2))) case let (.Assign(n1, v1), .Assign(n2, v2)) where n1 == n2: self = .Copy(.Assign(n2, Diff(v1, v2))) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index 0aecb62cc..bbf406337 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -27,7 +27,7 @@ public enum Term: CustomDebugStringConvertible, CustomDocConvertible, CustomStri public enum Syntax: CustomDebugStringConvertible, CustomDocConvertible { case Apply(Payload, [Payload]) - case Abstract([Payload], Payload) + case Abstract([Payload], [Payload]) case Assign(String, Payload) case Variable(String) case Literal(String) @@ -38,7 +38,7 @@ public enum Syntax: CustomDebugStringConvertible, CustomDocConvertible case let .Apply(f, args): return .Apply(transform(f), args.map(transform)) case let .Abstract(parameters, body): - return .Abstract(parameters.map(transform), transform(body)) + return .Abstract(parameters.map(transform), body.map(transform)) case let .Assign(n, v): return .Assign(n, transform(v)) case let .Variable(n): @@ -58,7 +58,7 @@ public enum Syntax: CustomDebugStringConvertible, CustomDocConvertible case let .Abstract(xs, x): initial = try xs.reduce(initial, combine: combine) - return try combine(initial, x) + return try x.reduce(initial, combine: combine) case let .Assign(_, x): return try combine(initial, x) From 5b1f35d7ffc31045fd86074a850c1a628f4e66fd Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:26:45 -0400 Subject: [PATCH 075/138] Term constructors. --- prototype/Doubt/Syntax.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index bbf406337..0461a5801 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -23,6 +23,14 @@ public enum Term: CustomDebugStringConvertible, CustomDocConvertible, CustomStri return s.doc } } + + + public static let Apply = Syntax.Apply >>> Term.init + public static let Abstract = Syntax.Abstract >>> Term.init + public static let Assign = Syntax.Assign >>> Term.init + public static let Variable = Syntax.Variable >>> Term.init + public static let Literal = Syntax.Literal >>> Term.init + public static let Group = Syntax.Group >>> Term.init } public enum Syntax: CustomDebugStringConvertible, CustomDocConvertible { From 8b6e1c1c0836c2d117456a0c3b387680f59b693b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:33:56 -0400 Subject: [PATCH 076/138] Fix an infinite loop in Doc construction. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I don’t know how this managed never to be tested. --- prototype/Doubt/Doc.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Doc.swift b/prototype/Doubt/Doc.swift index ac0c8a632..403b9d203 100644 --- a/prototype/Doubt/Doc.swift +++ b/prototype/Doubt/Doc.swift @@ -7,7 +7,7 @@ public enum Doc: CustomStringConvertible, Equatable { indirect case Join(Doc, [Doc]) public init(_ value: T) { - self.init((value as? CustomDocConvertible)?.doc ?? .Text(String(value))) + self = (value as? CustomDocConvertible)?.doc ?? .Text(String(value)) } public var description: String { From 0c5c3910f68f2a6000469c088bb8ae6cebd6bc9d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:35:41 -0400 Subject: [PATCH 077/138] Print the bodies of abstractions. --- prototype/Doubt/Syntax.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index 0461a5801..2949c8f79 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -114,7 +114,7 @@ public enum Syntax: CustomDebugStringConvertible, CustomDocConvertible .Text("λ"), .Join(.Text(", "), parameters.map(Doc.init)), .Text("."), - Doc(body) + .Vertical(body.map(Doc.init)) ]) case let .Assign(n, v): return .Horizontal([ .Text(n), .Text("="), Doc(v) ]) From 0b6f81f8b71332c709c0c19b4cb41822d1830e4d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:39:55 -0400 Subject: [PATCH 078/138] =?UTF-8?q?Don=E2=80=99t=20test=20the=20prism.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prototype/DoubtTests/SwiftTests.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index beb55aca7..54c503a41 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -15,10 +15,6 @@ final class SwiftTests: XCTestCase { } print(JSON(object: dictionary).map { Term(path: path, JSON: $0) }) - - let focus = prism.forward(dictionary) - XCTAssertEqual(focus?[0].0, "SwiftTests") - XCTAssertEqual(focus?[0].1 ?? [], ["testParsingAFile()"]) } } From f61b025c80fc9deee40df5e8269e8d473436b31c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:40:23 -0400 Subject: [PATCH 079/138] Unpack methods/functions differently from classes/extensions. --- prototype/DoubtTests/SwiftTests.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index 54c503a41..8a75cc551 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -33,7 +33,16 @@ extension Term { case let .Some(d) where d["key.name"] != nil && d["key.substructure"] != nil: let name = d["key.name"]?.string ?? "" let substructure = d["key.substructure"]?.array ?? [] - self = .Roll(.Group(.Roll(.Literal(name)), substructure.map(Term.init))) + switch d["key.kind"]?.string { + case .Some("source.lang.swift.decl.class"), .Some("source.lang.swift.decl.extension"): + self = .Group((.Literal(name), substructure.map(Term.init))) + + case .Some("source.lang.swift.decl.function.method.instance"), .Some("source.lang.swift.decl.function.free"): + self = .Assign((name, .Abstract(([], substructure.map(Term.init))))) + + default: + self = .Empty + } default: self = .Empty } From 7ef8a3f8c03db493ddba6a64ce562e8326a1032c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Tue, 22 Sep 2015 17:41:02 -0400 Subject: [PATCH 080/138] Clean up. --- prototype/DoubtTests/SwiftTests.swift | 5 ----- 1 file changed, 5 deletions(-) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index 8a75cc551..d065855f7 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -8,11 +8,6 @@ final class SwiftTests: XCTestCase { let structure = Structure(file: file) let dictionary = toAnyObject(structure.dictionary) - print(dictionary) - - let prism: Prism = JSON.JSON.dictionary["key.substructure"].array.map { - $0.dictionary["key.name"].string &&& $0.dictionary["key.substructure"].array.map { $0.dictionary["key.name"].string } - } print(JSON(object: dictionary).map { Term(path: path, JSON: $0) }) } From 68965379f7db75ef58bf1e4131ec8e0c78ab6fd0 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 11:33:34 -0400 Subject: [PATCH 081/138] Remove the JSON Prisms. --- prototype/Doubt/JSON.swift | 116 +++++++------------------------------ 1 file changed, 21 insertions(+), 95 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index bb6708f36..2071a356e 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -41,102 +41,28 @@ public enum JSON { } init?(object: AnyObject) { - guard let result = Doubt.JSON.JSON.forward(object) else { return nil } - self = result - } - - public static let JSON: Prism = Prism(forward: toJSON, backward: toAnyObject) - - public static let number: Prism = Prism(forward: { $0.number }, backward: { .Number($0) }) - public static let boolean: Prism = Prism(forward: { $0.boolean }, backward: { .Boolean($0) }) - public static let string: Prism = Prism(forward: { $0.string }, backward: { .String($0) }) - public static let array: Prism = Prism(forward: { $0.array }, backward: { .Array($0) }) - public static let dictionary: Prism = Prism(forward: { $0.dictionary }, backward: { .Dictionary($0) }) -} - -public protocol JSONConvertible { - init(JSON: Doubt.JSON) - var JSON: Doubt.JSON { get } -} - -extension JSON: JSONConvertible { - public init(JSON: Doubt.JSON) { - self = JSON - } - - public var JSON: Doubt.JSON { - return self - } -} - -extension JSONConvertible { - static var JSONConverter: Prism { - return Prism(forward: { $0.JSON }, backward: { Self(JSON: $0) }) - } -} - -extension Prism where To : JSONConvertible { - public var number: Prism { - return self >>> To.JSONConverter >>> Doubt.JSON.number - } - - public var boolean: Prism { - return self >>> To.JSONConverter >>> Doubt.JSON.boolean - } - - public var string: Prism { - return self >>> To.JSONConverter >>> Doubt.JSON.string - } - - public var array: Prism { - return self >>> To.JSONConverter >>> Doubt.JSON.array - } - - public var dictionary: Prism { - return self >>> To.JSONConverter >>> Doubt.JSON.dictionary - } -} - - -private func toJSON(object: AnyObject) -> JSON? { - struct E: ErrorType {} - func die() throws -> T { - throw E() - } - do { - switch object { - case let n as Double: - return JSON.Number(n) - case let b as Bool: - return JSON.Boolean(b) - case let s as String: - return JSON.String(s) - case let a as [AnyObject]: - return JSON.Array(try a.map { try toJSON($0) ?? die() }) - case let d as [String:AnyObject]: - return JSON.Dictionary(Dictionary(elements: try d.map { ($0, try toJSON($1) ?? die()) })) - case is NSNull: - return JSON.Null - default: - return nil + struct E: ErrorType {} + func die() throws -> T { + throw E() } - } catch { return nil } -} - -private func toAnyObject(json: JSON) -> AnyObject { - switch json { - case let .Number(n): - return n - case let .Boolean(b): - return b - case let .String(s): - return s - case let .Array(a): - return a.map(toAnyObject) - case let .Dictionary(d): - return Dictionary(elements: d.map { ($0, toAnyObject($1)) }) - case .Null: - return NSNull() + do { + switch object { + case let n as Double: + self = .Number(n) + case let b as Bool: + self = .Boolean(b) + case let s as Swift.String: + self = .String(s) + case let a as [AnyObject]: + self = .Array(try a.map { try Doubt.JSON(object: $0) ?? die() }) + case let d as [Swift.String:AnyObject]: + self = .Dictionary(Swift.Dictionary(elements: try d.map { ($0, try Doubt.JSON(object: $1) ?? die()) })) + case is NSNull: + self = .Null + default: + return nil + } + } catch { return nil } } } From 9fdd9f1109c8fc76ae96850c0c44eea522ed852f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 11:33:55 -0400 Subject: [PATCH 082/138] Remove Array/DictionaryConvertible. --- prototype/Doubt.xcodeproj/project.pbxproj | 8 -------- prototype/Doubt/ArrayConvertible.swift | 16 ---------------- prototype/Doubt/DictionaryConvertible.swift | 17 ----------------- 3 files changed, 41 deletions(-) delete mode 100644 prototype/Doubt/ArrayConvertible.swift delete mode 100644 prototype/Doubt/DictionaryConvertible.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index f7a6a1909..0d461c6da 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -26,8 +26,6 @@ D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEC1BB0652300E3C3C1 /* Prism.swift */; }; D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; - D4413FF31BB0A33600E3C3C1 /* ArrayConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF21BB0A33600E3C3C1 /* ArrayConvertible.swift */; }; - D4413FF51BB0A35F00E3C3C1 /* DictionaryConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF41BB0A35F00E3C3C1 /* DictionaryConvertible.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; @@ -66,8 +64,6 @@ D4413FEC1BB0652300E3C3C1 /* Prism.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prism.swift; sourceTree = ""; }; D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4413FF01BB08FDC00E3C3C1 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; - D4413FF21BB0A33600E3C3C1 /* ArrayConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayConvertible.swift; sourceTree = ""; }; - D4413FF41BB0A35F00E3C3C1 /* DictionaryConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryConvertible.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -151,8 +147,6 @@ D4413FEC1BB0652300E3C3C1 /* Prism.swift */, D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, D4413FF01BB08FDC00E3C3C1 /* JSON.swift */, - D4413FF21BB0A33600E3C3C1 /* ArrayConvertible.swift */, - D4413FF41BB0A35F00E3C3C1 /* DictionaryConvertible.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, ); path = Doubt; @@ -295,12 +289,10 @@ D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */, D4AAE54C1B5AE42D004E581F /* Equatable.swift in Sources */, D4AAE54A1B5AE2D0004E581F /* Syntax.swift in Sources */, - D4413FF51BB0A35F00E3C3C1 /* DictionaryConvertible.swift in Sources */, D432D4731BA9C55300F3FABC /* Stream.swift in Sources */, D4AAE5421B5AE2D0004E581F /* Doc.swift in Sources */, D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */, D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */, - D4413FF31BB0A33600E3C3C1 /* ArrayConvertible.swift in Sources */, D4AAE5461B5AE2D0004E581F /* Parse.swift in Sources */, D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, diff --git a/prototype/Doubt/ArrayConvertible.swift b/prototype/Doubt/ArrayConvertible.swift deleted file mode 100644 index be1281f5c..000000000 --- a/prototype/Doubt/ArrayConvertible.swift +++ /dev/null @@ -1,16 +0,0 @@ -public protocol ArrayConvertible { - typealias Element - - init(array: [Element]) - var array: [Element] { get } -} - -extension Array : ArrayConvertible { - public init(array: [Element]) { - self = array - } - - public var array: [Element] { - return self - } -} diff --git a/prototype/Doubt/DictionaryConvertible.swift b/prototype/Doubt/DictionaryConvertible.swift deleted file mode 100644 index 798147af2..000000000 --- a/prototype/Doubt/DictionaryConvertible.swift +++ /dev/null @@ -1,17 +0,0 @@ -public protocol DictionaryConvertible { - typealias Key : Hashable - typealias Value - - init(dictionary: [Key:Value]) - var dictionary: [Key:Value] { get } -} - -extension Dictionary: DictionaryConvertible { - public init(dictionary: [Key:Value]) { - self = dictionary - } - - public var dictionary: [Key:Value] { - return self - } -} From 6571de8514370831878fa3bdba3924d2ed3e4846 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 11:34:00 -0400 Subject: [PATCH 083/138] Remove Prism. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 -- prototype/Doubt/Prism.swift | 54 ----------------------- 2 files changed, 58 deletions(-) delete mode 100644 prototype/Doubt/Prism.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 0d461c6da..eadf28d2a 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -23,7 +23,6 @@ D4413FE61BB055A800E3C3C1 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; D4413FE81BB055AE00E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; D4413FE91BB055B500E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; - D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEC1BB0652300E3C3C1 /* Prism.swift */; }; D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; @@ -61,7 +60,6 @@ D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SWXMLHash.framework; path = ../External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug/SWXMLHash.framework; sourceTree = ""; }; D4413FDA1BB0536700E3C3C1 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Result.framework"; sourceTree = ""; }; D4413FE71BB055AE00E3C3C1 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Commandant.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Commandant.framework"; sourceTree = ""; }; - D4413FEC1BB0652300E3C3C1 /* Prism.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Prism.swift; sourceTree = ""; }; D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4413FF01BB08FDC00E3C3C1 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -144,7 +142,6 @@ D432D4721BA9C55300F3FABC /* Stream.swift */, D432D4741BA9D6A400F3FABC /* Memo.swift */, D40024EB1BAC62BA00A110B8 /* Swift.swift */, - D4413FEC1BB0652300E3C3C1 /* Prism.swift */, D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, D4413FF01BB08FDC00E3C3C1 /* JSON.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, @@ -292,7 +289,6 @@ D432D4731BA9C55300F3FABC /* Stream.swift in Sources */, D4AAE5421B5AE2D0004E581F /* Doc.swift in Sources */, D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */, - D4413FED1BB0652300E3C3C1 /* Prism.swift in Sources */, D4AAE5461B5AE2D0004E581F /* Parse.swift in Sources */, D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, diff --git a/prototype/Doubt/Prism.swift b/prototype/Doubt/Prism.swift deleted file mode 100644 index 2ad645ecd..000000000 --- a/prototype/Doubt/Prism.swift +++ /dev/null @@ -1,54 +0,0 @@ -public struct Prism { - public init(forward: From -> To?, backward: To -> From) { - self.forward = forward - self.backward = backward - } - - public let forward: From -> To? - public let backward: To -> From -} - -public func >>> (left: Prism, right: Prism) -> Prism { - return Prism(forward: { left.forward($0).flatMap(right.forward) }, backward: right.backward >>> left.backward) -} - - -extension Prism where To : DictionaryConvertible { - public subscript (key: To.Key) -> Prism { - return self >>> Prism(forward: { $0.dictionary[key] }, backward: { To(dictionary: [key: $0]) }) - } -} - -extension Prism where To : ArrayConvertible { - public subscript (index: Int) -> Prism { - return self >>> Prism( - forward: { - let array = $0.array - return array.count > index ? array[index] : nil - }, - backward: { To(array: [ $0 ]) }) - } - - public func map(transform: Prism) -> Prism { - return Prism( - forward: { self.forward($0)?.array.flatMap(transform.forward) }, - backward: { self.backward(To(array: $0.map(transform.backward))) }) - } - - public func map(transform: Prism -> Prism) -> Prism { - return map(transform(Prism(forward: { $0 }, backward: { $0 }))) - } -} - -public func &&& (left: Prism, right: Prism) -> Prism { - return Prism( - forward: { - if let a = left.forward($0), b = right.forward($0) { - return (a, b) - } - return nil - }, - backward: { - (left.backward($0), right.backward($1)).1 - }) -} From 00ff3c24476143b3202c837c1e7d8ef310067e4c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 11:34:35 -0400 Subject: [PATCH 084/138] We no longer need to namespace these. --- prototype/Doubt/JSON.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index 2071a356e..9c577fdfa 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -1,6 +1,6 @@ public enum JSON { - public typealias ArrayType = [Doubt.JSON] - public typealias DictionaryType = [Swift.String:Doubt.JSON] + public typealias ArrayType = [JSON] + public typealias DictionaryType = [Swift.String:JSON] case Number(Double) case Boolean(Bool) @@ -54,9 +54,9 @@ public enum JSON { case let s as Swift.String: self = .String(s) case let a as [AnyObject]: - self = .Array(try a.map { try Doubt.JSON(object: $0) ?? die() }) + self = .Array(try a.map { try JSON(object: $0) ?? die() }) case let d as [Swift.String:AnyObject]: - self = .Dictionary(Swift.Dictionary(elements: try d.map { ($0, try Doubt.JSON(object: $1) ?? die()) })) + self = .Dictionary(Swift.Dictionary(elements: try d.map { ($0, try JSON(object: $1) ?? die()) })) case is NSNull: self = .Null default: From 04550ca9bda87294d9b597f9c40d202dfc29f59a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 11:35:38 -0400 Subject: [PATCH 085/138] Remove SwiftAST. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 ---- prototype/Doubt/Equatable.swift | 15 --------------- prototype/Doubt/Swift.swift | 6 ------ 3 files changed, 25 deletions(-) delete mode 100644 prototype/Doubt/Swift.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index eadf28d2a..40c2fe4a4 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - D40024EC1BAC62BA00A110B8 /* Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40024EB1BAC62BA00A110B8 /* Swift.swift */; }; D40024EE1BAC819000A110B8 /* SwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D40024ED1BAC819000A110B8 /* SwiftTests.swift */; }; D432D4711BA9AC0B00F3FABC /* DiffTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4701BA9AC0B00F3FABC /* DiffTests.swift */; }; D432D4731BA9C55300F3FABC /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4721BA9C55300F3FABC /* Stream.swift */; }; @@ -49,7 +48,6 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - D40024EB1BAC62BA00A110B8 /* Swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Swift.swift; sourceTree = ""; }; D40024ED1BAC819000A110B8 /* SwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftTests.swift; sourceTree = ""; }; D432D4701BA9AC0B00F3FABC /* DiffTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffTests.swift; sourceTree = ""; }; D432D4721BA9C55300F3FABC /* Stream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stream.swift; sourceTree = ""; }; @@ -141,7 +139,6 @@ D432D4761BA9FE6A00F3FABC /* Comparable.swift */, D432D4721BA9C55300F3FABC /* Stream.swift */, D432D4741BA9D6A400F3FABC /* Memo.swift */, - D40024EB1BAC62BA00A110B8 /* Swift.swift */, D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, D4413FF01BB08FDC00E3C3C1 /* JSON.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, @@ -293,7 +290,6 @@ D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */, D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */, D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */, - D40024EC1BAC62BA00A110B8 /* Swift.swift in Sources */, D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/prototype/Doubt/Equatable.swift b/prototype/Doubt/Equatable.swift index e256bd737..34cfd49e7 100644 --- a/prototype/Doubt/Equatable.swift +++ b/prototype/Doubt/Equatable.swift @@ -60,18 +60,3 @@ public func == (left: Doc, right: Doc) -> Bool { return false } } - -func == (left: SwiftAST, right: SwiftAST) -> Bool { - switch (left, right) { - case let (.KeyValue(k1, v1), .KeyValue(k2, v2)): - return k1 == k2 && v1 == v2 - case let (.Branch(n1, b1), .Branch(n2, b2)): - return n1 == n2 && b1 == b2 - case let (.Atom(a), .Atom(b)): - return a == b - case let (.Symbol(s, u), .Symbol(t, v)): - return s == t && u == v - default: - return false - } -} diff --git a/prototype/Doubt/Swift.swift b/prototype/Doubt/Swift.swift deleted file mode 100644 index bc12a997d..000000000 --- a/prototype/Doubt/Swift.swift +++ /dev/null @@ -1,6 +0,0 @@ -enum SwiftAST: Equatable { - case Atom(String) - case Symbol(String, [String]) - case KeyValue(String, String) - case Branch(String, [SwiftAST]) -} From 22fa931d4d90931eb354f706043e36fd6ef4f8c5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 12:31:28 -0400 Subject: [PATCH 086/138] Use Term.Roll. --- prototype/Doubt/Syntax.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index 2949c8f79..5dfcc5c49 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -25,12 +25,12 @@ public enum Term: CustomDebugStringConvertible, CustomDocConvertible, CustomStri } - public static let Apply = Syntax.Apply >>> Term.init - public static let Abstract = Syntax.Abstract >>> Term.init - public static let Assign = Syntax.Assign >>> Term.init - public static let Variable = Syntax.Variable >>> Term.init - public static let Literal = Syntax.Literal >>> Term.init - public static let Group = Syntax.Group >>> Term.init + public static let Apply = Syntax.Apply >>> Roll + public static let Abstract = Syntax.Abstract >>> Roll + public static let Assign = Syntax.Assign >>> Roll + public static let Variable = Syntax.Variable >>> Roll + public static let Literal = Syntax.Literal >>> Roll + public static let Group = Syntax.Group >>> Roll } public enum Syntax: CustomDebugStringConvertible, CustomDocConvertible { From bd7bcaea00942f0eebcb2c8e21592508e146b65f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 12:32:25 -0400 Subject: [PATCH 087/138] Explicitly annotate types so we can call without extra parentheses. --- prototype/Doubt/Syntax.swift | 8 ++++---- prototype/DoubtTests/SwiftTests.swift | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index 5dfcc5c49..e89e889f9 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -25,12 +25,12 @@ public enum Term: CustomDebugStringConvertible, CustomDocConvertible, CustomStri } - public static let Apply = Syntax.Apply >>> Roll - public static let Abstract = Syntax.Abstract >>> Roll - public static let Assign = Syntax.Assign >>> Roll + public static let Apply: (Term, [Term]) -> Term = Syntax.Apply >>> Roll + public static let Abstract: ([Term], [Term]) -> Term = Syntax.Abstract >>> Roll + public static let Assign: (String, Term) -> Term = Syntax.Assign >>> Roll public static let Variable = Syntax.Variable >>> Roll public static let Literal = Syntax.Literal >>> Roll - public static let Group = Syntax.Group >>> Roll + public static let Group: (Term, [Term]) -> Term = Syntax.Group >>> Roll } public enum Syntax: CustomDebugStringConvertible, CustomDocConvertible { diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index d065855f7..2a0f09c58 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -30,10 +30,10 @@ extension Term { let substructure = d["key.substructure"]?.array ?? [] switch d["key.kind"]?.string { case .Some("source.lang.swift.decl.class"), .Some("source.lang.swift.decl.extension"): - self = .Group((.Literal(name), substructure.map(Term.init))) + self = .Group(.Literal(name), substructure.map(Term.init)) case .Some("source.lang.swift.decl.function.method.instance"), .Some("source.lang.swift.decl.function.free"): - self = .Assign((name, .Abstract(([], substructure.map(Term.init))))) + self = .Assign(name, .Abstract([], substructure.map(Term.init))) default: self = .Empty From 95697e15f8224fd397d236ce66b9a6766f459867 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 13:29:05 -0400 Subject: [PATCH 088/138] Doubt.framework does not need to link against SourceKittenFramework &c. --- prototype/Doubt.xcodeproj/project.pbxproj | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 40c2fe4a4..4083aca19 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -12,15 +12,10 @@ D432D4731BA9C55300F3FABC /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4721BA9C55300F3FABC /* Stream.swift */; }; D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4741BA9D6A400F3FABC /* Memo.swift */; }; D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4761BA9FE6A00F3FABC /* Comparable.swift */; }; - D4413FD51BB052ED00E3C3C1 /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; - D4413FD71BB0531E00E3C3C1 /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; - D4413FD91BB0534000E3C3C1 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; - D4413FDB1BB0536700E3C3C1 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; }; D4413FDD1BB0559400E3C3C1 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; }; D4413FDE1BB0559400E3C3C1 /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; D4413FE51BB055A600E3C3C1 /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; D4413FE61BB055A800E3C3C1 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; - D4413FE81BB055AE00E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; D4413FE91BB055B500E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; @@ -81,11 +76,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D4413FE81BB055AE00E3C3C1 /* Commandant.framework in Frameworks */, - D4413FDB1BB0536700E3C3C1 /* Result.framework in Frameworks */, - D4413FD91BB0534000E3C3C1 /* SWXMLHash.framework in Frameworks */, - D4413FD71BB0531E00E3C3C1 /* SwiftXPC.framework in Frameworks */, - D4413FD51BB052ED00E3C3C1 /* SourceKittenFramework.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; From 18d35a0beb2598d0b48469e1a6698a417fb017b7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 13:31:42 -0400 Subject: [PATCH 089/138] Share the Doubt scheme. --- .../xcshareddata/xcschemes/Doubt.xcscheme | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 prototype/Doubt.xcodeproj/xcshareddata/xcschemes/Doubt.xcscheme diff --git a/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/Doubt.xcscheme b/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/Doubt.xcscheme new file mode 100644 index 000000000..b5e50d7d1 --- /dev/null +++ b/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/Doubt.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 9fa5aba516d858c141318003479595b77bbc237d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 13:32:17 -0400 Subject: [PATCH 090/138] Add a Swift diff tool target. --- prototype/Doubt.xcodeproj/project.pbxproj | 110 ++++++++++++++++++ .../xcschemes/doubt-swift.xcscheme | 91 +++++++++++++++ prototype/doubt-swift/main.swift | 0 3 files changed, 201 insertions(+) create mode 100644 prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme create mode 100644 prototype/doubt-swift/main.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 4083aca19..f54ba6031 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -12,6 +12,13 @@ D432D4731BA9C55300F3FABC /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4721BA9C55300F3FABC /* Stream.swift */; }; D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4741BA9D6A400F3FABC /* Memo.swift */; }; D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4761BA9FE6A00F3FABC /* Comparable.swift */; }; + D435B7481BB31949000902F6 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D435B7471BB31949000902F6 /* main.swift */; }; + D435B74C1BB31951000902F6 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; + D435B74D1BB31951000902F6 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; }; + D435B74E1BB31951000902F6 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; + D435B74F1BB31951000902F6 /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; + D435B7501BB31951000902F6 /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; + D435B7511BB31958000902F6 /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4413FDD1BB0559400E3C3C1 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; }; D4413FDE1BB0559400E3C3C1 /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; D4413FE51BB055A600E3C3C1 /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; @@ -42,12 +49,26 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + D435B7431BB31949000902F6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ D40024ED1BAC819000A110B8 /* SwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftTests.swift; sourceTree = ""; }; D432D4701BA9AC0B00F3FABC /* DiffTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffTests.swift; sourceTree = ""; }; D432D4721BA9C55300F3FABC /* Stream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stream.swift; sourceTree = ""; }; D432D4741BA9D6A400F3FABC /* Memo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Memo.swift; sourceTree = ""; }; D432D4761BA9FE6A00F3FABC /* Comparable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Comparable.swift; sourceTree = ""; }; + D435B7451BB31949000902F6 /* doubt-swift */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "doubt-swift"; sourceTree = BUILT_PRODUCTS_DIR; }; + D435B7471BB31949000902F6 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SourceKittenFramework.framework; path = ../External/SourceKitten/build/Debug/SourceKittenFramework.framework; sourceTree = ""; }; D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftXPC.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/SwiftXPC.framework"; sourceTree = ""; }; D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SWXMLHash.framework; path = ../External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug/SWXMLHash.framework; sourceTree = ""; }; @@ -72,6 +93,19 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + D435B7421BB31949000902F6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D435B7511BB31958000902F6 /* Doubt.framework in Frameworks */, + D435B74C1BB31951000902F6 /* Commandant.framework in Frameworks */, + D435B74D1BB31951000902F6 /* Result.framework in Frameworks */, + D435B74E1BB31951000902F6 /* SWXMLHash.framework in Frameworks */, + D435B74F1BB31951000902F6 /* SwiftXPC.framework in Frameworks */, + D435B7501BB31951000902F6 /* SourceKittenFramework.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D4AAE4F91B5AE22E004E581F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -95,11 +129,20 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + D435B7461BB31949000902F6 /* doubt-swift */ = { + isa = PBXGroup; + children = ( + D435B7471BB31949000902F6 /* main.swift */, + ); + path = "doubt-swift"; + sourceTree = ""; + }; D4AAE4F31B5AE22E004E581F = { isa = PBXGroup; children = ( D4AAE4FF1B5AE22E004E581F /* Doubt */, D4AAE5111B5AE22E004E581F /* DoubtTests */, + D435B7461BB31949000902F6 /* doubt-swift */, D4AAE4FE1B5AE22E004E581F /* Products */, ); sourceTree = ""; @@ -109,6 +152,7 @@ children = ( D4AAE4FD1B5AE22E004E581F /* Doubt.framework */, D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */, + D435B7451BB31949000902F6 /* doubt-swift */, ); name = Products; sourceTree = ""; @@ -172,6 +216,23 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + D435B7441BB31949000902F6 /* doubt-swift */ = { + isa = PBXNativeTarget; + buildConfigurationList = D435B7491BB31949000902F6 /* Build configuration list for PBXNativeTarget "doubt-swift" */; + buildPhases = ( + D435B7411BB31949000902F6 /* Sources */, + D435B7421BB31949000902F6 /* Frameworks */, + D435B7431BB31949000902F6 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "doubt-swift"; + productName = "doubt-swift"; + productReference = D435B7451BB31949000902F6 /* doubt-swift */; + productType = "com.apple.product-type.tool"; + }; D4AAE4FC1B5AE22E004E581F /* Doubt */ = { isa = PBXNativeTarget; buildConfigurationList = D4AAE5171B5AE22E004E581F /* Build configuration list for PBXNativeTarget "Doubt" */; @@ -218,6 +279,9 @@ LastUpgradeCheck = 0710; ORGANIZATIONNAME = GitHub; TargetAttributes = { + D435B7441BB31949000902F6 = { + CreatedOnToolsVersion = 7.1; + }; D4AAE4FC1B5AE22E004E581F = { CreatedOnToolsVersion = 7.0; }; @@ -240,6 +304,7 @@ targets = ( D4AAE4FC1B5AE22E004E581F /* Doubt */, D4AAE50C1B5AE22E004E581F /* DoubtTests */, + D435B7441BB31949000902F6 /* doubt-swift */, ); }; /* End PBXProject section */ @@ -262,6 +327,14 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + D435B7411BB31949000902F6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D435B7481BB31949000902F6 /* main.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D4AAE4F81B5AE22E004E581F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -304,6 +377,35 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + D435B74A1BB31949000902F6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug", + "$(PROJECT_DIR)/External/SourceKitten/build/Debug", + ); + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D435B74B1BB31949000902F6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug", + "$(PROJECT_DIR)/External/SourceKitten/build/Debug", + ); + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; D4AAE5151B5AE22E004E581F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -464,6 +566,14 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + D435B7491BB31949000902F6 /* Build configuration list for PBXNativeTarget "doubt-swift" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D435B74A1BB31949000902F6 /* Debug */, + D435B74B1BB31949000902F6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; D4AAE4F71B5AE22E004E581F /* Build configuration list for PBXProject "Doubt" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme b/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme new file mode 100644 index 000000000..237b758dd --- /dev/null +++ b/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/prototype/doubt-swift/main.swift b/prototype/doubt-swift/main.swift new file mode 100644 index 000000000..e69de29bb From 74e93a14de2e95c090a727813d1a80bf5115a76a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 13:34:45 -0400 Subject: [PATCH 091/138] Move Term/JSON conversion into Term. --- prototype/Doubt/Syntax.swift | 35 +++++++++++++++++++++++++++ prototype/DoubtTests/SwiftTests.swift | 31 ------------------------ 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index e89e889f9..58f733420 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -31,8 +31,43 @@ public enum Term: CustomDebugStringConvertible, CustomDocConvertible, CustomStri public static let Variable = Syntax.Variable >>> Roll public static let Literal = Syntax.Literal >>> Roll public static let Group: (Term, [Term]) -> Term = Syntax.Group >>> Roll + + + // MARK: JSON representation. + + /// Constructs a Term representing the `JSON` in a file at `path`. + init(path: String, JSON: Doubt.JSON) { + switch JSON.dictionary?["key.substructure"] { + case let .Some(.Array(a)): + self = .Roll(.Group(.Roll(.Literal(path)), a.map(Term.init))) + default: + self = .Empty + } + } + + /// Constructs a Term representing `JSON`. + init(JSON: Doubt.JSON) { + switch JSON.dictionary { + case let .Some(d) where d["key.name"] != nil && d["key.substructure"] != nil: + let name = d["key.name"]?.string ?? "" + let substructure = d["key.substructure"]?.array ?? [] + switch d["key.kind"]?.string { + case .Some("source.lang.swift.decl.class"), .Some("source.lang.swift.decl.extension"): + self = .Group(.Literal(name), substructure.map(Term.init)) + + case .Some("source.lang.swift.decl.function.method.instance"), .Some("source.lang.swift.decl.function.free"): + self = .Assign(name, .Abstract([], substructure.map(Term.init))) + + default: + self = .Empty + } + default: + self = .Empty + } + } } + public enum Syntax: CustomDebugStringConvertible, CustomDocConvertible { case Apply(Payload, [Payload]) case Abstract([Payload], [Payload]) diff --git a/prototype/DoubtTests/SwiftTests.swift b/prototype/DoubtTests/SwiftTests.swift index 2a0f09c58..55332c62b 100644 --- a/prototype/DoubtTests/SwiftTests.swift +++ b/prototype/DoubtTests/SwiftTests.swift @@ -13,37 +13,6 @@ final class SwiftTests: XCTestCase { } } -extension Term { - init(path: String, JSON: Doubt.JSON) { - switch JSON.dictionary?["key.substructure"] { - case let .Some(.Array(a)): - self = .Roll(.Group(.Roll(.Literal(path)), a.map(Term.init))) - default: - self = .Empty - } - } - - init(JSON: Doubt.JSON) { - switch JSON.dictionary { - case let .Some(d) where d["key.name"] != nil && d["key.substructure"] != nil: - let name = d["key.name"]?.string ?? "" - let substructure = d["key.substructure"]?.array ?? [] - switch d["key.kind"]?.string { - case .Some("source.lang.swift.decl.class"), .Some("source.lang.swift.decl.extension"): - self = .Group(.Literal(name), substructure.map(Term.init)) - - case .Some("source.lang.swift.decl.function.method.instance"), .Some("source.lang.swift.decl.function.free"): - self = .Assign(name, .Abstract([], substructure.map(Term.init))) - - default: - self = .Empty - } - default: - self = .Empty - } - } -} - @testable import Doubt import SourceKittenFramework From a3aefe8e3737f462a33b34ac4848834a00ad2646 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 16:04:19 -0400 Subject: [PATCH 092/138] Use a .app target instead. --- prototype/Doubt.xcodeproj/project.pbxproj | 111 +++++++++--------- .../xcschemes/doubt-swift.xcscheme | 26 ++-- prototype/doubt-swift/Info.plist | 34 ++++++ 3 files changed, 109 insertions(+), 62 deletions(-) create mode 100644 prototype/doubt-swift/Info.plist diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index f54ba6031..1d64cd3a0 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -12,13 +12,6 @@ D432D4731BA9C55300F3FABC /* Stream.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4721BA9C55300F3FABC /* Stream.swift */; }; D432D4751BA9D6A400F3FABC /* Memo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4741BA9D6A400F3FABC /* Memo.swift */; }; D432D4771BA9FE6A00F3FABC /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D432D4761BA9FE6A00F3FABC /* Comparable.swift */; }; - D435B7481BB31949000902F6 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D435B7471BB31949000902F6 /* main.swift */; }; - D435B74C1BB31951000902F6 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; - D435B74D1BB31951000902F6 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; }; - D435B74E1BB31951000902F6 /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; - D435B74F1BB31951000902F6 /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; - D435B7501BB31951000902F6 /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; - D435B7511BB31958000902F6 /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4413FDD1BB0559400E3C3C1 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; }; D4413FDE1BB0559400E3C3C1 /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; D4413FE51BB055A600E3C3C1 /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; @@ -37,6 +30,14 @@ D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */; }; D4AAE54A1B5AE2D0004E581F /* Syntax.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53F1B5AE2D0004E581F /* Syntax.swift */; }; D4AAE54C1B5AE42D004E581F /* Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE54B1B5AE42D004E581F /* Equatable.swift */; }; + D4C2B12E1BB33CEC0096F92A /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D435B7471BB31949000902F6 /* main.swift */; }; + D4C2B12F1BB33D050096F92A /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; + D4C2B1301BB33D080096F92A /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; + D4C2B1311BB33D080096F92A /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; }; + D4C2B1321BB33D080096F92A /* SWXMLHash.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; }; + D4C2B1331BB33D080096F92A /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; + D4C2B1341BB33D080096F92A /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; + D4C2B1351BB33D1D0096F92A /* BoundsCheckedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D435B7521BB31BBC000902F6 /* BoundsCheckedArray.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -49,26 +50,15 @@ }; /* End PBXContainerItemProxy section */ -/* Begin PBXCopyFilesBuildPhase section */ - D435B7431BB31949000902F6 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - /* Begin PBXFileReference section */ D40024ED1BAC819000A110B8 /* SwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftTests.swift; sourceTree = ""; }; D432D4701BA9AC0B00F3FABC /* DiffTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffTests.swift; sourceTree = ""; }; D432D4721BA9C55300F3FABC /* Stream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stream.swift; sourceTree = ""; }; D432D4741BA9D6A400F3FABC /* Memo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Memo.swift; sourceTree = ""; }; D432D4761BA9FE6A00F3FABC /* Comparable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Comparable.swift; sourceTree = ""; }; - D435B7451BB31949000902F6 /* doubt-swift */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "doubt-swift"; sourceTree = BUILT_PRODUCTS_DIR; }; D435B7471BB31949000902F6 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; + D435B7521BB31BBC000902F6 /* BoundsCheckedArray.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoundsCheckedArray.swift; sourceTree = ""; }; + D435B7581BB32117000902F6 /* doubt-swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "doubt-swift.app"; sourceTree = BUILT_PRODUCTS_DIR; }; D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SourceKittenFramework.framework; path = ../External/SourceKitten/build/Debug/SourceKittenFramework.framework; sourceTree = ""; }; D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftXPC.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/SwiftXPC.framework"; sourceTree = ""; }; D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SWXMLHash.framework; path = ../External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug/SWXMLHash.framework; sourceTree = ""; }; @@ -93,16 +83,16 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - D435B7421BB31949000902F6 /* Frameworks */ = { + D435B7551BB32117000902F6 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D435B7511BB31958000902F6 /* Doubt.framework in Frameworks */, - D435B74C1BB31951000902F6 /* Commandant.framework in Frameworks */, - D435B74D1BB31951000902F6 /* Result.framework in Frameworks */, - D435B74E1BB31951000902F6 /* SWXMLHash.framework in Frameworks */, - D435B74F1BB31951000902F6 /* SwiftXPC.framework in Frameworks */, - D435B7501BB31951000902F6 /* SourceKittenFramework.framework in Frameworks */, + D4C2B12F1BB33D050096F92A /* Doubt.framework in Frameworks */, + D4C2B1301BB33D080096F92A /* Commandant.framework in Frameworks */, + D4C2B1311BB33D080096F92A /* Result.framework in Frameworks */, + D4C2B1321BB33D080096F92A /* SWXMLHash.framework in Frameworks */, + D4C2B1331BB33D080096F92A /* SwiftXPC.framework in Frameworks */, + D4C2B1341BB33D080096F92A /* SourceKittenFramework.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -133,6 +123,7 @@ isa = PBXGroup; children = ( D435B7471BB31949000902F6 /* main.swift */, + D435B7521BB31BBC000902F6 /* BoundsCheckedArray.swift */, ); path = "doubt-swift"; sourceTree = ""; @@ -152,7 +143,7 @@ children = ( D4AAE4FD1B5AE22E004E581F /* Doubt.framework */, D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */, - D435B7451BB31949000902F6 /* doubt-swift */, + D435B7581BB32117000902F6 /* doubt-swift.app */, ); name = Products; sourceTree = ""; @@ -216,13 +207,13 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - D435B7441BB31949000902F6 /* doubt-swift */ = { + D435B7571BB32117000902F6 /* doubt-swift */ = { isa = PBXNativeTarget; - buildConfigurationList = D435B7491BB31949000902F6 /* Build configuration list for PBXNativeTarget "doubt-swift" */; + buildConfigurationList = D435B7621BB32117000902F6 /* Build configuration list for PBXNativeTarget "doubt-swift" */; buildPhases = ( - D435B7411BB31949000902F6 /* Sources */, - D435B7421BB31949000902F6 /* Frameworks */, - D435B7431BB31949000902F6 /* CopyFiles */, + D435B7541BB32117000902F6 /* Sources */, + D435B7551BB32117000902F6 /* Frameworks */, + D435B7561BB32117000902F6 /* Resources */, ); buildRules = ( ); @@ -230,8 +221,8 @@ ); name = "doubt-swift"; productName = "doubt-swift"; - productReference = D435B7451BB31949000902F6 /* doubt-swift */; - productType = "com.apple.product-type.tool"; + productReference = D435B7581BB32117000902F6 /* doubt-swift.app */; + productType = "com.apple.product-type.application"; }; D4AAE4FC1B5AE22E004E581F /* Doubt */ = { isa = PBXNativeTarget; @@ -279,7 +270,7 @@ LastUpgradeCheck = 0710; ORGANIZATIONNAME = GitHub; TargetAttributes = { - D435B7441BB31949000902F6 = { + D435B7571BB32117000902F6 = { CreatedOnToolsVersion = 7.1; }; D4AAE4FC1B5AE22E004E581F = { @@ -296,6 +287,7 @@ hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = D4AAE4F31B5AE22E004E581F; productRefGroup = D4AAE4FE1B5AE22E004E581F /* Products */; @@ -304,12 +296,19 @@ targets = ( D4AAE4FC1B5AE22E004E581F /* Doubt */, D4AAE50C1B5AE22E004E581F /* DoubtTests */, - D435B7441BB31949000902F6 /* doubt-swift */, + D435B7571BB32117000902F6 /* doubt-swift */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + D435B7561BB32117000902F6 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D4AAE4FB1B5AE22E004E581F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -327,11 +326,12 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - D435B7411BB31949000902F6 /* Sources */ = { + D435B7541BB32117000902F6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D435B7481BB31949000902F6 /* main.swift in Sources */, + D4C2B1351BB33D1D0096F92A /* BoundsCheckedArray.swift in Sources */, + D4C2B12E1BB33CEC0096F92A /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -377,31 +377,31 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - D435B74A1BB31949000902F6 /* Debug */ = { + D435B7631BB32117000902F6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "-"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug", - "$(PROJECT_DIR)/External/SourceKitten/build/Debug", - ); + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "doubt-swift/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.doubt-swift"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; - D435B74B1BB31949000902F6 /* Release */ = { + D435B7641BB32117000902F6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug", - "$(PROJECT_DIR)/External/SourceKitten/build/Debug", - ); + INFOPLIST_FILE = "doubt-swift/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "com.antitypical.doubt-swift"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -502,6 +502,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; FRAMEWORK_VERSION = A; INFOPLIST_FILE = Doubt/Info.plist; INSTALL_PATH = "@rpath"; @@ -522,6 +523,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; FRAMEWORK_VERSION = A; INFOPLIST_FILE = Doubt/Info.plist; INSTALL_PATH = "@rpath"; @@ -566,13 +568,14 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - D435B7491BB31949000902F6 /* Build configuration list for PBXNativeTarget "doubt-swift" */ = { + D435B7621BB32117000902F6 /* Build configuration list for PBXNativeTarget "doubt-swift" */ = { isa = XCConfigurationList; buildConfigurations = ( - D435B74A1BB31949000902F6 /* Debug */, - D435B74B1BB31949000902F6 /* Release */, + D435B7631BB32117000902F6 /* Debug */, + D435B7641BB32117000902F6 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; D4AAE4F71B5AE22E004E581F /* Build configuration list for PBXProject "Doubt" */ = { isa = XCConfigurationList; diff --git a/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme b/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme index 237b758dd..0cf66e46a 100644 --- a/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme +++ b/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme @@ -14,8 +14,8 @@ buildForAnalyzing = "YES"> @@ -32,8 +32,8 @@ @@ -55,12 +55,22 @@ runnableDebuggingMode = "0"> + + + + + + @@ -74,8 +84,8 @@ runnableDebuggingMode = "0"> diff --git a/prototype/doubt-swift/Info.plist b/prototype/doubt-swift/Info.plist new file mode 100644 index 000000000..987aec559 --- /dev/null +++ b/prototype/doubt-swift/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2015 GitHub. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + From 8f78776d6a727f78464bf0267aeabd1c6fd12d9a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 16:26:00 -0400 Subject: [PATCH 093/138] Public constructor for JSON. --- prototype/Doubt/JSON.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/JSON.swift b/prototype/Doubt/JSON.swift index 9c577fdfa..26b53f200 100644 --- a/prototype/Doubt/JSON.swift +++ b/prototype/Doubt/JSON.swift @@ -40,7 +40,7 @@ public enum JSON { return false } - init?(object: AnyObject) { + public init?(object: AnyObject) { struct E: ErrorType {} func die() throws -> T { throw E() From ce6fd43eafa9f52365ff66dd3d75423a3b4b28b2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 16:27:29 -0400 Subject: [PATCH 094/138] Term JSON constructors are public. --- prototype/Doubt/Syntax.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index 58f733420..39a9f8e12 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -36,7 +36,7 @@ public enum Term: CustomDebugStringConvertible, CustomDocConvertible, CustomStri // MARK: JSON representation. /// Constructs a Term representing the `JSON` in a file at `path`. - init(path: String, JSON: Doubt.JSON) { + public init(path: String, JSON: Doubt.JSON) { switch JSON.dictionary?["key.substructure"] { case let .Some(.Array(a)): self = .Roll(.Group(.Roll(.Literal(path)), a.map(Term.init))) @@ -46,7 +46,7 @@ public enum Term: CustomDebugStringConvertible, CustomDocConvertible, CustomStri } /// Constructs a Term representing `JSON`. - init(JSON: Doubt.JSON) { + public init(JSON: Doubt.JSON) { switch JSON.dictionary { case let .Some(d) where d["key.name"] != nil && d["key.substructure"] != nil: let name = d["key.name"]?.string ?? "" From 7d05f5206bce06ad1b2d9ea45e855e9bc8a5be27 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 16:34:07 -0400 Subject: [PATCH 095/138] Add a BoundsCheckedArray for unpacking arguments. --- prototype/doubt-swift/BoundsCheckedArray.swift | 16 ++++++++++++++++ prototype/doubt-swift/main.swift | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 prototype/doubt-swift/BoundsCheckedArray.swift diff --git a/prototype/doubt-swift/BoundsCheckedArray.swift b/prototype/doubt-swift/BoundsCheckedArray.swift new file mode 100644 index 000000000..8349417fc --- /dev/null +++ b/prototype/doubt-swift/BoundsCheckedArray.swift @@ -0,0 +1,16 @@ +struct BoundsCheckedArray: CollectionType { + init(array: [Element]) { + self.array = array + } + + let array: [Element] + + let startIndex = 0 + var endIndex: Int { + return array.count + } + + subscript (i: Int) -> Element? { + return i < count ? array[i] : nil + } +} diff --git a/prototype/doubt-swift/main.swift b/prototype/doubt-swift/main.swift index e69de29bb..c06cf6964 100644 --- a/prototype/doubt-swift/main.swift +++ b/prototype/doubt-swift/main.swift @@ -0,0 +1,2 @@ +let arguments = BoundsCheckedArray(array: Process.arguments) + From 53270aacfa259de8d809e3326278b535eb1e40f6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 16:37:22 -0400 Subject: [PATCH 096/138] Try to construct terms for the argument files. --- prototype/doubt-swift/main.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/prototype/doubt-swift/main.swift b/prototype/doubt-swift/main.swift index c06cf6964..dbd5e17a8 100644 --- a/prototype/doubt-swift/main.swift +++ b/prototype/doubt-swift/main.swift @@ -1,2 +1,20 @@ +import Doubt +import SourceKittenFramework + let arguments = BoundsCheckedArray(array: Process.arguments) +extension Term { + init?(path: String) { + guard let term = File(path: path) + .map(Structure.init) + .map({ $0.dictionary }) + .map(toAnyObject) + .flatMap({ JSON(object: $0).map { Term(path: path, JSON: $0) } }) else { return nil } + self = term + } +} + +if let a = arguments[1].map(Term.init), b = arguments[2].map(Term.init) { + print(a) + print(b) +} From 1c60f97bbfdf7bacf687d14a9d4544ff066a3d5f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 16:39:30 -0400 Subject: [PATCH 097/138] Print the diff between the files. --- prototype/doubt-swift/main.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/prototype/doubt-swift/main.swift b/prototype/doubt-swift/main.swift index dbd5e17a8..11feacca9 100644 --- a/prototype/doubt-swift/main.swift +++ b/prototype/doubt-swift/main.swift @@ -14,7 +14,6 @@ extension Term { } } -if let a = arguments[1].map(Term.init), b = arguments[2].map(Term.init) { - print(a) - print(b) +if let a = arguments[1].flatMap(Term.init), b = arguments[2].flatMap(Term.init) { + print(Diff(a, b)) } From bf350ee2ed4b29697fb71fc7e27c3d0de7752aad Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 17:00:57 -0400 Subject: [PATCH 098/138] Bump SourceKitten. --- prototype/External/SourceKitten | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/External/SourceKitten b/prototype/External/SourceKitten index 5981d19d5..25aafd5ed 160000 --- a/prototype/External/SourceKitten +++ b/prototype/External/SourceKitten @@ -1 +1 @@ -Subproject commit 5981d19d53cccff7ab3b5b9b7533a875d89e7875 +Subproject commit 25aafd5ed37f855c713e87b75c4693d77dbabc63 From 5524e856539bdf5d1ad0a6e17cdf29187493b312 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 17:01:09 -0400 Subject: [PATCH 099/138] =?UTF-8?q?/dev/null=20=E2=86=92=20.Empty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prototype/doubt-swift/main.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prototype/doubt-swift/main.swift b/prototype/doubt-swift/main.swift index 11feacca9..2a6958243 100644 --- a/prototype/doubt-swift/main.swift +++ b/prototype/doubt-swift/main.swift @@ -5,6 +5,10 @@ let arguments = BoundsCheckedArray(array: Process.arguments) extension Term { init?(path: String) { + guard path != "/dev/null" else { + self = .Empty + return + } guard let term = File(path: path) .map(Structure.init) .map({ $0.dictionary }) From 75aa4c0527b71216d36e5905069ccfd9938a7c3a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 17:01:21 -0400 Subject: [PATCH 100/138] =?UTF-8?q?Don=E2=80=99t=20code=20sign.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prototype/Doubt.xcodeproj/project.pbxproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 1d64cd3a0..efa2d6612 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -381,7 +381,6 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "doubt-swift/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; @@ -395,7 +394,6 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; INFOPLIST_FILE = "doubt-swift/Info.plist"; From 5879e24a100f684133163116fd439a89c7992648 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 17:01:28 -0400 Subject: [PATCH 101/138] Copy frameworks into the .app. --- prototype/Doubt.xcodeproj/project.pbxproj | 36 +++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index efa2d6612..2aaa68005 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -38,6 +38,12 @@ D4C2B1331BB33D080096F92A /* SwiftXPC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; }; D4C2B1341BB33D080096F92A /* SourceKittenFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; }; D4C2B1351BB33D1D0096F92A /* BoundsCheckedArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = D435B7521BB31BBC000902F6 /* BoundsCheckedArray.swift */; }; + D4C2B13F1BB3474C0096F92A /* Commandant.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D4C2B1401BB3474C0096F92A /* Result.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FDA1BB0536700E3C3C1 /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D4C2B1411BB3474C0096F92A /* SWXMLHash.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D4C2B1421BB3474C0096F92A /* SwiftXPC.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D4C2B1431BB3474C0096F92A /* SourceKittenFramework.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D4C2B1441BB347500096F92A /* Doubt.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,6 +56,25 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + D4C2B1381BB346C80096F92A /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + D4C2B1441BB347500096F92A /* Doubt.framework in Copy Frameworks */, + D4C2B13F1BB3474C0096F92A /* Commandant.framework in Copy Frameworks */, + D4C2B1401BB3474C0096F92A /* Result.framework in Copy Frameworks */, + D4C2B1411BB3474C0096F92A /* SWXMLHash.framework in Copy Frameworks */, + D4C2B1421BB3474C0096F92A /* SwiftXPC.framework in Copy Frameworks */, + D4C2B1431BB3474C0096F92A /* SourceKittenFramework.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ D40024ED1BAC819000A110B8 /* SwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftTests.swift; sourceTree = ""; }; D432D4701BA9AC0B00F3FABC /* DiffTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiffTests.swift; sourceTree = ""; }; @@ -59,11 +84,11 @@ D435B7471BB31949000902F6 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; D435B7521BB31BBC000902F6 /* BoundsCheckedArray.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoundsCheckedArray.swift; sourceTree = ""; }; D435B7581BB32117000902F6 /* doubt-swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "doubt-swift.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SourceKittenFramework.framework; path = ../External/SourceKitten/build/Debug/SourceKittenFramework.framework; sourceTree = ""; }; - D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftXPC.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/SwiftXPC.framework"; sourceTree = ""; }; - D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SWXMLHash.framework; path = ../External/SourceKitten/Carthage/Checkouts/SWXMLHash/build/Debug/SWXMLHash.framework; sourceTree = ""; }; - D4413FDA1BB0536700E3C3C1 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Result.framework"; sourceTree = ""; }; - D4413FE71BB055AE00E3C3C1 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Commandant.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/Doubt-fdxdigwapqqdrjfcsvjosyndzrgg/Build/Products/Debug/Commandant.framework"; sourceTree = ""; }; + D4413FD41BB052ED00E3C3C1 /* SourceKittenFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SourceKittenFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D4413FD61BB0531E00E3C3C1 /* SwiftXPC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SwiftXPC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D4413FD81BB0534000E3C3C1 /* SWXMLHash.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SWXMLHash.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D4413FDA1BB0536700E3C3C1 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D4413FE71BB055AE00E3C3C1 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Commandant.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4413FF01BB08FDC00E3C3C1 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -214,6 +239,7 @@ D435B7541BB32117000902F6 /* Sources */, D435B7551BB32117000902F6 /* Frameworks */, D435B7561BB32117000902F6 /* Resources */, + D4C2B1381BB346C80096F92A /* Copy Frameworks */, ); buildRules = ( ); From 3a90f09363d092848100878189a1a71f274494ab Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 17:01:43 -0400 Subject: [PATCH 102/138] Remove the temporary arguments. --- .../xcshareddata/xcschemes/doubt-swift.xcscheme | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme b/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme index 0cf66e46a..f051f80cf 100644 --- a/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme +++ b/prototype/Doubt.xcodeproj/xcshareddata/xcschemes/doubt-swift.xcscheme @@ -61,16 +61,6 @@ ReferencedContainer = "container:Doubt.xcodeproj"> - - - - - - From 0a4dd8111faf2aa55ece80b39b972f06140cdfb2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 17:37:29 -0400 Subject: [PATCH 103/138] Spit out reflected diffs. --- prototype/doubt-swift/main.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/doubt-swift/main.swift b/prototype/doubt-swift/main.swift index 2a6958243..cd8f1d020 100644 --- a/prototype/doubt-swift/main.swift +++ b/prototype/doubt-swift/main.swift @@ -19,5 +19,5 @@ extension Term { } if let a = arguments[1].flatMap(Term.init), b = arguments[2].flatMap(Term.init) { - print(Diff(a, b)) + print(String(reflecting: Diff(a, b))) } From 975ac8fc2f4d4ab105eed310606b0c4360cc2ad5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 17:37:53 -0400 Subject: [PATCH 104/138] Term initialization is partial. --- prototype/Doubt/Syntax.swift | 54 +++++++++++++++++++++----------- prototype/doubt-swift/main.swift | 2 +- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index 39a9f8e12..2a0c54e0c 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -36,33 +36,49 @@ public enum Term: CustomDebugStringConvertible, CustomDocConvertible, CustomStri // MARK: JSON representation. /// Constructs a Term representing the `JSON` in a file at `path`. - public init(path: String, JSON: Doubt.JSON) { - switch JSON.dictionary?["key.substructure"] { - case let .Some(.Array(a)): - self = .Roll(.Group(.Roll(.Literal(path)), a.map(Term.init))) - default: - self = .Empty + public init?(path: String, JSON: Doubt.JSON) { + struct E: ErrorType {} + func die() throws -> A { + throw E() + } + do { + switch JSON.dictionary?["key.substructure"] { + case let .Some(.Array(a)): + self = .Roll(.Group(.Roll(.Literal(path)), try a.map { try Term(JSON: $0) ?? die() })) + default: + return nil + } + } catch _ { + return nil } } /// Constructs a Term representing `JSON`. - public init(JSON: Doubt.JSON) { - switch JSON.dictionary { - case let .Some(d) where d["key.name"] != nil && d["key.substructure"] != nil: - let name = d["key.name"]?.string ?? "" - let substructure = d["key.substructure"]?.array ?? [] - switch d["key.kind"]?.string { - case .Some("source.lang.swift.decl.class"), .Some("source.lang.swift.decl.extension"): - self = .Group(.Literal(name), substructure.map(Term.init)) + public init?(JSON: Doubt.JSON) { + struct E: ErrorType {} + func die() throws -> A { + throw E() + } + do { + switch JSON.dictionary { + case let .Some(d) where d["key.name"] != nil && d["key.substructure"] != nil: + let name = d["key.name"]?.string ?? "" + let substructure = d["key.substructure"]?.array ?? [] + switch d["key.kind"]?.string { + case .Some("source.lang.swift.decl.class"), .Some("source.lang.swift.decl.extension"): + self = .Group(.Literal(name), try substructure.map { try Term(JSON: $0) ?? die() }) - case .Some("source.lang.swift.decl.function.method.instance"), .Some("source.lang.swift.decl.function.free"): - self = .Assign(name, .Abstract([], substructure.map(Term.init))) + case .Some("source.lang.swift.decl.function.method.instance"), .Some("source.lang.swift.decl.function.free"): + self = .Assign(name, .Abstract([], try substructure.map { try Term(JSON: $0) ?? die() })) + default: + return nil + } default: - self = .Empty + return nil } - default: - self = .Empty + } catch _ { + return nil } } } diff --git a/prototype/doubt-swift/main.swift b/prototype/doubt-swift/main.swift index cd8f1d020..4ebe26b54 100644 --- a/prototype/doubt-swift/main.swift +++ b/prototype/doubt-swift/main.swift @@ -13,7 +13,7 @@ extension Term { .map(Structure.init) .map({ $0.dictionary }) .map(toAnyObject) - .flatMap({ JSON(object: $0).map { Term(path: path, JSON: $0) } }) else { return nil } + .flatMap({ JSON(object: $0).flatMap { Term(path: path, JSON: $0) } }) else { return nil } self = term } } From a6c419c6e1b8c5e43960fd87331aa21bb2f69bed Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Wed, 23 Sep 2015 18:22:27 -0400 Subject: [PATCH 105/138] Support enums, structs, and variables. --- prototype/Doubt/Syntax.swift | 39 +++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index 2a0c54e0c..34b34966e 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -55,25 +55,54 @@ public enum Term: CustomDebugStringConvertible, CustomDocConvertible, CustomStri /// Constructs a Term representing `JSON`. public init?(JSON: Doubt.JSON) { + enum Key: String { + case Name = "key.name" + case Substructure = "key.substructure" + } struct E: ErrorType {} func die() throws -> A { throw E() } do { - switch JSON.dictionary { - case let .Some(d) where d["key.name"] != nil && d["key.substructure"] != nil: + switch JSON { + case let .Dictionary(d) where d["key.name"] != nil: let name = d["key.name"]?.string ?? "" let substructure = d["key.substructure"]?.array ?? [] - switch d["key.kind"]?.string { - case .Some("source.lang.swift.decl.class"), .Some("source.lang.swift.decl.extension"): + let kind = d["key.kind"]?.string + switch kind { + case + .Some("source.lang.swift.decl.class"), + .Some("source.lang.swift.decl.extension"), + .Some("source.lang.swift.decl.enum"), + .Some("source.lang.swift.decl.struct"): self = .Group(.Literal(name), try substructure.map { try Term(JSON: $0) ?? die() }) - case .Some("source.lang.swift.decl.function.method.instance"), .Some("source.lang.swift.decl.function.free"): + case .Some("source.lang.swift.decl.enumelement"): + fallthrough + case + .Some("source.lang.swift.decl.function.method.instance"), + .Some("source.lang.swift.decl.function.free"): self = .Assign(name, .Abstract([], try substructure.map { try Term(JSON: $0) ?? die() })) + case + .Some("source.lang.swift.decl.var.instance"), + .Some("source.lang.swift.decl.var.static"): + self = .Variable(name) + default: return nil } + + case let .Dictionary(d) where d["key.kind"]?.string == "source.lang.swift.decl.enumcase" && d["key.substructure"]?.array?.count == 1: + let substructure = d["key.substructure"]?.array ?? [] + self = try Term(JSON: substructure[0]) ?? die() + + case let .Dictionary(d) where d["key.kind"]?.string == "source.lang.swift.syntaxtype.comment.mark": + self = .Empty + + case .Null: + self = .Empty + default: return nil } From abb625b501a63140255911c2d0c2c6d89eae7962 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 24 Sep 2015 13:28:46 -0400 Subject: [PATCH 106/138] Edit graph vertices. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 ++++ prototype/Doubt/Vertex.swift | 28 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 prototype/Doubt/Vertex.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 2aaa68005..05e32c478 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ D4413FE91BB055B500E3C3C1 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4413FE71BB055AE00E3C3C1 /* Commandant.framework */; }; D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; + D4A71DC51BB45B850051416D /* Vertex.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4A71DC41BB45B850051416D /* Vertex.swift */; settings = {ASSET_TAGS = (); }; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; @@ -91,6 +92,7 @@ D4413FE71BB055AE00E3C3C1 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Commandant.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4413FF01BB08FDC00E3C3C1 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; + D4A71DC41BB45B850051416D /* Vertex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vertex.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -191,6 +193,7 @@ D432D4741BA9D6A400F3FABC /* Memo.swift */, D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */, D4413FF01BB08FDC00E3C3C1 /* JSON.swift */, + D4A71DC41BB45B850051416D /* Vertex.swift */, D4AAE5001B5AE22E004E581F /* Supporting Files */, ); path = Doubt; @@ -371,6 +374,7 @@ D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */, D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */, D4AAE54C1B5AE42D004E581F /* Equatable.swift in Sources */, + D4A71DC51BB45B850051416D /* Vertex.swift in Sources */, D4AAE54A1B5AE2D0004E581F /* Syntax.swift in Sources */, D432D4731BA9C55300F3FABC /* Stream.swift in Sources */, D4AAE5421B5AE2D0004E581F /* Doc.swift in Sources */, diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift new file mode 100644 index 000000000..6fbea314c --- /dev/null +++ b/prototype/Doubt/Vertex.swift @@ -0,0 +1,28 @@ +public enum Vertex { + case X(Element, Memo) + case Y(Element, Memo) + case XY(Element, Memo, Memo, Memo) + case End(Element) + + public var row: Stream { + switch self { + case let .X(x, xs): + return .Cons(x, xs.map { $0.row }) + case let .XY(x, xs, _, _): + return .Cons(x, xs.map { $0.row }) + default: + return .Nil + } + } + + public var column: Stream { + switch self { + case let .Y(y, ys): + return .Cons(y, ys.map { $0.column }) + case let .XY(y, _, ys, _): + return .Cons(y, ys.map { $0.column }) + default: + return .Nil + } + } +} From 40211726bcfe0b40ed3787dbc52f8b041ed7ca09 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 24 Sep 2015 15:10:56 -0400 Subject: [PATCH 107/138] Add a lazy right-fold to Stream. --- prototype/Doubt/Stream.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/prototype/Doubt/Stream.swift b/prototype/Doubt/Stream.swift index eeb57611c..f79da6a20 100644 --- a/prototype/Doubt/Stream.swift +++ b/prototype/Doubt/Stream.swift @@ -63,6 +63,13 @@ public enum Stream: NilLiteralConvertible, SequenceType { } + public func fold(initial: Result, combine: (A, Memo) -> Result) -> Result { + return analysis( + ifCons: { combine($0, $1.map { $0.fold(initial, combine: combine) }) }, + ifNil: const(initial)) + } + + public init(nilLiteral: ()) { self = .Nil } From 089d5417aab26c3ee2f4b74cc6a99e09fd9c8f2d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 24 Sep 2015 15:45:36 -0400 Subject: [PATCH 108/138] Remove row, column, X, and Y from Vertex. This is a more wasteful representation but we can deal with that later. --- prototype/Doubt/Vertex.swift | 45 +++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 6fbea314c..bc728fa72 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -1,28 +1,37 @@ public enum Vertex { - case X(Element, Memo) - case Y(Element, Memo) - case XY(Element, Memo, Memo, Memo) - case End(Element) + case XY(Element, Memo, Memo) + case End - public var row: Stream { + + public var right: Memo { switch self { - case let .X(x, xs): - return .Cons(x, xs.map { $0.row }) - case let .XY(x, xs, _, _): - return .Cons(x, xs.map { $0.row }) - default: - return .Nil + case let .XY(_, xs, _): + return xs + case .End: + return Memo(evaluated: .End) } } - public var column: Stream { + public var down: Memo { switch self { - case let .Y(y, ys): - return .Cons(y, ys.map { $0.column }) - case let .XY(y, _, ys, _): - return .Cons(y, ys.map { $0.column }) - default: - return .Nil + case let .XY(_, _, ys): + return ys + case .End: + return Memo(evaluated: .End) + } + } + + public var diagonal: Memo { + return right.flatMap { $0.down } + } + + + public func map(transform: Element -> Other) -> Vertex { + switch self { + case let .XY(xy, xs, ys): + return .XY(transform(xy), xs.map { $0.map(transform) }, ys.map { $0.map(transform) }) + case .End: + return .End } } } From 8387f5ce711a1e056e7583e6024158e5cb5522cd Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 24 Sep 2015 15:45:56 -0400 Subject: [PATCH 109/138] Vertices can be constructed from pairs of streams. --- prototype/Doubt/Vertex.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index bc728fa72..ed9db5c62 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -24,6 +24,18 @@ public enum Vertex { public var diagonal: Memo { return right.flatMap { $0.down } } + + + public init(rows: Stream, columns: Stream, combine: (A, B) -> Element) { + self = columns + .map { b in rows.map { a in (a, b) } } + .fold(Vertex<(A, B)>.End) { + $0.fold(($1, .End)) { + ($1.flatMap { row, _ in row }.flatMap { $0.right }, .XY($0, $1.map { _, column in column }, $1.flatMap { row, _ in row })) + }.1 + } + .map(combine) + } public func map(transform: Element -> Other) -> Vertex { From 6e0cf0d6a125a70a6f09a8fc72c84b3e8bd2db48 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 24 Sep 2015 18:23:38 -0400 Subject: [PATCH 110/138] Memo does not need the evaluated label. --- prototype/Doubt/Memo.swift | 2 +- prototype/Doubt/Stream.swift | 6 +++--- prototype/Doubt/Vertex.swift | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/prototype/Doubt/Memo.swift b/prototype/Doubt/Memo.swift index 5d1677358..7c39e9916 100644 --- a/prototype/Doubt/Memo.swift +++ b/prototype/Doubt/Memo.swift @@ -3,7 +3,7 @@ public struct Memo { self.init(.Unevaluated(unevaluted)) } - public init(evaluated: A) { + public init(_ evaluated: A) { self.init(.Evaluated(evaluated)) } diff --git a/prototype/Doubt/Stream.swift b/prototype/Doubt/Stream.swift index f79da6a20..a8d3d3a71 100644 --- a/prototype/Doubt/Stream.swift +++ b/prototype/Doubt/Stream.swift @@ -32,7 +32,7 @@ public enum Stream: NilLiteralConvertible, SequenceType { } public var rest: Memo { - return analysis(ifCons: { $1 }, ifNil: { Memo(evaluated: .Nil) }) + return analysis(ifCons: { $1 }, ifNil: { Memo(.Nil) }) } public var isEmpty: Bool { @@ -59,7 +59,7 @@ public enum Stream: NilLiteralConvertible, SequenceType { } public func concat(other: Stream) -> Stream { - return concat(Memo(evaluated: other)) + return concat(Memo(other)) } @@ -76,7 +76,7 @@ public enum Stream: NilLiteralConvertible, SequenceType { public func generate() -> AnyGenerator { - var current = Memo(evaluated: self) + var current = Memo(self) return anyGenerator { let next = current.value.first current = current.value.rest diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index ed9db5c62..29f3ac9f7 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -8,7 +8,7 @@ public enum Vertex { case let .XY(_, xs, _): return xs case .End: - return Memo(evaluated: .End) + return Memo(.End) } } @@ -17,14 +17,14 @@ public enum Vertex { case let .XY(_, _, ys): return ys case .End: - return Memo(evaluated: .End) + return Memo(.End) } } public var diagonal: Memo { return right.flatMap { $0.down } } - + public init(rows: Stream, columns: Stream, combine: (A, B) -> Element) { self = columns From f1e06015d063433d41c6536cdccaedd96fe16881 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 24 Sep 2015 18:23:48 -0400 Subject: [PATCH 111/138] Work around a runtime deadlock. --- prototype/Doubt/Vertex.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 29f3ac9f7..515a9a816 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -1,5 +1,5 @@ public enum Vertex { - case XY(Element, Memo, Memo) + indirect case XY(Element, Memo, Memo) case End From a70fc630aaf223c05da1a2122742ad9e37027e5e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 24 Sep 2015 18:23:56 -0400 Subject: [PATCH 112/138] Add an element property to Vertex. --- prototype/Doubt/Vertex.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 515a9a816..43d64bfd6 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -2,6 +2,14 @@ public enum Vertex { indirect case XY(Element, Memo, Memo) case End + public var element: Element? { + switch self { + case let .XY(a, _, _): + return a + case .End: + return nil + } + } public var right: Memo { switch self { From b76d361412de746ee785fa82073c0d930d4568c6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 24 Sep 2015 18:24:05 -0400 Subject: [PATCH 113/138] Vertex equality. --- prototype/Doubt/Equatable.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/prototype/Doubt/Equatable.swift b/prototype/Doubt/Equatable.swift index 34cfd49e7..e134da62d 100644 --- a/prototype/Doubt/Equatable.swift +++ b/prototype/Doubt/Equatable.swift @@ -60,3 +60,14 @@ public func == (left: Doc, right: Doc) -> Bool { return false } } + +public func == (left: Vertex, right: Vertex) -> Bool { + switch (left, right) { + case (.End, .End): + return true + case let (.XY(a, x1, y1), .XY(b, x2, y2)): + return a == b && x1.value == y1.value && x2.value == y2.value + default: + return false + } +} From b25095372a3220911bc67632b092d02db1479bc4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Thu, 24 Sep 2015 18:26:23 -0400 Subject: [PATCH 114/138] Revert "Memo does not need the evaluated label." This reverts commit 238df4a1b54752041f134375569049c2afd79632. --- prototype/Doubt/Memo.swift | 2 +- prototype/Doubt/Stream.swift | 6 +++--- prototype/Doubt/Vertex.swift | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/prototype/Doubt/Memo.swift b/prototype/Doubt/Memo.swift index 7c39e9916..5d1677358 100644 --- a/prototype/Doubt/Memo.swift +++ b/prototype/Doubt/Memo.swift @@ -3,7 +3,7 @@ public struct Memo { self.init(.Unevaluated(unevaluted)) } - public init(_ evaluated: A) { + public init(evaluated: A) { self.init(.Evaluated(evaluated)) } diff --git a/prototype/Doubt/Stream.swift b/prototype/Doubt/Stream.swift index a8d3d3a71..f79da6a20 100644 --- a/prototype/Doubt/Stream.swift +++ b/prototype/Doubt/Stream.swift @@ -32,7 +32,7 @@ public enum Stream: NilLiteralConvertible, SequenceType { } public var rest: Memo { - return analysis(ifCons: { $1 }, ifNil: { Memo(.Nil) }) + return analysis(ifCons: { $1 }, ifNil: { Memo(evaluated: .Nil) }) } public var isEmpty: Bool { @@ -59,7 +59,7 @@ public enum Stream: NilLiteralConvertible, SequenceType { } public func concat(other: Stream) -> Stream { - return concat(Memo(other)) + return concat(Memo(evaluated: other)) } @@ -76,7 +76,7 @@ public enum Stream: NilLiteralConvertible, SequenceType { public func generate() -> AnyGenerator { - var current = Memo(self) + var current = Memo(evaluated: self) return anyGenerator { let next = current.value.first current = current.value.rest diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 43d64bfd6..1e5ee73d6 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -16,7 +16,7 @@ public enum Vertex { case let .XY(_, xs, _): return xs case .End: - return Memo(.End) + return Memo(evaluated: .End) } } @@ -25,14 +25,14 @@ public enum Vertex { case let .XY(_, _, ys): return ys case .End: - return Memo(.End) + return Memo(evaluated: .End) } } public var diagonal: Memo { return right.flatMap { $0.down } } - + public init(rows: Stream, columns: Stream, combine: (A, B) -> Element) { self = columns From ece5c942d5e1c48f172340af05e7a222c3680295 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 11:57:28 -0400 Subject: [PATCH 115/138] Memo can print itself. --- prototype/Doubt/Memo.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/Memo.swift b/prototype/Doubt/Memo.swift index 5d1677358..91d4b7806 100644 --- a/prototype/Doubt/Memo.swift +++ b/prototype/Doubt/Memo.swift @@ -1,4 +1,4 @@ -public struct Memo { +public struct Memo: CustomDebugStringConvertible, CustomStringConvertible { public init(unevaluted: () -> A) { self.init(.Unevaluated(unevaluted)) } @@ -25,6 +25,15 @@ public struct Memo { public func flatMap(transform: A -> Memo) -> Memo { return Memo { transform(self.value).value } } + + + public var description: String { + return String(value) + } + + public var debugDescription: String { + return String(reflecting: value) + } } private final class MutableBox { From 8178904a3607bf83fbaf41aa491e74997cbb7356 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 11:57:53 -0400 Subject: [PATCH 116/138] Generalize Vertex construction to arbitrary sequences. --- prototype/Doubt/Vertex.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 1e5ee73d6..90bde977e 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -34,10 +34,12 @@ public enum Vertex { } - public init(rows: Stream, columns: Stream, combine: (A, B) -> Element) { + public init(rows: S1, columns: S2, combine: (S1.Generator.Element, S2.Generator.Element) -> Element) { + let rows = Stream(sequence: rows) + let columns = Stream(sequence: columns) self = columns .map { b in rows.map { a in (a, b) } } - .fold(Vertex<(A, B)>.End) { + .fold(Vertex<(S1.Generator.Element, S2.Generator.Element)>.End) { $0.fold(($1, .End)) { ($1.flatMap { row, _ in row }.flatMap { $0.right }, .XY($0, $1.map { _, column in column }, $1.flatMap { row, _ in row })) }.1 From 0a88c407e56205b13a07afebf642e51f586b1092 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:22:31 -0400 Subject: [PATCH 117/138] Construct streams with unfold. --- prototype/Doubt/Stream.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prototype/Doubt/Stream.swift b/prototype/Doubt/Stream.swift index f79da6a20..183f6780a 100644 --- a/prototype/Doubt/Stream.swift +++ b/prototype/Doubt/Stream.swift @@ -69,6 +69,10 @@ public enum Stream: NilLiteralConvertible, SequenceType { ifNil: const(initial)) } + public static func unfold(state: State, _ unspool: State -> (A, State)?) -> Stream { + return unspool(state).map { value, next in .Cons(value, Memo { self.unfold(next, unspool) }) } ?? .Nil + } + public init(nilLiteral: ()) { self = .Nil From 24bc2610ff2e695081887f4b2060946edce08272 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:36:11 -0400 Subject: [PATCH 118/138] Add a case analysis method. --- prototype/Doubt/Vertex.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 90bde977e..0f4d88ff0 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -2,6 +2,15 @@ public enum Vertex { indirect case XY(Element, Memo, Memo) case End + public func analysis(@noescape ifXY ifXY: (Element, Memo, Memo) -> Result, @noescape ifEnd: () -> Result) -> Result { + switch self { + case let .XY(a, x, y): + return ifXY(a, x, y) + case .End: + return ifEnd() + } + } + public var element: Element? { switch self { case let .XY(a, _, _): From 39c46edeb94ecb6f935eab252626f9cc143772d5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:37:08 -0400 Subject: [PATCH 119/138] Implement the eliminators with analysis. --- prototype/Doubt/Vertex.swift | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 0f4d88ff0..d5c84bc95 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -12,30 +12,21 @@ public enum Vertex { } public var element: Element? { - switch self { - case let .XY(a, _, _): - return a - case .End: - return nil - } + return analysis( + ifXY: { x, _, _ in x }, + ifEnd: const(nil)) } public var right: Memo { - switch self { - case let .XY(_, xs, _): - return xs - case .End: - return Memo(evaluated: .End) - } + return analysis( + ifXY: { _, xs, _ in xs }, + ifEnd: const(Memo(evaluated: .End))) } public var down: Memo { - switch self { - case let .XY(_, _, ys): - return ys - case .End: - return Memo(evaluated: .End) - } + return analysis( + ifXY: { _, _, ys in ys }, + ifEnd: const(Memo(evaluated: .End))) } public var diagonal: Memo { From 21f3bc9dcc9f771d0fde0de2f129a321ff88def2 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:37:42 -0400 Subject: [PATCH 120/138] Xcode did not delete this before, apparently. --- prototype/Doubt/Vertex.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index d5c84bc95..20fb81327 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -32,7 +32,7 @@ public enum Vertex { public var diagonal: Memo { return right.flatMap { $0.down } } - + public init(rows: S1, columns: S2, combine: (S1.Generator.Element, S2.Generator.Element) -> Element) { let rows = Stream(sequence: rows) From 652d1f9db45daf955478ca0000be8d634ad48fc5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:37:58 -0400 Subject: [PATCH 121/138] Add row/column implementations back using Stream.unfold. --- prototype/Doubt/Vertex.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 20fb81327..06f09106f 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -34,6 +34,22 @@ public enum Vertex { } + public var row: Stream { + return Stream.unfold(Memo(evaluated: self)) { + $0.value.analysis( + ifXY: { here, across, _ in .Some(here, across) }, + ifEnd: const(nil)) + } + } + + public var column: Stream { + return Stream.unfold(Memo(evaluated: self)) { + $0.value.analysis( + ifXY: { here, _, down in .Some(here, down) }, + ifEnd: const(nil)) + } + } + public init(rows: S1, columns: S2, combine: (S1.Generator.Element, S2.Generator.Element) -> Element) { let rows = Stream(sequence: rows) let columns = Stream(sequence: columns) From 98e66acdbfcabb2c3602552eea9b1f78426a4af3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:38:11 -0400 Subject: [PATCH 122/138] Row-/column-major streams of vertices. --- prototype/Doubt/Vertex.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 06f09106f..e8bfc56ec 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -50,6 +50,23 @@ public enum Vertex { } } + public var rowMajor: Stream> { + return Stream.unfold(Memo(evaluated: self), { (state: Memo) -> (Stream, Memo)? in + state.value.analysis( + ifXY: { _, _, down in (state.value.row, down) }, + ifEnd: const(nil)) + }) + } + + public var columnMajor: Stream> { + return Stream.unfold(Memo(evaluated: self), { (state: Memo) -> (Stream, Memo)? in + state.value.analysis( + ifXY: { _, across, _ in (state.value.column, across) }, + ifEnd: const(nil)) + }) + } + + public init(rows: S1, columns: S2, combine: (S1.Generator.Element, S2.Generator.Element) -> Element) { let rows = Stream(sequence: rows) let columns = Stream(sequence: columns) From 3dc89059ace3b2d7049d1064c8df52ec11bc0ffb Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:43:54 -0400 Subject: [PATCH 123/138] Avoid an excess map. --- prototype/Doubt/Vertex.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index e8bfc56ec..094a08490 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -71,13 +71,12 @@ public enum Vertex { let rows = Stream(sequence: rows) let columns = Stream(sequence: columns) self = columns - .map { b in rows.map { a in (a, b) } } - .fold(Vertex<(S1.Generator.Element, S2.Generator.Element)>.End) { + .map { b in rows.map { a in combine(a, b) } } + .fold(Vertex.End) { $0.fold(($1, .End)) { ($1.flatMap { row, _ in row }.flatMap { $0.right }, .XY($0, $1.map { _, column in column }, $1.flatMap { row, _ in row })) }.1 } - .map(combine) } From 18bcad016588e74380ba48aee154ee02569acb2e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:44:20 -0400 Subject: [PATCH 124/138] Vertex is CustomDebugStringConvertible. --- prototype/Doubt/Vertex.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 094a08490..701c19f47 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -1,4 +1,4 @@ -public enum Vertex { +public enum Vertex: CustomDebugStringConvertible { indirect case XY(Element, Memo, Memo) case End @@ -88,4 +88,11 @@ public enum Vertex { return .End } } + + + public var debugDescription: String { + return rowMajor.map { + $0.map { String(reflecting: $0) }.joinWithSeparator("\t") + }.joinWithSeparator("\n") + } } From a0edc9fe4936ae975bdc65f047db6a756a051054 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:45:10 -0400 Subject: [PATCH 125/138] Vertex is CustomStringConvertible. --- prototype/Doubt/Vertex.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 701c19f47..fa5cacdf8 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -1,4 +1,4 @@ -public enum Vertex: CustomDebugStringConvertible { +public enum Vertex: CustomDebugStringConvertible, CustomStringConvertible { indirect case XY(Element, Memo, Memo) case End @@ -95,4 +95,10 @@ public enum Vertex: CustomDebugStringConvertible { $0.map { String(reflecting: $0) }.joinWithSeparator("\t") }.joinWithSeparator("\n") } + + public var description: String { + return rowMajor.map { + $0.map { String($0) }.joinWithSeparator("\t") + }.joinWithSeparator("\n") + } } From 00f1daa61a07f264cd567396dadfa585cefc60f9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 12:52:59 -0400 Subject: [PATCH 126/138] Construct vertices in row-major order. --- prototype/Doubt/Vertex.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index fa5cacdf8..c63b63a22 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -70,8 +70,8 @@ public enum Vertex: CustomDebugStringConvertible, CustomStringConvertib public init(rows: S1, columns: S2, combine: (S1.Generator.Element, S2.Generator.Element) -> Element) { let rows = Stream(sequence: rows) let columns = Stream(sequence: columns) - self = columns - .map { b in rows.map { a in combine(a, b) } } + self = rows + .map { a in columns.map { b in combine(a, b) } } .fold(Vertex.End) { $0.fold(($1, .End)) { ($1.flatMap { row, _ in row }.flatMap { $0.right }, .XY($0, $1.map { _, column in column }, $1.flatMap { row, _ in row })) From da12af7313b4988120e2ca1acd0ddfdb868bab83 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 13:57:35 -0400 Subject: [PATCH 127/138] Stream zipping. --- prototype/Doubt/Stream.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/prototype/Doubt/Stream.swift b/prototype/Doubt/Stream.swift index 183f6780a..5b2ffda00 100644 --- a/prototype/Doubt/Stream.swift +++ b/prototype/Doubt/Stream.swift @@ -74,6 +74,14 @@ public enum Stream: NilLiteralConvertible, SequenceType { } + public func zipWith(sequence: S) -> Stream<(A, S.Generator.Element)> { + return Stream<(A, S.Generator.Element)>.unfold((self, Stream(sequence: sequence))) { + guard let (x, xs) = $0.uncons, (y, ys) = $1.uncons else { return nil } + return ((x, y), (xs.value, ys.value)) + } + } + + public init(nilLiteral: ()) { self = .Nil } From 1a44c5ee7a7a5694bcc2628ede45071c460b7d64 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 25 Sep 2015 18:50:59 -0400 Subject: [PATCH 128/138] Correct the inversion of alternating rows. --- prototype/Doubt/Vertex.swift | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index c63b63a22..32e39a46c 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -70,12 +70,19 @@ public enum Vertex: CustomDebugStringConvertible, CustomStringConvertib public init(rows: S1, columns: S2, combine: (S1.Generator.Element, S2.Generator.Element) -> Element) { let rows = Stream(sequence: rows) let columns = Stream(sequence: columns) + func across(vertex: Vertex) -> Stream>> { + return Stream.unfold(Memo(evaluated: vertex)) { vertex in + vertex.value.analysis( + ifXY: { _, xs, _ in .Some(vertex, xs) }, + ifEnd: const(.Some(vertex, vertex))) + } + } self = rows .map { a in columns.map { b in combine(a, b) } } - .fold(Vertex.End) { - $0.fold(($1, .End)) { - ($1.flatMap { row, _ in row }.flatMap { $0.right }, .XY($0, $1.map { _, column in column }, $1.flatMap { row, _ in row })) - }.1 + .fold(.End) { + $0.zipWith(across($1.value)).fold(.End) { + .XY($0.0, $1, $0.1) + } } } From 4a16b06e9216bc2cb9cb6a94dc7db6bdf4a56167 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 09:54:44 -0400 Subject: [PATCH 129/138] Correct bogus equality tests. --- prototype/Doubt/Equatable.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Equatable.swift b/prototype/Doubt/Equatable.swift index e134da62d..476952c00 100644 --- a/prototype/Doubt/Equatable.swift +++ b/prototype/Doubt/Equatable.swift @@ -66,7 +66,7 @@ public func == (left: Vertex, right: Vertex) -> Bool { case (.End, .End): return true case let (.XY(a, x1, y1), .XY(b, x2, y2)): - return a == b && x1.value == y1.value && x2.value == y2.value + return a == b && x1.value == x2.value && y1.value == y2.value default: return false } From b97e2e4833afec871bc4906043efe238a50dc1e8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 09:55:04 -0400 Subject: [PATCH 130/138] Test Vertex construction. --- prototype/Doubt.xcodeproj/project.pbxproj | 4 +++ prototype/DoubtTests/VertexTests.swift | 38 +++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 prototype/DoubtTests/VertexTests.swift diff --git a/prototype/Doubt.xcodeproj/project.pbxproj b/prototype/Doubt.xcodeproj/project.pbxproj index 05e32c478..314c4060a 100644 --- a/prototype/Doubt.xcodeproj/project.pbxproj +++ b/prototype/Doubt.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ D4413FEF1BB06D4C00E3C3C1 /* Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */; }; D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4413FF01BB08FDC00E3C3C1 /* JSON.swift */; }; D4A71DC51BB45B850051416D /* Vertex.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4A71DC41BB45B850051416D /* Vertex.swift */; settings = {ASSET_TAGS = (); }; }; + D4A71DC71BB4AC9E0051416D /* VertexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4A71DC61BB4AC9E0051416D /* VertexTests.swift */; settings = {ASSET_TAGS = (); }; }; D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; }; D4AAE5401B5AE2D0004E581F /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* Array.swift */; }; D4AAE5411B5AE2D0004E581F /* Diff.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5361B5AE2D0004E581F /* Diff.swift */; }; @@ -93,6 +94,7 @@ D4413FEE1BB06D4C00E3C3C1 /* Dictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dictionary.swift; sourceTree = ""; }; D4413FF01BB08FDC00E3C3C1 /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; }; D4A71DC41BB45B850051416D /* Vertex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vertex.swift; sourceTree = ""; }; + D4A71DC61BB4AC9E0051416D /* VertexTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VertexTests.swift; sourceTree = ""; }; D4AAE4FD1B5AE22E004E581F /* Doubt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Doubt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4AAE5011B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -217,6 +219,7 @@ children = ( D432D4701BA9AC0B00F3FABC /* DiffTests.swift */, D40024ED1BAC819000A110B8 /* SwiftTests.swift */, + D4A71DC61BB4AC9E0051416D /* VertexTests.swift */, D4AAE5141B5AE22E004E581F /* Info.plist */, ); path = DoubtTests; @@ -393,6 +396,7 @@ files = ( D40024EE1BAC819000A110B8 /* SwiftTests.swift in Sources */, D432D4711BA9AC0B00F3FABC /* DiffTests.swift in Sources */, + D4A71DC71BB4AC9E0051416D /* VertexTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/prototype/DoubtTests/VertexTests.swift b/prototype/DoubtTests/VertexTests.swift new file mode 100644 index 000000000..c662a3663 --- /dev/null +++ b/prototype/DoubtTests/VertexTests.swift @@ -0,0 +1,38 @@ +final class VertexTests: XCTestCase { + func testConstructingWithStreamsProducesMatrixOfProducts() { + let actual = Vertex(rows: Stream(sequence: [ "a", "b" ]), columns: Stream(sequence: [ "0", "1" ]), combine: +) + + let expected: Vertex = { + let end = Memo>(evaluated: .End) + let b1 = Memo> { .XY("b1", end, end) } + let b0 = Memo> { .XY("b0", b1, end) } + let a1 = Memo> { .XY("a1", end, b1) } + let a0 = Memo> { .XY("a0", a1, b0) } + return a0.value + }() + XCTAssert(actual == expected, "\(String(reflecting: actual)) != \(String(reflecting: expected))") + } + + func testConstructingWithStreamsProducesMatrix() { + let actual = Vertex(rows: Stream(sequence: [ "a", "b", "c" ]), columns: Stream(sequence: [ "0", "1", "2" ]), combine: +) + + let expected: Vertex = { + let end = Memo>(evaluated: .End) + let c2 = Memo> { .XY("c2", end, end) } + let c1 = Memo> { .XY("c1", c2, end) } + let c0 = Memo> { .XY("c0", c1, end) } + let b2 = Memo> { .XY("b2", end, c2) } + let b1 = Memo> { .XY("b1", b2, c1) } + let b0 = Memo> { .XY("b0", b1, c0) } + let a2 = Memo> { .XY("a2", end, b2) } + let a1 = Memo> { .XY("a1", a2, b1) } + let a0 = Memo> { .XY("a0", a1, b0) } + return a0.value + }() + XCTAssert(actual == expected, "\(String(reflecting: actual)) != \(String(reflecting: expected))") + } +} + + +@testable import Doubt +import XCTest From d110a149dc4ae376498a005c63d188856e9d2403 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 10:02:31 -0400 Subject: [PATCH 131/138] Taking of n values from streams. --- prototype/Doubt/Stream.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/prototype/Doubt/Stream.swift b/prototype/Doubt/Stream.swift index 5b2ffda00..4b3a99fa8 100644 --- a/prototype/Doubt/Stream.swift +++ b/prototype/Doubt/Stream.swift @@ -82,6 +82,16 @@ public enum Stream: NilLiteralConvertible, SequenceType { } + public func take(n: Int) -> Stream { + return Stream.unfold((Memo(evaluated: self), n)) { stream, n in + guard let (x, xs) = stream.value.uncons else { return nil } + return n >= 0 + ? (x, (xs, n - 1)) + : nil + } + } + + public init(nilLiteral: ()) { self = .Nil } From 48bee808f68a22d2bf89ff77ef182f8696fa0685 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 10:28:44 -0400 Subject: [PATCH 132/138] =?UTF-8?q?Correct=20`take`=E2=80=99s=20semantics.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prototype/Doubt/Stream.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prototype/Doubt/Stream.swift b/prototype/Doubt/Stream.swift index 4b3a99fa8..7a47d336e 100644 --- a/prototype/Doubt/Stream.swift +++ b/prototype/Doubt/Stream.swift @@ -85,7 +85,7 @@ public enum Stream: NilLiteralConvertible, SequenceType { public func take(n: Int) -> Stream { return Stream.unfold((Memo(evaluated: self), n)) { stream, n in guard let (x, xs) = stream.value.uncons else { return nil } - return n >= 0 + return n > 0 ? (x, (xs, n - 1)) : nil } From 1a6f6b588b974757844d1f2a35890ee0a7157651 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 10:29:31 -0400 Subject: [PATCH 133/138] Add a Fibonacci stream to the tests. --- prototype/DoubtTests/VertexTests.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/prototype/DoubtTests/VertexTests.swift b/prototype/DoubtTests/VertexTests.swift index c662a3663..e7da1f006 100644 --- a/prototype/DoubtTests/VertexTests.swift +++ b/prototype/DoubtTests/VertexTests.swift @@ -31,6 +31,15 @@ final class VertexTests: XCTestCase { }() XCTAssert(actual == expected, "\(String(reflecting: actual)) != \(String(reflecting: expected))") } + + func testFib() { + XCTAssertEqual(Array(fib.take(7)), [ 1, 1, 2, 3, 5, 8, 13 ]) + } +} + + +private let fib: Stream = Stream.unfold((0, 1)) { x, y in + (y, (y, x + y)) } From b1a3c8046ebe265ab69ce658746d9d9f8055d24e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 12:09:43 -0400 Subject: [PATCH 134/138] Vertex emptiness. --- prototype/Doubt/Vertex.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prototype/Doubt/Vertex.swift b/prototype/Doubt/Vertex.swift index 32e39a46c..7c20f0554 100644 --- a/prototype/Doubt/Vertex.swift +++ b/prototype/Doubt/Vertex.swift @@ -11,6 +11,10 @@ public enum Vertex: CustomDebugStringConvertible, CustomStringConvertib } } + public var isEmpty: Bool { + return analysis(ifXY: const(false), ifEnd: const(true)) + } + public var element: Element? { return analysis( ifXY: { x, _, _ in x }, From 7237ecd7e4677bc7fd74b2c74841903afa333bab Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 14:17:48 -0400 Subject: [PATCH 135/138] Diff using Vertex. --- prototype/Doubt/Diff.swift | 51 ++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/prototype/Doubt/Diff.swift b/prototype/Doubt/Diff.swift index 906b624ca..4edfff89f 100644 --- a/prototype/Doubt/Diff.swift +++ b/prototype/Doubt/Diff.swift @@ -91,34 +91,47 @@ public enum Diff: Comparable, CustomDebugStringConvertible, CustomDocConvertible } public static func diff(a: C1, _ b: C2) -> [Diff] { - func magnitude(diffs: Stream) -> Int { - return diffs.map { $0.magnitude }.reduce(0, combine: +) + func magnitude(diffs: Stream<(Diff, Int)>) -> Int { + return diffs.first?.1 ?? 0 + // fixme; this should actually consider the rest of the diff, but we aren’t memoizing that correctly. +// return diffs.map { $1 }.fold(0, combine: { $0 + $1.value }) } func min(a: A, _ rest: A..., _ isLessThan: (A, A) -> Bool) -> A { - return rest.reduce(a, combine: { - isLessThan($0, $1) ? $0 : $1 - }) + return rest.reduce(a) { isLessThan($0, $1) ? $0 : $1 } } - func diff(a: Stream, _ b: Stream) -> Stream { - switch (a, b) { - case (.Nil, .Nil): + let graph = Vertex<(Term, Term, Diff, Int)>(rows: Stream(sequence: a), columns: Stream(sequence: b)) { + let diff = Diff($0, $1) + return ($0, $1, diff, diff.magnitude) + } + + func diff(vertex: Vertex<(Term, Term, Diff, Int)>) -> Stream<(Diff, Int)> { + switch vertex { + case .End: return .Nil - case (.Nil, .Cons): - return b.map(Diff.Insert) - case (.Cons, .Nil): - return a.map(Diff.Delete) - case let (.Cons(x, xs), .Cons(y, ys)): - let here = Stream.Cons(Diff(x, y), Memo { diff(xs.value, ys.value) }) - let insert = Stream.Cons(Diff.Insert(y), Memo { diff(a, ys.value) }) - let delete = Stream.Cons(Diff.Delete(x), Memo { diff(xs.value, b) }) - return min(here, insert, delete) { - magnitude($0) < magnitude($1) + + case let .XY((a, b, copy, copyCost), x, y): + let right = x.value + let down = y.value + switch (right, down) { + case (.End, .End): + return .Cons((copy, copyCost), Memo(evaluated: .Nil)) + case (.End, .XY): + return vertex.row.map { (Diff.Delete($0.0), 1) } + case (.XY, .End): + return vertex.column.map { (Diff.Insert($0.0), 1) } + case (.XY, .XY): + let copy = Stream.Cons((copy, copyCost), vertex.diagonal.map(diff)) + let insert = Stream.Cons((Diff.Insert(b), 1), x.map(diff)) + let delete = Stream.Cons((Diff.Delete(a), 1), y.map(diff)) + return min(copy, insert, delete) { + magnitude($0) < magnitude($1) + } } } } - return Array(diff(Stream(sequence: a), Stream(sequence: b))) + return Array(diff(graph).map { $0.0 }) } } From b43a5eaf2664c789b6dfa1fee5af6fedaa9c4c05 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 14:17:55 -0400 Subject: [PATCH 136/138] Revert "Diff using Vertex." This reverts commit 881436e01d381b404c12e9c63a8634d6110d251a. --- prototype/Doubt/Diff.swift | 51 ++++++++++++++------------------------ 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/prototype/Doubt/Diff.swift b/prototype/Doubt/Diff.swift index 4edfff89f..906b624ca 100644 --- a/prototype/Doubt/Diff.swift +++ b/prototype/Doubt/Diff.swift @@ -91,47 +91,34 @@ public enum Diff: Comparable, CustomDebugStringConvertible, CustomDocConvertible } public static func diff(a: C1, _ b: C2) -> [Diff] { - func magnitude(diffs: Stream<(Diff, Int)>) -> Int { - return diffs.first?.1 ?? 0 - // fixme; this should actually consider the rest of the diff, but we aren’t memoizing that correctly. -// return diffs.map { $1 }.fold(0, combine: { $0 + $1.value }) + func magnitude(diffs: Stream) -> Int { + return diffs.map { $0.magnitude }.reduce(0, combine: +) } func min(a: A, _ rest: A..., _ isLessThan: (A, A) -> Bool) -> A { - return rest.reduce(a) { isLessThan($0, $1) ? $0 : $1 } + return rest.reduce(a, combine: { + isLessThan($0, $1) ? $0 : $1 + }) } - let graph = Vertex<(Term, Term, Diff, Int)>(rows: Stream(sequence: a), columns: Stream(sequence: b)) { - let diff = Diff($0, $1) - return ($0, $1, diff, diff.magnitude) - } - - func diff(vertex: Vertex<(Term, Term, Diff, Int)>) -> Stream<(Diff, Int)> { - switch vertex { - case .End: + func diff(a: Stream, _ b: Stream) -> Stream { + switch (a, b) { + case (.Nil, .Nil): return .Nil - - case let .XY((a, b, copy, copyCost), x, y): - let right = x.value - let down = y.value - switch (right, down) { - case (.End, .End): - return .Cons((copy, copyCost), Memo(evaluated: .Nil)) - case (.End, .XY): - return vertex.row.map { (Diff.Delete($0.0), 1) } - case (.XY, .End): - return vertex.column.map { (Diff.Insert($0.0), 1) } - case (.XY, .XY): - let copy = Stream.Cons((copy, copyCost), vertex.diagonal.map(diff)) - let insert = Stream.Cons((Diff.Insert(b), 1), x.map(diff)) - let delete = Stream.Cons((Diff.Delete(a), 1), y.map(diff)) - return min(copy, insert, delete) { - magnitude($0) < magnitude($1) - } + case (.Nil, .Cons): + return b.map(Diff.Insert) + case (.Cons, .Nil): + return a.map(Diff.Delete) + case let (.Cons(x, xs), .Cons(y, ys)): + let here = Stream.Cons(Diff(x, y), Memo { diff(xs.value, ys.value) }) + let insert = Stream.Cons(Diff.Insert(y), Memo { diff(a, ys.value) }) + let delete = Stream.Cons(Diff.Delete(x), Memo { diff(xs.value, b) }) + return min(here, insert, delete) { + magnitude($0) < magnitude($1) } } } - return Array(diff(graph).map { $0.0 }) + return Array(diff(Stream(sequence: a), Stream(sequence: b))) } } From a7ea2ae201f47a8aab4f8543852bf79bbe5861c1 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 14:21:13 -0400 Subject: [PATCH 137/138] Avoid recomputing the magnitudes. --- prototype/Doubt/Diff.swift | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/prototype/Doubt/Diff.swift b/prototype/Doubt/Diff.swift index 906b624ca..746028fc8 100644 --- a/prototype/Doubt/Diff.swift +++ b/prototype/Doubt/Diff.swift @@ -91,8 +91,9 @@ public enum Diff: Comparable, CustomDebugStringConvertible, CustomDocConvertible } public static func diff(a: C1, _ b: C2) -> [Diff] { - func magnitude(diffs: Stream) -> Int { - return diffs.map { $0.magnitude }.reduce(0, combine: +) + func magnitude(diffs: Stream<(Diff, Int)>) -> Int { +// return diffs.first?.magnitude ?? 0 + return diffs.map { $1 }.reduce(0, combine: +) } func min(a: A, _ rest: A..., _ isLessThan: (A, A) -> Bool) -> A { @@ -101,24 +102,25 @@ public enum Diff: Comparable, CustomDebugStringConvertible, CustomDocConvertible }) } - func diff(a: Stream, _ b: Stream) -> Stream { + func diff(a: Stream, _ b: Stream) -> Stream<(Diff, Int)> { switch (a, b) { case (.Nil, .Nil): return .Nil case (.Nil, .Cons): - return b.map(Diff.Insert) + return b.map { (Diff.Insert($0), 1) } case (.Cons, .Nil): - return a.map(Diff.Delete) + return a.map { (Diff.Delete($0), 1) } case let (.Cons(x, xs), .Cons(y, ys)): - let here = Stream.Cons(Diff(x, y), Memo { diff(xs.value, ys.value) }) - let insert = Stream.Cons(Diff.Insert(y), Memo { diff(a, ys.value) }) - let delete = Stream.Cons(Diff.Delete(x), Memo { diff(xs.value, b) }) + let copy = Diff(x, y) + let here = Stream.Cons((copy, copy.magnitude), Memo { diff(xs.value, ys.value) }) + let insert = Stream.Cons((Diff.Insert(y), 1), Memo { diff(a, ys.value) }) + let delete = Stream.Cons((Diff.Delete(x), 1), Memo { diff(xs.value, b) }) return min(here, insert, delete) { magnitude($0) < magnitude($1) } } } - return Array(diff(Stream(sequence: a), Stream(sequence: b))) + return Array(diff(Stream(sequence: a), Stream(sequence: b)).map { $0.0 }) } } From 9147dd72db561bb7526fcf062a0a8ffed2025e9c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 28 Sep 2015 14:28:36 -0400 Subject: [PATCH 138/138] Add a test of SES over slightly longer sequences to demonstrate the performance problem. --- prototype/DoubtTests/DiffTests.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/prototype/DoubtTests/DiffTests.swift b/prototype/DoubtTests/DiffTests.swift index 32612a476..e7e50eb40 100644 --- a/prototype/DoubtTests/DiffTests.swift +++ b/prototype/DoubtTests/DiffTests.swift @@ -26,6 +26,11 @@ final class DiffTests: XCTestCase { func testSESCanDeleteInMiddle() { XCTAssertEqual(Diff.diff([ a, d, b, c ], [ a, b, c ]), [ Diff(a), Diff.Delete(d), Diff(b), Diff(c) ]) } + + func testSESOfLongerSequences() { + // fixme: this is awfully slow for such a short sequence + XCTAssertEqual(Diff.diff([ a, b, c, a, b, b, a ], [ c, b, a, b, a, c ]), [ Diff.Patch(a, c), Diff(b), Diff.Delete(c), Diff(a), Diff.Delete(b), Diff(b), Diff(a), Diff.Insert(c) ]) + } } private let a = Term(.Literal("a"))