1
1
mirror of https://github.com/github/semantic.git synced 2024-12-19 04:41:47 +03:00
semantic/prototype/Doubt/Interpreter.swift

52 lines
1.4 KiB
Swift
Raw Normal View History

2015-10-15 17:45:32 +03:00
/// An interpreter of `Algorithm`s.
2015-10-15 18:00:27 +03:00
public struct Interpreter<Term: TermType> {
2015-10-15 18:01:35 +03:00
public typealias Diff = Free<Term.LeafType, Patch<Term>>
2015-10-15 18:27:44 +03:00
private let equals: (Term, Term) -> Bool
2015-10-15 18:00:49 +03:00
2015-10-15 18:26:35 +03:00
private func recur(a: Term, _ b: Term) -> Diff? {
2015-10-15 18:04:37 +03:00
if equals(a, b) { return Diff(b) }
2015-10-15 18:26:35 +03:00
2015-10-15 18:07:35 +03:00
let algorithm: Algorithm<Term, Diff>
switch (a.unwrap, b.unwrap) {
case let (.Keyed(a), .Keyed(b)):
algorithm = .Roll(.ByKey(a, b, Syntax.Keyed >>> Diff.Roll >>> Algorithm.Pure))
case let (.Indexed(a), .Indexed(b)):
algorithm = .Roll(.ByIndex(a, b, Syntax.Indexed >>> Diff.Roll >>> Algorithm.Pure))
default:
algorithm = .Roll(.Recursive(a, b, Algorithm.Pure))
}
return recur(algorithm)
}
private func recur(algorithm: Algorithm<Term, Diff>) -> Diff? {
2015-10-15 18:29:49 +03:00
switch algorithm {
case let .Pure(diff):
return diff
case let .Roll(.Recursive(a, b, f)):
switch (a.unwrap, b.unwrap) {
case let (.Indexed(a), .Indexed(b)) where a.count == b.count:
return recur(f(.Indexed(zip(a, b).map(run))))
case let (.Keyed(a), .Keyed(b)) where Array(a.keys) == Array(b.keys):
return recur(f(.Keyed(Dictionary(elements: b.keys.map { ($0, self.run(a[$0]!, b[$0]!)) }))))
default:
2015-10-15 18:47:27 +03:00
// This must not call `recur` directly with `a` and `b`, as that would infinite loop if actually recursive.
return recur(f(.Replace(a, b)))
}
2015-10-15 18:29:49 +03:00
default:
return nil
}
2015-10-15 18:26:35 +03:00
}
public func run(a: Term, _ b: Term) -> Diff {
2015-10-15 18:29:56 +03:00
return recur(a, b) ?? .Replace(a, b)
2015-10-15 18:04:37 +03:00
}
2015-10-15 17:58:57 +03:00
}
2015-10-15 18:07:35 +03:00
import Prelude