Merge branch 'main' into tumbar-type-alias-syntax

This commit is contained in:
Rob Bocchino 2025-02-10 08:36:38 -08:00
commit a5ea983e12
25 changed files with 513 additions and 541 deletions

23
.github/workflows/odroid-keepalive.yml vendored Normal file
View File

@ -0,0 +1,23 @@
# The purpose of this workflow is to prevent the Odroid (self-hosted) runner
# from being de-registered by GitHub due to inactivity.
# We only use the Odroid on FPP releases, but runners get de-registered after 14 days
# of idling.
# See https://github.com/orgs/community/discussions/58146
# https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/removing-self-hosted-runners#removing-a-runner-from-a-repository
name: Odroid Keepalive
on:
# workflow_dispatch allows for manual trigger in the repo 'Actions' tab
workflow_dispatch:
# run every Monday 8am
schedule:
- cron: '0 8 * * 1'
jobs:
keepAlive:
runs-on: odroid
steps:
- name: Echo a message
run: echo I am still alive!

View File

@ -46,7 +46,10 @@ case class ComponentDataProducts (
addAccessTagAndComment(
"PROTECTED",
"Handlers to implement for data products",
containersByName.map((id, container) => getDpRecvHandler(container.getName)),
productRequestPort match {
case None => Nil
case _ => containersByName.map((id, container) => getDpRecvHandler(container.getName))
},
CppDoc.Lines.Hpp
)

View File

@ -155,9 +155,12 @@ case class ComponentImplWriter(
addAccessTagAndComment(
"PRIVATE",
s"Handler implementations for data products",
containersByName.map(
productRequestPort match {
case None => Nil
case _ => containersByName.map(
(id, container) => getDpRecvHandler(container.getName, lines("// TODO"))
)
}
)
private def getDestructor: CppDoc.Class.Member =

View File

@ -1298,42 +1298,6 @@ class ActiveGetProductsComponentBase :
Fw::Time timeTag = Fw::ZERO_TIME //!< The time tag
);
PROTECTED:
// ----------------------------------------------------------------------
// Handlers to implement for data products
// ----------------------------------------------------------------------
//! Receive a container of type Container1
virtual void dpRecv_Container1_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container2
virtual void dpRecv_Container2_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container3
virtual void dpRecv_Container3_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container4
virtual void dpRecv_Container4_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container5
virtual void dpRecv_Container5_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
PROTECTED:
// ----------------------------------------------------------------------

View File

@ -1063,42 +1063,6 @@ class PassiveGetProductsComponentBase :
Fw::Time timeTag = Fw::ZERO_TIME //!< The time tag
);
PROTECTED:
// ----------------------------------------------------------------------
// Handlers to implement for data products
// ----------------------------------------------------------------------
//! Receive a container of type Container1
virtual void dpRecv_Container1_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container2
virtual void dpRecv_Container2_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container3
virtual void dpRecv_Container3_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container4
virtual void dpRecv_Container4_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container5
virtual void dpRecv_Container5_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
PROTECTED:
// ----------------------------------------------------------------------

View File

@ -1298,42 +1298,6 @@ class QueuedGetProductsComponentBase :
Fw::Time timeTag = Fw::ZERO_TIME //!< The time tag
);
PROTECTED:
// ----------------------------------------------------------------------
// Handlers to implement for data products
// ----------------------------------------------------------------------
//! Receive a container of type Container1
virtual void dpRecv_Container1_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container2
virtual void dpRecv_Container2_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container3
virtual void dpRecv_Container3_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container4
virtual void dpRecv_Container4_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
//! Receive a container of type Container5
virtual void dpRecv_Container5_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) = 0;
PROTECTED:
// ----------------------------------------------------------------------

View File

@ -176,52 +176,3 @@ void ActiveGetProducts ::
{
// TODO
}
// ----------------------------------------------------------------------
// Handler implementations for data products
// ----------------------------------------------------------------------
void ActiveGetProducts ::
dpRecv_Container1_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void ActiveGetProducts ::
dpRecv_Container2_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void ActiveGetProducts ::
dpRecv_Container3_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void ActiveGetProducts ::
dpRecv_Container4_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void ActiveGetProducts ::
dpRecv_Container5_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}

View File

@ -180,42 +180,6 @@ class ActiveGetProducts :
const S& s //!< A struct
) override;
PRIVATE:
// ----------------------------------------------------------------------
// Handler implementations for data products
// ----------------------------------------------------------------------
//! Receive a container of type Container1
void dpRecv_Container1_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container2
void dpRecv_Container2_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container3
void dpRecv_Container3_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container4
void dpRecv_Container4_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container5
void dpRecv_Container5_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
};
#endif

