1
1
mirror of https://github.com/github/semantic.git synced 2024-12-26 08:25:19 +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)) return Cofree(annotations, .Leaf(b))
case let (.Indexed(a), .Indexed(b)): case let (.Indexed(a), .Indexed(b)):
return Cofree(annotations, .Indexed(Swift.zip(a, b).flatMap(zip))) 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)): 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) } }))) return Cofree(annotations, .Keyed(Dictionary(elements: b.keys.flatMap { key in zip(a[key]!, b[key]!).map { (key, $0) } })))
default: default:

View File

@ -71,6 +71,8 @@ public enum Free<Leaf, Annotation, Value>: CustomDebugStringConvertible {
return initial return initial
case let .Indexed(a): case let .Indexed(a):
return a.reduce(initial, combine: combine) return a.reduce(initial, combine: combine)
case let .Fixed(a):
return a.reduce(initial, combine: combine)
case let .Keyed(a): case let .Keyed(a):
return a.values.reduce(initial, combine: combine) return a.values.reduce(initial, combine: combine)
} }
@ -143,6 +145,8 @@ extension Free where Value: PatchType, Value.Element == Cofree<Leaf, ()> {
return Cofree((), .Leaf(a)) return Cofree((), .Leaf(a))
case let .Indexed(a): case let .Indexed(a):
return Cofree((), .Indexed(a.flatMap(id))) return Cofree((), .Indexed(a.flatMap(id)))
case let .Fixed(a):
return Cofree((), .Fixed(a.flatMap(id)))
case let .Keyed(a): case let .Keyed(a):
return Cofree((), .Keyed(Dictionary(elements: a.flatMap { k, v in v.map { (k, $0) } }))) 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 algorithm: Algorithm<Term, Diff>
let annotations = (a.extract, b.extract) 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) { switch (a.unwrap, b.unwrap) {
case let (.Leaf, .Leaf(leaf)) where equal(a, b): case let (.Leaf, .Leaf(leaf)) where equal(a, b):
return .Roll(annotations, .Leaf(leaf)) return .Roll(annotations, .Leaf(leaf))
case let (.Keyed(a), .Keyed(b)): case let (.Keyed(a), .Keyed(b)):
algorithm = .Roll(.ByKey(a, b, Syntax.Keyed >>> Diff.Introduce(annotations) >>> Algorithm.Pure)) algorithm = .Roll(.ByKey(a, b, Syntax.Keyed >>> Diff.Introduce(annotations) >>> Algorithm.Pure))
case let (.Indexed(a), .Indexed(b)): 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: default:
algorithm = .Roll(.Recursive(a, b, Algorithm.Pure)) algorithm = .Roll(.Recursive(a, b, Algorithm.Pure))
} }
@ -74,6 +81,8 @@ public struct Interpreter<Term: CofreeType> {
switch (a.unwrap, b.unwrap) { switch (a.unwrap, b.unwrap) {
case let (.Indexed(a), .Indexed(b)) where a.count == b.count: case let (.Indexed(a), .Indexed(b)) where a.count == b.count:
return recur(f(.Roll(annotations, .Indexed(zip(a, b).map(run))))) 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): 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]!)) }))))) 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 { public enum Syntax<Recur, A>: CustomDebugStringConvertible {
case Leaf(A) case Leaf(A)
case Indexed([Recur]) case Indexed([Recur])
case Fixed([Recur])
case Keyed([String:Recur]) case Keyed([String:Recur])
@ -13,6 +14,8 @@ public enum Syntax<Recur, A>: CustomDebugStringConvertible {
return .Leaf(n) return .Leaf(n)
case let .Indexed(x): case let .Indexed(x):
return .Indexed(x.map(transform)) return .Indexed(x.map(transform))
case let .Fixed(x):
return .Fixed(x.map(transform))
case let .Keyed(d): case let .Keyed(d):
return .Keyed(Dictionary(elements: d.map { ($0, transform($1)) })) return .Keyed(Dictionary(elements: d.map { ($0, transform($1)) }))
} }
@ -27,6 +30,8 @@ public enum Syntax<Recur, A>: CustomDebugStringConvertible {
return ".Leaf(\(n))" return ".Leaf(\(n))"
case let .Indexed(x): case let .Indexed(x):
return ".Indexed(\(String(reflecting: x)))" return ".Indexed(\(String(reflecting: x)))"
case let .Fixed(x):
return ".Fixed(\(String(reflecting: x)))"
case let .Keyed(d): case let .Keyed(d):
return ".Keyed(\(String(reflecting: d)))" return ".Keyed(\(String(reflecting: d)))"
} }
@ -108,6 +113,8 @@ extension Syntax {
return leaf(a) return leaf(a)
case let .Indexed(a): case let .Indexed(a):
return .Array(a.map(recur)) return .Array(a.map(recur))
case let .Fixed(a):
return .Array(a.map(recur))
case let .Keyed(d): case let .Keyed(d):
return .Dictionary(Dictionary(elements: d.map { ($0, recur($1)) })) return .Dictionary(Dictionary(elements: d.map { ($0, recur($1)) }))
} }

