== Type Options

A *type option* is one of the following:

. _Some_ stem:[T], representing a value of type stem:[T].

. _None_, representing no value.

Type options are used to specify the optional types associated with
signals, actions, and guards in <<Definitions_State-Machine-Definitions,state
machine definitions>>.

=== Conversion of Type Options

We say that a type option stem:[O_1] *may be converted to* another type option
stem:[O_2] in the following cases.

. Any type option may be converted to _None_.

. _Some_ stem:[T_1] may be converted to _Some_ stem:[T_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].

.. stem:[T_1] and stem:[T_2] are both
<<Types_Primitive-Integer-Types,unsigned primitive integer types>>,
and stem:[T_2] is at least as wide as stem:[T_1].

.. stem:[T_1] and stem:[T_2] are both
<<Types_Floating-Point-Types,floating-point types>>,
and stem:[T_2] is at least as wide as stem:[T_1].

.. stem:[T_1] and stem:[T_2] are both <<Types_String-Types,string types>>.

=== Computing a Common Type Option

==== Pairs of Type Options

Here are the rules for resolving two type options stem:[O_1] and stem:[O_2] to
a common type option stem:[O]:

. If either or both of stem:[O_1] and stem:[O_2] is _None_, then
let stem:[O] be _None_.

. Otherwise let stem:[O_1] be _Some_ stem:[T_1], and let
stem:[O_2] be _Some_ stem:[T_2].
Let stem:[O] be _Some_ stem:[T], where stem:[T]
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.

.. Otherwise if stem:[T_1] and stem:[T_2] are both
<<Types_Primitive-Integer-Types,unsigned primitive integer types>>,
then let stem:[T] be the wider of the two types.

.. Otherwise if stem:[T_1] and stem:[T_2] are both
<<Types_Floating-Point-Types,floating-point types>>,
then let stem:[T] be the wider of the two types.

.. Otherwise if stem:[T_1] and stem:[T_2] are both
<<Types_String-Types,string types>>, then
then let stem:[T] be `string`.

.. Otherwise the attempted resolution is invalid.
Throw an error.

==== Lists of Type Options

To compute a common type for a list of type options
stem:[O_1, ... , O_n], do the following:

.  Check that stem:[n > 0]. If not, then throw an error.

. Let stem:[O'_1] be stem:[O_1].

.  For each stem:[i in [2,n]], compute the
<<Type-Checking_Computing-a-Common-Type,common type>> stem:[O'_i] of
stem:[O'_(i-1)] and stem:[O_i].

.  Use stem:[O'_n] as the common type of the list.