View File

@ -110,52 +110,3 @@ void PassiveGetProducts ::
{
// TODO
}
// ----------------------------------------------------------------------
// Handler implementations for data products
// ----------------------------------------------------------------------
void PassiveGetProducts ::
dpRecv_Container1_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void PassiveGetProducts ::
dpRecv_Container2_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void PassiveGetProducts ::
dpRecv_Container3_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void PassiveGetProducts ::
dpRecv_Container4_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void PassiveGetProducts ::
dpRecv_Container5_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}

View File

@ -117,42 +117,6 @@ class PassiveGetProducts :
const S& s //!< A struct
) override;
PRIVATE:
// ----------------------------------------------------------------------
// Handler implementations for data products
// ----------------------------------------------------------------------
//! Receive a container of type Container1
void dpRecv_Container1_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container2
void dpRecv_Container2_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container3
void dpRecv_Container3_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container4
void dpRecv_Container4_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container5
void dpRecv_Container5_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
};
#endif

View File

@ -176,52 +176,3 @@ void QueuedGetProducts ::
{
// TODO
}
// ----------------------------------------------------------------------
// Handler implementations for data products
// ----------------------------------------------------------------------
void QueuedGetProducts ::
dpRecv_Container1_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void QueuedGetProducts ::
dpRecv_Container2_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void QueuedGetProducts ::
dpRecv_Container3_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void QueuedGetProducts ::
dpRecv_Container4_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}
void QueuedGetProducts ::
dpRecv_Container5_handler(
DpContainer& container,
Fw::Success::T status
)
{
// TODO
}

View File

@ -180,42 +180,6 @@ class QueuedGetProducts :
const S& s //!< A struct
) override;
PRIVATE:
// ----------------------------------------------------------------------
// Handler implementations for data products
// ----------------------------------------------------------------------
//! Receive a container of type Container1
void dpRecv_Container1_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container2
void dpRecv_Container2_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container3
void dpRecv_Container3_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container4
void dpRecv_Container4_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
//! Receive a container of type Container5
void dpRecv_Container5_handler(
DpContainer& container, //!< The container
Fw::Success::T status //!< The container status
) override;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.20">
<title>The F Prime Prime (FPP) User&#8217;s Guide, Unreleased, after v2.2.1</title>
<title>The F Prime Prime (FPP) User&#8217;s Guide, Unreleased, after v2.3.0</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
@ -436,7 +436,7 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
</head>
<body class="article toc2 toc-left">
<div id="header">
<h1>The F Prime Prime (FPP) User&#8217;s Guide, Unreleased, after v2.2.1</h1>
<h1>The F Prime Prime (FPP) User&#8217;s Guide, Unreleased, after v2.3.0</h1>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
@ -14859,7 +14859,7 @@ function, you may.</p>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2025-01-30 11:15:12 -0800
Last updated 2025-02-05 09:41:43 -0800
</div>
</div>
<script src="code-prettify/run_prettify.js"></script>

View File

@ -0,0 +1,30 @@
=== Alias Type Definitions
An *alias type definition* associates a name with a type
that is defined elsewhere.
==== Syntax
`type` <<Lexical-Elements_Identifiers,_identifier_>> = <<Type-Names,_type-name_>>
==== Semantics
The identifier is the name _N_ of the type.
The definition associates the name _N_ with
the type _T_ specified after the `=` symbol.
Elsewhere in the model, the name _N_ may be used as alias of (i.e., an
alternate name for) the type _T_.
==== Examples
[source,fpp]
----
# Defines a type A that is an alias of U32
type A = U32
# Defines a struct type B whose member x has type A
struct B {
x: A
y: F32
} default { y = 1 }
----

View File

@ -13,9 +13,6 @@ FSW build.
specifies the behavior of a state machine and
causes an implementation to be generated.
*Implementation note:*
As of FPP v2.2.1, only external state machine definitions are implemented.
==== Syntax
`state machine` <<Lexical-Elements_Identifiers,_identifier_>>

View File

@ -25,8 +25,8 @@ _]_
==== Semantics
The identifier is the name _N_ of the type. The definition associates the name
_N_ with a
The identifier is the name _N_ of the type.
The definition associates the name _N_ with a
<<Types_Struct-Types,struct type>> _T_ representing a structure with named members, each
of the specified type. Each
identifier appearing in the struct type member sequence must be distinct.

