2015-10-14 20:52:25 +03:00
|
|
|
/// The type of terms.
|
|
|
|
public protocol TermType {
|
2015-10-22 17:17:51 +03:00
|
|
|
typealias Leaf
|
2015-10-14 20:52:25 +03:00
|
|
|
|
2015-10-22 17:17:51 +03:00
|
|
|
var unwrap: Syntax<Self, Leaf> { get }
|
2015-10-14 20:52:25 +03:00
|
|
|
}
|
2015-10-14 20:57:21 +03:00
|
|
|
|
|
|
|
|
2015-10-15 01:42:20 +03:00
|
|
|
extension TermType {
|
2015-10-22 20:40:19 +03:00
|
|
|
public static func unwrap(term: Self) -> Syntax<Self, Leaf> {
|
2015-10-22 20:05:08 +03:00
|
|
|
return term.unwrap
|
|
|
|
}
|
|
|
|
|
2015-10-15 04:07:30 +03:00
|
|
|
/// Catamorphism over `TermType`s.
|
|
|
|
///
|
|
|
|
/// Folds the tree encoded by the receiver into a single value by recurring top-down through the tree, applying `transform` to leaves, then to branches, and so forth.
|
2015-10-22 17:17:51 +03:00
|
|
|
public func cata<Result>(transform: Syntax<Result, Leaf> -> Result) -> Result {
|
2015-10-22 20:05:16 +03:00
|
|
|
return self |> (Self.unwrap >>> { $0.map { $0.cata(transform) } } >>> transform)
|
2015-10-15 01:42:20 +03:00
|
|
|
}
|
2015-10-15 01:47:20 +03:00
|
|
|
|
2015-10-19 18:17:18 +03:00
|
|
|
/// Paramorphism over `TermType`s.
|
|
|
|
///
|
|
|
|
/// Folds the tree encoded by the receiver into a single value by recurring top-down through the tree, applying `transform` to leaves, then to branches, and so forth. Each recursive instance is made available in the `Syntax` alongside the result value at that node.
|
2015-10-22 17:17:51 +03:00
|
|
|
public func para<Result>(transform: Syntax<(Self, Result), Leaf> -> Result) -> Result {
|
2015-10-22 20:05:16 +03:00
|
|
|
return self |> (Self.unwrap >>> { $0.map { ($0, $0.para(transform)) } } >>> transform)
|
2015-10-19 18:15:44 +03:00
|
|
|
}
|
|
|
|
|
2015-10-15 01:47:20 +03:00
|
|
|
|
2015-10-15 20:45:30 +03:00
|
|
|
/// The count of nodes in the receiver.
|
|
|
|
///
|
|
|
|
/// This is used to compute the cost of patches, such that a patch inserting a very large tree will be charged approximately the same as a very large tree consisting of many small patches.
|
2015-10-15 01:47:20 +03:00
|
|
|
public var size: Int {
|
|
|
|
return cata {
|
|
|
|
switch $0 {
|
|
|
|
case .Leaf:
|
|
|
|
return 1
|
|
|
|
case let .Indexed(i):
|
|
|
|
return i.reduce(1, combine: +)
|
2015-10-23 21:47:44 +03:00
|
|
|
case let .Fixed(i):
|
|
|
|
return i.reduce(1, combine: +)
|
2015-10-15 01:47:20 +03:00
|
|
|
case let .Keyed(k):
|
|
|
|
return k.values.reduce(1, combine: +)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-15 01:42:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-14 23:31:32 +03:00
|
|
|
// MARK: - Equality
|
|
|
|
|
|
|
|
extension TermType {
|
2015-10-22 17:17:51 +03:00
|
|
|
public static func equals(leaf: (Leaf, Leaf) -> Bool)(_ a: Self, _ b: Self) -> Bool {
|
2015-10-22 17:46:51 +03:00
|
|
|
return Syntax.equals(leaf: leaf, recur: equals(leaf))(a.unwrap, b.unwrap)
|
2015-10-14 21:05:43 +03:00
|
|
|
}
|
|
|
|
}
|
2015-10-15 01:42:20 +03:00
|
|
|
|
|
|
|
|
|
|
|
import Prelude
|