mirror of
https://github.com/github/semantic.git
synced 2024-12-24 23:42:31 +03:00
Merge branch 'master' into syntax-highlighting
This commit is contained in:
commit
7f014eff8e
@ -43,7 +43,6 @@
|
||||
D49FCBC81BBF2C4300C5E9C3 /* Algorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49FCBC71BBF2C4300C5E9C3 /* Algorithm.swift */; };
|
||||
D4AAE50E1B5AE22E004E581F /* Doubt.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4AAE4FD1B5AE22E004E581F /* Doubt.framework */; };
|
||||
D4AAE5401B5AE2D0004E581F /* RangeReplaceableCollectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */; };
|
||||
D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53A1B5AE2D0004E581F /* Operators.swift */; };
|
||||
D4AAE5471B5AE2D0004E581F /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53C1B5AE2D0004E581F /* Optional.swift */; };
|
||||
D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */; };
|
||||
D4AAE54A1B5AE2D0004E581F /* Syntax.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4AAE53F1B5AE2D0004E581F /* Syntax.swift */; };
|
||||
@ -116,7 +115,6 @@
|
||||
D4AAE50D1B5AE22E004E581F /* DoubtTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DoubtTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D4AAE5141B5AE22E004E581F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RangeReplaceableCollectionType.swift; sourceTree = "<group>"; };
|
||||
D4AAE53A1B5AE2D0004E581F /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
|
||||
D4AAE53C1B5AE2D0004E581F /* Optional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Optional.swift; sourceTree = "<group>"; };
|
||||
D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringLiteralConvertible.swift; sourceTree = "<group>"; };
|
||||
D4AAE53F1B5AE2D0004E581F /* Syntax.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Syntax.swift; sourceTree = "<group>"; };
|
||||
@ -199,7 +197,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D4AAE5351B5AE2D0004E581F /* RangeReplaceableCollectionType.swift */,
|
||||
D4AAE53A1B5AE2D0004E581F /* Operators.swift */,
|
||||
D4AAE53C1B5AE2D0004E581F /* Optional.swift */,
|
||||
D4AAE53E1B5AE2D0004E581F /* StringLiteralConvertible.swift */,
|
||||
D4AAE53F1B5AE2D0004E581F /* Syntax.swift */,
|
||||
@ -464,7 +461,6 @@
|
||||
D4AAE5491B5AE2D0004E581F /* StringLiteralConvertible.swift in Sources */,
|
||||
D4413FF11BB08FDC00E3C3C1 /* JSON.swift in Sources */,
|
||||
D1F5FE211BDE9C450048BAE4 /* JSONLeaf.swift in Sources */,
|
||||
D4AAE5451B5AE2D0004E581F /* Operators.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -618,6 +614,7 @@
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_DISABLE_SAFETY_CHECKS = YES;
|
||||
SWIFT_INSTALL_OBJC_HEADER = NO;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
|
@ -83,7 +83,7 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
debugDocumentVersioning = "NO">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
|
@ -17,29 +17,6 @@ public enum Algorithm<Term: CofreeType, Result> {
|
||||
|
||||
/// A recursive instantiation of `Operation`, unrolling another iteration of the recursive type.
|
||||
indirect case Roll(Operation<Algorithm, Term, Diff>)
|
||||
|
||||
public func analysis<C>(@noescape ifPure ifPure: Result -> C, @noescape ifRoll: Operation<Algorithm, Term, Diff> -> C) -> C {
|
||||
switch self {
|
||||
case let .Pure(b):
|
||||
return ifPure(b)
|
||||
case let .Roll(a):
|
||||
return ifRoll(a)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Functor
|
||||
|
||||
public func map<Other>(transform: Result -> Other) -> Algorithm<Term, Other> {
|
||||
return analysis(ifPure: transform >>> Algorithm<Term, Other>.Pure, ifRoll: { .Roll($0.map { $0.map(transform) }) })
|
||||
}
|
||||
|
||||
|
||||
// MARK: Monad
|
||||
|
||||
public func flatMap<C>(transform: Result -> Algorithm<Term, C>) -> Algorithm<Term, C> {
|
||||
return analysis(ifPure: transform, ifRoll: { .Roll($0.map { $0.flatMap(transform) }) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -121,11 +121,11 @@ extension CofreeType {
|
||||
}
|
||||
|
||||
|
||||
/// Catamorphism over `TermType`s.
|
||||
/// Catamorphism over `CofreeType`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.
|
||||
public func cata<Result>(transform: (Annotation, Syntax<Result, Leaf>) -> Result) -> Result {
|
||||
return self |> (Self.eliminate >>> { ($0, $1.map { $0.cata(transform) }) } >>> transform)
|
||||
public func cata<Result>(transform: (Annotation, Syntax<Result, Leaf>) throws -> Result) rethrows -> Result {
|
||||
return try transform(extract, unwrap.map { try $0.cata(transform) })
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,15 +21,6 @@ public enum Free<Leaf, Annotation, Value>: CustomDebugStringConvertible {
|
||||
}
|
||||
|
||||
|
||||
public func analysis<C>(@noescape ifPure ifPure: Value throws -> C, @noescape ifRoll: (Annotation, Syntax<Free, Leaf>) throws -> C) rethrows -> C {
|
||||
switch self {
|
||||
case let .Pure(b):
|
||||
return try ifPure(b)
|
||||
case let .Roll(s):
|
||||
return try ifRoll(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Reduce the receiver by iteration.
|
||||
///
|
||||
/// `Pure` values are simply unpacked. `Roll` values are mapped recursively, and then have `transform` applied to them.
|
||||
@ -57,9 +48,12 @@ public enum Free<Leaf, Annotation, Value>: CustomDebugStringConvertible {
|
||||
///
|
||||
/// For a lucid, in-depth tutorial on recursion schemes, I recommend [Patrick Thomson](https://twitter.com/importantshock)’s _[An Introduction to Recursion Schemes](http://patrickthomson.ghost.io/an-introduction-to-recursion-schemes/)_ and _[Recursion Schemes, Part 2: A Mob of Morphisms](http://patrickthomson.ghost.io/recursion-schemes-part-2/)_.
|
||||
public func cata(@noescape transform: (Annotation, Syntax<Value, Leaf>) throws -> Value) rethrows -> Value {
|
||||
return try analysis(
|
||||
ifPure: id,
|
||||
ifRoll: { try transform($0, $1.map { try $0.cata(transform) }) })
|
||||
switch self {
|
||||
case let .Pure(a):
|
||||
return a
|
||||
case let .Roll(annotation, syntax):
|
||||
return try transform(annotation, syntax.map { try $0.cata(transform) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -88,14 +82,12 @@ public enum Free<Leaf, Annotation, Value>: CustomDebugStringConvertible {
|
||||
// MARK: Functor
|
||||
|
||||
public func map<C>(@noescape transform: Value throws -> C) rethrows -> Free<Leaf, Annotation, C> {
|
||||
return try analysis(ifPure: { try .Pure(transform($0)) }, ifRoll: { try .Roll($0, $1.map { try $0.map(transform) }) })
|
||||
}
|
||||
|
||||
|
||||
// MARK: Monad
|
||||
|
||||
public func flatMap<C>(@noescape transform: Value throws -> Free<Leaf, Annotation, C>) rethrows -> Free<Leaf, Annotation, C> {
|
||||
return try analysis(ifPure: transform, ifRoll: { try .Roll($0, $1.map { try $0.flatMap(transform) }) })
|
||||
switch self {
|
||||
case let .Pure(a):
|
||||
return try .Pure(transform(a))
|
||||
case let .Roll(annotation, syntax):
|
||||
return try .Roll(annotation, syntax.map { try $0.map(transform) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -216,14 +208,17 @@ public func == <Term: CofreeType, Annotation where Term.Leaf: Equatable> (left:
|
||||
|
||||
extension Free {
|
||||
public func JSON(pure pure: Value -> Doubt.JSON, leaf: Leaf -> Doubt.JSON, annotation: Annotation -> Doubt.JSON) -> Doubt.JSON {
|
||||
return analysis(
|
||||
ifPure: { [ "pure": pure($0) ] },
|
||||
ifRoll: {
|
||||
[ "roll": [
|
||||
"extract": annotation($0),
|
||||
"unwrap": $1.JSON(leaf: leaf, recur: { $0.JSON(pure: pure, leaf: leaf, annotation: annotation) })
|
||||
] ]
|
||||
})
|
||||
switch self {
|
||||
case let .Pure(a):
|
||||
return [ "pure": pure(a) ]
|
||||
case let .Roll(a, b):
|
||||
return [
|
||||
"roll": [
|
||||
"extract": annotation(a),
|
||||
"unwrap": b.JSON(leaf: leaf, recur: { $0.JSON(pure: pure, leaf: leaf, annotation: annotation) })
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
infix operator <> {
|
||||
associativity right
|
||||
precedence 140
|
||||
}
|
||||
|
||||
infix operator <+> {
|
||||
associativity right
|
||||
precedence 140
|
||||
}
|
||||
|
||||
infix operator </> {
|
||||
associativity right
|
||||
precedence 140
|
||||
}
|
||||
|
||||
infix operator >>> {
|
||||
associativity right
|
||||
precedence 170
|
||||
}
|
@ -48,8 +48,8 @@ public enum Syntax<Recur, A>: CustomDebugStringConvertible {
|
||||
/// Hylomorphisms are used to construct diffs corresponding to equal terms; see also `CofreeType.zip`.
|
||||
///
|
||||
/// `hylo` can be used with arbitrary functors which can eliminate to and introduce with `Syntax` values.
|
||||
public func hylo<A, B, Leaf>(down: Syntax<B, Leaf> -> B, _ up: A -> Syntax<A, Leaf>) -> A -> B {
|
||||
return up >>> { $0.map(hylo(down, up)) } >>> down
|
||||
public func hylo<A, B, Leaf>(down: Syntax<B, Leaf> -> B, _ up: A -> Syntax<A, Leaf>)(_ a: A) -> B {
|
||||
return down(up(a).map(hylo(down, up)))
|
||||
}
|
||||
|
||||
/// Reiteration through `Syntax`.
|
||||
@ -59,8 +59,9 @@ public func hylo<A, B, Leaf>(down: Syntax<B, Leaf> -> B, _ up: A -> Syntax<A, Le
|
||||
/// Hylomorphisms are used to construct diffs corresponding to equal terms; see also `CofreeType.zip`.
|
||||
///
|
||||
/// `hylo` can be used with arbitrary functors which can eliminate to and introduce with `Annotation` & `Syntax` pairs.
|
||||
public func hylo<A, B, Leaf, Annotation>(down: (Annotation, Syntax<B, Leaf>) -> B, _ up: A -> (Annotation, Syntax<A, Leaf>)) -> A -> B {
|
||||
return up >>> { ($0, $1.map(hylo(down, up))) } >>> down
|
||||
public func hylo<A, B, Leaf, Annotation>(down: (Annotation, Syntax<B, Leaf>) -> B, _ up: A -> (Annotation, Syntax<A, Leaf>))(_ a: A) -> B {
|
||||
let (annotation, syntax) = up(a)
|
||||
return down(annotation, syntax.map(hylo(down, up)))
|
||||
}
|
||||
|
||||
|
||||
@ -89,12 +90,12 @@ extension Syntax {
|
||||
switch (left, right) {
|
||||
case let (.Leaf(l1), .Leaf(l2)):
|
||||
return leaf(l1, l2)
|
||||
case let (.Indexed(v1), .Indexed(v2)):
|
||||
return v1.count == v2.count && zip(v1, v2).lazy.map(recur).reduce(true) { $0 && $1 }
|
||||
case let (.Fixed(v1), .Fixed(v2)):
|
||||
return v1.count == v2.count && zip(v1, v2).lazy.map(recur).reduce(true) { $0 && $1 }
|
||||
case let (.Keyed(d1), .Keyed(d2)):
|
||||
return Set(d1.keys) == Set(d2.keys) && d1.keys.map { recur(d1[$0]!, d2[$0]!) }.reduce(true) { $0 && $1 }
|
||||
case let (.Indexed(v1), .Indexed(v2)) where v1.count == v2.count:
|
||||
return zip(v1, v2).reduce(true) { $0 && recur($1) }
|
||||
case let (.Fixed(v1), .Fixed(v2)) where v1.count == v2.count:
|
||||
return zip(v1, v2).reduce(true) { $0 && recur($1) }
|
||||
case let (.Keyed(d1), .Keyed(d2)) where Set(d1.keys) == Set(d2.keys):
|
||||
return d1.keys.reduce(true) { $0 && recur(d1[$1]!, d2[$1]!) }
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
@ -14,15 +14,15 @@ extension TermType {
|
||||
/// 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.
|
||||
public func cata<Result>(transform: Syntax<Result, Leaf> -> Result) -> Result {
|
||||
return self |> (Self.unwrap >>> { $0.map { $0.cata(transform) } } >>> transform)
|
||||
public func cata<Result>(transform: Syntax<Result, Leaf> throws -> Result) rethrows -> Result {
|
||||
return try transform(unwrap.map { try $0.cata(transform) })
|
||||
}
|
||||
|
||||
/// 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.
|
||||
public func para<Result>(transform: Syntax<(Self, Result), Leaf> -> Result) -> Result {
|
||||
return self |> (Self.unwrap >>> { $0.map { ($0, $0.para(transform)) } } >>> transform)
|
||||
public func para<Result>(transform: Syntax<(Self, Result), Leaf> throws -> Result) rethrows -> Result {
|
||||
return try transform(unwrap.map { try ($0, $0.para(transform)) })
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,20 +26,20 @@ extension TSNode {
|
||||
var namedChildren: ChildrenCollection {
|
||||
return ChildrenCollection(node: self, count: ts_node_named_child_count(self), child: ts_node_named_child)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct ChildrenCollection: CollectionType {
|
||||
let node: TSNode
|
||||
let count: Int
|
||||
let child: (TSNode, Int) -> TSNode
|
||||
struct ChildrenCollection: CollectionType {
|
||||
let node: TSNode
|
||||
let count: Int
|
||||
let child: (TSNode, Int) -> TSNode
|
||||
|
||||
subscript (index: Int) -> TSNode {
|
||||
return child(node, index)
|
||||
}
|
||||
subscript (index: Int) -> TSNode {
|
||||
return child(node, index)
|
||||
}
|
||||
|
||||
let startIndex = 0
|
||||
var endIndex: Int {
|
||||
return count
|
||||
}
|
||||
let startIndex = 0
|
||||
var endIndex: Int {
|
||||
return count
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ import Doubt
|
||||
import Prelude
|
||||
import Madness
|
||||
|
||||
func benchmark<T>(label: String? = nil, _ f: () -> T) -> T {
|
||||
func benchmark<T>(label: String? = nil, _ f: () throws -> T) rethrows -> T {
|
||||
let start = NSDate.timeIntervalSinceReferenceDate()
|
||||
let result = f()
|
||||
let result = try f()
|
||||
let end = NSDate.timeIntervalSinceReferenceDate()
|
||||
print((label.map { "\($0): " } ?? "") + "\(end - start)s")
|
||||
return result
|
||||
@ -144,7 +144,7 @@ func parserForType(type: String) -> String throws -> Term {
|
||||
}
|
||||
}
|
||||
|
||||
let parsed = parse(argumentsParser, input: Process.arguments)
|
||||
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
|
||||
let jsonURL = NSURL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).URLByAppendingPathComponent("diff.json")
|
||||
@ -152,9 +152,9 @@ guard let uiPath = NSBundle.mainBundle().infoDictionary?["PathToUISource"] as? S
|
||||
guard aSource.type == bSource.type else { throw "can’t compare files of different types" }
|
||||
let parser = parserForType(aSource.type)
|
||||
|
||||
let a = try parser(aSource.contents)
|
||||
let b = try parser(bSource.contents)
|
||||
let diff = 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 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) }
|
||||
switch arguments.output {
|
||||
case .Split:
|
||||
let JSON: Doubt.JSON = [
|
||||
@ -178,5 +178,5 @@ case .Split:
|
||||
NSWorkspace.sharedWorkspace().openURL(URL)
|
||||
}
|
||||
case .Unified:
|
||||
print(benchmark { unified(diff, before: aSource.contents, after: bSource.contents) })
|
||||
print(benchmark("formatting unified diff") { unified(diff, before: aSource.contents, after: bSource.contents) })
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user