mirror of
https://github.com/github/semantic.git
synced 2024-12-27 00:44:57 +03:00
Merge pull request #220 from github/refine-leaf-replacements
Refine leaf replacements
This commit is contained in:
commit
45aa38e6ea
@ -104,6 +104,20 @@ public enum Free<Leaf, Annotation, Value>: CustomDebugStringConvertible {
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Monad
|
||||
|
||||
extension Free {
|
||||
public func flatMap<Other>(@noescape transform: Value throws -> Free<Leaf, Annotation, Other>) rethrows -> Free<Leaf, Annotation, Other> {
|
||||
switch self {
|
||||
case let .Pure(a):
|
||||
return try transform(a)
|
||||
case let .Roll(annotation, rest):
|
||||
return try .Roll(annotation, rest.map { try $0.flatMap(transform) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Anamorphism
|
||||
|
||||
extension Free {
|
||||
|
@ -144,6 +144,24 @@ func parserForType(type: String) -> String throws -> Term {
|
||||
}
|
||||
}
|
||||
|
||||
extension ForwardIndexType {
|
||||
/// The range encompassing a single index.
|
||||
var range: Range<Self> {
|
||||
return self..<self.successor()
|
||||
}
|
||||
}
|
||||
|
||||
func refineLeafReplacement(aString: String, _ bString: String)(_ patch: Patch<Term>) -> Diff {
|
||||
switch patch {
|
||||
case let .Replace(.Unroll(aExtract, .Leaf), .Unroll(bExtract, .Leaf)):
|
||||
let a = aString.utf16[aExtract.range].enumerate().map { Term(Info(range: (aExtract.range.startIndex + $0).range, categories: aExtract.categories), .Leaf(String($1))) }
|
||||
let b = bString.utf16[bExtract.range].enumerate().map { Term(Info(range: (bExtract.range.startIndex + $0).range, categories: bExtract.categories), .Leaf(String($1))) }
|
||||
return .Roll((aExtract, bExtract), .Indexed(SES(a, b, cost: Diff.sum(Patch.sum), recur: { Term.equals(annotation: const(true), leaf: ==)($0, $1) ? Term.zip($0, $1).map(Diff.init) : Diff.Replace($0, $1) })))
|
||||
default:
|
||||
return .Pure(patch)
|
||||
}
|
||||
}
|
||||
|
||||
let parsed = benchmark("parsing arguments & loading sources") { parse(argumentsParser, input: Process.arguments) }
|
||||
let arguments: Argument = try parsed.either(ifLeft: { throw "\($0)" }, ifRight: { $0 })
|
||||
let (aSource, bSource) = arguments.sources
|
||||
@ -154,7 +172,7 @@ let parser = parserForType(aSource.type)
|
||||
|
||||
let a = try benchmark("parsing source a") { try parser(aSource.contents) }
|
||||
let b = try benchmark("parsing source b") { try parser(bSource.contents) }
|
||||
let diff = benchmark("diffing") { Interpreter<Term>(equal: Term.equals(annotation: const(true), leaf: ==), comparable: Interpreter<Term>.comparable { $0.extract.categories }, cost: Free.sum(Patch.sum)).run(a, b) }
|
||||
let diff = benchmark("diffing") { Interpreter<Term>(equal: Term.equals(annotation: const(true), leaf: ==), comparable: Interpreter<Term>.comparable { $0.extract.categories }, cost: Free.sum(Patch.sum)).run(a, b).flatMap(refineLeafReplacement(aSource.contents, bSource.contents)) }
|
||||
switch arguments.output {
|
||||
case .Split:
|
||||
let JSON: Doubt.JSON = [
|
||||
|
Loading…
Reference in New Issue
Block a user