From 20e2a520e68d3ae95c8c2b8f0c16b817df88b2dd Mon Sep 17 00:00:00 2001 From: joshvera Date: Fri, 23 Oct 2015 14:47:44 -0400 Subject: [PATCH 1/2] add .Fixed to Syntax --- prototype/Doubt/Cofree.swift | 2 ++ prototype/Doubt/Free.swift | 4 ++++ prototype/Doubt/Interpreter.swift | 11 ++++++++++- prototype/Doubt/Syntax.swift | 7 +++++++ prototype/Doubt/TermType.swift | 2 ++ prototype/DoubtTests/UnannotatedTerm.swift | 23 ++++++++++++++++++++++ 6 files changed, 48 insertions(+), 1 deletion(-) diff --git a/prototype/Doubt/Cofree.swift b/prototype/Doubt/Cofree.swift index 72f9b9d19..ad84eb394 100644 --- a/prototype/Doubt/Cofree.swift +++ b/prototype/Doubt/Cofree.swift @@ -139,6 +139,8 @@ extension CofreeType { return Cofree(annotations, .Leaf(b)) case let (.Indexed(a), .Indexed(b)): return Cofree(annotations, .Indexed(Swift.zip(a, b).flatMap(zip))) + case let (.Fixed(a), .Fixed(b)): + return Cofree(annotations, .Fixed(Swift.zip(a, b).flatMap(zip))) case let (.Keyed(a), .Keyed(b)): return Cofree(annotations, .Keyed(Dictionary(elements: b.keys.flatMap { key in zip(a[key]!, b[key]!).map { (key, $0) } }))) default: diff --git a/prototype/Doubt/Free.swift b/prototype/Doubt/Free.swift index 9ce77752c..1fba0da64 100644 --- a/prototype/Doubt/Free.swift +++ b/prototype/Doubt/Free.swift @@ -71,6 +71,8 @@ public enum Free: CustomDebugStringConvertible { return initial case let .Indexed(a): return a.reduce(initial, combine: combine) + case let .Fixed(a): + return a.reduce(initial, combine: combine) case let .Keyed(a): return a.values.reduce(initial, combine: combine) } @@ -143,6 +145,8 @@ extension Free where Value: PatchType, Value.Element == Cofree { return Cofree((), .Leaf(a)) case let .Indexed(a): return Cofree((), .Indexed(a.flatMap(id))) + case let .Fixed(a): + return Cofree((), .Fixed(a.flatMap(id))) case let .Keyed(a): return Cofree((), .Keyed(Dictionary(elements: a.flatMap { k, v in v.map { (k, $0) } }))) } diff --git a/prototype/Doubt/Interpreter.swift b/prototype/Doubt/Interpreter.swift index 9407387f8..fb7007a6d 100644 --- a/prototype/Doubt/Interpreter.swift +++ b/prototype/Doubt/Interpreter.swift @@ -50,13 +50,20 @@ public struct Interpreter { let algorithm: Algorithm let annotations = (a.extract, b.extract) + + let rollByIndex = { (a, b) -> Algorithm in + .Roll(.ByIndex(a, b, Syntax.Indexed >>> Diff.Introduce(annotations) >>> Algorithm.Pure)) + } + switch (a.unwrap, b.unwrap) { case let (.Leaf, .Leaf(leaf)) where equal(a, b): return .Roll(annotations, .Leaf(leaf)) case let (.Keyed(a), .Keyed(b)): algorithm = .Roll(.ByKey(a, b, Syntax.Keyed >>> Diff.Introduce(annotations) >>> Algorithm.Pure)) case let (.Indexed(a), .Indexed(b)): - algorithm = .Roll(.ByIndex(a, b, Syntax.Indexed >>> Diff.Introduce(annotations) >>> Algorithm.Pure)) + algorithm = rollByIndex(a, b) + case let (.Fixed(a), .Fixed(b)): + algorithm = rollByIndex(a, b) default: algorithm = .Roll(.Recursive(a, b, Algorithm.Pure)) } @@ -74,6 +81,8 @@ public struct Interpreter { switch (a.unwrap, b.unwrap) { case let (.Indexed(a), .Indexed(b)) where a.count == b.count: return recur(f(.Roll(annotations, .Indexed(zip(a, b).map(run))))) + case let (.Fixed(a), .Fixed(b)) where a.count == b.count: + return recur(f(.Roll(annotations, .Fixed(zip(a, b).map(run))))) case let (.Keyed(a), .Keyed(b)) where Array(a.keys) == Array(b.keys): return recur(f(.Roll(annotations, .Keyed(Dictionary(elements: b.keys.map { ($0, self.run(a[$0]!, b[$0]!)) }))))) diff --git a/prototype/Doubt/Syntax.swift b/prototype/Doubt/Syntax.swift index 7f21673ca..53f581d70 100644 --- a/prototype/Doubt/Syntax.swift +++ b/prototype/Doubt/Syntax.swift @@ -2,6 +2,7 @@ public enum Syntax: CustomDebugStringConvertible { case Leaf(A) case Indexed([Recur]) + case Fixed([Recur]) case Keyed([String:Recur]) @@ -13,6 +14,8 @@ public enum Syntax: CustomDebugStringConvertible { return .Leaf(n) case let .Indexed(x): return .Indexed(x.map(transform)) + case let .Fixed(x): + return .Fixed(x.map(transform)) case let .Keyed(d): return .Keyed(Dictionary(elements: d.map { ($0, transform($1)) })) } @@ -27,6 +30,8 @@ public enum Syntax: CustomDebugStringConvertible { return ".Leaf(\(n))" case let .Indexed(x): return ".Indexed(\(String(reflecting: x)))" + case let .Fixed(x): + return ".Fixed(\(String(reflecting: x)))" case let .Keyed(d): return ".Keyed(\(String(reflecting: d)))" } @@ -108,6 +113,8 @@ extension Syntax { return leaf(a) case let .Indexed(a): return .Array(a.map(recur)) + case let .Fixed(a): + return .Array(a.map(recur)) case let .Keyed(d): return .Dictionary(Dictionary(elements: d.map { ($0, recur($1)) })) } diff --git a/prototype/Doubt/TermType.swift b/prototype/Doubt/TermType.swift index e6bf35cb0..f1a7a06b4 100644 --- a/prototype/Doubt/TermType.swift +++ b/prototype/Doubt/TermType.swift @@ -36,6 +36,8 @@ extension TermType { return 1 case let .Indexed(i): return i.reduce(1, combine: +) + case let .Fixed(i): + return i.reduce(1, combine: +) case let .Keyed(k): return k.values.reduce(1, combine: +) } diff --git a/prototype/DoubtTests/UnannotatedTerm.swift b/prototype/DoubtTests/UnannotatedTerm.swift index 35e78fc4f..a719566aa 100644 --- a/prototype/DoubtTests/UnannotatedTerm.swift +++ b/prototype/DoubtTests/UnannotatedTerm.swift @@ -3,17 +3,21 @@ struct UnannotatedTerm { let term: Term static let indexed = (prefix: "[\n\t", separator: ",\n\t", suffix: "\n]") + static let fixed = (prefix: "(\n\t", separator: ",\n\t", suffix: "\n)") static let keyed = (prefix: "[\n\t", separator: ",\n\t", suffix: "\n}") var source: String { let indexed = UnannotatedTerm.indexed let keyed = UnannotatedTerm.keyed + let fixed = UnannotatedTerm.fixed return term.cata { switch $0 { case let .Leaf(s): return s case let .Indexed(s): return indexed.prefix + s.joinWithSeparator(indexed.separator) + indexed.suffix + case let .Fixed(s): + return fixed.prefix + s.joinWithSeparator(fixed.separator) + fixed.suffix case let .Keyed(s): return keyed.prefix + s.map { "\"\($0)\": \($1)" }.joinWithSeparator(keyed.separator) + keyed.suffix } @@ -23,6 +27,8 @@ struct UnannotatedTerm { var ranged: Cofree> { let indexed = UnannotatedTerm.indexed let keyed = UnannotatedTerm.keyed + let fixed = UnannotatedTerm.fixed + return term.cata { switch $0 { case let .Leaf(s): @@ -40,6 +46,19 @@ struct UnannotatedTerm { length += value.extract.count } return Cofree(0..<(length + indexed.suffix.characters.count), .Indexed(results)) + case let .Fixed(i): + var length = fixed.prefix.characters.count + var results: [Cofree>] = [] + for value in i { + if results.count > 0 { + length += fixed.separator.characters.count + } + results.append(value.map { + ($0.startIndex + length)..<($0.endIndex + length) + }) + length += value.extract.count + } + return Cofree(0..<(length + fixed.suffix.characters.count), .Fixed(results)) case let .Keyed(k): var length = keyed.prefix.characters.count var results: [(String, Cofree>)] = [] @@ -105,6 +124,10 @@ extension UnannotatedTerm: Arbitrary { return Cofree((), .Indexed(i.reduce(true) { $0 && equal($1) } ? i.dropLast().map { $1 } : i.map { $1 })) + case let .Fixed(i): + return Cofree((), .Fixed(i.reduce(true) { $0 && equal($1) } + ? i.dropLast().map { $1 } + : i.map { $1 })) case let .Keyed(k): return Cofree((), .Keyed(Dictionary(elements: k.reduce(true) { $0 && equal($1.1) } ? k.dropLast().map { ($0, $1.1) } From f2aeae9e4b92e51445663f81d116c3a25c03dfb2 Mon Sep 17 00:00:00 2001 From: joshvera Date: Fri, 23 Oct 2015 17:03:12 -0400 Subject: [PATCH 2/2] Interpret Fixed cases recursively --- prototype/Doubt/Interpreter.swift | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/prototype/Doubt/Interpreter.swift b/prototype/Doubt/Interpreter.swift index fb7007a6d..815d14eec 100644 --- a/prototype/Doubt/Interpreter.swift +++ b/prototype/Doubt/Interpreter.swift @@ -51,19 +51,15 @@ public struct Interpreter { let algorithm: Algorithm let annotations = (a.extract, b.extract) - let rollByIndex = { (a, b) -> Algorithm in - .Roll(.ByIndex(a, b, Syntax.Indexed >>> Diff.Introduce(annotations) >>> Algorithm.Pure)) - } - switch (a.unwrap, b.unwrap) { case let (.Leaf, .Leaf(leaf)) where equal(a, b): return .Roll(annotations, .Leaf(leaf)) case let (.Keyed(a), .Keyed(b)): algorithm = .Roll(.ByKey(a, b, Syntax.Keyed >>> Diff.Introduce(annotations) >>> Algorithm.Pure)) case let (.Indexed(a), .Indexed(b)): - algorithm = rollByIndex(a, b) - case let (.Fixed(a), .Fixed(b)): - algorithm = rollByIndex(a, b) + algorithm = .Roll(.ByIndex(a, b, Syntax.Indexed >>> Diff.Introduce(annotations) >>> Algorithm.Pure)) + case (.Fixed(_), .Fixed(_)): + fallthrough default: algorithm = .Roll(.Recursive(a, b, Algorithm.Pure)) }