Skip to content

Instantly share code, notes, and snippets.

@Shannarra
Last active June 23, 2023 13:21
Show Gist options
  • Save Shannarra/a1def25cff80a14e5b26a9722a91469c to your computer and use it in GitHub Desktop.
Save Shannarra/a1def25cff80a14e5b26a9722a91469c to your computer and use it in GitHub Desktop.
A quick and easy-to-understand implementation of the `goto` directive in Ruby. Just wanted to prove that you can have goto in Ruby.
class Object
HASH = {}
def label(name, &block)
HASH[name] = proc(&block)
end
def goto(name)
raise "No label with name #{name} found" unless HASH.key?(name)
HASH[name].call
rescue LocalJumpError
puts '[ERROR]: Local jump instructions such as `yield` `return` and `break` are not allowed in `label` blocks.
Read more at https://ruby-doc.org/core-2.5.0/LocalJumpError.html'
exit(1)
end
def label_stack_main
raise 'Usage of labels should be done within a block provided to "label_stack"' unless block_given?
yield
goto :start
end
end
class InfiniteLoopStopper
class << self
def create_stop_label!
label :stop_infinite_loop do
puts 'I just jumped inside a class and stopped loop execution :D'
goto :outside_loop
end
end
end
end
def testing_function
label(:infinite_loop) do
(1..10**1000).each do |x|
puts x
goto :stop_infinite_loop if x == 1_578_216 # arbitrary number to prove control flow
end
end
label(:outside_loop) do
loop do
puts 'One-time message'
break # but local `breaks` are allowed :)
end
puts 'Phew, thought I will be looping forever'
exit(0) # `return` and `break` are not allowed inside `label`
end
puts 'Code outside of labels will always be executed first :)'
end
require 'pry'
label_stack_main do
label(:start) do
InfiniteLoopStopper.create_stop_label! # you can create labels inside labels via function/class calls!
testing_function
puts 'Gonna loop 10^1000 times, please wait.. :)'
goto :infinite_loop
end
end
Code outside of labels will always be executed first :)
Gonna loop 10^1000 times in 10 seconds, please wait.. :)
top label executed last
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
... # skipping some lines to make this more readable :)
1578208
1578209
1578210
1578211
1578212
1578213
1578214
1578215
1578216
I just jumped inside a class and stopped loop execution :D
One-time message
Phew, thought I will be looping forever
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment