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).
// Einzeiliger Kommentar – bis zum Zeilenende
/* Mehrzeiliger Kommentar
Nicht verschachtelbar: /* kein weiterer /* */ hier */
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) |
Reservierte Wörter, die nicht als Identifier verwendet werden dürfen:
abstract and array as assert
break case catch class co
con continue default dim dispose
do downto else enum extends
extern false finally fn for
if implements import in interface
is layout let Map match
new not null or override
panic parallel pool private protected
pub public repeat return RingBuffer
self Set signal static struct
super switch throw to true
try type unit until utype
var virtual where while widget
Zwei Sonderfälle:
self steht nicht in der Keyword-Tabelle des Lexers, sondern wird im Parser gesondert behandelt — reserviert ist es dennoch.char steht umgekehrt in der Keyword-Tabelle, lässt sich aber als Bezeichner verwenden: es ist ein Typname, kein reserviertes Wort.to ist reserviert und fällt in der Praxis auf, sobald jemand ein Paar from/to als Parameternamen schreibt: fn f(to: int64) bricht mit Parse error: expected IDENT, got reserved word 'to' ab. from ist frei — nur to nicht.Nicht reserviert, auch wenn ältere Fassungen dieser Seite das behaupteten:flat,packed,check,limitundSelf. Alle fünf sind als Bezeichner verwendbar.
defaultist zwar reserviert, inmatchaber nicht verwendbar — der Wildcard-Fall lautetcase _ ⇒. Guards werden mitifgeschrieben (case p if cond ⇒), nicht mitwhen;whenist kein Schlüsselwort.
Soft Keywords — als Bezeichner tokenisiert und nur im jeweiligen Kontext wirksam: range, wraps, defer, limit, grant, restrict, ref. limit wird nur unmittelbar hinter der Bedingung eines while und vor dem Block erkannt, gefolgt von (; überall sonst ist es ein gewöhnlicher Bezeichner.
Die Liste der 70 reservierten Wörter steht seit lyxc 1.1.3H auch in der normativen Grammatik (ebnf.md, Abschnitt 2.1) und wird dort von tests/schluesselwoerter_test.sh bei jedem Testlauf gegen den Compiler geprüft — jedes harte Wort muss abgewiesen, jedes weiche angenommen werden (#1653). Der Parser nennt seitdem auch den Anlass:
Parse error at line 1: expected IDENT, got reserved word 'unit'
ref gilt nur unmittelbar vor einem Parameternamen, auf den ein Doppelpunkt folgt. Überall sonst bleibt es ein gewöhnlicher Bezeichner — var ref := 5 und ein Parameter namens ref: int64 sind beide zulässig.
| Format | Beispiel | Typ |
|---|---|---|
| Dezimal | 42, -7 | int64 |
| Dezimal mit Ziffern-Trenner | 1_000, 9_000_000_000 | int64 |
| Hexadezimal | 0xFF, 0x3FF44000 | int64 |
| Binär | 0b1010 | int64 |
| Oktal | 0o755 | int64 |
Typsuffixe gibt es nicht. Schreibweisen mit angehängtem Typkürzel (42+i8,255+u8,1000+i32) sind ein Syntaxfehler. Der Zieltyp wird über die Deklaration bestimmt:var b: uint8 := 255;
| Format | Beispiel | Typ |
|---|---|---|
| Dezimal | 3.14, -0.5, 1.0 | f64 |
| Mit Ziffern-Trenner | 3.14_159, 1_000.5 | f64 |
| Wissenschaftlich | 1.0e-9, 1.0e9 | f64 |
Auch hier kein Suffix:3.14f32ist ungültig. Fürf32die Deklaration nutzen —var x: f32 := 3.14;
Sehr kleine Literale werden korrekt übersetzt — mit 1.1.0A nachgemessen (#1569 behoben):
^ Literal ^ Bitmuster ^
|1.0e-25| 4233087679066701273 |
|1.0e-27| 4202930039008934928 |
|1.0e-28| 4188260752279232537 |
Ältere Fassungen dieser Seite beschrieben eine Grenze bei Exponent −28, ab der solche Literale stillschweigend zu null wurden. Die gibt es nicht mehr; der dort empfohlene Umweg über eine Division ist unnötig.
Bei1.0e-30liegt das Ergebnis noch ein ULP unter dem exakten Wert. Für Toleranzrechnungen belanglos — wer Bitmuster vergleicht, prüft es mitFeqBitsaus std.feq.
| Typ | Literal | Anmerkung |
|---|---|---|
| bool | true, false | |
| char | 'a', '\n' | ASCII, ein Zeichen |
| pchar | „Hallo\n“ | Nullterminierter String, Typ pchar |
| null | null | Entspricht der Adresse 0 |
| Sequenz | Bedeutung |
|---|---|
\n | Zeilenumbruch (LF) |
\t | Tabulator |
\r | Wagenrücklauf (CR) |
\\ | Backslash |
\„ | Anführungszeichen |
\0 | Null-Byte (String-Terminator) |
→ Ausführlich: Variablen — Startwerte, Typableitung, Gültigkeitsbereich, Modulebene, Lebensdauer. Speicher und Lebensdauer vertieft Memory Management.
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 |
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)
:=.var name := „Lyx“; ergibt pchar) und bei new (var p := new Point();).pub vor der Speicherklasse macht die Variable aus anderen Units sichtbar: pub var x: int64 := 0;let und co müssen bei der Deklaration belegt werden. Eine spätere Zuweisung ist keine „einmalige“ mehr, sondern wird abgewiesen: assignment to let/co binding not allowed. let x: int64; ohne Initialisierer übersetzt zwar, ergibt aber einen Slot, der nie einen Wert bekommen kann.con verlangt einen zur Compile-Zeit auswertbaren Ausdruck. Ein Funktionsaufruf wird abgelehnt (function call not allowed in const expression); die Ableitung aus anderen con-Werten ist erlaubt (con B: int64 := A * 2;). Eine Zuweisung an con meldet assignment to con constant not allowed.| 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 |
f32 | 32 | IEEE 754 Single |
f64 | 64 | IEEE 754 Double |
bool | 1 (8 im Speicher) | true, false |
char | 8 | Ein ASCII-Zeichen |
pchar | 64 (Pointer) | Nullterminierter String (char*) |
void | – | Kein Rückgabewert |
isizeundusizestanden hier früher ebenfalls; der Compiler kennt sie nicht (unknown type in var decl). Für Indizes und Größenangabenint64bzw.uint64verwenden. Ebenso entfallen istqbool— der Typ existiert nicht.
Lyx hat keinen Pointer-Typ in der Typgrammatik. Es gibt weder ^T als Typangabe noch einen Address-of-Operator (^x bzw. &x) oder einen Dereferenz-Operator (p^). Adressen werden als int64 geführt, der Zugriff läuft über Builtins:
var cell: int64 := alloc(8); // 8 Byte anfordern
poke64(cell, 42); // schreiben
var v: int64 := peek64(cell); // lesen
free(cell, 8);
| Builtin | Bedeutung |
|---|---|
alloc(n) / free(p, n) | Speicher anfordern / freigeben — die Größe ist bei free Pflicht |
peek8/16/32/64(p) | Wert an Adresse lesen |
poke8/16/32/64(p, v) | Wert an Adresse schreiben |
Ein Ausgabeparameter wird als Zelle übergeben: alloc(8), Adresse an die Funktion, danach peek64.
Das ?-Suffix markiert einen Typ als nullable — er darf zusätzlich null annehmen:
var x: int64? := null;
var name: pchar? := null;
Für den Zugriff auf möglicherweise nicht gesetzte Werte gibt es den Safe-Access-Operator ?. — er liefert den Feldwert, ohne bei null zu dereferenzieren:
var a: A := new A();
a.v := 3;
var x: int64 := a?.v; // 3
type Altitude = int64 range -1000..60000;
type Speed = int64 range 0..300;
Die Grenzen werden auf zwei Ebenen durchgesetzt:
con, konstanter Ausdruck), meldet der Compiler einen Fehler: Wert liegt ausserhalb des Bereichs des Typs.Bereichstyp <Name>: Wert ausserhalb ab.Die Laufzeitprüfung greift überall dort, wo ein Wert den Bereichstyp annimmt — bei Zuweisung, als Parameter, als Rückgabewert und beim Schreiben in ein Strukturfeld:
type Alt = int64 range 0..100;
fn Setze(a: Alt): int64 { return a; }
fn Hole(): Alt { var x: int64 := 500; return x; } // bricht ab
type S = struct { a: Alt; };
fn main(): int64 {
var x: int64 := 500;
var a: Alt := x; // bricht ab
Setze(x); // bricht ab
var s: S;
s.a := x; // bricht ab
return 0;
}
| Operator | Operation | Beispiel |
|---|---|---|
+ | Addition | a + b |
- | Subtraktion / Negation | a - b, -x |
* | Multiplikation | a * b |
/ | Division (ganzzahlig bei int) | a / b |
% | Modulo (Rest) | a % b |
++ | Inkrement (postfix) | i++ |
– | Dekrement (postfix) | i– |
| Operator | Bedeutung |
|---|---|
== | Gleich |
!= | Ungleich |
< | Kleiner als |
> | Größer als |
⇐ | Kleiner oder gleich |
>= | Größer oder gleich |
in | Bereichsprüfung: x in 1..10 — beide Grenzen zählen mit |
Wichtig: Der Vergleichsoperator ist==, der Zuweisungsoperator:=. In einer Bedingung wird ein einzelnes=abgewiesen —if (x = 0)meldetParse error at line N: expected ), got = '='. Damit ist die in C klassische versehentliche Zuweisung in einer Bedingung strukturell ausgeschlossen.
Auch als eigenständige Anweisung wird=abgewiesen (#1575 behoben).x = 42;meldet mit 1.1.2EParse error at line N: `=` ist kein Zuweisungsoperator — gemeint ist `:=`. Ein=im Code ist damit nur noch ein Parametervorgabewert.
| Operator | Bedeutung | Anwendung |
|---|---|---|
&& | Logisches AND mit Kurzschluss | Bedingungen; rechte Seite nur bei wahrer linker |
|| | Logisches OR mit Kurzschluss | Bedingungen; rechte Seite nur bei falscher linker |
& | Logisches / Bitweises AND | bool-Ausdrücke und Integer-Maskierung; wertet immer beide Seiten |
| | Logisches / Bitweises OR | bool-Ausdrücke und Integer-Flags; wertet immer beide Seiten |
! | Logisches NOT | Nur auf bool |
~ | Bitweises NOT (Komplement) | Nur auf Integer |
^ | Bitweises XOR (Infix) | a ^ b |
|~ | Bitweises NOR | 12 |~ 10 = -15 — gleichbedeutend mit ~(12 | 10) |
« | Bitshift links | 1 « 3 = 8 |
» | Bitshift rechts, arithmetisch | 0x80 » 4 = 8; -16 » 2 = -4 |
Zwei Eigenheiten beim Schieben.
*>>zieht das Vorzeichenbit nach.-16 >> 2ergibt-4,-1 >> 1bleibt-1. Ein logisches Rechtsschieben, bei dem Nullen nachrücken, erhält man über die Umdeutung:(wert as uint64) >> n. Die Standardbibliothek nutzt genau diese Form, etwa inSwapEndian32.
* Die Schiebeweite wird modulo 64 genommen.1 << 64ergibt1,1 << 65ergibt2,1 << -1ergibt das Vorzeichenbit. Das entspricht dem Verhalten der Prozessorbefehle; eine Warnung gibt es nicht. Stammt die Weite aus einer Rechnung, ist sie vorher gegen0…63zu prüfen.
^ist ausschließlich XOR. Ältere Fassungen dieser Seite nannten zusätzlich einen Präfix-Gebrauch (^xals Adresse von x) und einen Postfix-Gebrauch (p^als Dereferenz). Beide gibt es nicht —^xergibtexpected expression, und einen Zeigertyp führt die Typgrammatik ohnehin nicht.6 ^ 3ergibt5.
| 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 null | node?.Next |
?? | Null-Coalesce | Fallback wenn null | 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 |
| Priorität | Operatoren | Assoziativität |
|---|---|---|
| 1 (höchste) | Unär: !, ~, - | Rechts |
| 2 | *, /, % | 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 |
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 (Bedingung) {
// ...
}
// Bounded – garantierte Terminierung
while (Bedingung) limit(Konstante) {
// ...
}
// 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
}
// C-Stil — ohne Klammern, ohne var
for i := 0; i < n; i++ {
// ...
}
// Bereichsform (seit 1.0.14), beide Grenzen einschließend
for i in 0..3 {
// i läuft 0, 1, 2, 3
}
for … in erwartet einen Bereich, keine Sammlung — for v in a über ein Array wird mit for … in erwartet einen Bereich abgewiesen.
Die Laufvariable wird automatisch inkrementiert / dekrementiert. Ihr Typ wird vom Compiler inferiert. for-Schleifen sind immer bounded – kein limit erforderlich.
repeat {
// Körper wird mindestens einmal ausgeführt
} until (Abbruchbedingung);
// Mit Bounded-Limit
repeat {
// ...
} until (Bedingung) limit(Konstante);
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 (Ausdruck) {
case Wert => Anweisung;
case A | B => Anweisung; // OR-Muster
case X if (Guard) => Anweisung; // mit Guard-Bedingung
case _ => Anweisung;
}
Bereichsmuster werden alscase lo..hi ⇒geschrieben; beide Grenzen zählen mit. Die obere Grenze darf entfallen (case lo.. ⇒).
match kann als Ausdruck verwendet werden (Ergebnis einer Case-Arm-Anweisung). Alle Fälle müssen abgedeckt sein (Exhaustivität). Details: Pattern Matching.
fn FunktionsName(param1: Typ1, param2: Typ2): RückgabeTyp {
// Körper
return Wert;
}
return werden weggelassen (implizit void).(Typ1, Typ2).pub voranstellen.
// Einfache Funktion
fn Add(a: int64, b: int64): int64 {
return a + b;
}
// Keine Rückgabe (void)
fn Log(msg: pchar) {
Print(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";
}
var result := Add(3, 4);
var quotient, ok := Divide(10, 3);
if (ok) { Print(IntToStr(quotient)); }
// Pipe-Operator: Wert als erstes Argument
var v := -3.14 |> Abs() |> Round();
→ Funktionen (vertieft) — Tupel-Rückgabe, anonyme Funktionen, Higher-Order Functions, Pipe-Operator
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.std.io, std.math, std.string, std.alloc, std.result, std.error, …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;
}
};
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() {
Print(self.name);
}
};
type Dog = class extends Animal {
override fn Speak() {
Print("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 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.
type Druckbar = interface {
fn Zeige(): int64;
};
type Punkt = class implements Druckbar {
x: int64;
y: int64;
fn Zeige(): int64 { return self.x + self.y; }
};
Fehlt eine der Signaturen in der Klasse, meldet der Compiler class missing interface method. trait und impl gibt es nicht.
Generics mit Trait-Schranken:
fn PrintAll<T: Printable>(items: [16]T) {
for i := 0 to 15 do {
items[i].Print();
}
}
dim benennt eine physikalische Dimension, utype eine Einheit darin, zusammen mit ihrem Faktor bezogen auf die Basiseinheit. Dimensionen lassen sich aus anderen ableiten:
dim Laenge;
dim Zeit;
dim Geschwindigkeit = Laenge / Zeit; // * und / sind erlaubt
utype Meter: Laenge = 1;
utype Kilometer: Laenge = 1000;
utype MeterProSekunde: Geschwindigkeit = 1.0; // Faktor auch als Float
fn main(): int64 {
var strecke: Kilometer := 2;
PrintLn(IntToStr(strecke as int64));
return 0;
}
Die Standardbibliothek bringt mit std.units rund 40 fertige Einheiten mit.
Die Dimensionsprüfung greift: Eine Länge lässt sich weder einer Zeit zuweisen noch mit ihr verrechnen.
var m: Meter := 5;
var s: Sekunde := m; // sema error: Zuweisung ueber Dimensionsgrenzen hinweg
var x: Meter := m + s; // sema error: Einheitentypen verschiedener Dimension verrechnet
var a: Meter := 500;
var b: Kilometer := 1;
var summe: Meter := a + b; // 1500 — der Faktor wirkt
if (a > b) { } // falsch — 500 m sind weniger als 1 km
var c: Meter := b; // 1000
Auch die abgeleitete Dimension wird geprüft: aus dim Tempo = Laenge / Zeit; folgt, dass meter / sekunde ein Tempo ist — die Zuweisung an eine Länge wird mit Zuweisung ueber Dimensionsgrenzen hinweg abgewiesen. Ein as-Cast über Dimensionsgrenzen ebenfalls; die Meldung verweist auf as f64, wenn nur der Zahlenwert gemeint ist.
Was weiterhin nicht geht: ein Einheitentyp mit einer nackten Zahl verrechnet (b + 30 → Einheitentyp mit dimensionsloser Zahl verrechnet). Die Zahl braucht denselben Typ.
wraps rechnet zuverlässig (#2004 behoben, nachgemessen 2026-09-08). Der Bereich 0..360 umfasst 361 Werte, gewrappt wird darüber hinaus:
359 -> 359 361 -> 0 362 -> 1 370 -> 9 720 -> 359
Konstanten und Laufzeitwerte liefern jetzt dasselbe. Zuvor kam bei Laufzeitwerten ein f64-Bitmuster heraus.
Die Modifikatoren range und wraps begrenzen den Wertebereich. range bricht bei Überschreitung ab, wraps rechnet zyklisch:
utype Grad: Winkel = 1 range 0..360; // 400 -> Abbruch "unit value out of range"
utype GradW: Winkel = 1 wraps 0..360; // 370 -> 9
range greift zweimal: steht der Wert schon beim Übersetzen fest, meldet der Compiler Wert liegt ausserhalb der Grenzen des Einheitentyps; kommt er erst zur Laufzeit, bricht das Programm mit unit value out of range und Rückgabecode 1 ab.
Eine nackte int64-Zahl lässt sich einem Einheitentyp ohne Cast zuweisen (var m: Meter := raw;) — im Gegensatz zum Verrechnen, das abgewiesen wird.
Der Umrechnungsfaktor wirkt bei der Zuweisung zwischen Einheiten derselben Dimension: 3 Meter, einer Millimeter-Variablen zugewiesen, ergeben 3000. Nur dort — siehe den Kasten oben.
Seit lyxc 1.0.15C wirken auch Float-Faktoren: Der Compiler führt sie als gekürzten Bruch (1000.0 → 1000/1, 0.017453 → 17453/1000000). Ein Faktor, den er nicht vollständig liest, wird gemeldet statt still als 1 gerechnet. Ebenfalls seit 1.0.15C wird pub an dim und utype exportiert — std.units ist damit importierbar.
Die ganzzahlige Umrechnung schneidet ab. In die gröbere Einheit geht Genauigkeit verloren, ohne Hinweis: 2500 Meter werden zu 2 Kilometern, 500 Meter zu 0. In die feinere Einheit ist die Umrechnung verlustfrei.
wraps 0..360rechnet modulo 361 — beide Grenzen zählen mit, wie beirange. Wer den Vollkreis meint, schreibtwraps 0..359.
// Generische Funktion
fn Max<T: Comparable>(a: T, b: T): T {
if (a > b) { return a; }
return b;
}
// Generischer Struct
type Stack<T> = 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<T: Printable + Comparable>(val: T) {
val.Print();
}
Attribute beginnen mit @ und stehen unmittelbar vor dem annotierten Element (Unit, Funktion, Variable).
| Attribut | Ziel | Beschreibung |
|---|---|---|
@flight_crit | Unit, Fn | Strikte Luftfahrt-Regeln: kein Heap, keine unsafe-Blöcke |