0 matches

Language Features

Complete reference for Loxel v2 — a modern, expression-oriented language with optional static typing, multilingual keywords, and built-in concurrency.

The statuses listed on the page are for developers only, and do not reflect the delivered binary. Everything is currently in beta, and subject to change.

✅ Working — Fully functional in all modes ⚠️ Partial — Works in some modes 🚧 In Progress — Under active development 📋 Planned — Designed but not started

Variables & Constants ✅ Working

Use let for mutable variables and const for immutable constants. Type annotations are optional; Loxel infers types automatically.

Example
variables.lox

Comments ✅ Working

Three comment styles: // single-line, /* */ multi-line (nestable), and /** */ documentation comments.

Example
comments.lox

Keywords: Strict vs Contextual ✅ Working

Loxel splits its keywords into two classes (the C#/TypeScript/Kotlin tradition). Hard (strict) keywords always mean their grammar construct and can never name a variable, parameter, function, or class — binding one is an immediate parse error. Contextual keywords only act as keywords in their exact grammar position; everywhere else they are ordinary identifiers.

Hard (24): if else for while break continue return throw try catch match await typeof def class let const import export true false nil self super

Contextual (21): as from in is extends implements uses case default static readonly public private protected async unsafe namespace type struct interface trait

Two extra rules: member position is always free — after ., in field declarations, and as map keys, every keyword (hard ones included) is an ordinary name. And all translations of a keyword behave identically: Spanish si is exactly as reserved as if, while tipo is exactly as bindable as type — and builtins like .namespace respond to every language's spelling. print is no longer a keyword at all — it is a builtin function (print(x), any language spelling), so let print = 42; binds and reads normally.

Example
keywords.lox

Expressions & Blocks ✅ Working

Everything in Loxel is an expression that returns a value — if, match, try, and blocks all yield results.

Example
expressions.lox

Only a bare trailing expression becomes the block's value — a trailing def is a declaration, not an expression, so it is not picked up:

block-gotcha.lox

Strings & HEREDOC ✅ Working

Backtick strings and HEREDOC both interpolate with ${}. HEREDOC (<<<END) just lets that span multiple lines. The nowdoc form (<<<'END') treats ${} as literal text instead of interpolating it. In a backtick string, a backslash escapes the ` and the ${ — see below.

String interpolation
strings.lox
Escaping ` and ${

A run of backslashes immediately in front of a $ follows parity: pairs collapse, and an odd leftover escapes the ${. That position is the only one where backslashes behave differently, because it is the only one where they are about interpolation.

escapes.lox
HEREDOC multi-line strings
heredoc.lox
Character-aware indexing & byteLength (v3.5.0)
unicode.lox

Control Flow ✅ Working

Standard if/else, while, C-style for, range-based for-in, and comprehensions. (do-while is 📋 planned.)

Example
control-flow.lox

Type Annotations ✅ Working

Types are optional but recommended for public APIs. Loxel supports three type-checking modes: OFF, WARN, and STRICT.

Primitive types & inference
types.lox
Function (callable) types

A function type (A, B) => R can be written inline on a parameter, aliased with type, applied to a binding, and nested inside other types (Map<String, MathOp>). In the native compiler the signature is enforced at compile time — both when a function is assigned to a function-typed binding and when a value is called through such a type. Enforcement is best-effort and conservative: arity is always checked; parameter types are checked when the lambda annotates them (an unannotated (a, b) => … infers Any params — Loxel has no contextual typing); the return type is checked when annotated or inferable; lambdas with default or rest parameters stay permissive. The VM/tree-walker do not run the static checker, matching every other typed-binding contract.

callable-types.lox

Generics ✅ Working

Generic classes and functions use <T> type parameters. Type bounds use extends. Since v3.4.0 a superclass reference can carry type arguments (class Orders < Map<String, Number>) — closing, forwarding, or partially closing the parent's parameters — with wrong arity or bound violations reported as clear errors. Works in the tree-walker, bytecode VM, and native/LLVM backend. Box<Number> is a first-class parameterized-class value in all three modes — it can be aliased, passed around, and called later (including with named constructor arguments). Method-level type arguments (obj.method<Number>(x)) are validated in all three modes: type-argument arity, declared bounds, and parameter types. Type arguments are erased for execution (as in most dynamically-typed languages) but recorded on instances for runtime checking of generic method parameters; the native backend additionally validates instantiation arity, non-generic misuse, and type bounds at compile time when the class is statically known, and at runtime otherwise.

Example
generics.lox

Union & Optional Types ✅ Working

Union types express "this OR that" with |. T? is shorthand for T | Nil.

Example
union-types.lox

Classes ✅ Working

Classes use def init for constructors and self (not this) for the instance reference. The @field syntax is not supported in v2.

Example
classes.lox

Inheritance ✅ Working

Single inheritance with extends. Use super.init() to call the parent constructor and super.method() to call overridden methods.

Example
inheritance.lox

Interfaces & Traits ✅ Working

Interfaces define contracts. Traits (mixins) provide reusable implementation. A class implements interfaces and uses traits.

Interface
interfaces.lox
Traits (mixins)
traits.lox

Property Promotion ✅ Working

Annotate constructor parameters with visibility/mutability modifiers to auto-create fields. Supported in the tree-walker, bytecode VM, and native/LLVM backend.

Example
promotion.lox

Visibility Modifiers ✅ Working

public (default), private, and protected control access to fields and methods. Enforced in all three modes, including the native/LLVM backend. Native (and the tree-walker) raise catchable errors; the bytecode VM raises the same messages but treats them as fatal. Note on inheritance: native resolves the calling class lexically, so a base-class method (e.g. via super.init) can always touch the base's own private/protected fields, and subclasses can access inherited protected (but not private) fields — the tree-walker and VM currently derive the calling class dynamically and each rejects one of those base-method patterns.

Example
visibility.lox

Operator Overloading ✅ Working

Define a method whose name is the operator symbol — def +(other) — to customize behavior for +, -, *, **, /, %, ==, !=, <, >, <=, >=, <=>, the bitwise |, &, ^, <<, >>, and the unary -@ / !.

Example
operator-overloading.lox
Compound-assignment contract: in-place += vs. allocating +

A class may also define +=, -=, *=, /=, or %= directly, distinct from its +-style method — mirroring Python's __iadd__ vs. __add__. x += y tries the class's own += method first (mutate self in place, no allocation) and falls back to + when += isn't defined.

compound-overload.lox

Decorators ⚠️ Partial

Decorators wrap functions, classes, or methods. The native compiler implements the full surface: user function decorators (stacking, decorated recursion — the @memoize fibonacci pattern — and use as values), class decorators, user-defined method decorators, and the built-in method decorators @cached/@deprecated/@logged/@timed; still-unsupported decorators (@onPropertyGet, @computed) emit a compile-time warning instead of silently dropping. Method-decorator convention: the decorator receives the unbound method — the receiver is its explicit first parameter (any name; self is a keyword) — and returns a callable invoked as (receiver, args...); decorations inherit to subclasses and compose under the built-ins (@cached memoizes the wrapped call). Earlier interpreted-mode gaps are resolved: the VM applies user function decorators (stacking, factory form) and the tree-walker applies class decorators; @cached hits no longer corrupt the VM stack and @deprecated("reason") reasons are preserved. The remaining gap is narrower: the VM still ignores user-defined method decorators (built-ins work).

Example
decorators.lox

Match Expressions ✅ Working

Nine pattern types: literal, variable, wildcard, array, object/map, type, range, guard, and OR. Works in all modes.

Core patterns
patterns.lox
Match as expression with complex example
match-expr.lox

Operators ✅ Working

Arithmetic (incl. exponentiation **), bitwise (| & ^ << >>), comparison (incl. strict === / !==), membership (~> / <~, Unicode ), logical, assignment, null-handling, pipeline, spread, and type-checking operators.

The ? family, one rule: thirteen constructs spell “this operand might not be what you want” — access (?. ?.[] ?.() T?), choice (? : ?: ??), conditional assignment (??= ?= =?? =?), and railway (?> ?!). In every one, the ? sits next to the operand being questioned, so the symbol itself tells you what gets tested. The assignment and railway forms are detailed below; access and Result behavior have their own sections.

All operators quick reference
operators.lox
Operator precedence (highest → lowest)
precedence.lox

Functions & Parameters ✅ Working

Named functions with def, arrow shorthand, default parameters, named arguments (colon syntax only), rest parameters (PHP-style unified map), lambdas, and higher-order functions.

Function syntax overview
functions.lox
Lambdas, closures & higher-order functions
lambdas.lox

Async / Await ✅ Working

Async functions return Promise<T>. await suspends execution until the Promise resolves. Use Promise.all for concurrent requests.

Example
async.lox

Channels & Spawn 🚧 In Progress

Channel-based concurrency and thread spawning. Support in progress.

Example
channels.lox

Enums 🚧 In Progress

Enums define a fixed set of named variants. Variants can carry associated data (like Rust enums) and work with pattern matching.

Example
enums.lox

Structs ✅ Working

Structs are value types — copied on assignment. Use them for small, immutable data (Point, Color, Vec2). Use classes for objects with identity and inheritance.

Value semantics vs. class reference semantics
structs.lox

Destructuring ✅ Working

Extract values from arrays, maps, and structs using destructuring assignment and function parameter patterns.

Array & object destructuring
destructuring.lox

Arrays ✅ Working

Dynamic arrays with rich built-in methods. Slice with arr[1:3] (exclusive end), stride with arr[::2], reverse with arr[::-1], and select or filter numpy-style with fancy indexing (arr[[0, 2]] or a boolean mask). Since v3.4.0, sort/sortBy/reverse return a new array and leave the receiver untouched, and the comparator sort is a stable O(n log n) merge sort in every backend.

Array operations
arrays.lox

Maps ✅ Working

Key-value dictionaries with property shorthand, spread, and comprehensive methods including entries(), clear(), and empty(). Data keys always win over method names on dot access, so v3.4.0 added non-shadowable static forms (Map.keys(m), Map.fromEntries(pairs), …) for code that must survive arbitrary JSON — and Self in a static resolves to the class it was invoked through, so subclasses inherit constructing statics that build the subclass.

Map operations
maps.lox

Sets & Tuples ✅ Working

Sets store unique values with union/intersection/difference operations. Tuples (v3.4.0) are fixed-arity, immutable, per-position-typed sequences — a distinct core class with the array read surface (indexing, length, iteration, destructuring) and every mutator rejected.

Sets
sets.lox
Tuples
tuples.lox

Module System ✅ Working

Per-module scope isolation, export-only visibility, and singleton execution. Supports stdlib (std::), relative paths (./), and bare package names.

Defining & importing a module
math_utils.lox
Import forms & module singletons
main.lox
Function-body imports & breaking module cycles

import is an ordinary statement — inside a function body it runs at call time, after all modules have loaded. Since loaded modules are cached and the circular-dependency check only guards loads in progress, this is the sanctioned way for two modules to refer to each other. The same pair with both imports at top level fails with Circular dependency detected.

a.lox
b.lox
Runtime dynamic loading — Module.load_exports / Module.load_source

A module can be resolved at runtime — from a path or from source text already in hand — and its export table returned as a Map. Same loader as static import: namespace requirement, export-only visibility, singleton caching, circular-import detection. Load failures (missing file, parse error, a module body that throws) are ordinary catchable errors.

Example project — a host program that discovers and loads plugins it was not compiled with:

file tree
plugins/shout.lox
host.lox

Compile the host natively — dynamic loading works in compiled binaries too (the loaded modules execute in an embedded interpreter; see the notes below):

terminal

Notes that matter:

  • Execution modes. In the bytecode VM the full surface works — exported classes are constructible from the returned Map. In a compiled binary, runtime-loaded modules run in an embedded bytecode VM: data and functions bridge across (functions arrive as callable closures), but class exports fail with an explicit error — export a factory function returning a Map instead. Native speed applies only to statically-compiled modules.
  • Singletons. A load_source name maps to one module for the life of the process, like a file path; re-registering a used name is an explicit error, never a silent replace.
  • Security. Loaded source runs with the full privileges of the host program — filesystem, network, process spawning. There is no sandbox. Load only source you trust or have vetted through your own gates; never feed it network input.

Multilingual Keywords ✅ Working

Write code in 7 languages. Keywords, type names, and (since v3.4.0) builtin method names are internationalized. There is no --lang flag: every language's spellings are active simultaneously, and languages can be mixed freely in one file — English is the canonical form.

Examples in multiple languages
i18n.lox
LanguageFunctionClassStringNumber.sort().keys()
EnglishdefclassStringNumbersortkeys
EspañoldefclaseCadenaNumeroordenarclaves
FrançaisdefclasseChaîneNombretrierclés
DeutschdefklasseZeichenketteZahlsortierenschlüssel
PortuguêsdefclasseCadeiaNumeroordenarchaves
日本語defクラス文字列数値整列キー
中文def字符串数字排序

Error Handling ✅ Working

Standard try/catch blocks (there is no finally clause in the language), custom error types via class inheritance, and try as an expression — the try block's final expression is the result, the catch block's on a caught throw, identical in all three modes.

Example
errors.lox

Result & Railway Operators ✅ Working

Recoverable failures as values: Ok(v) and Err(e) build a Result<T, E>, and the railway operators thread it through pipelines. ?> is the failure-aware sibling of |> — an Err skips every remaining stage (the stage is never evaluated), while an Ok payload flows into the next function, which must itself return a Result (bind semantics; use .map() for plain transforms). Postfix ?! unwraps an Ok or early-returns the Err from the enclosing function (like Rust's ?), and ?? gains unwrap-or: Ok(v) ?? d yields v, Err(_) ?? d yields d. Identical in all three modes; ?! at module top level is rejected at compile time in VM and native modes.

Example
railway.lox

Built-in Functions ✅ Working

Core built-ins always available without an import.

Output, type conversion & utilities
builtins.lox

String & Math ✅ Working

String methods
strings-methods.lox
Math module
math.lox

File, HTTP & JSON 🚧 In Progress

File I/O
file-io.lox
HTTP Client & JSON
http-json.lox

Data Structures ✅ Working (V2)

Import from std::collections, std::trees, and std::graphs.

Stack, Heap, Deque
collections.lox
Binary Search Tree, AVL Tree, Trie
trees.lox

NumPy & Machine Learning ✅ Working (V2)

N-dimensional arrays (std::numpy), ML algorithms (std::ml), and statistical computing (std::statistics).

NumPy-style arrays
numpy.lox
ML classifiers & regression
ml.lox

AI Training & LLMs ✅ Working (V2 · compiled)

A full pure-Loxel deep-learning stack — no PyTorch. Threaded f32 tensors and a fused 4-bit kernel (std::tensor), and real-model QLoRA fine-tuning plus Q4 KV-cache inference (std::llm), validated end-to-end on SmolLM2-360M. Instruct models are covered by two submodules: std::llm::qwen3 loads Qwen3-architecture GGUFs (ternary Bonsai Q2_0 and stock llama.cpp K-quant Q4_K_M), and std::llm::chat assembles conversations (templates, transcripts, stop tokens) for GGUF instruct models. This stack targets the LLVM-compiled backend (the reference for these modules) — compile with -O2 --cpu=native; it is not run through the interpreter.

QLoRA fine-tuning (4-bit frozen base + trainable adapters)
finetune.lox
Q4 KV-cache generation (temperature + top-k)
chat.lox
Instruct models — std::llm::qwen3 loaders & std::llm::chat templates

std::llm::chat is pure conversation assembly — it never generates and never touches the filesystem. std::llm::qwen3 loads Qwen3-architecture GGUFs into the same decoder core that generate_cached runs on.

instruct.lox
std::tensor — threaded matmul & fused 4-bit kernel
tensor.lox

Hardware Acceleration ✅ Working (V2 · compiled)

One port — std::device — and per-platform adapters behind it. Callers select and interrogate compute (select() / supports() / describe()) without naming a backend; select() never fails — a missing GPU is a slower route, not an error, and the CPU path is the reference every accelerator is gated against. Measured on qwen3-4b Q4_K_M: 0.42 → 33–35 tok/s end-to-end (device-resident decode on an RTX 2080).

CALLERS std::llm · std::ml · apps never name a backend std::device — THE PORT select() · supports(cap) · DeviceBuffer cpu SIMD + threads vulkan opt-in adapter cuda GGML adapter every refusal, everywhere: 0 = "use the CPU kernel" DESKTOP (CUDA · measured) qwen3-4b Q4_K_M · loxel-v2-native-cuda image · LOXEL_PERF_MODE=gpu VRAM (resident) 2.5 GB weights + KV cache Loxel (CPU) tokenize · embed · sample whole token = ONE device graph: norms → qkv → rope → KV append → GQA attention → projections → logits head (~19 ms/token) 0.42 → 7.6 → 33–35 tok/s (CPU → fused gemv → resident decode) MOBILE (Android · Vulkan) ternary Bonsai Q2_0 · unified memory · LOXEL_PERF_MODE=gpu zero-copy weights HOST_VISIBLE|DEVICE_LOCAL tern_gemv.comp CPU kernel = the reference EVERYWHERE ELSE no driver, no build flag, VM/tree-walker, tiny VRAM → the same code runs on CPU SIMD, bit-for-bit as before; select().describe() says why, for operators.
Desktop performance is the CUDA adapter's job (containers cannot reach a discrete GPU via Vulkan under WSL2); Vulkan serves Android's unified memory and llvmpipe CI runs. Full guide: docs/runtime/gpu-acceleration.md.
Selecting and probing a device (std::device)
Environment variables (the complete acceleration surface)
VariableRead byMeaning
LOXEL_PERF_MODE=gpuruntime (one gate)THE opt-in: permits Vulkan zero-copy buffers, the K-quant CUDA session, and device-resident decode. Unset = pure CPU, always.
LOXEL_DEVICEstd::device.select()Selection policy when no explicit arg: cpu, vulkan, cuda, prefer-gpu.
LOXEL_CHAT_SESSION_CAPloxel-chat infer workerSession length in tokens. Unset + CUDA: auto-sized to free VRAM (up to the model's native context). Unset + CPU: 1024.
LOXEL_CHAT_INFER_HOSTloxel-chat web tierWhich worker serves chat: infer (CPU, default) or infer-gpu (compose --profile gpu).
LOXEL_COMPUTE_DEVICEGGML backend strategyimage-gen's CPU/CUDA choice: gpu, cpu, auto.
LOXEL_DECODE_PROF=1std::llmPer-phase decode profiler (µs buckets: gemv/attn/rope/…). LOXEL_PREFILL_PROF=1 for prefill.
LOXEL_WORKER_CPUDockerfile build argCPU tuning for the worker's non-device half; the gpu profile passes native.
LOXEL_EXTRA_LINK_LIBSloxel compile link stepHow a build image hands its GGML/CUDA libraries to every compile it runs.

Execution Modes ✅ Working

Three modes, in priority order: the native LLVM compiler is the primary mode (most capable, ships production binaries), the bytecode VM is second (the default for loxel script.lox), and the tree-walking interpreter is third (simplest; useful for prototyping semantics). New features land native-first; a feature existing only in a lower mode is a gap, not a design.

ModeSpeedRoleUsage
Native (LLVM)50–100× tree-walkerPrimary — production binaries; debug builds via -gloxel compile script.lox -o out
Bytecode VM18× tree-walkerSecondary — the default interpreted modeloxel script.lox
Tree-walkerBaselineThird — prototyping / semantics referenceloxel script.lox --tree-walker
REPLN/AInteractiveloxel or loxel repl
REPL special commands
repl-session.txt

Language-Level Events ✅ Working

Event decorators on class methods intercept lifecycle events for AOP, logging, validation, and metaprogramming. The native compiler and the VM implement all five hooks (@onCall, @onReturn, @onThrow, @onPropertySet, @onInstantiate) — natively they fire through the runtime dispatcher, inherit to subclasses, and a throwing @onPropertySet validation hook aborts the write catchably. All three modes fire all five hooks (@onThrow in the tree-walker was the last gap to be fixed — user throws now trigger the hook and the catch body runs exactly once). Tree-walker wrinkle: a throwing @onPropertySet validation hook does not yet abort the field write there. @onPropertyGet/@onInherit remain interpreted-only (native warns at compile time). Native nuance: hooks fire on dispatched method calls, not on super.method() fast paths.

Event hook decorators
events.lox
Built-in method decorators
builtin-decorators.lox
DecoratorTriggerParameters
@onCallBefore any method callmethod_name, args
@onReturnAfter method returnsmethod_name, result
@onThrowException thrownmethod_name, error
@onPropertyGetProperty readproperty_name
@onPropertySetProperty writtenproperty_name, new_value
@onInstantiateAfter init()none
@onInheritClass subclassedchild_class

Unified Object Model ✅ Working

All primitive values behave as objects with methods. Internally they remain efficient (NaN-boxed doubles, bit-pattern booleans) — method calls dispatch directly to C++.

Primitive class contracts: every inline primitive is an instance of its core Loxel class (String, Number, Boolean, Array, Map, Set), and every core class extends Object. The class definitions in stdlib/core/*.lox are the declared contract — including operator methods with typed parameters like def <(other: String). Class methods may delegate to native functions, and the engines fast-path primitive receivers equivalently, but the semantics are the ones written on the class; subclass overrides dispatch through the method table and win. (Single-source build-time embedding of the core classes and typed operator contracts: ✅ landed 2026-07-03.)

Primitive methods
unified-object-model.lox

Core-Class Subclassing ✅ Working

Every core class (Number, String, Boolean, Array, Map, Set) is subclassable in all three execution modes. A subclass instance wraps its primitive, inherits the core class's methods and typed operator contracts (abs(), <, toString(), …), participates in arithmetic through them, and answers is through its class chain (Meters(3) is Number is true; typeof still reports the boxed kind). Combine with a decorator factory to normalize operands before a method body runs — units-style types in a few lines.

Example — unit-safe arithmetic via a coercion decorator
meters.lox

Abstract Classes 📋 Planned

Abstract classes define partial implementations. Subclasses must implement all abstract methods. Instantiating an abstract class is a runtime error.

Planned syntax
abstract.lox (planned)

Static Properties & Methods ⚠️ Partial

The static keyword works in the bytecode VM and the native/LLVM compiled backend. static let/static const fields may have an initializer, evaluated once when the class is defined. Both the bytecode VM and the native/LLVM backend enforce visibility and const/readonly mutability on static fields with matching error messages (write-once: the initializer or first assignment succeeds, later writes throw; native errors are catchable, VM errors are fatal). Static members are accessed via the class name, not self.

Static keyword (working)
static.lox
Static variable: visibility & mutability
static-variable.lox

Quick Reference

Feature support matrix across execution modes.

FeatureTree-walkerBytecode VMLLVM
Variables / const🚧
Functions & closures🚧
Classes & inheritance🚧
Interfaces & traits
Generics
All 9 pattern types🚧
Default parameters
Named arguments
Rest parameters
Async / await🚧
i18n support🚧
Module system🚧
Language events🚧
Unified object model🚧
Channels / spawn🚧
Abstract classes📋📋📋
Static properties📋🚧

Best Practices

Type annotations
best-practices-types.lox
Error handling
best-practices-errors.lox
Pattern matching vs. if/else
best-practices-match.lox

Known Limitations

  • Native (LLVM) is the primary mode: production binaries come from loxel compile; use -g for Loxel-level backtraces and bounds-checked buffers when debugging (see v2/docs/DEBUGGING.md). The interpreted modes are for iteration and prototyping.
  • Channels / threads: Implemented (native + VM): Thread spawn/join and Channel send/receive work in compiled code; a couple of known concurrency bugs remain in stress scenarios.
  • Visibility/mutability across modes: Enforced in all three modes (native records per-class field metadata and checks it at every field access). Divergences that remain: VM errors are fatal while native/tree-walker errors are catchable; the tree-walker has no static fields; and for inherited fields the lower modes derive the calling class dynamically (each rejecting a legitimate base-method access pattern that native's lexical resolution allows).
  • Abstract classes: Designed but not yet implemented (Phase 19).
  • Generics in LLVM: Generic instantiation works, and Box<Number> is a first-class parameterized-class value (aliasing let B = Box<Number>; B(x) and named/spread constructor arguments keep the type arguments). Arity/non-generic/bound errors are reported at compile time when the class is statically known; arity and non-generic misuse are also validated at runtime for dynamic class values. Type arguments are erased for execution, but each generic instance records its concrete type arguments, so a method parameter typed as a class type parameter (def set(v: T)) is validated at runtime in all three modes — Box<Number>().set("x") raises the same Type mismatch for parameter error natively, in the VM, and in the tree-walker. Method-level type arguments (obj.method<Number>() — arity, bounds, and parameter validation) and concrete/composite parameter types on generic receivers (v: Number, vs: Array<T> — container kind checked, element types unchecked) are likewise enforced in all three modes. Remaining nuances: native validates method-level type-argument bounds by type NAME (registered class hierarchies and primitives are exact; unresolvable names are accepted conservatively), and element types of Array<T>/Map<K,V> arguments are not deep-checked in any mode.
  • Decorators / event hooks: native implements the full surface and earlier interpreted-mode gaps are resolved (VM function decorators, tree-walker class decorators + @onThrow, @cached/@deprecated fixes). Remaining: VM user method decorators; tree-walker throwing-@onPropertySet abort; interpreted-only @onPropertyGet/@onInherit.
  • Planned syntax: map comprehensions, do-while. (try-as-expression has shipped — identical in all three modes.)