1
1
mirror of https://github.com/github/semantic.git synced 2024-12-12 14:45:40 +03:00
semantic/prototype/Doubt/Vertex.swift
2015-10-01 15:16:25 -04:00

128 lines
3.2 KiB
Swift

public enum Vertex<Element>: CustomDebugStringConvertible, CustomStringConvertible {
indirect case XY(Element, Memo<Vertex>, Memo<Vertex>)
case End
public func analysis<Result>(@noescape ifXY ifXY: (Element, Memo<Vertex>, Memo<Vertex>) -> Result, @noescape ifEnd: () -> Result) -> Result {
switch self {
case let .XY(a, x, y):
return ifXY(a, x, y)
case .End:
return ifEnd()
}
}
public var isEmpty: Bool {
return analysis(ifXY: const(false), ifEnd: const(true))
}
public var element: Element? {
return analysis(
ifXY: { x, _, _ in x },
ifEnd: const(nil))
}
public var right: Memo<Vertex> {
return analysis(
ifXY: { _, xs, _ in xs },
ifEnd: const(Memo(evaluated: .End)))
}
public var down: Memo<Vertex> {
return analysis(
ifXY: { _, _, ys in ys },
ifEnd: const(Memo(evaluated: .End)))
}
public var diagonal: Memo<Vertex> {
return right.flatMap { $0.down }
}
public var row: Stream<Element> {
return Stream.unfold(Memo(evaluated: self)) {
$0.value.analysis(
ifXY: { here, across, _ in .Some(here, across) },
ifEnd: const(nil))
}
}
public var column: Stream<Element> {
return Stream.unfold(Memo(evaluated: self)) {
$0.value.analysis(
ifXY: { here, _, down in .Some(here, down) },
ifEnd: const(nil))
}
}
public var rowMajor: Stream<Stream<Element>> {
return Stream.unfold(Memo(evaluated: self), { (state: Memo<Vertex>) -> (Stream<Element>, Memo<Vertex>)? in
state.value.analysis(
ifXY: { _, _, down in (state.value.row, down) },
ifEnd: const(nil))
})
}
public var columnMajor: Stream<Stream<Element>> {
return Stream.unfold(Memo(evaluated: self), { (state: Memo<Vertex>) -> (Stream<Element>, Memo<Vertex>)? in
state.value.analysis(
ifXY: { _, across, _ in (state.value.column, across) },
ifEnd: const(nil))
})
}
public init<S1: SequenceType, S2: SequenceType>(rows: S1, columns: S2, combine: (S1.Generator.Element, S2.Generator.Element) -> Element) {
let rows = Stream(sequence: rows)
let columns = Stream(sequence: columns)
func across(vertex: Vertex<Element>) -> Stream<Memo<Vertex<Element>>> {
return Stream.unfold(Memo(evaluated: vertex)) { vertex in
vertex.value.analysis(
ifXY: { _, xs, _ in .Some(vertex, xs) },
ifEnd: const(.Some(vertex, vertex)))
}
}
self = rows
.map { a in columns.map { b in combine(a, b) } }
.fold(.End) {
$0.zipWith(across($1.value)).fold(.End) {
.XY($0.0, $1, $0.1)
}
}
}
public func map<Other>(transform: Element -> Other) -> Vertex<Other> {
switch self {
case let .XY(xy, xs, ys):
return .XY(transform(xy), xs.map { $0.map(transform) }, ys.map { $0.map(transform) })
case .End:
return .End
}
}
public var debugDescription: String {
return rowMajor.map {
$0.map { String(reflecting: $0) }.joinWithSeparator("\t")
}.joinWithSeparator("\n")
}
public var description: String {
return rowMajor.map {
$0.map { String($0) }.joinWithSeparator("\t")
}.joinWithSeparator("\n")
}
}
public func == <A: Equatable> (left: Vertex<A>, right: Vertex<A>) -> Bool {
switch (left, right) {
case (.End, .End):
return true
case let (.XY(a, x1, y1), .XY(b, x2, y2)):
return a == b && x1.value == x2.value && y1.value == y2.value
default:
return false
}
}