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
// 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 — ganze Zahlen im Bereich 0..4294967295
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:
0..4294967295 (uint32). Negative Werte und alles darüber werden abgewiesen: enum E: der Wert von A liegt ausserhalb von 0..4294967295. Ein Enum trägt also keine beliebigen int64-Werte.E1.X und E2.X).enum Empty {} — selten sinnvoll, aber erlaubt).enum E { A, A } — derselbe Name doppelt — wird abgewiesen.enum E { A = 1, B = 1 } — zwei Namen auf denselben Wert — ist dagegen erlaubt: als Alias ist das oft gewollt.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.
Ein Tippfehler im Member-Namen ist ein Compile-Fehler: Color.Rrd wird abgewiesen, nicht stillschweigend zu 0.
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:
sema error (line 3): match does not cover variant 'GoAround' — add a case or a wildcard _ => { ... }
Das ist eine Sicherheitsgarantie: Neue Zustände können nicht unbehandelt durchrutschen.
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;
case _ => 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 istdefaultbei zustandsbehafteten Enums ein Compiler-Fehler wenn@dal(A)oder@dal(B)gesetzt ist. Alle Zustände müssen explizit behandelt sein.
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;
case _ => HttpStatus.ServerErr; // Fallback bei unbekanntem Code
};
}
Die KonvertierungintVal as HttpStatusist technisch möglich, aber gefährlich: Der Wert999wäre ein ungültigerHttpStatus. In@dal(A)-Code ist der direkte Cast vonint64zu einem Enum verboten — stattdessen mussParseStatusoder eine vergleichbare Funktion mit explizitemmatchverwendet werden.
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.
Seit 1.0.20A gelten Enum-Werte auch in con-Ausdrücken und in Startwerten globaler Variablen (#1507). Damit lässt sich eine Maske einmal benennen, statt sie an jeder Prüfstelle neu zusammenzusetzen:
enum P { Read = 1, Write = 2, Exec = 4 }
con MASK: int64 := P.Read as int64 | P.Write as int64;
var perms: int64 := P.Read as int64;
fn main(): int64 {
PrintLn("MASK=", IntToStr(MASK), " perms=", IntToStr(perms));
return 0;
}
MASK=3 perms=1
Die Vorwärtsreferenz ist zulässig — das enum darf unter der con-Zeile stehen, die es benutzt.
<WRAP alert>
Vor 1.0.20A ergab genau dieses Muster still 0. Die con-Zeile übersetzte ohne Warnung, MASK war aber 0 — und damit jede Prüfung (wert & MASK) != 0 immer falsch. Wer eine ältere Fassung benutzt, prüft seine Masken nach; der Fehler ist am Quelltext nicht zu sehen.
</WRAP>
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;
}
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 |
| 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-08-09
Codebeispiele geprüft: gegen lyxc 1.2.5C übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die pub fn-Signaturen in aurum/std gehalten, 0 Abweichungen).