Last active
January 20, 2021 20:38
-
-
Save jrr6/33645b27f1d2c56c93a8e9f784de210e to your computer and use it in GitHub Desktop.
An implementation of triple ref pointers in Swift, primarily to disprove Professor Brailsford from the relevant Computerphile video (https://www.youtube.com/watch?v=1s0w_p5HEuY).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // An implementation of the Triple-Ref method as described here: https://www.youtube.com/watch?v=0ZEX_l0DFK0 | |
| // The original C code is here: http://www.eprg.org/computerphile/tripref.c | |
| // Mark - Main code | |
| import Foundation | |
| prefix operator * | |
| extension Optional where Wrapped == UnsafeMutablePointer<Any> { | |
| static prefix func *(item: UnsafeMutablePointer<T>?) -> T { | |
| return item?.pointee | |
| } | |
| static prefix func *<Q>(item: UnsafeMutablePointer<Q>?) -> Q? { | |
| return item?.pointee | |
| } | |
| } | |
| extension UnsafeMutablePointer { | |
| static prefix func *(item: UnsafeMutablePointer) -> Pointee { | |
| return item.pointee | |
| } | |
| } | |
| typealias P<C> = UnsafeMutablePointer<C> | |
| struct Thing { | |
| var item: String | |
| var next: P<Thing>? | |
| init(_ item: String, _ next: P<Thing>?) { | |
| self.item = item | |
| self.next = next | |
| } | |
| } | |
| typealias T = P<Thing>? | |
| typealias TT = P<T>? | |
| var start: T = nil | |
| func insertThing(_ head: TT, _ newp: UnsafeMutablePointer<Thing>) { | |
| var tracer: TT = head | |
| while let pointee = *tracer, (*pointee).item < (*newp).item { | |
| tracer = P(&pointee.pointee.next) | |
| } | |
| newp.pointee.next = *tracer | |
| tracer?.pointee = newp | |
| } | |
| func removeThing(_ head: TT, _ text: String) { | |
| var tracer: TT = head | |
| while let pointee = *tracer, (*pointee).item != text { | |
| tracer = P(&pointee.pointee.next) | |
| } | |
| if let pointee = *tracer { | |
| var old: T = *tracer | |
| tracer?.pointee = P(pointee.pointee.next) | |
| // old item is automatically dealloced by ARC | |
| } | |
| } | |
| // MARK: - Logging | |
| var arrowStr = "\t\t↓" | |
| var sepStr = "-----------------------------------------" | |
| func addrStr(_ addr: String) -> String { | |
| return addr != "NULL" ? "\t\(addr)\t" : "\t \(addr) \t\t\t" | |
| } | |
| func itemStr(_ item: String) -> String { | |
| return "\t\(item)\t" | |
| } | |
| func printList() { | |
| print(sepStr) | |
| var head: T = start | |
| print("|\(addrStr(head?.debugDescription ?? "NULL"))| ← START\n\(arrowStr)") | |
| while let cur = *head { | |
| let item = cur.item | |
| let next = cur.next?.debugDescription ?? "NULL" | |
| print("|\(addrStr(next))|\(itemStr(item))|") | |
| if next != "NULL" { | |
| print(arrowStr) | |
| } | |
| head = cur.next | |
| } | |
| print(sepStr) | |
| print() | |
| } | |
| // MARK: - Demo | |
| printList() | |
| var thing1 = Thing("chips", nil) | |
| insertThing(P(&start), P(&thing1)) | |
| printList() | |
| var thing2 = Thing("pizza", nil) | |
| insertThing(P(&start), P(&thing2)) | |
| printList() | |
| var thing3 = Thing("burgers", nil) | |
| insertThing(P(&start), P(&thing3)) | |
| printList() | |
| var thing4 = Thing("zucchini", nil) | |
| insertThing(P(&start), P(&thing4)) | |
| printList() | |
| removeThing(P(&start), "pizza") | |
| printList() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment