1
1
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:
Josh Vera 2015-11-06 10:55:14 -05:00
commit 45aa38e6ea
2 changed files with 33 additions and 1 deletions

View File

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

View File

@ -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 = [