View File

@ -9,6 +9,7 @@ redo-ifchange defs.sh
export FILES="
Introduction.adoc
Abstract-Type-Definitions.adoc
Alias-Type-Definitions.adoc
Array-Definitions.adoc
Component-Definitions.adoc
Component-Instance-Definitions.adoc

View File

@ -3,6 +3,3 @@
A *state machine behavior element* specifies an element of the behavior
associated with a
<<Definitions_State-Machine-Definitions,state machine definition>>.
*Implementation note:*
As of FPP v2.2.1, state machine behavior elements are not implemented.

View File

@ -241,6 +241,8 @@ are both the same
. Each of stem:[T_1] and stem:[T_2]
is an
<<Types_Abstract-Types,abstract type>>,
<<Types_Alias-Types,alias type>>,
<<Types_Array-Types,array type>>,
<<Types_Enum-Types,enum type>>, or
<<Types_Struct-Types,struct type>>,
@ -257,6 +259,12 @@ Here are the rules for type conversion:
. stem:[T_1] may be converted to stem:[T_2] if stem:[T_1] and stem:[T_2]
are <<Type-Checking_Identical-Types,identical types>>.
. If either stem:[T_1] or stem:[T_2] or both is an
<<Types_Alias-Types,alias type>>, then stem:[T_1]
may be converted to stem:[T_2] if the <<Types_Underlying-Types,underlying
type>> of stem:[T_1] may be converted to
the <<Types_Underlying-Types,underlying type>> of stem:[T_2].
. Any <<Types_String-Types,string type>> may be converted
to any other string type.
@ -331,6 +339,11 @@ the whole expression):
<<Type-Checking_Identical-Types,identical types>>, then let
stem:[T] be stem:[T_1].
. Otherwise if stem:[T_1] or stem:[T_2] or both are <<Types_Alias-Types,alias
types>>, then replace
each alias type with its <<Types_Underlying-Types,underlying type>>
and reapply these rules.
. Otherwise if stem:[T_1] and stem:[T_2] are both
<<Types_Internal-Types_Numeric-Types,numeric types>>, then do the following:

View File

@ -62,6 +62,7 @@ A *qualified identifier type name* is a
<<Scoping-of-Names_Qualified-Identifiers,qualified
identifier>> that refers to an
<<Definitions_Abstract-Type-Definitions,abstract type definition>>,
<<Definitions_Alias-Type-Definitions,alias type definition>>,
<<Definitions_Array-Definitions,array definition>>,
<<Definitions_Enum-Definitions,enum definition>>, or
<<Definitions_Struct-Definitions,struct definition>>

View File

