Pureline

Pureline Emvus

Aktuelles Emvus-Design: method, Result, scoped, Data Classes.

Pureline Emvus folgt dem **aktuellen Emvus-Sprachdesign**. Es ist ein Stilprofil für die beabsichtigte `.ev`-Syntax, keine Behauptung, dass jedes gezeigte Feature bereits von Ring 1 implementiert ist.

method / whereOptionale SemikolonsResult statt try/catchscopedData Classes
18Profilregeln

Dieses Profil ist dokumentiert, wird vom Browser-Checker aber noch nicht automatisch geprüft.

Profilregeln

PL-EV-001

Native Methodendeklarationen

Methoden werden mit method deklariert, bei Bedarf mit Rückgabetyp in method<Type>. Generische Typvariablen werden über where eingeführt, nicht durch eine zweite Generic-Parameterliste am Methodennamen.

Eine Methode ohne expliziten Rückgabetyp gibt Void zurück.

Avoid
Generic-Liste am Methodennamen
method<T> first<T>(List<T> items) {
    return items.get(0)
}
Pureline
method<Int> square(Int value) {
    return value * value
}

method<T> first(List<T> items) where T {
    return items.get(0)
}
PL-EV-002

Leere Deklarationsklammern optional, Aufrufklammern nicht

Beide parameterlosen Deklarationsformen sind Pureline-konform. Sie deklarieren Methoden ohne Argumente; der Unterschied ist kosmetisch, **kein** Overload-Unterschied.

Zum Ausführen wird immer refresh() oder shutdown() geschrieben; object.refresh ist kein Methodenaufruf. Formatter bewahren oder konfigurieren beide Deklarationsstile konsistent, ohne den jeweils anderen als Fehler zu markieren.

Avoid
Aufruf ohne Klammern
cache.refresh
Pureline
method refresh {
    updateCache()
}

method shutdown() {
    closeConnections()
}
PL-EV-003

Braces Pflicht, Semikolons optional

Für if, Schleifen und vergleichbaren Kontrollfluss werden explizite { ... }-Blöcke verwendet. Optionale Semikolons werden im idiomatischen Emvus weggelassen, bestehender gültiger Code mit Semikolons wird aber nicht abgelehnt.

Inline-Guards ohne Braces und unnötige else-Blöcke sind nicht Pureline. Fortsetzungszeilen und lange Ausdrücke bleiben eindeutig.

Avoid
Inline-Guard ohne Braces
if (value < 0) return
Pureline
method process(Int value) {
    if (value < 0) {
        return
    }

    println(value)
}
PL-EV-004

Naming, Imports und Sichtbarkeit

Typen: PascalCase; Interfaces: I-Prefix (IStorage, IConnection). Methoden, Felder, Properties, Parameter und lokale Variablen: camelCase. Konstanten: UPPER_SNAKE_CASE. Packages: kleingeschriebene Punktpfade.

Quelldateinamen sind **camelCase**, z. B. sessionService.ev, auch wenn die primäre Klasse SessionService heißt.

Die Standardsichtbarkeit ist public; private oder protected wird bei Bedarf angegeben.

Die Symbolauflösung ist case-insensitiv, die Schreibweise bleibt aber erhalten: die **deklarierte Schreibweise** wird konsistent verwendet, und es werden keine Namen definiert, die sich nur in der Groß-/Kleinschreibung unterscheiden.

Explizite Imports und Aliase ersetzen das Verlassen auf verwirrende Kollisionen.

Pureline
package app.session

use {
    std.collections.[IList, IIterator],
    app.storage.userStorage as Storage
}
PL-EV-005

Typen sollen Absicht vermitteln

Emvus ist standardmäßig statisch typisiert. var führt **statische Typinferenz** durch; dynamic fordert ausdrücklich laufzeitgetyptes Verhalten an.

dynamic wird an wirklich dynamischen Grenzen verwendet, nicht um normale Typprüfungen zu umgehen. Explizite und inferierte statische lokale Typen sind beide Pureline-konform.

Pureline
Person person = Person("Jason", 20)
var current = person.copy()
dynamic payload = receiveUnknownPayload()
PL-EV-006

Nullability über stabilen Kontrollfluss behandeln

Emvus verlangt keine T?-Annotation, sondern verfolgt Null-Zustände über den Kontrollfluss. Ein möglicherweise null-wertiger Wert wird früh abgesichert, und von veränderlichen Properties wird vorher ein stabiler lokaler Snapshot genommen.

Man verlässt sich nie darauf, dass wiederholte, unsynchronisierte Lesezugriffe auf eine veränderliche Property denselben Wert liefern. Erforderliche Feldinitialisierung wird explizit gemacht.

Avoid
Wiederholte Reads einer veränderlichen Property
method<String> displayName(Profile profile) {
    if (profile.nickname == null) {
        return "Unknown"
    }

    return profile.nickname
}
Pureline
method<String> displayName(Profile profile) {
    final var nickname = profile.nickname

    if (nickname == null) {
        return "Unknown"
    }

    return nickname
}
PL-EV-007

