Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ sealed interface Action {

is MatchDescription ->
MatchAction(
Expression.from(description.value),
description.cases.associate {
Expression.from(it.of) to it.then.map { desc -> create(desc) }
},
Expand All @@ -61,6 +60,8 @@ sealed interface Action {

is ResetDescription -> TimeoutResetAction(description.name)

is LogDescription -> LogAction(Expression.from(description.message))

else -> error("unknown action type: ${description.javaClass.simpleName}")
}

Expand Down Expand Up @@ -96,17 +97,14 @@ internal constructor(
}

class MatchAction
internal constructor(
val value: Expression,
val cases: Map<Expression, List<Action>>,
val default: Action? = null,
) : EventRaisingAction {
internal constructor(val cases: Map<Expression, List<Action>>, val default: Action? = null) :
EventRaisingAction {
override fun raises(): List<Event> =
(cases.values + listOfNotNull(default)).filterIsInstance<EventRaisingAction>().flatMap {
it.raises()
}

override fun toString() = "MatchAction(value='$value', cases='$cases', default='$default')"
override fun toString() = "MatchAction(cases='$cases', default='$default')"
}

class RaiseAction internal constructor(val event: Event, val target: Expression?) :
Expand All @@ -128,3 +126,5 @@ internal constructor(val name: String, val delay: Expression, val `do`: Action)
class TimeoutResetAction internal constructor(val action: String) : Action {
override fun toString() = "TimeoutResetAction(action='$action')"
}

class LogAction internal constructor(val message: Expression) : Action
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import mu.KotlinLogging

private val logger = KotlinLogging.logger {}

data class CommandExecutionContext(
val scope: Scope,
val serviceImplementationSelector: ServiceImplementationSelector,
Expand All @@ -27,13 +29,14 @@ class ActionCommandFactoryImpl(private val meterRegistry: MeterRegistry) : Actio
commandExecutionContext: CommandExecutionContext,
): ActionCommand =
when (action) {
is EvalAction -> ActionEvalCommand(action, commandExecutionContext, this, meterRegistry)
is InvokeAction -> ActionInvokeCommand(action, commandExecutionContext, this, meterRegistry)
is MatchAction -> ActionMatchCommand(action, commandExecutionContext, this, meterRegistry)
is RaiseAction -> ActionRaiseCommand(action, commandExecutionContext, this, meterRegistry)
is TimeoutAction -> ActionTimeoutCommand(action, commandExecutionContext, this, meterRegistry)
is EvalAction -> EvalActionCommand(action, commandExecutionContext, this, meterRegistry)
is InvokeAction -> InvokeActionCommand(action, commandExecutionContext, this, meterRegistry)
is MatchAction -> MatchActionCommand(action, commandExecutionContext, this, meterRegistry)
is RaiseAction -> RaiseActionCommand(action, commandExecutionContext, this, meterRegistry)
is TimeoutAction -> TimeoutActionCommand(action, commandExecutionContext, this, meterRegistry)
is TimeoutResetAction ->
ActionTimeoutResetCommand(action, commandExecutionContext, this, meterRegistry)
TimeoutResetActionCommand(action, commandExecutionContext, this, meterRegistry)
is LogAction -> LogActionCommand(action, commandExecutionContext, this, meterRegistry)
else -> error("unknown action type: ${action::class.simpleName}")
}
}
Expand All @@ -51,7 +54,7 @@ internal constructor(
abstract fun execute(): List<ActionCommand>
}

class ActionEvalCommand
class EvalActionCommand
internal constructor(
private val evalAction: EvalAction,
commandExecutionContext: CommandExecutionContext,
Expand All @@ -62,7 +65,7 @@ internal constructor(
evalAction.expression.execute(commandExecutionContext.scope.extent).run { emptyList() }
}

class ActionInvokeCommand
class InvokeActionCommand
internal constructor(
private val invokeAction: InvokeAction,
commandExecutionContext: CommandExecutionContext,
Expand Down Expand Up @@ -107,7 +110,7 @@ internal constructor(
}
}

class ActionMatchCommand
class MatchActionCommand
internal constructor(
private val matchAction: MatchAction,
commandExecutionContext: CommandExecutionContext,
Expand All @@ -116,19 +119,18 @@ internal constructor(
) : ActionCommand(commandExecutionContext, commandFactory, meterRegistry) {
override fun execute(): List<ActionCommand> {
val extent = commandExecutionContext.scope.extent
val matchValue = matchAction.value.execute(extent)

val selectedActions: List<Action> =
matchAction.cases.entries
.filter { (expression, _) -> expression.execute(extent) == matchValue }
.filter { (expression, _) -> expression.execute(extent) == true }
.flatMap { it.value }
.ifEmpty { listOfNotNull(matchAction.default) }

return selectedActions.map { commandFactory.create(it, commandExecutionContext) }
}
}

class ActionRaiseCommand
class RaiseActionCommand
internal constructor(
private val raiseAction: RaiseAction,
commandExecutionContext: CommandExecutionContext,
Expand All @@ -150,7 +152,7 @@ internal constructor(
}
}

class ActionTimeoutCommand
class TimeoutActionCommand
internal constructor(
private val timeoutAction: TimeoutAction,
commandExecutionContext: CommandExecutionContext,
Expand All @@ -161,7 +163,7 @@ internal constructor(
listOf(commandFactory.create(timeoutAction.`do`, commandExecutionContext))
}

class ActionTimeoutResetCommand
class TimeoutResetActionCommand
internal constructor(
val timeoutResetAction: TimeoutResetAction,
commandExecutionContext: CommandExecutionContext,
Expand All @@ -170,3 +172,19 @@ internal constructor(
) : ActionCommand(commandExecutionContext, commandFactory, meterRegistry) {
override fun execute(): List<ActionCommand> = emptyList()
}

class LogActionCommand
internal constructor(
private val logAction: LogAction,
commandExecutionContext: CommandExecutionContext,
commandFactory: ActionCommandFactory,
meterRegistry: MeterRegistry,
) : ActionCommand(commandExecutionContext, commandFactory, meterRegistry) {
override fun execute(): List<ActionCommand> {
logAction.message.execute(commandExecutionContext.scope.extent).toString().also {
logger.info(it)
}

return emptyList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ internal constructor(
val nextBatch =
commands.flatMap { command ->
command.execute().also {
if (command is ActionTimeoutResetCommand) stopTimeout(command.timeoutResetAction.action)
if (command is TimeoutResetActionCommand) stopTimeout(command.timeoutResetAction.action)
}
}
execute(nextBatch)
Expand All @@ -232,7 +232,7 @@ internal constructor(
val command = commandFactory.create(action, createContext(this, null))
execute(
listOf(
command as? ActionRaiseCommand ?: error("timeout action '$action' must be a raise action")
command as? RaiseActionCommand ?: error("timeout action '$action' must be a raise action")
)
)
}
Expand Down
8 changes: 5 additions & 3 deletions src/main/resources/pkl/csm/csml.pkl
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,14 @@ class CaseDescription {
}

class MatchDescription extends ActionDescription {
value: Expression
cases: Listing<CaseDescription>
default: ActionDescription?
}

class LogDescription extends ActionDescription {
message: Expression
}

typealias EventTopic = String(matches(Regex(#"^[a-zA-Z_]\w*$"#)))

typealias EventChannel = "internal"|"external"|"global"|"peripheral"
Expand Down Expand Up @@ -188,13 +191,12 @@ typealias Transition = TransitionDescription
typealias Action = ActionDescription
typealias Eval = EvalDescription
typealias Invoke = InvokeDescription

typealias Case = CaseDescription
typealias Match = MatchDescription

typealias Raise = RaiseDescription
typealias Timeout = TimeoutDescription
typealias Reset = ResetDescription
typealias Log = LogDescription

// Event aliases
typealias Event = EventDescription
Expand Down
3 changes: 1 addition & 2 deletions src/test/resources/pkl/complete/completeStateMachine.pkl
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ sm = new csml.StateMachine {
new csml.Eval { expression = "v = x" }
new csml.Eval { expression = "d = d - 1" }
new csml.Match {
value = "d"
cases {
new csml.Case {
of = "0"; then { new csml.Raise { event = new csml.Internal { topic = "e3" } } }
of = "d == 0"; then { new csml.Raise { event = new csml.Internal { topic = "e3" } } }
}
}
default = new csml.Raise { event = new csml.Internal { topic = "e4" } }
Expand Down
8 changes: 2 additions & 6 deletions src/test/resources/pkl/timeout/timeoutStateMachine.pkl
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,10 @@ sm = new csml.StateMachine {
to = "a"
do {
new csml.Match {
value = "v < 10"
cases {
new csml.Case { of = "true"; then { new csml.Eval { expression = "v = v + 1" } } }
new csml.Case {
of = "false"
then { new csml.Raise { event = new csml.Internal { topic = "tob" } } }
}
new csml.Case { of = "v < 10"; then { new csml.Eval { expression = "v = v + 1" } } }
}
default = new csml.Raise { event = new csml.Internal { topic = "tob" } }
}
}
}
Expand Down