@ -21,6 +21,13 @@ stem:[O_2] in the following cases.
.. stem:[T_1] and stem:[T_2] are <<Type-Checking_Identical-Types,identical types>>.
.. Either or both of stem:[T_1] and stem:[T_2] is an <<Types_Alias-Types,alias
type>>,
and _Some_ stem:[T'_1] may be converted to _Some_ stem:[T'_2], where
stem:[T'_1] is the <<Types_Underlying-Types,underlying type>> of stem:[T_1],
and
stem:[T'_2] is the <<Types_Underlying-Types,underlying type>> of stem:[T_2].
.. stem:[T_1] and stem:[T_2] are both
<<Types_Primitive-Integer-Types,signed primitive integer types>>,
and stem:[T_2] is at least as wide as stem:[T_1].
@ -53,6 +60,10 @@ is computed as follows:
.. If stem:[T_1] and stem:[T_2] are <<Type-Checking_Identical-Types,identical types>>,
then let stem:[T] be stem:[T_1].
.. Otherwise if either stem:[T_1] or stem:[T_2] is an <<Types_Alias-Types,alias type>>,
then replace each alias type with its <<Types_Underlying-Types,underlying type>>
and reapply these rules.
.. Otherwise if stem:[T_1] and stem:[T_2] are both
<<Types_Primitive-Integer-Types,signed primitive integer types>>,
then let stem:[T] be the wider of the two types.

View File

@ -80,6 +80,15 @@ An abstract type is written using its
<<Scoping-of-Names_Names-of-Definitions,unique qualified
name>>.
=== Alias Types
An *alias type* is a type associated with an
<<Definitions_Alias-Type-Definitions,alias type definition>>.
There is one alias type per alias type definition.
An alias type is written using its
<<Scoping-of-Names_Names-of-Definitions,unique qualified
name>>.
=== Internal Types
*Internal types* do not have syntactic names in FPP source models.
@ -118,9 +127,25 @@ The order of the members is not significant.
For example, `{ a: U32, b: F32 }` represents the same
type as `{ b : F32, a: U32 }`.
=== Canonical Types
A type is a *canonical type* if it is not an <<Types_Alias-Types,alias type>>.
=== Underlying Types
The *underlying type* of a type _T_ is the <<Types_Canonical-Types, canonical type>>
associated with _T_.
* If _T_ is a canonical type, then the underlying type of _T_ is _T_.
* Otherwise _T_ is an <<Types_Alias-Types,alias type>>.
In this case, the underlying type of _T_ is the underlying type of the type
associated with _T_ in the definition of _T_.
=== Displayable Types
A type is a **displayable type** if it is one of the following:
A *displayable type* is a type that the F Prime ground data system can display.
It is one of the following:
* A <<Types_Primitive-Integer-Types,primitive integer type>>.
* A <<Types_Floating-Point-Types,floating-point type>>.
@ -129,10 +154,13 @@ A type is a **displayable type** if it is one of the following:
* An <<Types_Enum-Types,enum type>>.
* An <<Types_Array-Types,array type>> whose member type is a displayable type.
* A <<Types_Struct-Types,struct type>> whose member types are all displayable types.
* An <<Types_Alias-Types,alias type>> whose <<Types_Underlying-Types,underlying
type>> is a displayable type.
=== Types with Numeric Members
A type *has numeric members* if it is one of the following:
A type *has numeric members* if its <<Types_Underlying-Types,underlying type>>
is one of the following:
* A <<Types_Internal-Types_Numeric-Types,numeric type>>.
@ -192,3 +220,8 @@ struct definitions>> for examples.
<<Values_Abstract-Type-Values,single value associated with _T_>>.
This value is left abstract in the FPP model; the implementation
of _T_ must provide a concrete value.
* The default value associated with an
<<Types_Alias-Types,alias type>> _T_ is the
<<Types_Default-Values,default value>> of its
<<Types_Underlying-Types,underlying type>>.

View File

@ -24,12 +24,26 @@ A *value* is one of the following:
* A struct value
Every value belongs to exactly one type.
Every value _v_ belongs to exactly one <<Types_Canonical-Types,canonical type>>
_T_, except as follows:
* Every string value belongs to the type `string` and to
all types `string` _n_, for any _n_.
* Every value that belongs to type _T_ also belongs to every
<<Types_Alias-Types,alias type>> whose
<<Types_Underlying-Types,underlying type>> is _T_.
When a value _v_ belongs to a type _T_, we say that _v_ is a value
*of type _T_*.
In the following subsections, we describe each kind of value and
its associated canonical types.
=== Primitive Integer Values
A *primitive integer value* is an ordinary (mathematical) integer value
together with a
together with its canonical type, which is a
<<Types_Primitive-Integer-Types,primitive integer type>>. Formally, the set of
primitive integer values
is the disjoint union over the integer types of the values
@ -43,14 +57,15 @@ stem:[[0, 255\]].
stem:[[-2^(w-1), 2^(w-1)-1\]]. For example, `I8` represents the integers
stem:[[-128, 127\]].
We represent a primitive integer value as an expression followed by a colon and a type.
We represent a primitive integer value as an expression followed by a colon and
a primitive integer type.
For example, we write the value 1 at type `U32` as `1: U32`. The value `1:
U32` is distinct from the value `1: U8`.
=== Integer Values
An *integer value* is an ordinary (mathematical) integer value.
It has type _Integer_.
Its canonical type is _Integer_.
We represent an integer value as an integer number, with no explicit type.
For example, `1` is an integer value.
@ -66,11 +81,12 @@ over the types `F32` and `F64` of the values represented by each type:
We write a floating-point values analogously to primitive integer values. For
example, we write the value 1.0 at type `F32` as `1.0: F32`.
The canonical type of a floating-point value is `F32` or `F64`.
=== Boolean Values
A *Boolean value* is one of the values `true` and `false`.
Its type is `bool`.
Its canonical type is `bool`.
=== String Values
@ -78,13 +94,21 @@ A *string value* is a sequence of characters that can be
represented as a <<Expressions_String-Literals,string literal expression>>.
It is written in the same way as a string literal expression,
e.g., `"abc"`.
Its type is `string`.
A string value belongs to the following canonical types:
* `string`
* `string` _n_ for any _n_
=== Abstract Type Values
An *abstract type value* is a value associated with an abstract
type.
There is one value associated with each abstract type stem:[T].
For each abstract type stem:[T], there is one
value with canonical type stem:[T].
This value is not represented explicitly in the model, but it
may be represented in the generated code, e.g., as an object
with default initialization.
We write the value `value of type` stem:[T].
=== Anonymous Array Values
@ -93,10 +117,17 @@ An *anonymous array value* is a value associated with an anonymous
array type.
We write an anonymous array value similarly to an
<<Expressions_Array-Expressions,array expression>>:
an anonymous array value has the form `[` stem:[v_1] `,` stem:[...] `,`
an anonymous array value stem:[v] has the form `[` stem:[v_1] `,` stem:[...]
`,`
stem:[v_n] `]`, where for each stem:[i in [1,n]], stem:[v_i] is a value of type
stem:[T] for some stem:[T].
The type of the value is _[_ stem:[n] _]_ stem:[T].
stem:[T] for some <<Types_Canonical-Types,canonical type>> stem:[T].
The canonical type of stem:[v] is _[_ stem:[n] _]_ stem:[T].
Note that for an anonymous array value stem:[v] to be well-formed, the member
values must have identical types.
If an array expression appearing in the source syntax has
member values with non-identical types, then one or more members must be
converted to a different type before forming stem:[v].
=== Array Values
@ -116,8 +147,12 @@ that refers to a
with member type stem:[T].
. For each stem:[i in [1,n]], stem:[v_i] is a value of type stem:[T].
Note that stem:[T] need not be a canonical type.
For example, it is permissible for stem:[T] to be `T`, for
`T` to be an alias of `U32`, and for stem:[v] to be the value `[ 1: U32, 2: U32 ]`.
In this case `1: U32` and `2: U32` are values of type `T`, as required.
The type of the value is stem:[Q].
The canonical type of the value is stem:[Q].
=== Enumeration Values
@ -125,7 +160,7 @@ An *enumeration value* is a value associated with an
<<Definitions_Enumerated-Constant-Definitions,enumerated constant definition>>.
It is a pair consisting of the name and the integer value
specified in the enumerated constant definition.
Its type is the type associated with the
Its canonical type is the type associated with the
<<Definitions_Enum-Definitions,enum definition>> in which
the enumerated constant definition appears.
@ -139,8 +174,9 @@ We write an anonymous struct value stem:[v] similarly to a
a struct value has the form `{` stem:[m_1] `=` stem:[v_1] `,` stem:[...] `,`
stem:[m_n] `=` stem:[v_n] `}`,
where for each stem:[i in [1,n]], stem:[v_i] is a value of type stem:[T_i].
The type of stem:[v] is _{_ stem:[m_1] _:_ stem:[T_1] _,_ stem:[...] _,_
stem:[m_n] _:_ stem:[T_n] _}_.
Each type stem:[T_i] must be a <<Types_Canonical-Types,canonical type>>.
The canonical type of the value is _{_ stem:[m_1] _:_ stem:[T_1] _,_ stem:[...]
_,_ stem:[m_n] _:_ stem:[T_n] _}_.
=== Struct Values
@ -161,8 +197,13 @@ that refers to a
. The members of stem:[Q] are stem:[m_i] `:` stem:[T_i] for stem:[i in [1,n\]].
. For each stem:[i in [1,n]], stem:[v_i] is a value of type stem:[T_i].
Note that stem:[T_i] need not be a canonical type.
For example, it is permissible for stem:[T_1] to be `T`, for
`T` to be an alias of `U32`, and for stem:[v_1] to be the value `1: U32`.
In this case `1: U32` is a value of type `T`, as required.
All the members must be explicitly assigned values.
Each member of the struct value must have an explicit value.
The canonical type of the struct value is stem:[Q].
=== Serialized Sizes
@ -200,3 +241,7 @@ the sum of the serialized sizes of the members of _v_
* If _T_ is an
<<Types_Abstract-Types,abstract type>>, then _s_ is not specified in FPP. It
is up to the implementer of _T_ to provide the serialized size.
* If _T_ is a
<<Types_Alias-Types,alias type>>, then apply these rules to its
<<Types_Underlying-Types,underlying type>>.

View File

@ -2,4 +2,4 @@
# The FPP version
# ----------------------------------------------------------------------
export VERSION="Unreleased, after v2.2.1"
export VERSION="Unreleased, after v2.3.0"