Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Swift Restart Skip Block
// Let's start with an example
var c = 0
// Inside a jump block, calling the restart function starts over
// and calling the skip function exists the block
jump { restart, skip in
for i in 1...4 {
println("c: \(c); i: \(i)")
if c == 4 { skip() }
else if i == 3 { c++; restart() }
}
}
// We will use the jump function to implement a while loop!
func myWhile(test: () -> Bool, loop: () -> ()) {
jump { restart, skip in
if test() {
loop()
restart()
}
}
}
var x = 0
myWhile({ x < 3 }){
println(x++) // -> 0 --> 1 --> 2
}
// Note that this is equivalent to having a start: goto before our block
// and a skip: goto after our block in a lanaguage that supports gotos
// Note that this is also equivalent to the following
// Also note that this simpler alternative cannot be implemented with closures
// because continue and break cannot be used in closures even if called by a loop
var repeat = true
while repeat {
// Insert code goes here
// restart() --> continue
// skip() --> repeat = false; break
repeat = false
}
// Implementation, it's pretty cool
// We use C's setjmp and longjmp
typealias JumpType = UnsafeMutablePointer<Int32>
let jumpSize = UInt(sizeof(jmp_buf))
func jump(f: (() -> (), () -> ()) -> ()) {
// Malloc
let skip = JumpType(malloc(jumpSize))
let restart = JumpType(malloc(jumpSize))
// Declare restart jump
let didRestart = setjmp(restart)
// Wait for setup, and then call
if (didRestart != 0) {
f({ longjmp(restart, Int32(-1)) }, { longjmp(skip, Int32(-1)) })
}
let didSkip = setjmp(skip)
// If we haven't yet run the function, skip back to the start
if (didSkip == 0) {
longjmp(restart, Int32(-1))
}
// Avoid memory leakage
free(skip)
free(restart)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.