├── script ├── schemes.awk ├── xctool.awk ├── bootstrap ├── LICENSE.md ├── README.md └── cibuild ├── FingerTree.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ ├── FingerTreeTest.xcscheme │ │ └── FingerTree.xcscheme └── project.pbxproj ├── FingerTree ├── TODO.txt ├── main.swift ├── Node.swift ├── Measure.swift ├── Affix.swift ├── Split.swift ├── Collection.swift ├── TreeView.swift └── FingerTree.swift ├── .travis.yml ├── README.md ├── .gitignore ├── FingerTreeTest ├── Info.plist ├── FingerTreeTest.swift ├── NodeTest.swift └── AffixTest.swift └── LICENSE /script/schemes.awk: -------------------------------------------------------------------------------- 1 | BEGIN { 2 | FS = "\n"; 3 | } 4 | 5 | /Schemes:/ { 6 | while (getline && $0 != "") { 7 | sub(/^ +/, ""); 8 | print "'" $0 "'"; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /FingerTree.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FingerTree/TODO.txt: -------------------------------------------------------------------------------- 1 | TODO: 2 | - Complete test coverage 3 | - Clean up API and code/style 4 | - Prevent unnecessary copying of objects 5 | - Don't use sub-Arrays (getting a Slice and converting to Array) 6 | - Profile performance 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode9 3 | git: 4 | submodules: false 5 | branches: 6 | only: 7 | - master 8 | script: script/cibuild 9 | notifications: 10 | email: true 11 | before_install: 12 | - brew update 13 | after_success: 14 | - bash <(curl -s https://codecov.io/bash) 15 | 16 | -------------------------------------------------------------------------------- /script/xctool.awk: -------------------------------------------------------------------------------- 1 | # Exit statuses: 2 | # 3 | # 0 - No errors found. 4 | # 1 - Wrong SDK. Retry with SDK `iphonesimulator`. 5 | # 2 - Missing target. 6 | 7 | BEGIN { 8 | status = 0; 9 | } 10 | 11 | { 12 | print; 13 | } 14 | 15 | /Testing with the '(.+)' SDK is not yet supported/ { 16 | status = 1; 17 | } 18 | 19 | /does not contain a target named/ { 20 | status = 2; 21 | } 22 | 23 | END { 24 | exit status; 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FingerTree [![Build Status](https://travis-ci.org/lazytype/FingerTree.svg?branch=master)](https://travis-ci.org/lazytype/FingerTree) [![Coverage Status](https://coveralls.io/repos/lazytype/FingerTree/badge.svg?branch=master&service=github)](https://coveralls.io/github/lazytype/FingerTree?branch=master) 2 | ========== 3 | 4 | Implementation of a generic 2-3 finger tree in Swift based on the Haskell implementation demonstrated in http://andrew.gibiansky.com/blog/haskell/finger-trees 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | .DS_Store 20 | 21 | # CocoaPods 22 | # 23 | # We recommend against adding the Pods directory to your .gitignore. However 24 | # you should judge for yourself, the pros and cons are mentioned at: 25 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 26 | # 27 | # Pods/ 28 | -------------------------------------------------------------------------------- /FingerTreeTest/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /script/bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export SCRIPT_DIR=$(dirname "$0") 4 | 5 | ## 6 | ## Bootstrap Process 7 | ## 8 | 9 | main () 10 | { 11 | local submodules=$(git submodule status) 12 | local result=$? 13 | 14 | if [ "$result" -ne "0" ] 15 | then 16 | exit $result 17 | fi 18 | 19 | if [ -n "$submodules" ] 20 | then 21 | echo "*** Updating submodules..." 22 | update_submodules 23 | fi 24 | } 25 | 26 | bootstrap_submodule () 27 | { 28 | local bootstrap="script/bootstrap" 29 | 30 | if [ -e "$bootstrap" ] 31 | then 32 | echo "*** Bootstrapping $name..." 33 | "$bootstrap" >/dev/null 34 | else 35 | update_submodules 36 | fi 37 | } 38 | 39 | update_submodules () 40 | { 41 | git submodule sync --quiet && git submodule update --init && git submodule foreach --quiet bootstrap_submodule 42 | } 43 | 44 | export -f bootstrap_submodule 45 | export -f update_submodules 46 | 47 | main 48 | -------------------------------------------------------------------------------- /script/LICENSE.md: -------------------------------------------------------------------------------- 1 | **Copyright (c) 2013 Justin Spahr-Summers** 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-Present, Michael Mitchell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | and associated documentation files (the "Software"), to deal in the Software without 7 | restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /FingerTree/main.swift: -------------------------------------------------------------------------------- 1 | // main.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /FingerTreeTest/FingerTreeTest.swift: -------------------------------------------------------------------------------- 1 | // FingerTreeTest.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | import XCTest 21 | 22 | class FingerTreeTest: XCTestCase { 23 | } 24 | -------------------------------------------------------------------------------- /FingerTreeTest/NodeTest.swift: -------------------------------------------------------------------------------- 1 | // NodeTest.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | import XCTest 21 | 22 | class NodeTwoTest: XCTestCase { 23 | var node: Node, Size> { 24 | return Node.branch2(Value("a").makeElement(), Value("b").makeElement(), Size(2)) 25 | } 26 | 27 | var array: [Character] { 28 | return ["a", "b"] 29 | } 30 | 31 | func testToArray() { 32 | XCTAssertEqual(node.makeArray().map {$0.value!.value}, array) 33 | } 34 | 35 | func testMeasure() { 36 | XCTAssertEqual(node.measure, 2) 37 | } 38 | 39 | func testGenerate() { 40 | XCTAssertEqual(node.makeIterator().map {$0.value!.value}, array) 41 | } 42 | } 43 | 44 | class NodeThreeTest: XCTestCase { 45 | var node: Node, Size> { 46 | return Node.branch3(Value("a").makeElement(), Value("b").makeElement(), Value("c").makeElement(), Size(3)) 47 | } 48 | 49 | var array: [Character] { 50 | return ["a", "b", "c"] 51 | } 52 | 53 | func testToArray() { 54 | XCTAssertEqual(node.makeArray().map {$0.value!.value}, array) 55 | } 56 | 57 | func testMeasure() { 58 | XCTAssertEqual(node.measure, 3) 59 | } 60 | 61 | func testGenerate() { 62 | XCTAssertEqual(node.makeIterator().map {$0.value!.value}, array) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /FingerTree/Node.swift: -------------------------------------------------------------------------------- 1 | // Node.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | enum TreeElement 21 | : Measurable where TAnnotation == TValue.Annotation { 22 | 23 | case aValue(TValue) 24 | case aNode(Node) 25 | 26 | var node: Node? { 27 | if case let .aNode(node) = self { 28 | return node 29 | } 30 | 31 | return nil 32 | } 33 | 34 | var value: TValue? { 35 | if case let .aValue(value) = self { 36 | return value 37 | } 38 | 39 | return nil 40 | } 41 | 42 | var measure: TAnnotation { 43 | switch self { 44 | case let .aNode(node): 45 | return node.measure 46 | case let .aValue(value): 47 | return value.measure 48 | } 49 | } 50 | } 51 | 52 | enum Node 53 | : Measurable, Sequence where TAnnotation == TValue.Annotation { 54 | 55 | typealias Element = TreeElement 56 | 57 | indirect case branch2(Element, Element, TAnnotation) 58 | indirect case branch3(Element, Element, Element, TAnnotation) 59 | 60 | var measure: TAnnotation { 61 | switch self { 62 | case let .branch2(_, _, annotation): 63 | return annotation 64 | case let .branch3(_, _, _, annotation): 65 | return annotation 66 | } 67 | } 68 | 69 | func makeArray() -> [Element] { 70 | switch self { 71 | case let .branch2(a, b, _): 72 | return [a, b] 73 | case let .branch3(a, b, c, _): 74 | return [a, b, c] 75 | } 76 | } 77 | 78 | func makeElement() -> Element { 79 | return Element.aNode(self) 80 | } 81 | 82 | func makeIterator() -> IndexingIterator<[Element]> { 83 | return makeArray().makeIterator() 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /script/README.md: -------------------------------------------------------------------------------- 1 | # objc-build-scripts 2 | 3 | This project is a collection of scripts created with two goals: 4 | 5 | 1. To standardize how Objective-C projects are bootstrapped after cloning 6 | 1. To easily build Objective-C projects on continuous integration servers 7 | 8 | ## Scripts 9 | 10 | Right now, there are two important scripts: [`bootstrap`](#bootstrap) and 11 | [`cibuild`](#cibuild). Both are Bash scripts, to maximize compatibility and 12 | eliminate pesky system configuration issues (like setting up a working Ruby 13 | environment). 14 | 15 | The structure of the scripts on disk is meant to follow that of a typical Ruby 16 | project: 17 | 18 | ``` 19 | script/ 20 | bootstrap 21 | cibuild 22 | ``` 23 | 24 | ### bootstrap 25 | 26 | This script is responsible for bootstrapping (initializing) your project after 27 | it's been checked out. Here, you should install or clone any dependencies that 28 | are required for a working build and development environment. 29 | 30 | By default, the script will verify that [xctool][] is installed, then initialize 31 | and update submodules recursively. If any submodules contain `script/bootstrap`, 32 | that will be run as well. 33 | 34 | To check that other tools are installed, you can set the `REQUIRED_TOOLS` 35 | environment variable before running `script/bootstrap`, or edit it within the 36 | script directly. Note that no installation is performed automatically, though 37 | this can always be added within your specific project. 38 | 39 | ### cibuild 40 | 41 | This script is responsible for building the project, as you would want it built 42 | for continuous integration. This is preferable to putting the logic on the CI 43 | server itself, since it ensures that any changes are versioned along with the 44 | source. 45 | 46 | By default, the script will run [`bootstrap`](#bootstrap), look for any Xcode 47 | workspace or project in the working directory, then build all targets/schemes 48 | (as found by `xcodebuild -list`) using [xctool][]. 49 | 50 | You can also specify the schemes to build by passing them into the script: 51 | 52 | ```sh 53 | script/cibuild ReactiveCocoa-Mac ReactiveCocoa-iOS 54 | ``` 55 | 56 | As with the `bootstrap` script, there are several environment variables that can 57 | be used to customize behavior. They can be set on the command line before 58 | invoking the script, or the defaults changed within the script directly. 59 | 60 | ## Getting Started 61 | 62 | To add the scripts to your project, read the contents of this repository into 63 | a `script` folder: 64 | 65 | ``` 66 | $ git remote add objc-build-scripts https://github.com/jspahrsummers/objc-build-scripts.git 67 | $ git fetch objc-build-scripts 68 | $ git read-tree --prefix=script/ -u objc-build-scripts/master 69 | ``` 70 | 71 | Then commit the changes, to incorporate the scripts into your own repository's 72 | history. You can also freely tweak the scripts for your specific project's 73 | needs. 74 | 75 | To merge in upstream changes later: 76 | 77 | ``` 78 | $ git fetch -p objc-build-scripts 79 | $ git merge --ff --squash -Xsubtree=script objc-build-scripts/master 80 | ``` 81 | 82 | [xctool]: https://github.com/facebook/xctool 83 | -------------------------------------------------------------------------------- /FingerTree/Measure.swift: -------------------------------------------------------------------------------- 1 | // Measure.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | protocol Monoid { 21 | static var identity: Self {get} 22 | func append(_ other: Self) -> Self 23 | } 24 | 25 | precedencegroup Additive { 26 | associativity: left 27 | } 28 | 29 | infix operator <> : Additive 30 | internal func <> (lhs: TAnnotation, rhs: TAnnotation) -> TAnnotation { 31 | return lhs.append(rhs) 32 | } 33 | 34 | internal protocol Measurable { 35 | associatedtype Annotation: Monoid 36 | var measure: Annotation {get} 37 | } 38 | 39 | struct Value: Measurable, CustomStringConvertible { 40 | typealias Annotation = Size 41 | 42 | let value: T 43 | 44 | init(_ value: T) { 45 | self.value = value 46 | } 47 | 48 | var measure: Size { 49 | return 1 50 | } 51 | 52 | var description: String { 53 | return "'\(value)'" 54 | } 55 | } 56 | 57 | extension Measurable { 58 | func makeElement() -> TreeElement { 59 | return TreeElement.aValue(self) 60 | } 61 | } 62 | 63 | typealias Size = Int 64 | 65 | extension Size: Monoid { 66 | static var identity: Size = 0 67 | 68 | func append(_ other: Size) -> Size { 69 | return self + other 70 | } 71 | } 72 | 73 | struct Prioritized: Measurable { 74 | typealias Annotation = Priority 75 | 76 | let value: T 77 | let priority: Int 78 | 79 | init(_ value: T, priority: Int) { 80 | self.value = value 81 | self.priority = priority 82 | } 83 | 84 | var measure: Priority { 85 | return Priority.value(priority) 86 | } 87 | } 88 | 89 | enum Priority: Monoid { 90 | case negativeInfinity 91 | case value(Int) 92 | 93 | static var identity: Priority { 94 | return Priority.negativeInfinity 95 | } 96 | 97 | func append(_ other: Priority) -> Priority { 98 | switch (self, other) { 99 | case (.negativeInfinity, _): 100 | return other 101 | case (_, .negativeInfinity): 102 | return self 103 | case let (.value(value), .value(otherValue)): 104 | return value > otherValue ? self : other 105 | default: 106 | // All cases have actually been exhausted. Remove when the compiler is smarter about this. 107 | return self 108 | } 109 | } 110 | } 111 | 112 | func == (lhs: Priority, rhs: Priority) -> Bool { 113 | switch (lhs, rhs) { 114 | case (.negativeInfinity, .negativeInfinity): 115 | return true 116 | case let (.value(lvalue), .value(rvalue)): 117 | return lvalue == rvalue 118 | default: 119 | return false 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /FingerTree.xcodeproj/xcshareddata/xcschemes/FingerTreeTest.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 58 | 59 | 65 | 66 | 67 | 68 | 69 | 70 | 76 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /FingerTree/Affix.swift: -------------------------------------------------------------------------------- 1 | // Affix.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | enum AffixError: Error { 21 | case tooLarge 22 | } 23 | 24 | enum Affix 25 | : Measurable, Sequence where TAnnotation == TValue.Annotation { 26 | 27 | typealias Element = TreeElement 28 | 29 | case one(Element) 30 | case two(Element, Element) 31 | case three(Element, Element, Element) 32 | case four(Element, Element, Element, Element) 33 | 34 | var viewFirst: (Element, Affix?) { 35 | switch self { 36 | case let .one(a): 37 | return (a, nil) 38 | case let .two(a, b): 39 | return (a, Affix.one(b)) 40 | case let .three(a, b, c): 41 | return (a, Affix.two(b, c)) 42 | case let .four(a, b, c, d): 43 | return (a, Affix.three(b, c, d)) 44 | } 45 | } 46 | 47 | var viewLast: (Affix?, Element) { 48 | switch self { 49 | case let .one(a): 50 | return (nil, a) 51 | case let .two(a, b): 52 | return (Affix.one(a), b) 53 | case let .three(a, b, c): 54 | return (Affix.two(a, b), c) 55 | case let .four(a, b, c, d): 56 | return (Affix.three(a, b, c), d) 57 | } 58 | } 59 | 60 | var measure: TAnnotation { 61 | switch self { 62 | case let .one(a): 63 | return a.measure 64 | case let .two(a, b): 65 | return a.measure <> b.measure 66 | case let .three(a, b, c): 67 | return a.measure <> b.measure <> c.measure 68 | case let .four(a, b, c, d): 69 | return a.measure <> b.measure <> c.measure <> d.measure 70 | } 71 | } 72 | 73 | func preface(_ element: Element) throws -> Affix { 74 | switch self { 75 | case let .one(a): 76 | return Affix.two(element, a) 77 | case let .two(a, b): 78 | return Affix.three(element, a, b) 79 | case let .three(a, b, c): 80 | return Affix.four(element, a, b, c) 81 | case .four: 82 | throw AffixError.tooLarge 83 | } 84 | } 85 | 86 | func append(_ element: Element) throws -> Affix { 87 | switch self { 88 | case let .one(a): 89 | return Affix.two(a, element) 90 | case let .two(a, b): 91 | return Affix.three(a, b, element) 92 | case let .three(a, b, c): 93 | return Affix.four(a, b, c, element) 94 | case .four: 95 | throw AffixError.tooLarge 96 | } 97 | } 98 | 99 | func makeArray() -> [Element] { 100 | switch self { 101 | case let .one(a): 102 | return [a] 103 | case let .two(a, b): 104 | return [a, b] 105 | case let .three(a, b, c): 106 | return [a, b, c] 107 | case let .four(a, b, c, d): 108 | return [a, b, c, d] 109 | } 110 | } 111 | 112 | func makeIterator() -> IndexingIterator<[Element]> { 113 | return makeArray().makeIterator() 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /FingerTree/Split.swift: -------------------------------------------------------------------------------- 1 | // Split.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | enum SplitError: Error { 21 | case notFound 22 | } 23 | 24 | extension FingerTree { 25 | func split( 26 | predicate: (TAnnotation) -> Bool, 27 | startAnnotation: TAnnotation 28 | ) throws -> (FingerTree, FingerTree) { 29 | switch self { 30 | case .empty: 31 | break 32 | case .single: 33 | if predicate(startAnnotation <> measure) { 34 | return (FingerTree.empty, self) 35 | } 36 | case let .deep(prefix, deeper, suffix, _): 37 | if !predicate(startAnnotation <> measure) { 38 | throw SplitError.notFound 39 | } 40 | 41 | let startToPrefix = startAnnotation <> prefix.measure 42 | if predicate(startToPrefix) { 43 | if let (before, after) = FingerTree.splitList( 44 | predicate: predicate, 45 | startAnnotation: startAnnotation, 46 | values: prefix 47 | ) { 48 | let left: FingerTree 49 | if let affix: Affix = before { 50 | left = affix.makeFingerTree() 51 | } else { 52 | left = FingerTree.empty 53 | } 54 | 55 | return (left, FingerTree.createDeep(prefix: after, deeper: deeper, suffix: suffix)) 56 | } 57 | } else if predicate(startToPrefix <> deeper.measure) { 58 | let (left, right) = try! deeper.split(predicate: predicate, startAnnotation: startToPrefix) 59 | let (element, rest) = right.viewLeft! 60 | 61 | if let (beforeNode, afterNode) = FingerTree.splitList( 62 | predicate: predicate, 63 | startAnnotation: startToPrefix <> left.measure, 64 | values: element.node!.makeAffix() 65 | ) { 66 | return ( 67 | FingerTree.createDeep(prefix: prefix, deeper: left, suffix: beforeNode), 68 | FingerTree.createDeep(prefix: afterNode, deeper: rest, suffix: suffix) 69 | ) 70 | } 71 | } else if let (before, after) = FingerTree.splitList( 72 | predicate: predicate, 73 | startAnnotation: startToPrefix <> deeper.measure, 74 | values: suffix 75 | ) { 76 | return ( 77 | FingerTree.createDeep(prefix: prefix, deeper: deeper, suffix: before), 78 | after.makeFingerTree() 79 | ) 80 | } 81 | } 82 | 83 | throw SplitError.notFound 84 | } 85 | 86 | private static func splitList( 87 | predicate: (TAnnotation) -> Bool, 88 | startAnnotation: TAnnotation, 89 | values: Affix 90 | ) -> (Affix?, Affix)? { 91 | let (first, rest) = values.viewFirst 92 | 93 | let start = startAnnotation <> first.measure 94 | 95 | if predicate(start) { 96 | return (nil, values) 97 | } 98 | 99 | if rest == nil { 100 | return nil 101 | } 102 | 103 | if let (before, after) = splitList( 104 | predicate: predicate, 105 | startAnnotation: start, 106 | values: rest! 107 | ) { 108 | if before == nil { 109 | return (Affix.one(first), after) 110 | } 111 | 112 | return (try! before!.preface(first), after) 113 | } 114 | 115 | return nil 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /script/cibuild: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export SCRIPT_DIR=$(dirname "$0") 4 | 5 | ## 6 | ## Configuration Variables 7 | ## 8 | 9 | SCHEMES="$@" 10 | 11 | config () 12 | { 13 | # The workspace to build. 14 | # 15 | # If not set and no workspace is found, the -workspace flag will not be passed 16 | # to `xctool`. 17 | # 18 | # Only one of `XCWORKSPACE` and `XCODEPROJ` needs to be set. The former will 19 | # take precedence. 20 | : ${XCWORKSPACE=$(find_pattern "*.xcworkspace")} 21 | 22 | # The project to build. 23 | # 24 | # If not set and no project is found, the -project flag will not be passed 25 | # to `xctool`. 26 | # 27 | # Only one of `XCWORKSPACE` and `XCODEPROJ` needs to be set. The former will 28 | # take precedence. 29 | : ${XCODEPROJ=$(find_pattern "*.xcodeproj")} 30 | 31 | # A bootstrap script to run before building. 32 | # 33 | # If this file does not exist, it is not considered an error. 34 | : ${BOOTSTRAP="$SCRIPT_DIR/bootstrap"} 35 | 36 | # Extra options to pass to xctool. 37 | : ${XCTOOL_OPTIONS="RUN_CLANG_STATIC_ANALYZER=NO"} 38 | 39 | # A whitespace-separated list of default schemes to build. 40 | # 41 | # Individual names can be quoted to avoid word splitting. 42 | : ${SCHEMES:=$(xcodebuild -list -project "$XCODEPROJ" 2>/dev/null | awk -f "$SCRIPT_DIR/schemes.awk")} 43 | 44 | # A whitespace-separated list of executables that must be present and locatable. 45 | : ${REQUIRED_TOOLS="xctool"} 46 | 47 | export XCWORKSPACE 48 | export XCODEPROJ 49 | export BOOTSTRAP 50 | export XCTOOL_OPTIONS 51 | export SCHEMES 52 | export REQUIRED_TOOLS 53 | } 54 | 55 | ## 56 | ## Build Process 57 | ## 58 | 59 | main () 60 | { 61 | config 62 | 63 | if [ -n "$REQUIRED_TOOLS" ] 64 | then 65 | echo "*** Checking dependencies..." 66 | check_deps 67 | fi 68 | 69 | if [ -f "$BOOTSTRAP" ] 70 | then 71 | echo "*** Bootstrapping..." 72 | "$BOOTSTRAP" || exit $? 73 | fi 74 | 75 | echo "*** The following schemes will be built:" 76 | echo "$SCHEMES" | xargs -n 1 echo " " 77 | echo 78 | 79 | echo "$SCHEMES" | xargs -n 1 | ( 80 | local status=0 81 | 82 | while read scheme 83 | do 84 | build_scheme "$scheme" || status=1 85 | done 86 | 87 | exit $status 88 | ) 89 | } 90 | 91 | check_deps () 92 | { 93 | for tool in $REQUIRED_TOOLS 94 | do 95 | which -s "$tool" 96 | if [ "$?" -ne "0" ] 97 | then 98 | echo "*** Error: $tool not found. Please install it and cibuild again." 99 | exit 1 100 | fi 101 | done 102 | } 103 | 104 | find_pattern () 105 | { 106 | ls -d $1 2>/dev/null | head -n 1 107 | } 108 | 109 | run_xctool () 110 | { 111 | if [ -n "$XCWORKSPACE" ] 112 | then 113 | xctool -workspace "$XCWORKSPACE" $XCTOOL_OPTIONS "$@" 2>&1 114 | elif [ -n "$XCODEPROJ" ] 115 | then 116 | xctool -project "$XCODEPROJ" $XCTOOL_OPTIONS "$@" 2>&1 117 | else 118 | echo "*** No workspace or project file found." 119 | exit 1 120 | fi 121 | } 122 | 123 | parse_build () 124 | { 125 | awk -f "$SCRIPT_DIR/xctool.awk" 2>&1 >/dev/null 126 | } 127 | 128 | build_scheme () 129 | { 130 | local scheme=$1 131 | 132 | echo "*** Building and testing $scheme..." 133 | echo 134 | 135 | local sdkflag= 136 | local action=test 137 | 138 | # Determine whether we can run unit tests for this target. 139 | run_xctool -scheme "$scheme" run-tests | parse_build 140 | 141 | local awkstatus=$? 142 | 143 | if [ "$awkstatus" -eq "1" ] 144 | then 145 | # SDK not found, try for iphonesimulator. 146 | sdkflag="-sdk iphonesimulator" 147 | 148 | # Determine whether the unit tests will run with iphonesimulator 149 | run_xctool $sdkflag -scheme "$scheme" run-tests | parse_build 150 | 151 | awkstatus=$? 152 | 153 | if [ "$awkstatus" -ne "0" ] 154 | then 155 | # Unit tests will not run on iphonesimulator. 156 | sdkflag="" 157 | fi 158 | fi 159 | 160 | if [ "$awkstatus" -ne "0" ] 161 | then 162 | # Unit tests aren't supported. 163 | action=build 164 | fi 165 | 166 | run_xctool $sdkflag -scheme "$scheme" $action 167 | } 168 | 169 | export -f build_scheme 170 | export -f run_xctool 171 | export -f parse_build 172 | 173 | main 174 | -------------------------------------------------------------------------------- /FingerTree.xcodeproj/xcshareddata/xcschemes/FingerTree.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 35 | 41 | 42 | 43 | 44 | 45 | 51 | 52 | 53 | 54 | 55 | 56 | 67 | 69 | 75 | 76 | 77 | 78 | 79 | 82 | 83 | 84 | 90 | 92 | 98 | 99 | 100 | 101 | 103 | 104 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /FingerTreeTest/AffixTest.swift: -------------------------------------------------------------------------------- 1 | // AffixTest.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | import XCTest 21 | 22 | 23 | class AffixOneTest: XCTestCase { 24 | var affix: Affix, Size> { 25 | return Affix.one(Value("a").makeElement()) 26 | } 27 | 28 | var array: [Character] { 29 | return ["a"] 30 | } 31 | 32 | func testToArray() { 33 | XCTAssertEqual(affix.makeArray().map {$0.value!.value}, array) 34 | } 35 | 36 | func testPreface() { 37 | var array = self.array; 38 | array.insert("x", at: 0) 39 | 40 | XCTAssertEqual(try! affix.preface(Value("x").makeElement()).makeArray().map {$0.value!.value}, array) 41 | } 42 | 43 | func testAppend() { 44 | var array = self.array 45 | array.append("x") 46 | 47 | XCTAssertEqual(try! affix.append(Value("x").makeElement()).makeArray().map {$0.value!.value}, array) 48 | } 49 | 50 | func testMeasure() { 51 | XCTAssertEqual(affix.measure, array.count) 52 | } 53 | 54 | func testGenerate() { 55 | XCTAssertEqual(affix.makeIterator().map {$0.value!.value}, array) 56 | } 57 | } 58 | 59 | class AffixTwoTest: AffixOneTest { 60 | override var affix: Affix, Size> { 61 | return Affix.two(Value("a").makeElement(), Value("b").makeElement()) 62 | } 63 | 64 | override var array: [Character] { 65 | return ["a", "b"] 66 | } 67 | 68 | override func testToArray() { 69 | XCTAssertEqual(affix.makeArray().map {$0.value!.value}, self.array) 70 | } 71 | } 72 | 73 | class AffixThreeTest: AffixOneTest { 74 | override var affix: Affix, Size> { 75 | return Affix.three(Value("a").makeElement(), Value("b").makeElement(), Value("c").makeElement()) 76 | } 77 | 78 | override var array: [Character] { 79 | return ["a", "b", "c"] 80 | } 81 | } 82 | 83 | class AffixFourTest: AffixOneTest { 84 | override var affix: Affix, Size> { 85 | return Affix.four( 86 | Value("a").makeElement(), 87 | Value("b").makeElement(), 88 | Value("c").makeElement(), 89 | Value("d").makeElement() 90 | ) 91 | } 92 | 93 | override var array: [Character] { 94 | return ["a", "b", "c", "d"] 95 | } 96 | 97 | override func testPreface() { 98 | do { 99 | _ = try affix.preface(Value("x").makeElement()) 100 | } catch AffixError.tooLarge { 101 | return 102 | } catch {} 103 | 104 | XCTFail("preface() should throw AffixError.TooLarge") 105 | } 106 | 107 | override func testAppend() { 108 | do { 109 | _ = try affix.append(Value("x").makeElement()) 110 | } catch AffixError.tooLarge { 111 | return 112 | } catch {} 113 | 114 | XCTFail("append() should throw AffixError.TooLarge") 115 | } 116 | } 117 | 118 | class AffixTest: XCTestCase { 119 | func testViewFirst() { 120 | let array = ["a", "b", "c", "d"] 121 | var affix: Affix? = Affix.four( 122 | Value("a").makeElement(), 123 | Value("b").makeElement(), 124 | Value("c").makeElement(), 125 | Value("d").makeElement() 126 | ) 127 | for value in array { 128 | let (first, rest) = affix!.viewFirst 129 | 130 | affix = rest 131 | XCTAssert(value == first.value!.value) 132 | } 133 | 134 | XCTAssert(affix == nil) 135 | } 136 | 137 | func testViewLast() { 138 | let array = ["a", "b", "c", "d"] 139 | var affix: Affix? = Affix.four( 140 | Value("a").makeElement(), 141 | Value("b").makeElement(), 142 | Value("c").makeElement(), 143 | Value("d").makeElement() 144 | ) 145 | for value in array.reversed() { 146 | let (rest, last) = affix!.viewLast 147 | 148 | affix = rest 149 | XCTAssert(value == last.value!.value) 150 | } 151 | 152 | XCTAssert(affix == nil) 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /FingerTree/Collection.swift: -------------------------------------------------------------------------------- 1 | // Collection.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | public struct ImmutableCollection: Collection { 21 | private let tree: FingerTree, Size> 22 | 23 | init(_ tree: FingerTree, Size> = FingerTree.empty) { 24 | self.tree = tree 25 | } 26 | 27 | public let startIndex: Int = 0 28 | 29 | public var endIndex: Int { 30 | return tree.measure 31 | } 32 | 33 | public subscript(index: Int) -> T { 34 | let (_, right) = try! tree.split( 35 | predicate: {$0 > index && index >= 0}, 36 | startAnnotation: Size.identity 37 | ) 38 | 39 | let (element, _) = right.viewLeft! 40 | return element.value!.value 41 | } 42 | 43 | public func index(after i: Int) -> Int { 44 | precondition(i < endIndex, "Can't advance beyond endIndex") 45 | return i + 1 46 | } 47 | 48 | public func makeIterator() -> AnyIterator { 49 | return AnyIterator(tree.makeIterator().lazy.map {$0.value!.value}.makeIterator()) 50 | } 51 | 52 | public func reversed() -> AnyIterator { 53 | return AnyIterator(tree.reversed().lazy.map {$0.value!.value}.makeIterator()) 54 | } 55 | 56 | public func preface(_ element: T) -> ImmutableCollection { 57 | return ImmutableCollection(tree.preface(Value(element).makeElement())) 58 | } 59 | 60 | public func append(_ element: T) -> ImmutableCollection { 61 | return ImmutableCollection(tree.append(Value(element).makeElement())) 62 | } 63 | 64 | func insert(_ element: T, atIndex: Int) -> ImmutableCollection { 65 | do { 66 | let (left, right) = try tree.split( 67 | predicate: {$0 > atIndex && atIndex >= 0}, 68 | startAnnotation: Size.identity 69 | ) 70 | let middle = [Value(element).makeElement()] 71 | let newTree = FingerTree.concatenate(middle: middle, left: left, right: right) 72 | 73 | return ImmutableCollection(newTree) 74 | } catch { 75 | return ImmutableCollection(FingerTree.single(Value(element).makeElement())) 76 | } 77 | } 78 | } 79 | 80 | public struct PriorityQueue { 81 | let tree: FingerTree, Priority> 82 | 83 | init(_ tree: FingerTree, Priority>) { 84 | self.tree = tree 85 | } 86 | 87 | public func pop() -> (T, PriorityQueue) { 88 | let (left, right) = try! tree.split( 89 | predicate: {$0 == self.tree.measure}, 90 | startAnnotation: Priority.negativeInfinity 91 | ) 92 | 93 | let (element, rest) = right.viewLeft! 94 | 95 | let newTree = left.extend(rest) // wrong! 96 | 97 | return (element.value!.value, PriorityQueue(newTree)) 98 | } 99 | 100 | public func push(_ element: T, value: Int) -> PriorityQueue { 101 | let prioritized = Prioritized(element, priority: value) 102 | let newTree: FingerTree, Priority> 103 | 104 | switch tree { 105 | case .empty: 106 | newTree = FingerTree, Priority>.single(prioritized.makeElement()) 107 | case let .single(a): 108 | newTree = FingerTree.createDeep( 109 | prefix: Affix, Priority>.one(a), 110 | deeper: FingerTree, Priority>.empty, 111 | suffix: Affix, Priority>.one(prioritized.makeElement()) 112 | ) 113 | case let .deep(prefix, deeper, suffix, annotation): 114 | switch prefix { 115 | case let .four(a, b, c, d): 116 | newTree = FingerTree, Priority>.deep( 117 | prefix: Affix.two(prioritized.makeElement(), a), 118 | deeper: deeper.preface( 119 | Node.branch3(b, c, d, b.measure <> c.measure <> d.measure).makeElement() 120 | ), 121 | suffix: suffix, 122 | prioritized.measure <> annotation 123 | ) 124 | default: 125 | newTree = FingerTree.deep( 126 | prefix: try! prefix.preface(prioritized.makeElement()), 127 | deeper: deeper, 128 | suffix: suffix, 129 | prioritized.measure <> annotation 130 | ) 131 | } 132 | } 133 | 134 | return PriorityQueue(newTree) 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /FingerTree/TreeView.swift: -------------------------------------------------------------------------------- 1 | // TreeView.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | extension FingerTree { 21 | var viewLeft: (Element, FingerTree)? { 22 | switch self { 23 | case .empty: 24 | return nil 25 | case let .single(a): 26 | return (a, FingerTree.empty) 27 | case let .deep(.one(a), deeper, suffix, _): 28 | let rest: FingerTree 29 | 30 | if let (element, deeperRest) = deeper.viewLeft { 31 | rest = FingerTree.deep( 32 | prefix: element.node!.makeAffix(), 33 | deeper: deeperRest, 34 | suffix: suffix, 35 | deeper.measure <> suffix.measure 36 | ) 37 | } else { 38 | rest = suffix.makeFingerTree() 39 | } 40 | 41 | return (a, rest) 42 | 43 | case let .deep(prefix, deeper, suffix, _): 44 | let (first, rest) = prefix.viewFirst 45 | let annotation = rest!.measure <> deeper.measure <> suffix.measure 46 | return (first, FingerTree.deep(prefix: rest!, deeper: deeper, suffix: suffix, annotation)) 47 | } 48 | } 49 | 50 | var viewRight: (FingerTree, Element)? { 51 | switch self { 52 | case .empty: 53 | return nil 54 | case let .single(a): 55 | return (FingerTree.empty, a) 56 | case let .deep(prefix, deeper, .one(a), _): 57 | let rest: FingerTree 58 | 59 | if let (deeperRest, element) = deeper.viewRight { 60 | rest = FingerTree.deep( 61 | prefix: prefix, 62 | deeper: deeperRest, 63 | suffix: element.node!.makeAffix(), 64 | prefix.measure <> deeper.measure 65 | ) 66 | } else { 67 | rest = prefix.makeFingerTree() 68 | } 69 | 70 | return (rest, a) 71 | 72 | case let .deep(prefix, deeper, suffix, _): 73 | let (rest, last) = suffix.viewLast 74 | let annotation = prefix.measure <> deeper.measure <> rest!.measure 75 | return (FingerTree.deep(prefix: prefix, deeper: deeper, suffix: rest!, annotation), last) 76 | } 77 | } 78 | } 79 | 80 | extension Affix { 81 | func makeFingerTree() -> FingerTree { 82 | switch self { 83 | case let .one(a): 84 | return FingerTree.single(a) 85 | case let .two(a, b): 86 | return FingerTree.deep( 87 | prefix: Affix.one(a), 88 | deeper: FingerTree.empty, 89 | suffix: Affix.one(b), 90 | a.measure <> b.measure 91 | ) 92 | case let .three(a, b, c): 93 | return FingerTree.deep( 94 | prefix: Affix.two(a, b), 95 | deeper: FingerTree.empty, 96 | suffix: Affix.one(c), 97 | a.measure <> b.measure <> c.measure 98 | ) 99 | case let .four(a, b, c, d): 100 | return FingerTree.deep( 101 | prefix: Affix.two(a, b), 102 | deeper: FingerTree.empty, 103 | suffix: Affix.two(c, d), 104 | a.measure <> b.measure <> c.measure <> d.measure 105 | ) 106 | } 107 | } 108 | } 109 | 110 | extension Node { 111 | func makeAffix() -> Affix { 112 | switch self { 113 | case let .branch2(a, b, _): 114 | return Affix.two(a, b) 115 | case let .branch3(a, b, c, _): 116 | return Affix.three(a, b, c) 117 | } 118 | } 119 | } 120 | 121 | extension FingerTree { 122 | static func createDeep( 123 | prefix: Affix?, 124 | deeper: FingerTree, 125 | suffix: Affix? 126 | ) -> FingerTree { 127 | if prefix == nil && suffix == nil { 128 | if let (element, rest) = deeper.viewLeft { 129 | return createDeep(prefix: element.node!.makeAffix(), deeper: rest, suffix: nil) 130 | } else { 131 | return FingerTree.empty 132 | } 133 | } else if prefix == nil { 134 | if let (rest, element) = deeper.viewRight { 135 | return createDeep(prefix: element.node!.makeAffix(), deeper: rest, suffix: suffix) 136 | } else { 137 | return suffix!.makeFingerTree() 138 | } 139 | } else if suffix == nil { 140 | if let (rest, element) = deeper.viewRight { 141 | return createDeep(prefix: prefix, deeper: rest, suffix: element.node!.makeAffix()) 142 | } else { 143 | return prefix!.makeFingerTree() 144 | } 145 | } else { 146 | let annotation = prefix!.measure <> deeper.measure <> suffix!.measure 147 | return FingerTree.deep(prefix: prefix!, deeper: deeper, suffix: suffix!, annotation) 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /FingerTree/FingerTree.swift: -------------------------------------------------------------------------------- 1 | // FingerTree.swift 2 | // 3 | // Copyright (c) 2015-Present, Michael Mitchell 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | // and associated documentation files (the "Software"), to deal in the Software without 7 | // restriction, including without limitation the rights to use, copy, modify, merge, publish, 8 | // distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 9 | // Software is furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all copies or 12 | // substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 15 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | enum FingerTree 21 | : Measurable where TAnnotation == TValue.Annotation { 22 | 23 | typealias Element = TreeElement 24 | 25 | case empty 26 | case single(Element) 27 | indirect case deep( 28 | prefix: Affix, 29 | deeper: FingerTree, 30 | suffix: Affix, 31 | TAnnotation 32 | ) 33 | 34 | var measure: TAnnotation { 35 | switch self { 36 | case .empty: 37 | return TAnnotation.identity 38 | case let .single(a): 39 | return a.measure 40 | case let .deep(_, _, _, annotation): 41 | return annotation 42 | } 43 | } 44 | 45 | func preface(_ element: Element) -> FingerTree { 46 | switch self { 47 | case .empty: 48 | return FingerTree.single(element) 49 | case let .single(a): 50 | return FingerTree.deep( 51 | prefix: Affix.one(element), 52 | deeper: FingerTree.empty, 53 | suffix: Affix.one(a), 54 | element.measure <> a.measure 55 | ) 56 | case let .deep(.four(a, b, c, d), deeper, suffix, annotation): 57 | return FingerTree.deep( 58 | prefix: Affix.two(element, a), 59 | deeper: deeper.preface( 60 | Node.branch3(b, c, d, b.measure <> c.measure <> d.measure).makeElement() 61 | ), 62 | suffix: suffix, 63 | element.measure <> annotation 64 | ) 65 | case let .deep(prefix, deeper, suffix, annotation): 66 | return FingerTree.deep( 67 | prefix: try! prefix.preface(element), 68 | deeper: deeper, 69 | suffix: suffix, 70 | element.measure <> annotation 71 | ) 72 | } 73 | } 74 | 75 | func append(_ element: Element) -> FingerTree { 76 | switch self { 77 | case .empty: 78 | return FingerTree.single(element) 79 | case let .single(a): 80 | return FingerTree.deep( 81 | prefix: Affix.one(a), 82 | deeper: FingerTree.empty, 83 | suffix: Affix.one(element), 84 | a.measure <> element.measure 85 | ) 86 | case let .deep(prefix, deeper, .four(a, b, c, d), annotation): 87 | return FingerTree.deep( 88 | prefix: prefix, 89 | deeper: deeper.append( 90 | Node.branch3(a, b, c, a.measure <> b.measure <> c.measure).makeElement() 91 | ), 92 | suffix: Affix.two(d, element), 93 | annotation <> element.measure 94 | ) 95 | case let .deep(prefix, deeper, suffix, annotation): 96 | return FingerTree.deep( 97 | prefix: prefix, 98 | deeper: deeper, 99 | suffix: try! suffix.append(element), 100 | annotation <> element.measure 101 | ) 102 | } 103 | } 104 | 105 | private static func nodes(_ array: [Element]) -> [Element]? { 106 | switch array.count { 107 | case 1: 108 | return nil 109 | case 2: 110 | let annotation = array[0].measure <> array[1].measure 111 | return [Node.branch2(array[0], array[1], annotation).makeElement()] 112 | case 3: 113 | let annotation = array[0].measure <> array[1].measure <> array[2].measure 114 | return [Node.branch3(array[0], array[1], array[2], annotation).makeElement()] 115 | default: 116 | var nodeArray = nodes(Array(array[0..<(array.count - 2)])) 117 | let annotation = array[array.count - 2].measure <> array[array.count - 1].measure 118 | nodeArray!.append( 119 | Node.branch2(array[array.count - 2], array[array.count - 1], annotation).makeElement() 120 | ) 121 | return nodeArray 122 | } 123 | } 124 | 125 | static func concatenate(middle: [Element], left: FingerTree, right: FingerTree) -> FingerTree { 126 | switch (middle, left, right) { 127 | case (_, .empty, _) where middle.isEmpty: 128 | return right 129 | 130 | case (_, _, .empty) where middle.isEmpty: 131 | return left 132 | 133 | case (_, .empty, _): 134 | let middle = Array(middle[1.. deeper.measure <> rightSuffix.measure 157 | return FingerTree.deep(prefix: leftPrefix, deeper: deeper, suffix: rightSuffix, annotation) 158 | 159 | default: 160 | // All cases have actually been exhausted. Remove when the compiler is smarter about this. 161 | return FingerTree.empty 162 | } 163 | } 164 | 165 | func extend(_ tree: FingerTree) -> FingerTree { 166 | return FingerTree.concatenate(middle: [], left: self, right: tree) 167 | } 168 | 169 | func makeIterator() -> AnyIterator { 170 | switch self { 171 | case .empty: 172 | return AnyIterator(EmptyIterator()) 173 | case let .single(a): 174 | return AnyIterator(IteratorOverOne(_elements: a)) 175 | case let .deep(prefix, deeper, suffix, _): 176 | var (prefixIter, deeperIter, suffixIter) = ( 177 | prefix.makeIterator(), 178 | deeper.makeIterator(), 179 | suffix.makeIterator() 180 | ) 181 | 182 | var nodeIter = deeperIter.next()?.node!.makeIterator() 183 | 184 | return AnyIterator { 185 | if let value = prefixIter.next() { 186 | return value 187 | } 188 | 189 | repeat { 190 | if let value = nodeIter?.next() { 191 | return value 192 | } 193 | 194 | nodeIter = deeperIter.next()?.node!.makeIterator() 195 | } while nodeIter != nil 196 | 197 | if let value = suffixIter.next() { 198 | return value 199 | } 200 | 201 | return nil 202 | } 203 | } 204 | } 205 | 206 | func reversed() -> AnyIterator { 207 | switch self { 208 | case .empty: 209 | return AnyIterator(EmptyIterator()) 210 | case let .single(a): 211 | return AnyIterator(IteratorOverOne(_elements: a)) 212 | case let .deep(prefix, deeper, suffix, _): 213 | var (prefixIter, deeperIter, suffixIter) = ( 214 | prefix.reversed().makeIterator(), 215 | deeper.reversed(), 216 | suffix.reversed().makeIterator() 217 | ) 218 | 219 | var nodeIter = deeperIter.next()?.node!.makeIterator() 220 | 221 | return AnyIterator { 222 | if let value = suffixIter.next() { 223 | return value 224 | } 225 | 226 | repeat { 227 | if let value = nodeIter?.next() { 228 | return value 229 | } 230 | 231 | nodeIter = deeperIter.next()?.node!.makeIterator() 232 | } while nodeIter != nil 233 | 234 | return prefixIter.next() 235 | } 236 | } 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /FingerTree.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 47; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 22DE31BA22EAD8EF74655BC6 /* Split.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DE346643185F70CBED1D22 /* Split.swift */; }; 11 | 22DE35CD6B042406277DD9FC /* TreeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DE369326DC5EABE49EECFE /* TreeView.swift */; }; 12 | 850503C91B6DA453004C5B1A /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 850503C81B6DA453004C5B1A /* Collection.swift */; }; 13 | 850996581C36B13300FF7FD5 /* NodeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 850996571C36B13300FF7FD5 /* NodeTest.swift */; }; 14 | 852DB6AE1B9D277F004FD22D /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852DB6AD1B9D277F004FD22D /* main.swift */; }; 15 | 852DB6AF1B9D277F004FD22D /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852DB6AD1B9D277F004FD22D /* main.swift */; }; 16 | 8557DBCE1B76E238005E5CDD /* FingerTreeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8557DBCD1B76E238005E5CDD /* FingerTreeTest.swift */; }; 17 | 8557DBD81B76E7F1005E5CDD /* FingerTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858F87011A07714A0074F885 /* FingerTree.swift */; }; 18 | 8557DBD91B76E80A005E5CDD /* Measure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858F87031A0774040074F885 /* Measure.swift */; }; 19 | 8557DBDA1B76E80A005E5CDD /* TreeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DE369326DC5EABE49EECFE /* TreeView.swift */; }; 20 | 8557DBDB1B76E80A005E5CDD /* Split.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22DE346643185F70CBED1D22 /* Split.swift */; }; 21 | 8557DBDE1B76E80A005E5CDD /* Collection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 850503C81B6DA453004C5B1A /* Collection.swift */; }; 22 | 8557DBE01B77435D005E5CDD /* AffixTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8557DBDF1B77435D005E5CDD /* AffixTest.swift */; }; 23 | 8557DBE41B7744E5005E5CDD /* Affix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8557DBE31B7744E5005E5CDD /* Affix.swift */; }; 24 | 8557DBE51B7744E5005E5CDD /* Affix.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8557DBE31B7744E5005E5CDD /* Affix.swift */; }; 25 | 8557DBE71B774569005E5CDD /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8557DBE61B774569005E5CDD /* Node.swift */; }; 26 | 8557DBE81B774569005E5CDD /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8557DBE61B774569005E5CDD /* Node.swift */; }; 27 | 858F87021A07714A0074F885 /* FingerTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858F87011A07714A0074F885 /* FingerTree.swift */; }; 28 | 858F87041A0774040074F885 /* Measure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 858F87031A0774040074F885 /* Measure.swift */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXCopyFilesBuildPhase section */ 32 | 858F86F51A07711D0074F885 /* CopyFiles */ = { 33 | isa = PBXCopyFilesBuildPhase; 34 | buildActionMask = 2147483647; 35 | dstPath = /usr/share/man/man1/; 36 | dstSubfolderSpec = 0; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 1; 40 | }; 41 | /* End PBXCopyFilesBuildPhase section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 22DE32A13C4CEEB93C6D442B /* TODO.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TODO.txt; sourceTree = ""; }; 45 | 22DE346643185F70CBED1D22 /* Split.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Split.swift; sourceTree = ""; }; 46 | 22DE369326DC5EABE49EECFE /* TreeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TreeView.swift; sourceTree = ""; }; 47 | 850503C81B6DA453004C5B1A /* Collection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Collection.swift; sourceTree = ""; }; 48 | 850996571C36B13300FF7FD5 /* NodeTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = NodeTest.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 49 | 852DB6AD1B9D277F004FD22D /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 50 | 8557DBCB1B76E238005E5CDD /* FingerTreeTest.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FingerTreeTest.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 8557DBCD1B76E238005E5CDD /* FingerTreeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FingerTreeTest.swift; sourceTree = ""; }; 52 | 8557DBCF1B76E238005E5CDD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 8557DBD71B76E7BF005E5CDD /* FingerTree */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = FingerTree; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 8557DBDF1B77435D005E5CDD /* AffixTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AffixTest.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 55 | 8557DBE31B7744E5005E5CDD /* Affix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Affix.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 56 | 8557DBE61B774569005E5CDD /* Node.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Node.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 57 | 858F87011A07714A0074F885 /* FingerTree.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = FingerTree.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 58 | 858F87031A0774040074F885 /* Measure.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Measure.swift; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 8557DBC81B76E238005E5CDD /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | 858F86F41A07711D0074F885 /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 8557DBCC1B76E238005E5CDD /* FingerTreeTest */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 8557DBCD1B76E238005E5CDD /* FingerTreeTest.swift */, 83 | 8557DBDF1B77435D005E5CDD /* AffixTest.swift */, 84 | 850996571C36B13300FF7FD5 /* NodeTest.swift */, 85 | 8557DBCF1B76E238005E5CDD /* Info.plist */, 86 | ); 87 | path = FingerTreeTest; 88 | sourceTree = ""; 89 | }; 90 | 858F86EE1A07711D0074F885 = { 91 | isa = PBXGroup; 92 | children = ( 93 | 858F86F91A07711D0074F885 /* FingerTree */, 94 | 8557DBCC1B76E238005E5CDD /* FingerTreeTest */, 95 | 8557DBD71B76E7BF005E5CDD /* FingerTree */, 96 | 8557DBCB1B76E238005E5CDD /* FingerTreeTest.xctest */, 97 | ); 98 | sourceTree = ""; 99 | }; 100 | 858F86F91A07711D0074F885 /* FingerTree */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 858F87011A07714A0074F885 /* FingerTree.swift */, 104 | 858F87031A0774040074F885 /* Measure.swift */, 105 | 22DE369326DC5EABE49EECFE /* TreeView.swift */, 106 | 22DE346643185F70CBED1D22 /* Split.swift */, 107 | 850503C81B6DA453004C5B1A /* Collection.swift */, 108 | 8557DBE31B7744E5005E5CDD /* Affix.swift */, 109 | 8557DBE61B774569005E5CDD /* Node.swift */, 110 | 22DE32A13C4CEEB93C6D442B /* TODO.txt */, 111 | 852DB6AD1B9D277F004FD22D /* main.swift */, 112 | ); 113 | path = FingerTree; 114 | sourceTree = ""; 115 | }; 116 | /* End PBXGroup section */ 117 | 118 | /* Begin PBXNativeTarget section */ 119 | 8557DBCA1B76E238005E5CDD /* FingerTreeTest */ = { 120 | isa = PBXNativeTarget; 121 | buildConfigurationList = 8557DBD01B76E238005E5CDD /* Build configuration list for PBXNativeTarget "FingerTreeTest" */; 122 | buildPhases = ( 123 | 8557DBC71B76E238005E5CDD /* Sources */, 124 | 8557DBC81B76E238005E5CDD /* Frameworks */, 125 | 8557DBC91B76E238005E5CDD /* Resources */, 126 | ); 127 | buildRules = ( 128 | ); 129 | dependencies = ( 130 | ); 131 | name = FingerTreeTest; 132 | productName = FingerTreeTest; 133 | productReference = 8557DBCB1B76E238005E5CDD /* FingerTreeTest.xctest */; 134 | productType = "com.apple.product-type.bundle.unit-test"; 135 | }; 136 | 858F86F61A07711D0074F885 /* FingerTree */ = { 137 | isa = PBXNativeTarget; 138 | buildConfigurationList = 858F86FE1A07711D0074F885 /* Build configuration list for PBXNativeTarget "FingerTree" */; 139 | buildPhases = ( 140 | 858F86F31A07711D0074F885 /* Sources */, 141 | 858F86F41A07711D0074F885 /* Frameworks */, 142 | 858F86F51A07711D0074F885 /* CopyFiles */, 143 | ); 144 | buildRules = ( 145 | ); 146 | dependencies = ( 147 | ); 148 | name = FingerTree; 149 | productName = FingerTree; 150 | productReference = 8557DBD71B76E7BF005E5CDD /* FingerTree */; 151 | productType = "com.apple.product-type.tool"; 152 | }; 153 | /* End PBXNativeTarget section */ 154 | 155 | /* Begin PBXProject section */ 156 | 858F86EF1A07711D0074F885 /* Project object */ = { 157 | isa = PBXProject; 158 | attributes = { 159 | LastSwiftUpdateCheck = 0700; 160 | LastUpgradeCheck = 0900; 161 | TargetAttributes = { 162 | 8557DBCA1B76E238005E5CDD = { 163 | CreatedOnToolsVersion = 7.0; 164 | LastSwiftMigration = 0900; 165 | }; 166 | 858F86F61A07711D0074F885 = { 167 | CreatedOnToolsVersion = 6.1; 168 | LastSwiftMigration = 0900; 169 | }; 170 | }; 171 | }; 172 | buildConfigurationList = 858F86F21A07711D0074F885 /* Build configuration list for PBXProject "FingerTree" */; 173 | compatibilityVersion = "Xcode 6.3"; 174 | developmentRegion = English; 175 | hasScannedForEncodings = 0; 176 | knownRegions = ( 177 | en, 178 | ); 179 | mainGroup = 858F86EE1A07711D0074F885; 180 | productRefGroup = 858F86EE1A07711D0074F885; 181 | projectDirPath = ""; 182 | projectRoot = ""; 183 | targets = ( 184 | 858F86F61A07711D0074F885 /* FingerTree */, 185 | 8557DBCA1B76E238005E5CDD /* FingerTreeTest */, 186 | ); 187 | }; 188 | /* End PBXProject section */ 189 | 190 | /* Begin PBXResourcesBuildPhase section */ 191 | 8557DBC91B76E238005E5CDD /* Resources */ = { 192 | isa = PBXResourcesBuildPhase; 193 | buildActionMask = 2147483647; 194 | files = ( 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | }; 198 | /* End PBXResourcesBuildPhase section */ 199 | 200 | /* Begin PBXSourcesBuildPhase section */ 201 | 8557DBC71B76E238005E5CDD /* Sources */ = { 202 | isa = PBXSourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | 8557DBE01B77435D005E5CDD /* AffixTest.swift in Sources */, 206 | 8557DBD81B76E7F1005E5CDD /* FingerTree.swift in Sources */, 207 | 8557DBDA1B76E80A005E5CDD /* TreeView.swift in Sources */, 208 | 8557DBE81B774569005E5CDD /* Node.swift in Sources */, 209 | 8557DBE51B7744E5005E5CDD /* Affix.swift in Sources */, 210 | 8557DBDE1B76E80A005E5CDD /* Collection.swift in Sources */, 211 | 8557DBCE1B76E238005E5CDD /* FingerTreeTest.swift in Sources */, 212 | 852DB6AF1B9D277F004FD22D /* main.swift in Sources */, 213 | 850996581C36B13300FF7FD5 /* NodeTest.swift in Sources */, 214 | 8557DBD91B76E80A005E5CDD /* Measure.swift in Sources */, 215 | 8557DBDB1B76E80A005E5CDD /* Split.swift in Sources */, 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | 858F86F31A07711D0074F885 /* Sources */ = { 220 | isa = PBXSourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | 858F87021A07714A0074F885 /* FingerTree.swift in Sources */, 224 | 852DB6AE1B9D277F004FD22D /* main.swift in Sources */, 225 | 850503C91B6DA453004C5B1A /* Collection.swift in Sources */, 226 | 8557DBE71B774569005E5CDD /* Node.swift in Sources */, 227 | 858F87041A0774040074F885 /* Measure.swift in Sources */, 228 | 8557DBE41B7744E5005E5CDD /* Affix.swift in Sources */, 229 | 22DE35CD6B042406277DD9FC /* TreeView.swift in Sources */, 230 | 22DE31BA22EAD8EF74655BC6 /* Split.swift in Sources */, 231 | ); 232 | runOnlyForDeploymentPostprocessing = 0; 233 | }; 234 | /* End PBXSourcesBuildPhase section */ 235 | 236 | /* Begin XCBuildConfiguration section */ 237 | 8557DBD11B76E238005E5CDD /* Debug */ = { 238 | isa = XCBuildConfiguration; 239 | buildSettings = { 240 | COMBINE_HIDPI_IMAGES = YES; 241 | DEBUG_INFORMATION_FORMAT = dwarf; 242 | GCC_NO_COMMON_BLOCKS = YES; 243 | INFOPLIST_FILE = FingerTreeTest/Info.plist; 244 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 245 | PRODUCT_BUNDLE_IDENTIFIER = lazytype.FingerTreeTest; 246 | PRODUCT_NAME = "$(TARGET_NAME)"; 247 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 248 | SWIFT_VERSION = 4.0; 249 | }; 250 | name = Debug; 251 | }; 252 | 8557DBD21B76E238005E5CDD /* Release */ = { 253 | isa = XCBuildConfiguration; 254 | buildSettings = { 255 | COMBINE_HIDPI_IMAGES = YES; 256 | COPY_PHASE_STRIP = NO; 257 | GCC_NO_COMMON_BLOCKS = YES; 258 | INFOPLIST_FILE = FingerTreeTest/Info.plist; 259 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 260 | PRODUCT_BUNDLE_IDENTIFIER = lazytype.FingerTreeTest; 261 | PRODUCT_NAME = "$(TARGET_NAME)"; 262 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 263 | SWIFT_VERSION = 4.0; 264 | }; 265 | name = Release; 266 | }; 267 | 858F86FC1A07711D0074F885 /* Debug */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | ALWAYS_SEARCH_USER_PATHS = NO; 271 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 272 | CLANG_CXX_LIBRARY = "libc++"; 273 | CLANG_ENABLE_MODULES = YES; 274 | CLANG_ENABLE_OBJC_ARC = YES; 275 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 276 | CLANG_WARN_BOOL_CONVERSION = YES; 277 | CLANG_WARN_COMMA = YES; 278 | CLANG_WARN_CONSTANT_CONVERSION = YES; 279 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 280 | CLANG_WARN_EMPTY_BODY = YES; 281 | CLANG_WARN_ENUM_CONVERSION = YES; 282 | CLANG_WARN_INFINITE_RECURSION = YES; 283 | CLANG_WARN_INT_CONVERSION = YES; 284 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 285 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 286 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 287 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 288 | CLANG_WARN_STRICT_PROTOTYPES = YES; 289 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 290 | CLANG_WARN_UNREACHABLE_CODE = YES; 291 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 292 | COPY_PHASE_STRIP = NO; 293 | ENABLE_STRICT_OBJC_MSGSEND = YES; 294 | ENABLE_TESTABILITY = YES; 295 | GCC_C_LANGUAGE_STANDARD = gnu99; 296 | GCC_DYNAMIC_NO_PIC = NO; 297 | GCC_NO_COMMON_BLOCKS = YES; 298 | GCC_OPTIMIZATION_LEVEL = fast; 299 | GCC_PREPROCESSOR_DEFINITIONS = ( 300 | "DEBUG=1", 301 | "$(inherited)", 302 | ); 303 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 304 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 305 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 306 | GCC_WARN_UNDECLARED_SELECTOR = YES; 307 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 308 | GCC_WARN_UNUSED_FUNCTION = YES; 309 | GCC_WARN_UNUSED_VARIABLE = YES; 310 | MACOSX_DEPLOYMENT_TARGET = 10.11; 311 | MTL_ENABLE_DEBUG_INFO = YES; 312 | ONLY_ACTIVE_ARCH = YES; 313 | SDKROOT = macosx; 314 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 315 | SWIFT_VERSION = 4.0; 316 | }; 317 | name = Debug; 318 | }; 319 | 858F86FD1A07711D0074F885 /* Release */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | ALWAYS_SEARCH_USER_PATHS = NO; 323 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 324 | CLANG_CXX_LIBRARY = "libc++"; 325 | CLANG_ENABLE_MODULES = YES; 326 | CLANG_ENABLE_OBJC_ARC = YES; 327 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 328 | CLANG_WARN_BOOL_CONVERSION = YES; 329 | CLANG_WARN_COMMA = YES; 330 | CLANG_WARN_CONSTANT_CONVERSION = YES; 331 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 332 | CLANG_WARN_EMPTY_BODY = YES; 333 | CLANG_WARN_ENUM_CONVERSION = YES; 334 | CLANG_WARN_INFINITE_RECURSION = YES; 335 | CLANG_WARN_INT_CONVERSION = YES; 336 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 337 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 338 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 339 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 340 | CLANG_WARN_STRICT_PROTOTYPES = YES; 341 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 342 | CLANG_WARN_UNREACHABLE_CODE = YES; 343 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 344 | COPY_PHASE_STRIP = YES; 345 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 346 | ENABLE_NS_ASSERTIONS = NO; 347 | ENABLE_STRICT_OBJC_MSGSEND = YES; 348 | GCC_C_LANGUAGE_STANDARD = gnu99; 349 | GCC_NO_COMMON_BLOCKS = YES; 350 | GCC_OPTIMIZATION_LEVEL = fast; 351 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 353 | GCC_WARN_UNDECLARED_SELECTOR = YES; 354 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 355 | GCC_WARN_UNUSED_FUNCTION = YES; 356 | GCC_WARN_UNUSED_VARIABLE = YES; 357 | MACOSX_DEPLOYMENT_TARGET = 10.11; 358 | MTL_ENABLE_DEBUG_INFO = NO; 359 | ONLY_ACTIVE_ARCH = YES; 360 | SDKROOT = macosx; 361 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 362 | SWIFT_VERSION = 4.0; 363 | }; 364 | name = Release; 365 | }; 366 | 858F86FF1A07711D0074F885 /* Debug */ = { 367 | isa = XCBuildConfiguration; 368 | buildSettings = { 369 | CLANG_USE_OPTIMIZATION_PROFILE = YES; 370 | DEFINES_MODULE = YES; 371 | GCC_OPTIMIZATION_LEVEL = fast; 372 | LLVM_LTO = YES; 373 | PRODUCT_NAME = "$(TARGET_NAME)"; 374 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 375 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 376 | SWIFT_VERSION = 4.0; 377 | }; 378 | name = Debug; 379 | }; 380 | 858F87001A07711D0074F885 /* Release */ = { 381 | isa = XCBuildConfiguration; 382 | buildSettings = { 383 | CLANG_USE_OPTIMIZATION_PROFILE = YES; 384 | DEFINES_MODULE = YES; 385 | GCC_OPTIMIZATION_LEVEL = fast; 386 | LLVM_LTO = YES; 387 | PRODUCT_NAME = "$(TARGET_NAME)"; 388 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 389 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 390 | SWIFT_VERSION = 4.0; 391 | }; 392 | name = Release; 393 | }; 394 | /* End XCBuildConfiguration section */ 395 | 396 | /* Begin XCConfigurationList section */ 397 | 8557DBD01B76E238005E5CDD /* Build configuration list for PBXNativeTarget "FingerTreeTest" */ = { 398 | isa = XCConfigurationList; 399 | buildConfigurations = ( 400 | 8557DBD11B76E238005E5CDD /* Debug */, 401 | 8557DBD21B76E238005E5CDD /* Release */, 402 | ); 403 | defaultConfigurationIsVisible = 0; 404 | defaultConfigurationName = Release; 405 | }; 406 | 858F86F21A07711D0074F885 /* Build configuration list for PBXProject "FingerTree" */ = { 407 | isa = XCConfigurationList; 408 | buildConfigurations = ( 409 | 858F86FC1A07711D0074F885 /* Debug */, 410 | 858F86FD1A07711D0074F885 /* Release */, 411 | ); 412 | defaultConfigurationIsVisible = 0; 413 | defaultConfigurationName = Release; 414 | }; 415 | 858F86FE1A07711D0074F885 /* Build configuration list for PBXNativeTarget "FingerTree" */ = { 416 | isa = XCConfigurationList; 417 | buildConfigurations = ( 418 | 858F86FF1A07711D0074F885 /* Debug */, 419 | 858F87001A07711D0074F885 /* Release */, 420 | ); 421 | defaultConfigurationIsVisible = 0; 422 | defaultConfigurationName = Release; 423 | }; 424 | /* End XCConfigurationList section */ 425 | }; 426 | rootObject = 858F86EF1A07711D0074F885 /* Project object */; 427 | } 428 | --------------------------------------------------------------------------------