Rules and guards
Rules are actions
A rule is a method marked [Rule] on a model program. Each rule is an action
the system can take. During exploration, SEK tries every rule in every reachable
state.
[Rule("Cart.Checkout")]
public void Checkout()
{
Require(Items.Count > 0, "cart is empty");
Checked = true;
}
The action label is what appears on transitions and what Cord and bindings
refer to. It defaults to DeclaringType.MethodName; pass an explicit label to match
your Cord declarations, e.g. [Rule("Cart.Checkout")].
Guards enable or disable an action
A guard is a precondition. In a given state an action is enabled only if all
its guards hold. SEK expresses guards with Require:
protected static void Require(bool condition, string reason);
If condition is false, Require throws GuardDisabledException, which the
explorer catches and interprets as "this action is not enabled in this state" —
the action simply produces no transition from that state. Any other exception is
reported as a diagnostic (it indicates a bug in the model, not a disabled action).
[Rule("Turnstile.Push")]
public void Push()
{
Require(!Locked, "still locked"); // disabled while locked
Locked = true;
}
Condition.IsTrue(condition, "reason") is an equivalent spelling carried over from
Spec Explorer.
Parameters
Rules can take parameters. Their candidate values (their domain) come from Cord
Condition.In, a [Domain] method, reachable objects, or the type's natural domain
— see Parameter generation and
Object domains. For each combination of parameter values, SEK
invokes the rule on a fresh copy of the state and records the resulting transition
(unless a guard disables it).
Effects
After the guards pass, the rule body mutates state to describe the action's effect. The resulting state is snapshotted and de-duplicated by canonical hash.
Guard patterns
- Preconditions:
Require(Balance >= amount, "insufficient funds"). - Bounding the state space:
Require(Items.Count < 3, "cap items")keeps exploration finite. - Parameter validity:
Require(atx == X, "must match current position")pairs well with a state-dependent[Domain].