Consolidating my various blogs into one. This was originally posted on 2010/2/26
I had a bit of fun in the past few days writing a telnet server implementation in #scala. Part of that was implementing a state machine, which I then cleaned up so the definitions are simple.
The entire code, fairly independent and reusable, is at SM.scala
Here's a sample state machine:
/** sample state machine */
class SampleSM extends razie.SM.StateMachine {
import razie.SM._
implicit val sm = this
val states@(s1, s2, s3) = ("s1", "s2", "s3")
override def start = state("s1") // TODO there's an issue if i use s1 instead of "s1"
override val transitions : Seq[Transition] =
(s1, 2) -> s2 ::
(s1, 0) -> s1 :: // NOP
(s2, 1) -> s1 + echo ("back to s1") :: // CR
(s2, 3) -> s3 ::
(s3, Seq(4, 5, 6, 7)) -> s2 ::
(s3, AnyEvent) -> s1 ::
(s2, {_:Event=>true}) -> s2 + eatChar + echo ("s2 eats all others") :: // eating stuff
(""".*""".r, -1) -> s1 :: // some reset event applies to all states
Nil
def eatChar(sm: StateMachine, t: Transition, e: Event) =
println("ate char: " + e.asInstanceOf[IEvent].i.toChar)
}
object SampleSMain extends App {
implicit def e(i: Int) = SM.IEvent(i)
val sm = new SampleSM()
sm move 2 move 1 move 3 move -1 move 2 move 3 move 6 move 59
}
Try this online at bit.ly/1jv1AED.
The basic structure is:
(state, event-matcher) -> newstate + callback ++ unitcalback... + callback :: Nil
The event-matcher can be:
The callback is a function with either of these signatures:
def push (sm:StateMachine, t:Transition, e:Event) - use + for these
def reset : Unit - use ++ for these (hey, I'm still getting my head around advanced scala stuff)
Enjoy, and if you likee, contribute, eh? If you want to see more state machine DSL, see Implementing the Telnet state machine.