Each method then becomes a concise description of the state transitions:
code
self atEndOfInput
ifTrue:
[^#final]. "Go to #final State"
self input == $"
ifTrue:
[ self writeToOutput.
^#insideComment]. "Go to #insideComment"
^#code "Stay in #code"
insideComment
self input == $"
ifTrue:
[^#code]. "Go to to #code"
^#insideComment "Stay in #insideComment"
Then debugging just becomes a matter of putting breakpoints in methods. #perform: is almost as fast a a regular message send, and the methods themselves are mostly #ifTrue: statements, which are bytecode optimized, so this is mostly JIT-ed to machine code.
With states as methods, you have an instance variable for "state" and you just run a loop:
Each method then becomes a concise description of the state transitions: Then debugging just becomes a matter of putting breakpoints in methods. #perform: is almost as fast a a regular message send, and the methods themselves are mostly #ifTrue: statements, which are bytecode optimized, so this is mostly JIT-ed to machine code.