Inhaltsverzeichnis

Enums — Aufzählungstypen

Ein enum definiert einen Typ, dessen gültige Werte eine abgeschlossene, benannte Menge bilden. Der Compiler kennt alle Werte zur Compile-Zeit — das ist die Grundlage der Exhaustivitätsprüfung in match: Wird ein Enum-Wert nicht behandelt, ist es ein Fehler, keine Warnung.

Enums sind in Lyx ganzzahlige Typen (intern int64) mit benannten Konstanten. Sie haben keine Methoden und keine Vererbung — ihr einziger Zweck ist die typsichere Zustandsdarstellung.

Pattern Matching · Datentypen · DO-178C


1. Deklaration

// Einfachster Fall: Werte beginnen bei 0 und zählen aufwärts
enum Direction { North, South, East, West }
// North=0, South=1, East=2, West=3

// Explizite Werte — beliebige int64-Konstanten
enum HttpStatus {
    Ok        = 200,
    Created   = 201,
    NotFound  = 404,
    ServerErr = 500
}

// Gemischt: erste Konstante setzt den Startwert, die folgenden zählen weiter
enum Priority {
    Low    = 1,
    Medium,     // = 2
    High,       // = 3
    Critical    // = 4
}

Regeln:


2. Verwendung

Ein einfaches Anwendungsbeispiel:

enum Color { Red, Green, Blue }

// Variablendeklaration
var c: Color := Color::Red;

// Übergabe als Parameter
fn PrintColor(col: Color): void {
    match (col) {
        case Color::Red   => Print("Rot\n");
        case Color::Green => Print("Grün\n");
        case Color::Blue  => Print("Blau\n");
    }
}

// Rückgabe aus Funktion
fn OppositeDirection(d: Direction): Direction {
    return match (d) {
        case Direction::North => Direction::South;
        case Direction::South => Direction::North;
        case Direction::East  => Direction::West;
        case Direction::West  => Direction::East;
    };
}

Der Zugriff auf einen Enum-Wert erfolgt immer mit EnumName::Wert — der Namespace-Qualifier ist Pflicht. Das verhindert Namenskollisionen zwischen verschiedenen Enums.


3. Enums und match

Die Stärke von Enums zeigt sich in Kombination mit match: Der Compiler erzwingt, dass jeder mögliche Wert behandelt wird.

enum FlightPhase {
    Preflight, Taxiing, Takeoff, Climbing,
    Cruise, Descending, Approach, Landing, Rollout
}

fn PhaseToString(p: FlightPhase): pchar {
    return match (p) {
        case FlightPhase::Preflight  => "Vor dem Start";
        case FlightPhase::Taxiing    => "Rollen";
        case FlightPhase::Takeoff    => "Start";
        case FlightPhase::Climbing   => "Steigflug";
        case FlightPhase::Cruise     => "Reiseflug";
        case FlightPhase::Descending => "Sinkflug";
        case FlightPhase::Approach   => "Anflug";
        case FlightPhase::Landing    => "Landung";
        case FlightPhase::Rollout    => "Ausrollen";
    };
}

Wird später FlightPhase::GoAround hinzugefügt, meldet der Compiler:

error: non-exhaustive match — FlightPhase::GoAround not covered
  --> flight_ctrl.lyx:12:12
  hint: add 'case FlightPhase::GoAround =>' or a 'default =>' arm

Das ist eine Sicherheitsgarantie: Neue Zustände können nicht unbehandelt durchrutschen.

Wann default erlaubt ist

default unterdrückt die Exhaustivitätsprüfung. Das ist explizit erlaubt, aber sparsam einsetzen:

fn IsErrorStatus(s: HttpStatus): bool {
    return match (s) {
        case HttpStatus::ServerErr => true;
        default                    => false;
        // Explizite Entscheidung: alle nicht genannten Werte sind "kein Fehler"
        // Risiko: neuer Wert wie HttpStatus::GatewayTimeout wird stillschweigend false
    };
}

In DO-178C DAL-A/B-Code ist default bei zustandsbehafteten Enums ein Compiler-Fehler wenn @dal(A) oder @dal(B) gesetzt ist. Alle Zustände müssen explizit behandelt sein.

4. Enum als Integer

Intern ist jeder Enum-Wert ein int64. Die explizite Konvertierung erfolgt mit as:

enum HttpStatus { Ok = 200, NotFound = 404, ServerErr = 500 }

// Enum → int64
var code: int64 := HttpStatus::Ok as int64;   // 200

// int64 → Enum (unsafe: der Compiler prüft den Wert nicht)
var s: HttpStatus := 404 as HttpStatus;

// In der Praxis: Wert aus Netzwerk empfangen, in Enum konvertieren
fn ParseStatus(raw: int64): HttpStatus {
    return match (raw) {
        case 200 => HttpStatus::Ok;
        case 404 => HttpStatus::NotFound;
        case 500 => HttpStatus::ServerErr;
        default  => HttpStatus::ServerErr;   // Fallback bei unbekanntem Code
    };
}