Typisierte Result-Behandlung für erwartete Fehler

Emvus hat keine try/catch/finally-Syntax. Es werden Result<T, E>, success, fail, ? und switch so verwendet, wie die Sprache es vorsieht.

? dient der bewussten Fehlerweitergabe, wo die Typen es erlauben. ! löst bei einem Fehler einen Panic aus und bleibt etablierten Invarianten oder Grenzprüfungen vorbehalten, die sich wirklich nicht beheben lassen.

Ein Result wird nicht verworfen, und erwartete Fehler werden nicht hinter panic versteckt. success, fail und return bleiben getrennt, statt jede Operation unnötig zu verpacken.

Avoid
try/catch existiert nicht
method<Int> validatePort(Int port) {
    try {
        check(port)
    } catch (RangeException e) {
        println(e)
    }
}
Pureline
method<Result<Int, RangeException>> validatePort(Int port) {
    if (port < 1 || port > 65535) {
        fail RangeException(port, 1, 65535)
    }

    success port
}

method showPort(Int port) {
    switch (validatePort(port)) {
        success(value) -> println(value)
        error(problem) -> errprintln(problem.message)
    }
}
PL-EV-008

Ressourcenlebensdauer mit `scoped` sichtbar machen

Für Ressourcen, die am Ende ihres Scopes geschlossen werden müssen, wird Emvus' scoped-Konstrukt verwendet.

scoped wird nicht durch Java-try-with-resources, Go-defer oder ein nicht existierendes Emvus-finally ersetzt. Die Lebensdauer einer Ressource bleibt klar, auch wenn der Compiler den Speicher optimiert.

Pureline
method<String> readFile(String path) {
    scoped var file = Files.open(path)
    return file.readAll()
}
PL-EV-009

Data Classes statt Boilerplate

data class wird für kleine, benannte, datenzentrierte Typen mit dem eingebauten generierten Verhalten verwendet.

Primäre Data-Properties sind außerhalb der Initialisierung schreibgeschützt. copy() und withX(...) drücken veränderte Kopien aus und sind standardmäßig flach. Generierte Gleichheit, Hashing und Textdarstellung werden, wo passend, dem manuellen Neuschreiben vorgezogen. Größere, verhaltensreiche Typen bleiben reguläre Klassen.

**Es gibt keine separate record-Stilvorgabe:** das vereinbarte Emvus-Design nutzt data class für benannte Datenmodelle und Dictionary für Dictionary-/Objektliteral-Daten.

Pureline
data class Member(String name, Int age)

data class Server(String host, Int port = 25565)
PL-EV-010

Listen, Tupel und Dictionaries behalten ihre Semantik

Bei [...]-Literalen bedeutet **exakt gleicher Typ aller Elemente** eine List, sonst ist der Ausdruck ein Tupel. Pureline überschreibt diese typgetriebene Regel nicht durch eine Stilpräferenz.

Dictionary-Literale verwenden { key: value }; inferierte gemischte Werttypen nutzen dynamic, wo das Sprachmodell es verlangt. Auf Dictionaries wird über **Schlüssel** zugegriffen, nicht über Record-Punktnotation.

Ein wechselnder Elementtyp kann die Inferenz zwischen Liste und Tupel legitim ändern. Dieses Verhalten bleibt an API-Grenzen, wo passend, durch explizit deklarierte Typen sichtbar.

Avoid
Dictionary per Punktnotation
println(server.name)
Pureline
var numbers = [10, 20, 30]        // List<Int>
var response = [200, "Success"]   // [Int, String]
Dictionary
var server = {
    "name": "Emvus",
    "port": 25565
}

println(server["name"])
PL-EV-011

Destructuring ist positional

{ ... } destrukturiert Tupel- oder Data-Class-Komponenten in Deklarationsreihenfolge. _ kann ein Element überspringen.

Destructuring wird nicht als benanntes Record-Matching umgedeutet. Kurze, aussagekräftige Bindungen sind wahlloser Entpackung vorzuziehen.

Pureline
var { status, message } = [200, "OK"]
var { first, _ } = loadPair()
PL-EV-012

`switch` soll vollständige Verzweigung zeigen

switch-Anweisungen oder -Ausdrücke werden für echte Zustandsalternativen verwendet. Ausdrücke sind exhaustiv oder haben einen definierten Catch-All-/Failure-Arm.

Für Result sind klare success(...)- und error(...)-Muster verschachtelten Bedingungen vorzuziehen. Catch-All-Muster bleiben bewusst und sind kein Weg, vergessene Fälle zu verstecken.

Pureline
method<String> rankLabel(Rank rank) {
    return switch (rank) {
        MEMBER -> "Member"
        MODERATOR -> "Moderator"
        ADMIN -> "Admin"
    }
}
PL-EV-013

Cascades nur für einen einzelnen Receiver

Cascades mit .. eignen sich für eine kurze Folge von Operationen auf demselben Receiver.

Ketten, die unzusammenhängende Effekte verbergen, mehrere Objekte implizit verändern oder sich über viele Anweisungen erstrecken, werden vermieden.

Pureline
Person person = Person("Anna", 20)
    ..birthday()
    ..age = 21
PL-EV-014

Fibers und Threads brauchen klare Lebenszyklen

fiber {}, virtual {} und thread {} sind unterschiedliche Ausführungskonstrukte mit einem gemeinsamen Task-Ergebnismuster. Gewählt wird nach der tatsächlichen Arbeitslast, nicht weil Nebenläufigkeit kompakt aussieht.

Ergebnisse und Fehler, die zählen, werden awaited. Abbruch und Ownership langlebiger Tasks sind klar. Geteilter veränderlicher Zustand wird synchronisiert; @Synchronized steht bereit, wo passend.

Es wird nicht angenommen, dass ein vom Task erfasstes Objekt stack-lokal ist oder freigegeben werden kann, wenn die startende Methode zurückkehrt. Verstecktes Fire-and-forget in gewöhnlichen Business-Methoden wird vermieden.

Pureline
var task = fiber {
    return calculate(10)
}

Int result = task.await()
PL-EV-015

Macros sollen Auffindbarkeit verbessern, nicht verschleiern

Emvus-Macros sind Compile-Time-AST-Transformationen mit Zieldeklarationen, quote, $(...)-Substitution und AST-Builder-APIs.

Pureline verlangt: kleine Macros mit klar benannter Verantwortung und unterstützten Zielen; deterministische Expansion, bei der Reihenfolge und entstehende Member auffindbar bleiben; Hygiene gegen versehentliche Namenskollisionen; Compiler-Diagnosen bei widersprüchlichem oder ungültigem expandierten Code; gewöhnliche Methoden statt Macros, wenn kein substanzieller Compile-Time-Nutzen besteht; keine Abhängigkeit von ungeprüftem Macro-Time-I/O, Netzwerk, Uhr oder Zufall.

Generierter Code muss semantische Prüfungen bestehen; Checker-/Formatter-Tooling behandelt generierte Stellen nicht wie gewöhnlich handgepflegte Dateien.

Pureline
macro Trace on Method {
    target.body.prepend(quote statement {
        println("Method entered")
    })
}
PL-EV-016

Nicht gegen HyperAlloc-Flow-Interna programmieren

Emvus-Code darf über Sublang, Optimind und HyperAlloc Flow optimiert werden. Entwickler drücken **Semantik und Lebensdauern** aus und raten nicht manuell eine künftige Allokationsstrategie.

Geradlinige Objektlebenszyklen und stabile Ownership sind zu bevorzugen, geteilter veränderlicher Zustand bleibt explizit, besonders über Tasks hinweg. Für einfache Werte sind unveränderliche Data Classes zu bevorzugen, wo sie zur Domäne passen.

APIs werden nicht um die Annahme gebaut, ein Objekt sei immer stack-allokiert, scalar-replaced oder gepoolt. Allokation und Escape-Verhalten in Hot Paths werden durch Messung und Diagnose bewertet, nicht durch Folklore.

PL-EV-017

Package-Dichte und Source-Organisation

Ein Package-/Source-Ordner enthält standardmäßig höchstens **8** produktive .ev-Module. Tests, generierte Quellen und reine Metadaten-Dateien zählen nicht mit. Aufgeteilt wird nach tatsächlicher Feature-Verantwortung, nicht durch mechanisches Anlegen beliebiger Subpackages.

Package-Name und Dateiname sind verschiedene Konzepte: app.session bleibt kleingeschrieben, sessionService.ev ist camelCase.

PL-EV-018

Sprachnative Regeln schlagen sprachübergreifende Nachahmung

Pureline-Tooling meldet keinen Verstoß, nur weil Emvus sich von Java, Rust oder Go unterscheidet:

Optionale () in **parameterlosen Methodendeklarationen** sind gültig, Aufrufe brauchen immer (). Optionale Semikolons sind gültig. where ist die native Generic-Deklarationssyntax. var ist statisch inferiert, dynamic ist ausdrücklich dynamisch. success, fail, ?, !, scoped und AST-Macros haben Emvus-spezifische Bedeutungen. { ... } hat gültige kontextabhängige Verwendungen, darunter Dictionaries und positionales Destructuring. [ ... ] wird nach Emvus' Regel der exakt gleichen Elementtypen als Liste oder Tupel typisiert.

Der Formatter ist AST-bewusst, bewahrt die Bedeutung und wendet nie ::-Namespaces oder eine Semikolonpflicht aus anderen Sprachen auf .ev-Dateien an.