Pureline

Pureline Emvus

Current Emvus design: method, Result, scoped, data classes.

Pureline Emvus follows the **current Emvus language design**. This is a style profile for intended `.ev` syntax, not a claim that every showcased feature is already implemented by Ring 1.

method / whereOptional SemicolonsResult over try/catchscopedData Classes
18Profile rules

This profile is documented, but the browser checker does not check it automatically yet.

Profile rules

PL-EV-001

Native Method Declarations

Declare methods with method and, when needed, a return type in method<Type>. Generic type variables are introduced through where, not by attaching another generic parameter list to the method name.

A method without an explicit return type returns Void.

Avoid
Generic list on the method name
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

Empty Declaration Parentheses Are Optional; Call Parentheses Are Not

Both parameterless declarations are Pureline-compliant. Both spellings declare zero-argument methods; the difference is cosmetic, **not** an overload distinction.

Always write refresh() or shutdown() to execute the method; object.refresh is not a method call. Formatters should preserve or consistently configure either valid declaration style without marking the other as an error.

Avoid
Call without parentheses
cache.refresh
Pureline
method refresh {
    updateCache()
}

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

Braces Required; Semicolons Optional

Use explicit { ... } blocks for if, loops, and comparable control flow. Prefer omitting optional semicolons in idiomatic Emvus, but do not reject existing valid semicolon-terminated code.

Brace-free inline guards and unnecessary else blocks are not Pureline. Keep continuation lines and long expressions unambiguous.

Avoid
Inline guard without braces
if (value < 0) return
Pureline
method process(Int value) {
    if (value < 0) {
        return
    }

    println(value)
}
PL-EV-004

Naming, Imports, and Visibility

Types: PascalCase; interfaces: I prefix (IStorage, IConnection). Methods, fields, properties, parameters, and locals: camelCase. Constants: UPPER_SNAKE_CASE. Packages: lower-case dotted paths.

Source filenames: **camelCase**, for example sessionService.ev, even if the primary class is SessionService.

The default visibility is public; specify private or protected when required.

Symbol resolution is case-insensitive but source spelling is preserved: use the **declared spelling** consistently and do not define names that differ only in case.

Use explicit imports and aliases instead of relying on confusing collisions.

Pureline
package app.session

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

Types Should Communicate Intent

Emvus is statically typed by default. var performs **static type inference**; dynamic explicitly requests runtime-typed behavior.

Use dynamic at genuinely dynamic boundaries, not to bypass normal type checks. Both explicit and inferred static local types are Pureline-compliant.

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

Handle Nullability Through Stable Flow

Emvus does not require a T? annotation. It tracks null states through control flow. Guard a possibly-null value early and prefer a stable local snapshot of mutable properties before reasoning about their nullability.

Never rely on repeated unsynchronized reads of a mutable property having the same value. Make required field initialization explicit.

Avoid
Repeated reads of a mutable 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

Prefer Typed Result Handling for Expected Failures

Emvus has no try/catch/finally syntax. Use Result<T, E>, success, fail, ?, and switch as the language specifies.

? is for deliberate error propagation where types permit it. ! causes a panic on error; reserve it for established invariants or boundary checks that truly cannot recover.

Do not discard a Result or hide expected failure behind panic. Keep success, fail, and return distinct rather than wrapping every operation unnecessarily.

Avoid
try/catch does not exist
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

Make Resource Lifetimes Visible with `scoped`

Use Emvus's scoped construct for resources that must be closed when their scope ends.

Do not replace scoped with Java try-with-resources, Go defer, or a nonexistent Emvus finally. A resource's lifetime should remain clear even when the compiler optimizes memory.

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

Prefer Data Classes to Boilerplate

Use data class for small, named, data-centric types with the built-in generated behavior.

Primary data properties are read-only outside initialization. copy() and withX(...) express modified copies and are shallow by default. Prefer generated equality, hashing, and textual representation where appropriate rather than rewriting them manually. Keep larger behavior-rich types as regular classes.

**Do not introduce a separate record style requirement:** the agreed Emvus design uses data class for named data models and Dictionary for dictionary/object-literal data.

Pureline
data class Member(String name, Int age)

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

Lists, Tuples, and Dictionaries Retain Their Defined Semantics

For [...] literals, **all element types exactly equal** implies a List; otherwise the expression is a tuple. Do not make Pureline overwrite the language's type-driven rule with a stylistic preference.

Dictionary literals use { key: value }; inferred mixed value types use dynamic where required by the language model. Dictionaries are accessed by **keys**, not structural-record dot notation.

A changing element type can legitimately change list-versus-tuple inference. Keep that behavior visible at API boundaries through explicit declared types where appropriate.

Avoid
Dictionary via dot notation
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 Is Positional

Use { ... } to destructure tuple or data-class components in declaration order. _ may skip an element.

Do not reinterpret destructuring as named record matching. Prefer short meaningful bindings, not indiscriminate unpacking.

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

`switch` Should Expose Complete Branching

Use switch statements or expressions for real state alternatives. Expressions must be exhaustive or have a defined catch-all / failure arm.

Prefer clear success(...) and error(...) patterns to nested conditions for Result. Keep catch-all patterns deliberate, not a way to hide forgotten cases.

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

Use Cascades Only When They Clarify a Single Receiver

Cascades with .. are useful for a short sequence of operations on the same receiver.

Avoid chains that conceal unrelated effects, mutate several objects implicitly, or stretch across many statements.

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

Fibers and Threads Need Clear Lifecycles

fiber {}, virtual {}, and thread {} are distinct execution constructs with a common task-result pattern. Choose based on the actual workload, not because concurrency looks compact.

Await results and failures that matter. Make cancellation and ownership clear for long-lived tasks. Synchronize shared mutable state; @Synchronized is available where appropriate.

Do not assume a task's captured object is stack-local or can be released when the spawning method returns. Avoid hidden fire-and-forget work in ordinary business methods.

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

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

Macros Must Improve Discoverability, Not Obscure It

Emvus macros are compile-time AST transformations with target declarations, quote, $(...) substitution, and AST builder APIs.

Pureline requires: small macros with clearly stated responsibilities and supported targets; deterministic expansion where source-order behavior and resulting members remain discoverable; hygiene to avoid accidental name collisions; compiler diagnostics when expansion creates conflicting or invalid code; ordinary methods instead of macros when no substantial compile-time benefit exists; no reliance on unreviewed macro-time I/O, network, clock, or random side effects.

Generated code must satisfy semantic checks; checker/formatter tooling should not treat generated locations as ordinary hand-maintained files.

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

Do Not Program Against HyperAlloc Flow Internals

Emvus code may be optimized through Sublang, Optimind, and HyperAlloc Flow. Developers should express **semantics and lifetimes**, not manually guess a future allocation strategy.

Favor straightforward object lifecycles and stable ownership. Keep shared mutable state explicit, especially across tasks. Prefer immutable data classes for simple values when they fit the domain.

Do not build APIs around assumptions that an object is always stack-allocated, scalar-replaced, or pooled. Evaluate hot-path allocation and escape behavior through measurement and diagnostics, not folklore.

PL-EV-017

Package Density and Source Organization

A package/source folder should contain at most **8** production .ev modules by default. Tests, generated sources, and metadata-only files do not count. Split by actual feature responsibility rather than mechanically creating arbitrary subpackages.

A package name and a filename are different concepts: app.session remains lower-case, while sessionService.ev is camelCase.

PL-EV-018

Language-Native Rules Override Cross-Language Imitation

Pureline tooling must not report a violation merely because Emvus differs from Java, Rust, or Go:

Optional () in **parameterless method declarations** are valid; calls always require (). Optional semicolons are valid. where is the native generic declaration syntax. var is statically inferred; dynamic is explicitly dynamic. success, fail, ?, !, scoped, and AST macros have Emvus-specific meanings. { ... } has valid context-dependent uses, including dictionaries and positional destructuring. [ ... ] is typed as a list or tuple according to Emvus's exact-element-type rule.

The formatter should be AST-aware, preserve meaning, and never apply :: namespaces or semicolon requirements from other languages to .ev files.