Created
July 11, 2015 15:12
-
-
Save pabloogc/fa8d7bb9f074d6c9768b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.ArrayList | |
public class StateMachine<S, T>( | |
private var stateObject: State<S, T>, | |
private var states: List<State<S, T>> | |
) { | |
public val state: S | |
get() = stateObject.value | |
public fun move(input: T) { | |
stateObject.transitions.forEach { t -> | |
val (function, newState) = t | |
if (function.invoke(input)) { | |
stateObject = newState; | |
return | |
} | |
} | |
throw IllegalStateException("Transition from state '${stateObject.value}' not defined for the input '${input}'") | |
} | |
public fun reset() { | |
stateObject = states[0] | |
} | |
} | |
public class State<S, T>( | |
public val value: S, | |
public val transitions: MutableList<Pair<Function1<T, Boolean>, State<S, T>>>) { | |
} | |
public fun stateMachine<S, T>(init: StateMachineBuilder<S, T>.() -> Unit): StateMachine<S, T> { | |
val builder = StateMachineBuilder<S, T>(ArrayList()) | |
builder.init() | |
return builder.build() | |
} | |
public class StateMachineBuilder<S, T>( | |
private val states: MutableList<StateBuilder<S, T>> | |
) { | |
fun state(value: S, transitions: StateBuilder<S, T>.() -> Unit): StateBuilder<T> { | |
val s = StateBuilder<S, T>(value, ArrayList()) | |
s.transitions() | |
states.add(s) | |
return s; | |
} | |
fun build(): StateMachine<S, T> { | |
val linkedStates = ArrayList<State<S, T>>(states.size()) | |
if (states.isEmpty()) throw IllegalStateException("At least one state is required") | |
states.forEach { s -> | |
val ref = linkedStates.firstOrNull { ls -> ls.value == s.value } | |
if (ref != null) | |
throw IllegalStateException("State '${s.value} already declared") | |
linkedStates.add(State(s.value, ArrayList<Pair<Function1<T, Boolean>, State<S, T>>>())) | |
} | |
for (i in states.indices) { | |
states[i].transitions.forEach { t -> | |
val ref = linkedStates.firstOrNull { ls -> ls.value == t.second } | |
?: throw IllegalStateException("Error in '${states[i].value}'. State '${t.second}' does not exist.") | |
linkedStates[i].transitions.add(Pair(t.first, ref)) | |
} | |
} | |
return StateMachine(linkedStates[0], linkedStates) | |
} | |
} | |
public class StateBuilder<S, T>( | |
val value: S, | |
val transitions: MutableList<Pair<(T) -> Boolean, S>> | |
) { | |
fun moveIf(next: S, predicate: (T) -> Boolean) { | |
transitions.add(Pair(predicate, next)); | |
} | |
fun moveEq(next: S, funcValue: () -> T) { | |
moveIf(next, { t -> t.equals(funcValue()) }) | |
} | |
fun move(next: S) { | |
moveIf(next, { true }) | |
} | |
fun loopIf(predicate: (T) -> Boolean) { | |
moveIf(value, predicate) | |
} | |
fun loopEq(predicate: () -> T) { | |
moveEq(value, predicate) | |
} | |
fun loop() { | |
moveIf(value, { true }) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment