1
1
mirror of https://github.com/github/semantic.git synced 2024-12-18 20:31:55 +03:00
semantic/prototype/Doubt/TermType.swift

60 lines
1.8 KiB
Swift
Raw Normal View History

2015-10-14 20:52:25 +03:00
/// The type of terms.
public protocol TermType {
typealias Leaf
2015-10-14 20:52:25 +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 {
public static func unwrap(term: Self) -> Syntax<Self, Leaf> {
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-11-03 18:40:12 +03:00
public func cata<Result>(transform: Syntax<Result, Leaf> throws -> Result) rethrows -> Result {
return try transform(unwrap.map { try $0.cata(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-11-03 18:40:19 +03:00
public func para<Result>(transform: Syntax<(Self, Result), Leaf> throws -> Result) rethrows -> Result {
return try transform(unwrap.map { try ($0, $0.para(transform)) })
}
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 {
2015-11-13 01:27:07 +03:00
func size(term: Self) -> Int {
switch term.unwrap {
2015-10-15 01:47:20 +03:00
case .Leaf:
return 1
2015-11-13 01:27:07 +03:00
case let .Indexed(a):
return a.reduce(0) { $0 + size($1) }
case let .Fixed(a):
return a.reduce(0) { $0 + size($1) }
case let .Keyed(a):
return a.reduce(0) { $0 + size($1.1) }
2015-10-15 01:47:20 +03:00
}
}
2015-11-13 01:27:07 +03:00
return size(self)
2015-10-15 01:47:20 +03:00
}
2015-10-15 01:42:20 +03:00
}
// MARK: - Equality
extension TermType {
public static func equals(leaf: (Leaf, Leaf) -> Bool)(_ a: Self, _ b: Self) -> Bool {
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