View File

@ -36,6 +36,8 @@ extension TermType {
return 1 return 1
case let .Indexed(i): case let .Indexed(i):
return i.reduce(1, combine: +) return i.reduce(1, combine: +)
case let .Fixed(i):
return i.reduce(1, combine: +)
case let .Keyed(k): case let .Keyed(k):
return k.values.reduce(1, combine: +) return k.values.reduce(1, combine: +)
} }

View File

@ -3,17 +3,21 @@ struct UnannotatedTerm {
let term: Term let term: Term
static let indexed = (prefix: "[\n\t", separator: ",\n\t", suffix: "\n]") 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}") static let keyed = (prefix: "[\n\t", separator: ",\n\t", suffix: "\n}")
var source: String { var source: String {
let indexed = UnannotatedTerm.indexed let indexed = UnannotatedTerm.indexed
let keyed = UnannotatedTerm.keyed let keyed = UnannotatedTerm.keyed
let fixed = UnannotatedTerm.fixed
return term.cata { return term.cata {
switch $0 { switch $0 {
case let .Leaf(s): case let .Leaf(s):
return s return s
case let .Indexed(s): case let .Indexed(s):
return indexed.prefix + s.joinWithSeparator(indexed.separator) + indexed.suffix 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): case let .Keyed(s):
return keyed.prefix + s.map { "\"\($0)\": \($1)" }.joinWithSeparator(keyed.separator) + keyed.suffix return keyed.prefix + s.map { "\"\($0)\": \($1)" }.joinWithSeparator(keyed.separator) + keyed.suffix
} }
@ -23,6 +27,8 @@ struct UnannotatedTerm {
var ranged: Cofree<String, Range<Int>> { var ranged: Cofree<String, Range<Int>> {
let indexed = UnannotatedTerm.indexed let indexed = UnannotatedTerm.indexed
let keyed = UnannotatedTerm.keyed let keyed = UnannotatedTerm.keyed
let fixed = UnannotatedTerm.fixed
return term.cata { return term.cata {
switch $0 { switch $0 {
case let .Leaf(s): case let .Leaf(s):
@ -40,6 +46,19 @@ struct UnannotatedTerm {
length += value.extract.count length += value.extract.count
} }
return Cofree(0..<(length + indexed.suffix.characters.count), .Indexed(results)) 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): case let .Keyed(k):
var length = keyed.prefix.characters.count var length = keyed.prefix.characters.count
var results: [(String, Cofree<String, Range<Int>>)] = [] var results: [(String, Cofree<String, Range<Int>>)] = []
@ -105,6 +124,10 @@ extension UnannotatedTerm: Arbitrary {
return Cofree((), .Indexed(i.reduce(true) { $0 && equal($1) } return Cofree((), .Indexed(i.reduce(true) { $0 && equal($1) }
? i.dropLast().map { $1 } ? i.dropLast().map { $1 }
: i.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): case let .Keyed(k):
return Cofree((), .Keyed(Dictionary(elements: k.reduce(true) { $0 && equal($1.1) } return Cofree((), .Keyed(Dictionary(elements: k.reduce(true) { $0 && equal($1.1) }
? k.dropLast().map { ($0, $1.1) } ? k.dropLast().map { ($0, $1.1) }