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

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.

String interpolation
strings.lox
HEREDOC multi-line strings
heredoc.lox

Control Flow ✅ Working

Standard if/else, unless, while, do-while, C-style for, range-based for-in, and comprehensions.

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

Generics ✅ Working

Generic classes and functions use <T> type parameters. Type bounds use extends. 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 +, -, *, **, /, %, ==, !=, <, >, <=, >=, <=>, and the unary -@ / !. There is no operator keyword.

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 or classes. Fully working in tree-walker. Bytecode support in progress.

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 **), comparison (incl. strict === / !==), membership (~> / <~, Unicode ), logical, assignment, null-handling, pipeline, spread, and type-checking operators.

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) or arr[1..=3] (inclusive).

Array operations
arrays.lox

Maps ✅ Working

Key-value dictionaries with property shorthand, spread, and comprehensive methods including entries(), clear(), and empty().

Map operations
maps.lox

Sets & Tuples 🚧 In Progress

Sets store unique values with union/intersection/difference operations. Tuples are fixed-structure named pairs.

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

Multilingual Keywords ✅ Working

Write code in 7 languages. Keywords and type names are internationalized. Run with loxel run --lang es.

Examples in multiple languages
i18n.lox
LanguageFunctionClassStringNumber
EnglishdefclassStringNumber
EspañoldefclaseCadenaNumero
FrançaisdefclasseChaîneNombre
DeutschdefklasseZeichenketteZahl
PortuguêsdefclasseCadeiaNumero
日本語defクラス文字列数値
中文def字符串数字

Error Handling ✅ Working

Standard try/catch/finally blocks, custom error types via class inheritance, and try as an expression.

Example
errors.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. 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
std::tensor — threaded matmul & fused 4-bit kernel
tensor.lox

Execution Modes ✅ Working

Three modes: tree-walking interpreter (default, full feature support), bytecode VM (faster, most features), and LLVM compiler (native code, 50–100× speedup).

ModeSpeedFeaturesUsage
Tree-walkerBaselineAll featuresloxel script.lox
Bytecode VM18× fasterCore featuresloxel script.lox --bytecode
LLVM50–100× fasterNative binaryloxel compile script.lox -o out
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.

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

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

  • LLVM: Compiler in progress (Phase 7). Use --bytecode for production.
  • Channels / spawn: Not yet implemented. Async uses Promises; channel-based concurrency in progress.
  • 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.
  • Object pattern guards in bytecode: Guards on object/map patterns work in tree-walker; bytecode support in progress.
  • Promise.all / race: Not yet implemented in any mode.

Workarounds

  • Use loxel script.lox --tree-walker for full feature access.