Internet DRAFT - draft-petithuguenin-formal-fsm
draft-petithuguenin-formal-fsm
Network Working Group M. Petit-Huguenin
Internet-Draft Impedance Mismatch LLC
Intended status: Standards Track 11 October 2021
Expires: 14 April 2022
A Formal Language to Describe State Machines
draft-petithuguenin-formal-fsm-00
Abstract
This document describes a meta-language for finite state machines.
Editorial Note
The intent of this Internet-Draft is not to be published as an RFC
but to solicit reviews on the meta-language described in it. The
meta-language described will become a section in the specific
Internet-Draft that will succeed it.
The ABNF was generated using the RFC5234 DSL described in computerate
specifying [I-D.petithuguenin-computerate-specifying].
Discussion of this document takes place on the FDT mailing list
(mailto:fdt@w3.org), which is archived at
https://mailarchive.ietf.org/arch/browse/fdt/.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on 14 April 2022.
Copyright Notice
Copyright (c) 2021 IETF Trust and the persons identified as the
document authors. All rights reserved.
Petit-Huguenin Expires 14 April 2022 [Page 1]
Internet-Draft Formal FSM October 2021
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document. Code Components
extracted from this document must include Simplified BSD License text
as described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Simplified BSD License.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2
2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 2
3. Presentation Language for Finite State Machine . . . . . . . 3
3.1. Semantics . . . . . . . . . . . . . . . . . . . . . . . . 3
3.2. Syntax . . . . . . . . . . . . . . . . . . . . . . . . . 3
3.2.1. Formatting . . . . . . . . . . . . . . . . . . . . . 3
3.2.2. Names . . . . . . . . . . . . . . . . . . . . . . . . 4
3.2.3. Constants . . . . . . . . . . . . . . . . . . . . . . 4
3.2.4. State . . . . . . . . . . . . . . . . . . . . . . . . 4
3.2.5. Event . . . . . . . . . . . . . . . . . . . . . . . . 5
3.2.6. Action . . . . . . . . . . . . . . . . . . . . . . . 5
3.2.7. Event and State Patterns . . . . . . . . . . . . . . 6
3.2.8. Expression . . . . . . . . . . . . . . . . . . . . . 8
3.2.9. State Assignment . . . . . . . . . . . . . . . . . . 9
3.2.10. Action Assignment . . . . . . . . . . . . . . . . . . 10
3.2.11. Transition . . . . . . . . . . . . . . . . . . . . . 10
3.2.12. State Machine . . . . . . . . . . . . . . . . . . . . 11
4. References . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.1. Normative References . . . . . . . . . . . . . . . . . . 13
4.2. Informative References . . . . . . . . . . . . . . . . . 13
Appendix A. ABNF . . . . . . . . . . . . . . . . . . . . . . . . 13
Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 15
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 15
1. Introduction
TBD.
2. Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP
14 [RFC2119][RFC8174] when, and only when, they appear in all
capitals, as shown here.
Petit-Huguenin Expires 14 April 2022 [Page 2]
Internet-Draft Formal FSM October 2021
3. Presentation Language for Finite State Machine
The only tentative of formalization of a standalone presentation
language for Finite State Machines (FSM) at the IETF was Cosmogol
[I-D.bortzmeyer-language-state-machines], which did not generate
enough interest from the community to be published as an RFC.
Instead this document proposes an ad-hoc meta-language to describe
FSMs and purposely delays efforts to make it a standard.
3.1. Semantics
The state machines formalized by this meta-language are based on
Mealy machines, i.e, as finite state machines whose next state and
actions are determined both by its current state and the current
event, in the form of a transition. This model is enriched by the
possibility of having actions, states and events carrying additional
data. Regardless of these data the state machines described are
still deterministic, in that for each possible value carried by a
state and for each possible value carried by an event, only one
transition is possible. This implies that there MUST NOT be a
combination of state and event values that does not trigger exactly
one of the transitions described in that state machine.
A simple calculus is used to assign values to the data carried by the
next state and by the actions triggered by a transition. This
permits to carry as much information as possible in a compact way to
the people or processes that will implement, or verify conformance
to, the described state machine.
3.2. Syntax
The syntax of the meta-language is described in the following
sections in bottom up order by using ABNF [RFC5234], including the
Core Rules defined in appendix B.
The retransmission state machine underlying section 6.2.1 of STUN
[RFC8489] will be used to illustrate the syntax of the meta-language.
3.2.1. Formatting
Each element of the language is presented either on a single line or
unfolded on several lines with the subsequent lines starting with
either a space or an horizontal tab character.
LWS = [*WSP CRLF] 1*WSP
Petit-Huguenin Expires 14 April 2022 [Page 3]
Internet-Draft Formal FSM October 2021
3.2.2. Names
Constants, states, events, actions, and their eventual parameters are
all assigned to a name. Bindings are assignments of names to a
parameter values in the context of a transition.
A name is composed of an alphabetic character, followed by a
repetition of either alphanumeric characters, the "-" character, or
the "_" character. Names are case-sensitive.
name = ALPHA *ALPHA / DIGIT / "-" / "_"
"init", and "RTO" are examples of name.
3.2.3. Constants
Constants are immutable values that are used by transitions and set
to a specific value before the state machine is instantiated. The
specific value used is not part of the definition of the state
machine.
Constants can also be thought as total functions that takes the
current value of all the possible bindings available when that
constant is accessed and return a value. Here it is the function
that is constant, although the value returned may not be when it
depends on the values of bindings.
Constants are declared with the keyword "constant". The name of a
constant MUST be unique among all constant names defined in an FSM.
constant = name [LWS] "<-" [LWS] "constant"
"RTO <- constant" and "POWER2 <- constant" are two examples of
constants used by the STUN retransmission state machine.
3.2.4. State
States represent the possible values of an implicit binding that is
the current state in the execution of a state machine. State can
carry parameters, which must be named at the same time than the
state. States are declared with the keyword "state". The name of a
state MUST be unique among all state names defined in an FSM. The
name of a state parameter MUST be unique among all state parameter
names for a specific state.
state = name [LWS] "<-" [LWS] "state" *(LWS name)
Petit-Huguenin Expires 14 April 2022 [Page 4]
Internet-Draft Formal FSM October 2021
"Init <- state" and "Sending <- state request count" are two examples
of states used by the STUN retransmission state machine (we use the
convention that states names start with an uppercase).
In the second example the Sending state carries the number of
remaining retransmissions and the request to be retransmitted.
3.2.5. Event
An event is a signal external of the state machine that when received
triggers a transition. An event can carry parameters which are
declared similarly to states. Events are declared with the keyword
"event". The name of an event MUST be unique among all event names
defined in an FSM. The name of an event parameter MUST be unique
among all event parameter names for a specific event.
state = name [LWS] "<-" [LWS] "state" *(LWS name)
The "init" event is implicitly defined and is always the first event
received by a state machine. It does not carry any parameter.
"appRequest <- event request" and "timeout <- event" are two examples
of events used by the STUN retransmission state machine (we use the
convention that event names start with a lowercase).
3.2.6. Action
An action is a signal sent by the state machine following a
transition, and that is sent externally. An action can carry
parameters which are declared similarly to states. Actions are
declared with the keyword "action". The name of an action MUST be
unique among all action names defined in an FSM. Although actions
names are not used elsewhere, the name of an action parameter MUST be
unique among all action parameter names for a specific action.
action = name [LWS] "<-" [LWS] "action" *(LWS name)
Note that an external piece of code can be represented as either a
constant, or as both an action and one or more events. A rule of
thumb is that an action/event should be used for something that is
taking time or that is doing I/O and that a constant as function
should be used when the value can be calculated by using only the
constants and bindings defined in the state machine.
"netRequest <- action request" and "timer <- action delay" are two
examples of actions used by the STUN retransmission state machine (we
use the convention that action names start with a lowercase).
Petit-Huguenin Expires 14 April 2022 [Page 5]
Internet-Draft Formal FSM October 2021
3.2.7. Event and State Patterns
An event pattern is used to select the particular event for which a
particular transition is described. The pattern matching is done on
the name of the event and possibly on values for the parameters of
that event.
Using "*" as the name of the event means that this transition is for
all possible events. In that case it is not possible to pattern
match on event parameters.
The meta-language permits to combine two different ways to pattern
match on a parameter: positional pattern matching and named pattern
matching.
Positional pattern matching is useful when most of the parameters
need to be pattern matched or will be used later. On the other hand
if only one or two parameters are needed, it becomes quickly annoying
to use positional pattern matching.
Named pattern matching is useful when a few of the parameters need to
be pattern matched or will be used later. On the other hand if most
of the parameters are needed, it becomes quickly annoying to have to
name all of them.
Combining the two ways permits to get the best of each type of
pattern matching, especially if the most used parameters are declared
first.
So state parameters can be patterned-matched using positional
pattern, i.e., using either a value, a name, or a "*" for each of the
parameter, in the same order than parameters were declared for the
event.
Using a value means that this parameter must have this exact value.
Using a name in a positional pattern binds that name to the value of
the parameter in that position. It means that there is no
restriction to the value that this parameter can take, but that we
can reference that value elsewhere. That name can be identical to
the parameter name, but it does not have to be.
Using a "*" in a positional pattern means that there is no
restriction of the value of that parameter, but that we will not be
able to use that value.
Petit-Huguenin Expires 14 April 2022 [Page 6]
Internet-Draft Formal FSM October 2021
num-value = "0" / (%x31-39 *DIGIT)
str-value = DQUOTE *( %x01-21 / %x32-5B / %x5D-7F /
("\" DQUOTE) / ("\" "\") ) DQUOTE
bool-value = "true" / "false"
value = num-value / str-value / bool-value
pattern = "*" / name / value
positional-patterns = pattern *(LWS pattern)
Alternatively variables can be pattern-matched using named patterns,
in which each parameter is named and possibly associated with either
a value, a name, or "*" by using the "=" symbol. The parameter name
MUST be one of the names used when declaring the event. Parameter
names do not have to be used in the same order that declared in the
event, but they cannot be used more than once.
Like for positional pattern matching, using a value means that the
named parameter must have this exact value. A parameter name alone,
i.e. without the "=" symbol, implicitly creates a binding to that
parameter, binding that has the same name than the parameter.
Using a value after the "=" symbol means that this parameter must
have this exact value.
Using a name after the "=" symbol binds that name to the value of the
parameter. It means that there is no restriction to the value that
this parameter can take, but that use that value elsewhere. That
name can be identical to the parameter name, but it does not have to
be.
Using a "*" after the "=" symbol means that there is no restriction
of the value of that parameter, but that we do not need to use that
value.
A name declared as an event parameter but that is not used in either
the positional or named patterns is implicitly associated with "*".
This means that an empty set of named patterns will match any values
for any parameter for the specified event.
named-pattern = name [[LWS] "=" [LWS] pattern]
named-patterns = "{" [LWS] [named-pattern *([LWS] "," [LWS]
named-pattern)] [LWS] "}"
Petit-Huguenin Expires 14 April 2022 [Page 7]
Internet-Draft Formal FSM October 2021
Positional and named patterns can be combined by listing first a
subset of the positional patterns followed by the named patterns, as
long as positional patterns come first, and as long as named patterns
do not use the name of a parameter that is already used by a
positional pattern.
patterns = "*" / ("(" [LWS] "*" [LWS] ")") / name / ("(" [LWS]
name [LWS] ")") / ("(" [LWS] name [LWS
positional-patterns] [LWS named-patterns] [LWS] ")")
The state pattern is identical to the event pattern, but with the
name of a state replacing the name of the event, and the names of the
state parameters replacing the names of the event parameters.
"*", "init", "(Sending r c)", and "(appRequest {})" are examples of
event or state patterns.
3.2.8. Expression
An expression is the combination of constant names, binding names, or
values with binary operators between each of them.
Each operators is assigned a precedence that permits to unambiguously
resolve the order these operators are processed. In the following
ABNF, an operator defined by a rule with a name ending with a lower
number binds loosely than an operator with a rule name ending with an
higher number.
ops-1 = "||"
ops-2 = "&&"
ops-3 = "<" / "<=" / "==" / "!=" / ">" / ">="
ops-4 = "+" / "-"
ops-5 = "*" / "/" / "%"
ops = ops-1 / ops-2 / ops-3 / ops-4 / ops-5
Parentheses can be used to override the precedence rules. The two
unary operators binds as close as possible to the next value, name or
opening parenthesis.
Petit-Huguenin Expires 14 April 2022 [Page 8]
Internet-Draft Formal FSM October 2021
un-ops = "!" / "-"
sub-expr = ([un-ops [LWS]] name) / ([un-ops [LWS]] value) /
( [un-ops [LWS]] ("(" [LWS] ops [LWS] ")") )
expr = sub-expr *([LWS] ops [LWS] sub-expr)
The type (numeric, character string, or boolean) of an expression is
inferred by recursively applying a series of rules on the combination
of names, values, and operators for that expression.
* The type of a numeric value is the numeric type.
* The type of a character string value is the character string type.
* The type of a boolean value is the boolean type.
* The type of the operators "||" and "&&" is boolean if the
expressions on the right and left of them are of type boolean.
* The type of the operators "<", "<=", "==", "!=", ">", and "`>="`
is numeric if the expressions on the right and left of them are of
type numeric.
* The type of the operators "<", "<=", "==", "!=", ">", and ">=" is
character string if the expressions on the right and left of them
are of type character string.
* The type of the operators "+", "-", "*", "/", and "%" is numeric
if the expressions on the right and left of them are of type
numeric.
* the type of the unary operator "!" is boolean if the expression on
the right of it is of type boolean.
* the type of the unary operator "-" is numeric if the expression on
the right of it is of type numeric.
* Each binding associated to an event parameter or state parameter
has the same type than the parameter.
* Each constant in a whole state machine have a unique type.
* Each event parameter, state parameter, or action parameter in a
whole state machine has a unique type.
* Any expression that does not match one of these rules is
incorrect.
"(1 + 1) * 4 < name && true || !false" is an example of expression.
Its type is the boolean type.
3.2.9. State Assignment
A state assignment assigns an expression to each parameter of the
next state. The expression can use any constant, and any binding
that is defined in the state or event pattern in the transition. The
type of the expressions assigned to a specific parameter of a state
MUST be the same across all transitions.
Petit-Huguenin Expires 14 April 2022 [Page 9]
Internet-Draft Formal FSM October 2021
Most of the time state parameters are assigned to the same value than
is carried by the previous state. To simplify this use case, it is
also possible to assign only the parameters that require
modification, and to implicitly assign the same value by default for
the others. Positional assignments and named assignments can be used
in the same way than positional patterns and named patterns are.
named-assignment = name [[LWS] "=" [LWS] expr]
named-assignment = ("{" [LWS] "}") / ("{" [LWS] named-assignment
*([LWS] "," [LWS] named-assignment) [LWS]
"}")
state-assignment = name named-assignment
"Disabled {last=last+1}" is an example of state assignment.
3.2.10. Action Assignment
An action assignment assigns an expression to each parameter of an
action. The expression can use any constant, and any binding that is
defined in the state or event pattern in the transition. The type of
the expressions assigned to a specific parameter of an action MUST be
the same across all transitions.
The number of expressions after the name of the action must be equal
to the number of parameters declared for this action.
action-assignment = name *(LWS expr)
"timer (RTO * POWER2 c)" is an example of action assignment.
3.2.11. Transition
A transition describes what happen when an event is received on a
state and under an optional condition.
A transition is composed of 5 elements: a state pattern, an event
pattern, an optional condition which is an expression of type
boolean, an optional next state, and a possibly empty set of actions.
If the next state is not present then the transition leaves the state
machine in the same state.
transition = patterns LWS patterns [[LWS] "|" [LWS] expr] [LWS]
"->" [[LWS] state-assignment] *(LWS
action-assignment)
Petit-Huguenin Expires 14 April 2022 [Page 10]
Internet-Draft Formal FSM October 2021
Note that the result of an expression cannot be used in an
expression, as the result of each expression is built only from the
values set in the event and state patterns. That makes the execution
of the state change and actions atomic, deterministic, and
unambiguous.
The name of all the bindings in a transition MUST be unique in that
transition.
The following is an example of transition.
timeout (Disabled {last}) ->
Disabled {last=last+1}
timer CONNECTIVITY_TIMEOUT
probe (last+1) 0
Figure 1
3.2.12. State Machine
A state machine is composed of constants, states, events, actions,
transitions, empty lines, or comments.
element = constant / state / event / action / transition /
("#" *VCHAR)
state-machine = [element] *(CRLF [element])
The following example is the STUN retransmission state machine.
Petit-Huguenin Expires 14 April 2022 [Page 11]
Internet-Draft Formal FSM October 2021
init * -> Init
(appRequest r) Init ->
Sending r 0
netRequest r
timer RTO
* Init ->
(appRequest _) (Sending {}) ->
timeout (Sending r c) | c < RC - 1 ->
Sending {count=c+1}
netRequest r
timer (RTO * POWER2 c)
timeout (Sending r c) | c = RC - 1 ->
Last
netRequest r
timer (RTO * RM)
netIcmp Sending ->
End
cancelTimer
appError
netResponse Sending
End
cancelTimer
appResponse
(appRequest _) Last ->
timeout Last ->
End
appTimeout
netIcmp Last ->
End
cancelTimer
appError
netResponse Last
End
cancelTimer
appResponse
* End ->
Petit-Huguenin Expires 14 April 2022 [Page 12]
Internet-Draft Formal FSM October 2021
Figure 2
4. References
4.1. Normative References
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", RFC 5234, DOI 10.17487/RFC5234,
January 2008, <https://www.rfc-editor.org/info/rfc5234>.
[RFC8174] Leiba, B., "RFC 2119 Key Words: Clarifying the Use of
Capitalization", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
4.2. Informative References
[I-D.bortzmeyer-language-state-machines]
Bortzmeyer, S., "Cosmogol: a language to describe finite
state machines", Work in Progress, Internet-Draft, draft-
bortzmeyer-language-state-machines-01, 1 November 2006,
<https://datatracker.ietf.org/doc/html/draft-bortzmeyer-
language-state-machines-01>.
[I-D.petithuguenin-computerate-specifying]
Petit-Huguenin, M., "The Computerate Specifying Paradigm",
Work in Progress, Internet-Draft, draft-petithuguenin-
computerate-specifying-13, 27 September 2021,
<https://datatracker.ietf.org/doc/html/draft-
petithuguenin-computerate-specifying-13>.
[RFC8489] Petit-Huguenin, M., Salgueiro, G., Rosenberg, J., Wing,
D., Mahy, R., and P. Matthews, "Session Traversal
Utilities for NAT (STUN)", RFC 8489, DOI 10.17487/RFC8489,
February 2020, <https://www.rfc-editor.org/info/rfc8489>.
Appendix A. ABNF
The complete ABNF for the meta-language is listed here:
Petit-Huguenin Expires 14 April 2022 [Page 13]
Internet-Draft Formal FSM October 2021
LWS = [*WSP CRLF] 1*WSP
name = ALPHA *ALPHA / DIGIT / "-" / "_"
constant = name [LWS] "<-" [LWS] "constant"
state = name [LWS] "<-" [LWS] "state" *(LWS name)
event = name [LWS] "<-" [LWS] "event" *(LWS name)
action = name [LWS] "<-" [LWS] "action" *(LWS name)
num-value = "0" / (%x31-39 *DIGIT)
str-value = DQUOTE *( %x01-21 / %x32-5B / %x5D-7F / ("\"
DQUOTE) / ("\" "\") ) DQUOTE
bool-value = "true" / "false"
value = num-value / str-value / bool-value
pattern = "*" / name / value
positional-patterns = pattern *(LWS pattern)
named-pattern = name [[LWS] "=" [LWS] pattern]
named-patterns = "{" [LWS] [named-pattern *([LWS] "," [LWS]
named-pattern)] [LWS] "}"
patterns = "*" / ("(" [LWS] "*" [LWS] ")") / name / ("("
[LWS] name [LWS] ")") / ("(" [LWS] name [LWS
positional-patterns] [LWS named-patterns]
[LWS] ")")
ops-1 = "||"
ops-2 = "&&"
ops-3 = "<" / "<=" / "==" / "!=" / ">" / ">="
ops-4 = "+" / "-"
ops-5 = "*" / "/" / "%"
un-ops = "!" / "-"
sub-expr = ([un-ops [LWS]] name) / ([un-ops [LWS]]
Petit-Huguenin Expires 14 April 2022 [Page 14]
Internet-Draft Formal FSM October 2021
value) / ( [un-ops [LWS]] ("(" [LWS] ops
[LWS] ")") )
expr = sub-expr *([LWS] ops [LWS] sub-expr)
named-assignment = name [[LWS] "=" [LWS] expr]
named-assignment = ("{" [LWS] "}") / ("{" [LWS] named-assignment
*([LWS] "," [LWS] named-assignment) [LWS]
"}")
state-assignment = name named-assignment
action-assignment = name *(LWS expr)
transition = patterns LWS patterns [[LWS] "|" [LWS] expr]
[LWS] "->" [[LWS] state-assignment] *(LWS
action-assignment)
element = constant / state / event / action /
transition / ("#" *VCHAR)
state-machine = [element] *(CRLF [element])
Acknowledgements
Thanks to Stephane Bryant and Colin Perkins for the comments,
suggestions, and questions that helped improve this document.
Author's Address
Marc Petit-Huguenin
Impedance Mismatch LLC
Email: marc@petit-huguenin.org
URI: hallway@jabber.ietf.org/MPH
Petit-Huguenin Expires 14 April 2022 [Page 15]