//////////////////////////////////////////////////////////////////////////////
// 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

[[lang-tut-values-chapter-if-and-switch]]
== If and switch expressions

In some models one wants to produce different values under different circumstances.
Or one needs to convert from one type to another type.
`if` and `switch` expressions provide means to do this in a concise manner.
This lesson provides an introduction to both these expressions.
For more practical examples, see the <<sbe-in-practice-example-simulation-model,simulation model>> of the synthesis-based engineering example elsewhere in the documentation.

indexterm:[if]
indexterm:[expression,if]
indexterm:[if,expression]

[[lang-tut-values-chapter-if-expression]]
=== If expression

Consider the following expression:

[source, cif]
----
if x > 0: 1 elif x < 0: -1 else 0 end
----

This expression takes a real number `x` and produces its link:https://en.wikipedia.org/wiki/Signum_function[sign].
The `if` expression is used to detect the different situations, and to produce the correct result in each of those situations.

An `if` expression always consist of the `if` and the `else` parts.
In between can optionally be any number of `elif` parts:

[source, cif]
----
if x > 0: 1 elif x < 0: -1 else 0 end
if x > 0: 1 else 0 end
if x > 0: 1 elif x < -10: -2 elif x < 0: -1 else 0 end
----

If the 'guard predicate' of an `if` or `elif` (the expression before the `:`) holds, that alternative is chosen.
In the following example, if `x` has a value of `2` and `y` a value of `3`, then value `-2.8` is produced:

[source, cif]
----
if x > 0 and y = 2: 1.5 elif x > 0 and y != 2 or x < 0: -2.8 else 0.1 end
----

The `if` and `elif` alternatives are considered in order.
The first alternative that has a guard that holds determines what value is produced by the `if` expression.
Consider the following `if` expression:

[source, cif]
----
if x > 0: 1.5 elif x > 0: -2.8 else 0.1 end
----

For any value `x > 0`, this `if` expression produces `1.5`.
It will never produce `-2.8`, as the `if` part is considered before the `elif` part.

indexterm:[switch]
indexterm:[expression,switch]
indexterm:[switch,expression]

[[lang-tut-values-chapter-switch-expression]]
=== Switch expression

Similar to an `if` expression, a `switch` expression can be used to produce different values under different circumstances.
Consider the following partial CIF model:

[source, cif]
----
enum mode = OFF, ON1, ON2, ON3, DISCONNECTED;
automaton rotary_switch:
  disc mode m = OFF;
  ...
end

alg int speed = switch rotary_switch.m:
                  case ON1: 5
                  case ON2: 10
                  case ON3: 15
                  else      0
                end;
end
----

This `switch` expression takes the operation mode `rotary_switch.m` and provides the speed corresponding to that mode.
If the value of `m` matches one of the cases, the `switch` expression will produce the corresponding value.
For example, if `m` has value `ON2`, this `switch` expression produces `10`.
If none of the cases match, the value of the `else` case is taken.
For example, if `m` has value `DISCONNECTED`, this `switch` expression produces `0`.
Note that multiple values can be captured by the `else` case, i.e., you do not have to cover each possible value with a separate case.

One can use different kinds of types as long as the types of the cases match the type of the `switch` expression.
In the example above, `m` is of type `mode`, which is an enumeration.
Hence all cases should be of type `mode` as well.
Below is an example using a ranged integer in the `switch` expression:

[source, cif]
----
alg int[0,2] num_products;

alg string display_text = switch num_products:
                            case 0: "There are no products in the buffer."
                            case 1: "There is one product in the buffer."
                            case 2: "There are two products in the buffer."
                          end;
----

One can also use an automaton as a variable of the `switch` expression, where the cases have to be locations of that automaton:

[source, cif]
----
automaton controller:
  location accelerate: ...
  location decelerate: ...
  location steady: ...
end

alg int acceleration = switch controller:
                         case accelerate:  5
                         case decelerate: -3
                         case steady:      0
                       end;
----

Note that in this `switch` expression we omitted the `else` case, as the three cases together already cover all possible locations of automaton `controller`.

It is possible to rewrite a `switch` expression into an `if` expression (the other way around is not always possible).
This rewrite can be automated using a <<tools-cif2cif-chapter-switches-to-ifs,CIF to CIF transformation>>.
