====== Lyx – Syntax-Referenz ====== Diese Seite ist die vollständige Syntax-Referenz für Lyx. Sie beschreibt alle lexikalischen Regeln, Operatoren, Kontrollstrukturen und Deklarationsformen. Für konzeptuelle Erläuterungen und Code-Beispiele zu einzelnen Themen existieren eigene Unterseiten (verlinkt am Ende jedes Abschnitts). ===== 1. Lexikalische Regeln ===== ==== Kommentare ==== // Einzeiliger Kommentar – bis zum Zeilenende /* Mehrzeiliger Kommentar Nicht verschachtelbar: /* kein weiterer /* */ hier */ ==== Identifier ==== Bezeichner folgen dem Muster ''[A-Za-z_][A-Za-z0-9_]*''. Lyx ist **case-sensitive**: ''MyVar'', ''myVar'' und ''MYVAR'' sind drei verschiedene Bezeichner. ^ Gültig ^ Ungültig ^ | ''counter'', ''_tmp'', ''Vec2'' | ''2fast'' (beginnt mit Zahl) | | ''MAX_SPEED'', ''isReady'' | ''my-var'' (Bindestrich) | | ''x64'', ''uart0'' | ''for'' (Schlüsselwort) | ==== Schlüsselwörter ==== Reservierte Wörter, die nicht als Identifier verwendet werden dürfen: and as break case class co con continue default dispose do downto else enum extends false fn for if impl import is let limit match mod new nil not or override pub repeat return self struct super to trait true type unit unsafe until var virtual when while ===== 2. Literale ===== ==== Integer-Literale ==== ^ Format ^ Beispiel ^ Typ ^ | Dezimal (Standard) | ''42'', ''-7'' | int64 | | Dezimal mit Suffix | ''42i8'', ''255u8'', ''1000i32'' | wie Suffix | | Hexadezimal | ''0xFF'', ''0x3FF44000'' | int64 (oder mit Suffix) | | Hexadezimal mit Suffix | ''0xFFu8'', ''0x80u32'' | wie Suffix | Integer-Suffixe: ^ Suffix ^ Typ ^ Suffix ^ Typ ^ | (keiner) | int64 | ''u8'' | uint8 | | ''i8'' | int8 | ''u16'' | uint16 | | ''i16'' | int16 | ''u32'' | uint32 | | ''i32'' | int32 | ''u64'' | uint64 | ==== Float-Literale ==== ^ Format ^ Beispiel ^ Typ ^ | Dezimal (Standard) | ''3.14'', ''-0.5'', ''1.0'' | f64 | | Mit Suffix | ''3.14f32'', ''0.0f32'' | f32 | ==== Sonstige Literale ==== ^ Typ ^ Literal ^ Anmerkung ^ | bool | ''true'', ''false'' | | | qbool | ''0.5q'', ''0.0q'', ''1.0q'' | Wahrscheinlichkeitswert 0.0–1.0 | | char | ''%%'a'%%'', ''%%'\n'%%'' | ASCII, ein Zeichen | | pchar | ''"Hallo\n"'' | Nullterminierter String, Typ pchar | | nil | ''nil'' | Null-Pointer für jeden Pointer-Typ | ==== String-Escape-Sequenzen ==== ^ Sequenz ^ Bedeutung ^ | ''\n'' | Zeilenumbruch (LF) | | ''\t'' | Tabulator | | ''\r'' | Wagenrücklauf (CR) | | ''\\'' | Backslash | | ''\"'' | Anführungszeichen | | ''\0'' | Null-Byte (String-Terminator) | ===== 3. Speicherklassen & Variablen ===== Jede Variable in Lyx trägt eine explizite Speicherklasse. Die Klasse bestimmt Mutabilität und Lebenszeit. ^ Keyword ^ Mutabilität ^ Speicherort ^ Beschreibung ^ | ''var'' | Veränderlich | Stack / Data-Segment | Standard-Variable; Wert kann jederzeit geändert werden | | ''let'' | Einmalig | Stack / Data-Segment | Wert wird einmalig zur Laufzeit gesetzt, danach read-only | | ''co'' | Read-only | Stack | Schreibgeschützter Stack-Slot; ähnlich wie ''let'', aber ohne Heap-Zugriff | | ''con'' | Compile-Zeit | Code (Immediate) | Compile-Zeit-Konstante; wird direkt in den Maschinencode eingebettet | ==== Syntax ==== var counter: int64 := 0; // Typ explizit, Wert zugewiesen var name := "Lyx"; // Typ inferiert: pchar let max_val: int64 := ReadConfig(); // Einmalige Zuweisung co PI: f64 := 3.14159265358979; // Stack-Konstante con MAX_BUFFER := 4096; // Compile-Zeit-Konstante (int64 inferiert) * Der Zuweisungsoperator ist immer '':=''. * Typangabe ist optional wenn der Typ aus dem Initialisierer eindeutig inferierbar ist. * ''pub'' vor der Speicherklasse macht die Variable aus anderen Units sichtbar: ''pub var x: int64 := 0;'' ===== 4. Typsystem ===== ==== Primitive Typen ==== ^ Typ ^ Bits ^ Wertebereich ^ | ''int8'' | 8 | −128 … 127 | | ''int16'' | 16 | −32 768 … 32 767 | | ''int32'' | 32 | −2 147 483 648 … 2 147 483 647 | | ''int64'' / ''int'' | 64 | −9 223 372 036 854 775 808 … 9 223 372 036 854 775 807 | | ''uint8'' | 8 | 0 … 255 | | ''uint16'' | 16 | 0 … 65 535 | | ''uint32'' | 32 | 0 … 4 294 967 295 | | ''uint64'' | 64 | 0 … 18 446 744 073 709 551 615 | | ''isize'' | Plattform | Pointer-Größe (signiert) | | ''usize'' | Plattform | Pointer-Größe (unsigniert); Standard für Indizes | | ''f32'' | 32 | IEEE 754 Single | | ''f64'' | 64 | IEEE 754 Double | | ''bool'' | 1 (8 im Speicher) | ''true'', ''false'' | | ''qbool'' | 64 (f64) | Probabilistischer Typ; 0.0 … 1.0 | | ''char'' | 8 | Ein ASCII-Zeichen | | ''pchar'' | 64 (Pointer) | Nullterminierter String (char*) | ==== Pointer-Typen ==== var p: ^int64 := ^x; // Pointer auf int64 (Address-of: ^x) var pp: ^(^int64) := ^p; // Pointer auf Pointer auf int64 var v: ^uint8 := nil; // Null-Pointer p^ := 42; // Dereferenz (Schreiben) PrintInt(p^); // Dereferenz (Lesen) Alle Pointer sind intern 64-Bit-Integer. Der Cast ''ptr as int64'' und ''addr as ^T'' ist explizit möglich. ==== Nullable Typen ==== Das ''?''-Suffix markiert einen Typ als nullable (kann ''nil'' sein): var name: pchar? := GetOptionalName(); // darf nil sein var node: BSTNode? := FindNode(key); ==== Range-Typen ==== type Altitude = int64 range -1000..60000; type Speed = int64 range 0..300; Compile-Zeit: Literale außerhalb des Bereichs → Fehler. Laufzeit: Nicht-konstante Zuweisung → ''panic''. ===== 5. Operatoren ===== ==== Arithmetik ==== ^ Operator ^ Operation ^ Beispiel ^ | ''+'' | Addition | ''a + b'' | | ''-'' | Subtraktion / Negation | ''a - b'', ''-x'' | | ''*'' | Multiplikation | ''a * b'' | | ''/'' | Division (ganzzahlig bei int) | ''a / b'' | | ''mod'' | Modulo (Rest) | ''a mod b'' | | ''++'' | Inkrement (postfix) | ''i++'' | | ''--'' | Dekrement (postfix) | ''i--'' | ==== Vergleich ==== ^ Operator ^ Bedeutung ^ | ''='' | Gleich | | ''!='' | Ungleich | | ''<'' | Kleiner als | | ''>'' | Größer als | | ''<='' | Kleiner oder gleich | | ''>='' | Größer oder gleich | > **Wichtig:** In Lyx ist ''='' der **Vergleichs**operator. Der **Zuweisungs**operator ist '':=''. Es gibt kein ''==''. ==== Logisch & Bitweise ==== ^ Operator ^ Bedeutung ^ Anwendung ^ | ''&'' | Logisches / Bitweises AND | bool-Ausdrücke und Integer-Maskierung | | ''|'' | Logisches / Bitweises OR | bool-Ausdrücke und Integer-Flags | | ''!'' | Logisches NOT | Nur auf bool | | ''~'' | Bitweises NOT (Komplement) | Nur auf Integer | | ''^'' | Bitweises XOR (Infix) | ''a ^ b'' | | ''<<'' | Bitshift links | ''1 << 3'' = 8 | | ''>>'' | Bitshift rechts | ''0x80 >> 4'' = 8 | > **Pointer vs. XOR:** > Das Zeichen ''%%^%%'' hat je nach Position unterschiedliche Bedeutungen: > Präfix (''%%^x%%'') = Address-of-Operator, Postfix (''%%p^%%'') = Dereferenz, Infix (''%%a ^ b%%'') = Bitweises XOR. ==== Spezialoperatoren ==== ^ Operator ^ Name ^ Beschreibung ^ Beispiel ^ | '':='' | Zuweisung | Weist einen Wert zu | ''x := 42'' | | ''|>'' | Pipe | Ergebnis links als erstes Argument rechts | ''val |> Abs()'' | | ''?.'' | Safe Call | Memberzugriff nur wenn nicht nil | ''node?.Next'' | | ''??'' | Null-Coalesce | Fallback wenn nil | ''name ?? "Gast"'' | | ''as'' | Cast | Explizite Typkonvertierung | ''x as f64'' | | ''is'' | Typ-Test | Prüft Laufzeit-Typ | ''obj is Circle'' | | ''..'' | Bereich | In match-Mustern und Range-Typen | ''100..199'' | ==== Operator-Präzedenz (absteigend) ==== ^ Priorität ^ Operatoren ^ Assoziativität ^ | 1 (höchste) | Unär: ''!'', ''~'', ''-'', ''%%^x%%'' (Adresse), ''%%p^%%'' (Deref) | Rechts | | 2 | ''*'', ''/'', ''mod'' | Links | | 3 | ''+'', ''-'' | Links | | 4 | ''%%<<%%'', ''>>'' | Links | | 5 | ''&'' | Links | | 6 | ''^'' (XOR) | Links | | 7 | ''|'' | Links | | 8 | ''='', ''!='', ''<'', ''>'', ''<='', ''>='' | Nicht-assoziativ | | 9 | ''as'', ''is'' | Links | | 10 | ''?.'' | Links | | 11 | ''??'' | Rechts | | 12 | ''|>'' | Links | | 13 (niedrigste) | '':='' | Rechts | ===== 6. Kontrollfluss ===== ==== if / else ==== if (Bedingung) { // ... } else if (andere_Bedingung) { // ... } else { // ... } ''if'' ist kein Ausdruck – es gibt keinen ternären Operator ''?:''. Bedingte Werte werden über ''match'' oder Hilfsfunktionen ausgedrückt. ==== while ==== while (Bedingung) { // ... } // Bounded – garantierte Terminierung while (Bedingung) limit(Konstante) { // ... } ==== for ==== // Aufwärts (inklusive Grenzen) for i := Startwert to Endwert do { // i läuft von Startwert bis einschließlich Endwert } // Abwärts for i := Endwert downto Startwert do { // i läuft von Endwert bis einschließlich Startwert } Die Laufvariable wird automatisch inkrementiert / dekrementiert. Ihr Typ wird vom Compiler inferiert. ''for''-Schleifen sind immer bounded – kein ''limit'' erforderlich. ==== repeat-until ==== repeat { // Körper wird mindestens einmal ausgeführt } until (Abbruchbedingung); // Mit Bounded-Limit repeat { // ... } until (Bedingung) limit(Konstante); ==== break & continue ==== while (true) { if (DoneCondition()) { break; } // verlässt die innerste Schleife if (SkipCondition()) { continue; } // springt zum nächsten Durchlauf } ''break'' und ''continue'' wirken immer auf die **innerste** umgebende Schleife. ==== match ==== match (Ausdruck) { case Wert => Anweisung; case A | B => Anweisung; // OR-Muster case lo..hi => Anweisung; // Bereichsmuster case X when (Guard) => Anweisung; // mit Guard-Bedingung default => Anweisung; } ''match'' kann als Ausdruck verwendet werden (Ergebnis einer Case-Arm-Anweisung). Alle Fälle müssen abgedeckt sein (Exhaustivität). Details: [[lyx_-_programmiersprache:pattern-matching|Pattern Matching]]. ===== 7. Funktionen ===== ==== Deklaration ==== fn FunktionsName(param1: Typ1, param2: Typ2): RückgabeTyp { // Körper return Wert; } * Kein Rückgabewert: Rückgabetyp und ''return'' werden weggelassen (implizit ''void''). * Mehrere Rückgabewerte: Tupel-Syntax ''(Typ1, Typ2)''. * Öffentliche Sichtbarkeit: ''pub'' voranstellen. ==== Beispiele ==== // Einfache Funktion fn Add(a: int64, b: int64): int64 { return a + b; } // Keine Rückgabe (void) fn Log(msg: pchar) { PrintStr(msg); } // Tupel-Rückgabe (mehrere Werte) fn Divide(a: int64, b: int64): (int64, bool) { if (b = 0) { return (0, false); } return (a / b, true); } // Öffentlich pub fn GetVersion(): pchar { return "1.0.0"; } ==== Aufruf ==== var result := Add(3, 4); var (quotient, ok) := Divide(10, 3); if (ok) { PrintInt(quotient); } // Pipe-Operator: Wert als erstes Argument var v := -3.14 |> Abs() |> Round(); → [[lyx_-_programmiersprache:funktionen|Funktionen (vertieft) — Tupel-Rückgabe, anonyme Funktionen, Higher-Order Functions, Pipe-Operator]] ===== 8. Units & Imports ===== Jede Lyx-Quelldatei beginnt mit einer ''unit''-Deklaration. Sie definiert den Namensraum der Datei. unit my_module; import std.io; import std.math; import my_project.utils; * ''unit''-Name und Dateiname müssen übereinstimmen (''my_module.lyx'' → ''unit my_module;''). * ''import'' macht alle ''pub''-Symbole der Ziel-Unit sichtbar. * Standard-Bibliothek: ''std.io'', ''std.math'', ''std.string'', ''std.alloc'', ''std.result'', ''std.error'', … ===== 9. Typdefinitionen ===== ==== struct ==== Stack-allozierte Wertetypen. Zuweisung kopiert den gesamten Wert. type Vec2 = struct { x: f64; y: f64; fn Length(): f64 { return Sqrt(self.x * self.x + self.y * self.y); } fn Scale(factor: f64) { self.x := self.x * factor; self.y := self.y * factor; } }; ==== class ==== Heap-allozierte Referenztypen. ''new'' erzeugt, ''dispose'' gibt frei. type Animal = class { name: pchar; fn Create(n: pchar) { self.name := n; } fn Destroy() { // Aufräum-Logik } virtual fn Speak() { PrintStr(self.name); } }; type Dog = class extends Animal { override fn Speak() { PrintStr("Wuff!"); } }; var d := new Dog("Bello"); d.Speak(); // "Wuff!" dispose d; Schlüsselwörter für Klassen: ^ Keyword ^ Bedeutung ^ | ''extends'' | Einfachvererbung | | ''virtual fn'' | Überschreibbare Methode (V-Table-Eintrag) | | ''override fn'' | Überschreibt eine virtuelle Methode | | ''abstract fn'' | Muss in abgeleiteten Klassen implementiert werden | | ''super.Methode()'' | Aufruf der Eltern-Implementierung | | ''self'' | Referenz auf das aktuelle Objekt | | ''new T(args)'' | Heap-Allokation | | ''dispose ptr'' | Heap-Freigabe | ==== enum ==== enum Richtung { Nord, Sued, Ost, West } enum StatusCode { Ok = 200, NotFound = 404, Error = 500 } // Zugriff über :: var d := Richtung::Nord; var s := StatusCode::Ok; ''match'' über Enums prüft Exhaustivität: Fehlt ein Fall, erzeugt der Compiler einen Fehler. ==== trait & impl ==== trait Printable { fn Print(); fn ToString(): pchar; // muss implementiert werden } type Point = struct { x: int64; y: int64; }; impl Printable for Point { fn Print() { PrintStr(self.ToString()); } fn ToString(): pchar { return FormatStr("(%d, %d)", self.x, self.y); } } Generics mit Trait-Schranken: fn PrintAll(items: [16]T) { for i := 0 to 15 do { items[i].Print(); } } ===== 10. Generics ===== // Generische Funktion fn Max(a: T, b: T): T { if (a > b) { return a; } return b; } // Generischer Struct type Stack = struct { data: [64]T; top: int64; fn Push(val: T) { self.data[self.top] := val; self.top++; } fn Pop(): T { self.top--; return self.data[self.top]; } }; // Mehrere Schranken mit + fn Process(val: T) { val.Print(); } ===== 11. Attribute & Pragmas ===== Attribute beginnen mit ''@'' und stehen unmittelbar vor dem annotierten Element (Unit, Funktion, Variable). ==== Sicherheit & Zertifizierung ==== ^ Attribut ^ Ziel ^ Beschreibung ^ | ''@flight_crit'' | Unit, Fn | Strikte Luftfahrt-Regeln: kein Heap, keine unsafe-Blöcke | | ''@dal(A)''..'@dal(E)'' | Unit, Fn | Design Assurance Level nach DO-178C | | ''@stack_limit(N)'' | Fn | Hartes Stack-Limit in Bytes; geprüft mit ''--stack-check'' | | ''@wcet(N)'' | Fn | WCET-Annotation in Nanosekunden | | ''@redundant'' | Variable | Triple Modular Redundancy (TMR) | | ''@integrity'' | Unit, Fn | Prüfsummen-Überwachung (''scrubbed'' / ''lockstep'') | ==== Performance & Code-Generierung ==== ^ Attribut ^ Ziel ^ Beschreibung ^ | ''@inline'' | Fn | Erzwingt Inlining unabhängig vom Energy-Level | | ''@no_opt'' | Fn | Deaktiviert alle Optimierungen (Timing, Treiber) | | ''@parallel'' | Schleife | Signalisiert SIMD-Vektorisierbarkeit | | ''@energy(1..5)'' | Fn | Steuert Optimierungs-Aggressivität des Backends | | ''@section("name")'' | Fn, Var | Platziert in benannter ELF-Sektion | ==== Interoperabilität ==== ^ Attribut ^ Ziel ^ Beschreibung ^ | ''@extern'' | Fn | Externe C-Funktion (Linkage) | | ''@variadic'' | Fn | Variadische Argumentliste (C-Stil) | | ''@export'' | Fn | Exportiert als C-kompatibles Symbol | | ''@volatile'' | Var | Verhindert Wegoptimieren von Zugriffen (MMIO) | | ''@packed'' | Struct | Kein Padding – exaktes Hardware-Layout | | ''@stdcall'' | Fn | Windows-Aufrufkonvention | ==== Mehrere Attribute kombinieren ==== @flight_crit @dal(B) @stack_limit(512) @wcet(10000) fn ProcessFlightData(val: f64): f64 { @redundant var heading: f64 := val; return Clamp(heading, 0.0, 360.0); } ===== 12. unsafe-Blöcke ===== ''unsafe''-Blöcke heben die Typsicherheits-Garantien für einen begrenzten Bereich auf und erlauben Pointer-Arithmetik und Reinterpret-Casts. unsafe { var ptr: ^uint8 := base + offset; // Pointer-Arithmetik var p32: ^uint32 := ptr as ^uint32; // Reinterpret-Cast var val := p32^; // Dereferenz berechneter Adresse } In Modulen mit ''@dal(A)'' oder ''@dal(B)'' erzeugt ''unsafe'' einen Compiler-Fehler. ===== 13. Sonderzeichen & Strukturregeln ===== ^ Zeichen ^ Bedeutung ^ | '';'' | Statement-Terminator (Pflicht am Zeilenende) | | '':'' | Typ-Trenner in Deklarationen (''name: Typ'') | | ''{ }'' | Block-Begrenzer für Funktionskörper, Schleifen, Bedingungen | | ''( )'' | Ausdruck-Gruppierung; Pflicht in ''if'', ''while'', ''match'' | | ''[ ]'' | Array-Index (''arr[i]'') und Array-Typ (''[N]T'') | | ''.'' | Memberzugriff (''obj.field'', ''obj.Method()'') | | ''::'' | Enum-Wert-Zugriff (''Status::Ok'') | | '','' | Trennzeichen in Parameterlisten und Tupeln | | ''%%^%%'' | Präfix: Address-of (''%%^x%%''); Postfix: Deref (''%%p^%%''); Infix: XOR (''%%a ^ b%%'') | | ''@'' | Attribut-Präfix (''@inline'', ''@dal(A)'') | ==== Semikolons ==== Semikolons sind in Lyx **Pflicht** als Statement-Abschluss. Sie können nicht weggelassen werden: var x: int64 := 42; // ✅ var y: int64 := 10 // ✗ Compiler-Fehler: fehlendes ; Ausnahme: Nach ''}''-Blöcken (Funktionskörper, if, while) wird kein Semikolon benötigt. ===== 14. Vollständige Grammatik-Übersicht (kompakt) ===== Program → (Unit Import* Decl*)? Unit → 'unit' Ident ';' Import → 'import' QualIdent ';' Decl → VarDecl | FnDecl | TypeDecl | TraitDecl | ImplDecl VarDecl → Modifier? StorageClass Ident (':' Type)? ':=' Expr ';' StorageClass → 'var' | 'let' | 'co' | 'con' Modifier → 'pub' FnDecl → Attr* Modifier? 'fn' Ident GenericParams? '(' Params ')' (':' Type)? Block Params → (Ident ':' Type (',' Ident ':' Type)*)? TypeDecl → 'type' Ident GenericParams? '=' ('struct' | 'class' ('extends' Ident)?) '{' Member* '}' EnumDecl → 'enum' Ident '{' (Ident ('=' IntLit)? (',' Ident ('=' IntLit)?)*)? '}' TraitDecl → 'trait' Ident '{' FnSignature* '}' ImplDecl → 'impl' Ident 'for' Ident '{' FnDecl* '}' Block → '{' Stmt* '}' Stmt → VarDecl | ExprStmt | IfStmt | WhileStmt | ForStmt | RepeatStmt | MatchStmt | ReturnStmt | BreakStmt | ContinueStmt | UnsafeBlock IfStmt → 'if' '(' Expr ')' Block ('else' 'if' '(' Expr ')' Block)* ('else' Block)? WhileStmt → 'while' '(' Expr ')' ('limit' '(' IntLit ')')? Block ForStmt → 'for' Ident ':=' Expr ('to' | 'downto') Expr 'do' Block RepeatStmt → 'repeat' Block 'until' '(' Expr ')' ('limit' '(' IntLit ')')? ';' MatchStmt → 'match' '(' Expr ')' '{' MatchArm* '}' MatchArm → ('case' Pattern ('when' '(' Expr ')')? | 'default') '=>' Stmt ';' Expr → ... (vollständige Präzedenz-Hierarchie; siehe Abschnitt 5) **Weiterführende Seiten:** * [[lyx_-_programmiersprache:datentypen|Datentypen – vollständige Typ-Referenz]] * [[lyx_-_programmiersprache:erste-schritte|Erste Schritte – Einführung mit Beispielen]] * [[lyx_-_programmiersprache:pattern-matching|Pattern Matching – match im Detail]] * [[lyx_-_programmiersprache:oop|OOP – Klassen, Traits, Generics]] * [[lyx_-_programmiersprache:pointer-inlining|Pointer & Inlining – ^T, unsafe, @inline]] * [[lyx_-_programmiersprache:attributes-pragmas|Attribute & Pragmas – vollständige @-Referenz]] * [[lyx_-_programmiersprache:ffi|FFI – @extern, @export, @packed]]