Skip to main content

Transitions

Transitions define behavior: how the system changes state. A transition body is a sequence of operations.

Transition Kinds​

KeywordRole
initInitialization transition; the states it reaches from the declaration valuation are the initial states.
tranStep transition; runs on every step.

The implicit base class Anything provides empty init and tran transitions, so any class that does not declare its own inherits these no-ops.

The declaration valuation, every variable at its initializer, is not a state: the system starts in the states init reaches from it, and an init with no enabled execution leaves the system without states (Initial States).

Declaring a Transition​

A transition declaration consists of one of the kind keywords, a name, a parameter list, and a body in { }.

tran increment() {
value := value + 1
}

With parameters:

tran setBy(amount: int) {
value := value + amount
}

Parameters are passed by value when the transition is invoked through an inline call. A parameter cannot be an array (OXSTS.UNSUPPORTED_FEATURE), and two parameters of one transition cannot share a name (OXSTS.DUPLICATE_NAME). A parameter may reuse the name of a member of the class, which the body then reaches as self.name.

The Implicit main and init​

A transition declared without a name has an implicit name based on its kind:

DeclarationImplicit name
tran { ... }main
init { ... }init

Hence tran { value := value + 1 } is equivalent to a transition tran main() { value := value + 1 }. The implicit main and init transitions are the special transitions checked and run by the model checker.

class Counter {
var value: int := 0

redefine init {
value := 0
}

redefine tran {
value := value + 1
}
}

Multiple Branches with or​

A transition body may contain alternative branches separated by or. This is a shorthand for wrapping the body in a top-level choice.

tran step() {
value := value + 1
} or {
value := value - 1
}

The verifier explores both branches non-deterministically.

Abstract Transitions​

An abstract transition has no body. Concrete subclasses must redefine it.

abstract tran fire()

Redefining Transitions​

Override an inherited transition of the same name with redefine.

redefine tran increment() {
if (value < maximum()) {
value := value + 1
}
}

The implicit transitions inherited from Anything are overridden by declaring them, with or without redefine: a class has one main and one init, and a second anonymous transition of a kind in the same class is a duplicate name (OXSTS.DUPLICATE_NAME).

redefine init {
value := 0
}
redefine tran {
inline child.main()
}