//////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2010, 2026 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available
// under the terms of the MIT License which is available at
// https://opensource.org/licenses/MIT
//
// SPDX-License-Identifier: MIT
//////////////////////////////////////////////////////////////////////////////

include::../_part_attributes.asciidoc[]

:leveloffset: -2

[[tools-cif2cif-chapter-merge-enums]]
== Merge enumerations

indexterm:[CIF to CIF transformer,merge enumerations]
indexterm:[merge enumerations]
indexterm:[enumeration,merge]
This CIF to CIF transformation merges all enumerations together to a single enumeration.

See also: <<tools-cif2cif-chapter-enums-to-ints>> and <<tools-cif2cif-chapter-enums-to-consts>>.

indexterm:[merge enumerations,supported specifications]

=== Supported specifications

This transformation supports a subset of CIF specifications.
The following restrictions apply:

* Component definitions and component instantiations are not supported.

indexterm:[merge enumerations,preprocessing]

=== Preprocessing

To increase the subset of specifications that can be transformed, apply the following <<tools-cif2cif-chapter-index,CIF to CIF transformations>> (in the given order) prior to using this transformation:

* <<tools-cif2cif-chapter-elim-comp-def-inst>>

The following <<tools-cif2cif-chapter-index,CIF to CIF transformations>> are automatically applied as preprocessing (in the given order), to increase the subset of CIF specifications that can be transformed:

* <<tools-cif2cif-chapter-add-default-init-values>>

indexterm:[merge enumerations,implementation]

=== Implementation details

If there are any enumerations in the specification, a single new enumeration is created.
This enumeration is named `E`.
All literals of the original enumerations are added to this new enumeration.
Obviously, duplicate literals are only included once.
The literals are added in sorted order.

The original enumerations are removed.

For instance, the following specification:

[source, cif]
----
enum A = B, C;

automaton p:
  enum A = C, B;
  enum X = D, C;
  disc A a = C;
  disc X x = D;
  location:
    initial;
end
----

is transformed to the following specification:

[source, cif]
----
enum E = B, C, D;

automaton p:
  disc E a = C;
  disc E x = D;
  location:
    initial;
end
----

indexterm:[merge enumerations,renaming]

=== Renaming

The newly created enumeration `E` and its literals, may conflict with declarations already present in the specification.
If this is the case, they are renamed.
For instance, if `E` is already in use, `E2`, or `E3`, etc, is used instead.
If renaming is performed, a warning is printed to the console.

In general, renaming of enumeration literals may influence value equality for _compatible_ enumerations (enumerations with the same number of literals, with the same names, in the same order).
However, since the resulting specification has at most one enumeration, there are no multiple enumerations, and thus compatibility is not an issue (since the enumeration is always compatible with itself).

indexterm:[merge enumerations,default initial values]

=== Default initial values

Consider the following specification:

[source, cif]
----
group g1:
  enum e1 = A, B;
end

group g2:
  enum e2 = B, A;
end

automaton p:
  disc g1.e1 v1;
  disc g2.e2 v2;

  location:
    initial;
end
----

If we apply merging of enumerations directly, we get the following:

[source, cif]
----
enum E = A, B;

group g1:
end

group g2:
end

automaton p:
  disc E v1;
  disc E v2;

  location:
    initial;
end
----

In the original specification, `v1` had value `A`, and `v2` had value `B`.
After the merging of the enumerations, both `v1` and `v2` have implicit initial value `A`.
Thus, they had different initial values beforehand, and the same initial values afterward.
To solve this problem, the <<tools-cif2cif-chapter-add-default-init-values>> CIF to CIF transformation is automatically applied as preprocessing before the actual elimination of the enumerations, to ensure that the explicit initial values are properly transformed.

indexterm:[merge enumerations,switch expressions]

=== Switch expressions

Consider the following specification:

[source, cif]
----
enum E1 = A, B;
enum E2 = C, D;

input E1 i;
invariant switch i:
            case A: true
            case B: false
          end;
----

After merging the enumerations, the single merged enumeration has four literals (`A`, `B`, `C` and `D`).
The `switch` expression is then incomplete, as it does not cover the extra literals from `E2` (`C` and `D`) that got merged with `E1`.
To ensure that `switch` expressions remain complete and valid, all `switch` expressions that switch over a value that has a type that includes an enumeration type, but do not have an `else`, are modified.
Their last `case` is converted to an `else`, removing the key of the `case` in the process.
For the example above, this results in:

[source, cif]
----
enum E = A, B, C, D;

input E i;
invariant switch i:
            case A: true
            else    false
          end;
----

indexterm:[merge enumerations,size considerations]

=== Size considerations

Since enumerations are merged, duplicate literals become a single new literal.
Therefore, this transformation may decrease the size of the specification.

The added default initial values may significantly increase the size of the specification.

Removing the key of the last `case` of a `switch` expressions may slightly decrease the size of the specification.

=== Optimality

n/a

=== Annotations

This transformation does not process or add any specific annotations.
The annotations of enumerations are removed.
The annotations of enumeration literals are moved to the merged literals.