Die Konvertierung intVal as HttpStatus ist technisch möglich, aber gefährlich: Der Wert 999 wäre ein ungültiger HttpStatus. In @dal(A)-Code ist der direkte Cast von int64 zu einem Enum verboten — stattdessen muss ParseStatus oder eine vergleichbare Funktion mit explizitem match verwendet werden.

5. Bit-Flag-Enums

Für Bit-Masken werden Enums mit Zweierpotenzen als Werte deklariert und mit Integer-Operatoren kombiniert:

enum Permission {
    Read    = 0x01,   // Bit 0
    Write   = 0x02,   // Bit 1
    Execute = 0x04,   // Bit 2
    Admin   = 0x08    // Bit 3
}

// Mehrere Flags kombinieren (als int64 — nicht als Permission)
var perms: int64 := Permission::Read as int64 | Permission::Write as int64;

// Flag prüfen
fn HasPermission(perms: int64, flag: Permission): bool {
    return (perms & (flag as int64)) != 0;
}

fn main(): int64 {
    var p: int64 := Permission::Read as int64 | Permission::Execute as int64;
    if (HasPermission(p, Permission::Write)) {
        PrintLn("Schreiben erlaubt");
    } else {
        Print("Kein Schreibzugriff\n");   // Dieser Zweig wird ausgeführt
    }
    return 0;
}

Bit-Flag-Enums werden immer als int64 kombiniert — Lyx bietet keinen speziellen Bitset-Typ. Das ist ein bewusstes Design: Bitoperationen sind explizit und direkt im Code sichtbar.


6. Enums in Datenstrukturen

Enums als Felder in Structs und als Array-Elemente:

import std.alloc;

enum State { Idle, Running, Paused, Stopped }

// Enum-Feld in einem alloc'd Puffer (Offset-Muster)
pub con TASK_SIZE:  int64 := 24;
pub con TASK_STATE: int64 := 0;   // State als int64 gespeichert
pub con TASK_ID:    int64 := 8;
pub con TASK_PRIO:  int64 := 16;

fn TaskCreate(id: int64, prio: int64): int64 {
    var t: int64 := alloc(TASK_SIZE);
    if (t == 0) { return 0; }
    poke64(t + TASK_STATE, State::Idle as int64);
    poke64(t + TASK_ID,    id);
    poke64(t + TASK_PRIO,  prio);
    return t;
}

fn TaskGetState(t: int64): State {
    return peek64(t + TASK_STATE) as State;
}

fn TaskSetState(t: int64, s: State): void {
    poke64(t + TASK_STATE, s as int64);
}

fn TaskIsRunning(t: int64): bool {
    return TaskGetState(t) == State::Running;
}


7. Enums in Safety-Code

Enums sind ein bevorzugtes Mittel in sicherheitskritischem Code, weil sie den Zustandsraum explizit und abgeschlossen definieren:

@flight_crit(DAL-A)
enum EngineState {
    Off        = 0,
    Starting   = 1,
    Idle       = 2,
    Running    = 3,
    Overspeed  = 4,
    Shutdown   = 5
}

@flight_crit(DAL-A)
fn EngineTransition(current: EngineState, cmd: EngineCommand): EngineState {
    // Vollständige Zustandsmaschine — kein default, alle Kombinationen explizit
    return match (current) {
        case EngineState::Off      => match (cmd) { ... };
        case EngineState::Starting => match (cmd) { ... };
        case EngineState::Idle     => match (cmd) { ... };
        case EngineState::Running  => match (cmd) { ... };
        case EngineState::Overspeed => EngineState::Shutdown;   // immer herunterfahren
        case EngineState::Shutdown => EngineState::Off;
    };
}

Eigenschaft Enum int64-Konstanten
Compiler-Exhaustivitätsprüfung ✅ Ja ❌ Nein
Typsicherheit im Parameter ✅ Ja ❌ Nein (jede int64 passt)
Dokumentation im Code ✅ Explizite Namen Eingeschränkt
Gültigkeitsbereich Pro Enum getrennt Global
DO-178C geeignet ✅ Empfohlen für Zustände Bedingt

8. Zusammenfassung

Frage Antwort
Basistyp int64 (immer)
Zugriffssyntax EnumName::Wert
Methoden Nicht unterstützt
Enum → int64 val as int64
int64 → Enum intVal as EnumTyp (unsafe — Wert unklar)
match-Exhaustivität Pflicht ohne default
In Safety-Code Enums für alle Zustände bevorzugen, kein default
Bit-Flags Werte als Zweierpotenzen; kombinieren als int64

Pattern Matching — match, Guards, Exhaustivität
Datentypen — vollständige Typübersicht
Typ-Aliase und Typumwandlung (as, is)

Letzte Aktualisierung: 2026-06-05