Skip to content

Instantly share code, notes, and snippets.

@firejox
Last active December 21, 2019 13:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save firejox/f9d258084a4c3f7e48a28ac279f03f53 to your computer and use it in GitHub Desktop.
Save firejox/f9d258084a4c3f7e48a28ac279f03f53 to your computer and use it in GitHub Desktop.
State machine (pure inline)
struct Machine
enum State
Before
Run
After
Next
end
def initialize(@state : State, @line : Int32)
end
def run_on?(line)
if @state == State::Run && @line <= line
yield
true
end
end
def transition_at(@state, @line)
end
def transition(@state)
end
def it_impl(line, end_line)
yield
end
def before
yield if @state.before?
end
def after
yield if @state.after?
end
macro it(line = __LINE__, end_line = __END_LINE__)
next if run_on?({{ line }}) do
it_impl({{ line }}, {{ end_line }}) do
{{ yield }}
end
transition_at(Machine::State::Next, {{ end_line }})
end
end
macro describe(line = __LINE__, end_line = __END_LINE__)
next if run_on?({{ line }}) do
describe_impl({{ line }}) do
{{ yield }}
end
transition_at(Machine::State::Next, {{ end_line }})
end
end
end
def describe_impl(line = __LINE__)
machine = Machine.new(Machine::State::Before, line)
while true
with machine yield
case machine.@state
when .before?
machine.transition(Machine::State::Run)
when .next?
machine.transition(Machine::State::After)
when .after?
machine.transition(Machine::State::Before)
else
break
end
end
end
def describe(line = __LINE__)
describe_impl(line) do
with itself yield
end
end
describe do
before do
pp "before"
end
after do
pp "after"
end
it do
pp "Test 1"
end
describe do
before do
pp "inner before"
end
after do
pp "inner after"
end
describe do
before do
pp "inner inner before"
end
after do
pp "inner inner after"
end
it do
pp "Test 4"
end
end
it do
pp "Test 3"
end
end
it do
pp "Test 2"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment