1
1
mirror of https://github.com/github/semantic.git synced 2024-12-25 16:02:43 +03:00

add .Fixed to Syntax

This commit is contained in:
joshvera 2015-10-23 14:47:44 -04:00
parent 829e43a168
commit 20e2a520e6
6 changed files with 48 additions and 1 deletions

View File

@ -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:

View File

@ -71,6 +71,8 @@ public enum Free<Leaf, Annotation, Value>: 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<Leaf, ()> {
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) } })))
}

View File

@ -50,13 +50,20 @@ public struct Interpreter<Term: CofreeType> {
let algorithm: Algorithm<Term, Diff>
let annotations = (a.extract, b.extract)
let rollByIndex = { (a, b) -> Algorithm<Term, Diff> 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<Term: CofreeType> {
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]!)) })))))

View File

@ -2,6 +2,7 @@
public enum Syntax<Recur, A>: CustomDebugStringConvertible {
case Leaf(A)
case Indexed([Recur])
case Fixed([Recur])
case Keyed([String:Recur])
@ -13,6 +14,8 @@ public enum Syntax<Recur, A>: 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<Recur, A>: 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)) }))
}

View File

@ -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: +)
}

View File

@ -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<String, Range<Int>> {
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<String, Range<Int>>] = []
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<String, Range<Int>>)] = []
@ -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) }