1
1
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:
joshvera 2015-11-03 17:09:06 -05:00
commit 7f014eff8e
10 changed files with 61 additions and 110 deletions

View File

@ -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 = "";

View File

@ -83,7 +83,7 @@
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
debugDocumentVersioning = "NO">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference

View File

@ -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) }) })
}
}

View File

@ -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) })
}

View File

@ -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) })
]
]
}
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)) })
}

View File

@ -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
}
}

View File

@ -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 "cant 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) })
}