2015-10-08 02:32:02 +03:00
|
|
|
import Cocoa
|
2015-10-14 21:17:56 +03:00
|
|
|
import Doubt
|
|
|
|
import Prelude
|
2015-10-08 02:20:40 +03:00
|
|
|
|
2015-10-14 21:17:56 +03:00
|
|
|
typealias Term = Cofree<JSONLeaf, ()>
|
2015-10-14 21:00:46 +03:00
|
|
|
typealias Diff = Free<JSONLeaf, Patch<Term>>
|
2015-10-14 20:57:12 +03:00
|
|
|
|
2015-10-09 17:14:07 +03:00
|
|
|
enum JSONLeaf: Equatable, CustomJSONConvertible, CustomStringConvertible {
|
2015-10-08 02:21:26 +03:00
|
|
|
case Number(Double)
|
|
|
|
case Boolean(Bool)
|
|
|
|
case String(Swift.String)
|
|
|
|
case Null
|
2015-10-08 03:08:34 +03:00
|
|
|
|
|
|
|
|
2015-10-09 17:14:07 +03:00
|
|
|
// MARK: CustomJSONConvertible
|
|
|
|
|
|
|
|
var JSON: Doubt.JSON {
|
|
|
|
switch self {
|
|
|
|
case let .Number(n):
|
|
|
|
return .Number(n)
|
|
|
|
case let .Boolean(b):
|
|
|
|
return .Boolean(b)
|
|
|
|
case let .String(s):
|
|
|
|
return .String(s)
|
|
|
|
case .Null:
|
|
|
|
return .Null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-09 17:13:09 +03:00
|
|
|
// MARK: CustomStringConvertible
|
|
|
|
|
2015-10-08 03:08:34 +03:00
|
|
|
var description: Swift.String {
|
|
|
|
switch self {
|
|
|
|
case let .Number(n):
|
|
|
|
return Swift.String(n)
|
|
|
|
case let .Boolean(b):
|
|
|
|
return Swift.String(b)
|
|
|
|
case let .String(s):
|
|
|
|
return Swift.String(reflecting: s)
|
|
|
|
case .Null:
|
|
|
|
return "null"
|
|
|
|
}
|
|
|
|
}
|
2015-10-08 02:21:26 +03:00
|
|
|
}
|
2015-10-08 02:32:02 +03:00
|
|
|
|
2015-10-08 02:43:00 +03:00
|
|
|
func == (left: JSONLeaf, right: JSONLeaf) -> Bool {
|
|
|
|
switch (left, right) {
|
|
|
|
case let (.Number(a), .Number(b)):
|
|
|
|
return a == b
|
|
|
|
case let (.Boolean(a), .Boolean(b)):
|
|
|
|
return a == b
|
|
|
|
case let (.String(a), .String(b)):
|
|
|
|
return a == b
|
|
|
|
case (.Null, .Null):
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-08 02:36:58 +03:00
|
|
|
|
2015-10-08 02:32:02 +03:00
|
|
|
extension JSON {
|
|
|
|
init?(path: Swift.String) {
|
|
|
|
guard let data = try? NSData(contentsOfFile: path, options: []) else { return nil }
|
|
|
|
guard let object = try? NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) else { return nil }
|
|
|
|
self.init(object: object)
|
|
|
|
}
|
2015-10-08 02:36:43 +03:00
|
|
|
|
2015-10-08 02:38:24 +03:00
|
|
|
var term: Term {
|
2015-10-14 21:17:56 +03:00
|
|
|
func annotate(json: Syntax<Term, JSONLeaf>) -> Term {
|
|
|
|
return Cofree((), json)
|
|
|
|
}
|
2015-10-08 02:38:24 +03:00
|
|
|
switch self {
|
|
|
|
case let .Array(a):
|
2015-10-14 21:17:56 +03:00
|
|
|
return annotate(.Indexed(a.map { $0.term }))
|
2015-10-08 02:38:24 +03:00
|
|
|
case let .Dictionary(d):
|
2015-10-14 21:17:56 +03:00
|
|
|
return annotate(.Keyed(Swift.Dictionary(elements: d.map { ($0, $1.term) })))
|
2015-10-08 02:38:24 +03:00
|
|
|
case let .Number(n):
|
2015-10-14 21:17:56 +03:00
|
|
|
return annotate(.Leaf(.Number(n)))
|
2015-10-08 02:38:24 +03:00
|
|
|
case let .Boolean(b):
|
2015-10-14 21:17:56 +03:00
|
|
|
return annotate(.Leaf(.Boolean(b)))
|
2015-10-08 02:38:24 +03:00
|
|
|
case let .String(s):
|
2015-10-14 21:17:56 +03:00
|
|
|
return annotate(.Leaf(.String(s)))
|
2015-10-08 02:38:24 +03:00
|
|
|
case .Null:
|
2015-10-14 21:17:56 +03:00
|
|
|
return annotate(.Leaf(.Null))
|
2015-10-08 02:38:24 +03:00
|
|
|
}
|
|
|
|
}
|
2015-10-08 02:32:02 +03:00
|
|
|
}
|
2015-10-08 02:43:22 +03:00
|
|
|
|
|
|
|
let arguments = BoundsCheckedArray(array: Process.arguments)
|
|
|
|
if let a = arguments[1].flatMap(JSON.init), b = arguments[2].flatMap(JSON.init) {
|
2015-10-14 21:17:56 +03:00
|
|
|
let diff = Algorithm<Term, Diff>(a.term, b.term).evaluate(Cofree.equals(annotation: const(true), leaf: ==))
|
|
|
|
if let JSON = NSString(data: diff.JSON(ifPure: { $0.JSON { $0.JSON(annotation: const([:]), leaf: { $0.JSON }) } }, ifLeaf: { $0.JSON }).serialize(), encoding: NSUTF8StringEncoding) {
|
2015-10-09 17:20:46 +03:00
|
|
|
print(JSON)
|
|
|
|
}
|
2015-10-08 02:43:22 +03:00
|
|
|
}
|