Version: 0.1.0 Last Updated: 2026-02-07
This document is the authoritative specification for the Eclexia programming language.
Reserved keywords that cannot be used as identifiers:
fn let mut if else
match for while loop break
continue return struct enum type
impl trait use pub resource
adaptive shadow dimension requires provides
Some None Ok Err true
false const
Identifiers start with a letter or underscore, followed by letters, digits, or underscores:
identifier ::= ( letter | '_' ) ( letter | digit | '_' )*
letter ::= 'a'..'z' | 'A'..'Z'
digit ::= '0'..'9'Examples:
x
myVariable
_internal
snake_case_name
CamelCaseName
Integer literals:
integer ::= decimal_literal | hex_literal | binary_literal | octal_literal
decimal_literal ::= digit ( digit | '_' )*
hex_literal ::= '0x' hex_digit ( hex_digit | '_' )*
binary_literal ::= '0b' ('0' | '1') ( '0' | '1' | '_' )*
octal_literal ::= '0o' octal_digit ( octal_digit | '_' )*Examples: 42, 1_000_000, 0xFF, 0b1010, 0o755
Float literals:
float ::= decimal_literal '.' decimal_literal ( exponent )?
| decimal_literal exponent
exponent ::= ( 'e' | 'E' ) ( '+' | '-' )? decimal_literalExamples: 3.14, 1.0e-10, 6.022e23
String literals:
string ::= '"' ( string_char | escape_sequence )* '"'
string_char ::= any character except '"' or '\'
escape_sequence ::= '\n' | '\t' | '\r' | '\\' | '\"' | '\0'Examples: "hello", "line1\nline2", "quote: \"text\""
Dimensional literals:
dimensional_literal ::= ( integer | float ) dimension_unit
dimension_unit ::= 'J' | 's' | 'm' | 'kg' | 'K' | 'A' | 'mol' | 'cd'
| derived_unit
derived_unit ::= base_unit ( '·' base_unit )* ( '/' base_unit )*
| base_unit '^' integerExamples: 100J, 5s, 3.14m, 10kg·m²/s²
Arithmetic: + - * / % ^
Comparison: == != < > <= >=
Logical: && || !
Bitwise: & | ^ << >>
Assignment: = += -= *= /=
Other: . :: -> => ? @
Line comments:
// This is a line comment
Block comments:
/* This is a
block comment */
Documentation comments:
/// Documentation for the following item
fn documented_function() { }
//! Documentation for the containing module
Complete formal grammar in Extended Backus-Naur Form:
(* Program *)
program ::= item*
item ::= function_def
| type_def
| const_def
| use_statement
| resource_def
| impl_block
(* Functions *)
function_def ::= 'fn' identifier type_params? '(' param_list? ')' return_type? resource_annotation? block
param_list ::= param ( ',' param )*
param ::= identifier ':' type
return_type ::= '->' type
type_params ::= '<' identifier ( ',' identifier )* '>'
resource_annotation ::= '@requires' '(' resource_req ( ',' resource_req )* ')'
| '@provides' '(' resource_prov ( ',' resource_prov )* ')'
resource_req ::= identifier ':' expression
resource_prov ::= identifier ':' expression
(* Types *)
type_def ::= 'type' identifier type_params? '=' type
| 'struct' identifier type_params? '{' field_list '}'
| 'enum' identifier type_params? '{' variant_list '}'
field_list ::= field ( ',' field )*
field ::= identifier ':' type
variant_list ::= variant ( ',' variant )*
variant ::= identifier ( '(' type_list ')' )?
type ::= primitive_type
| identifier type_args?
| '(' type_list ')'
| '[' type ']'
| 'fn' '(' type_list ')' '->' type
| type '+' type
| type '-' type
| type '*' type
| type '/' type
type_list ::= type ( ',' type )*
type_args ::= '<' type_list '>'
primitive_type ::= 'Int' | 'Float' | 'Bool' | 'String' | 'Unit'
(* Constants *)
const_def ::= 'const' identifier ':' type '=' expression
(* Use Statements *)
use_statement ::= 'use' path ( '::' '{' identifier_list '}' )?
path ::= identifier ( '::' identifier )*
identifier_list ::= identifier ( ',' identifier )*
(* Resources *)
resource_def ::= 'resource' identifier '{' resource_config '}'
resource_config ::= resource_field ( ',' resource_field )*
resource_field ::= 'dimension' ':' type
| 'budget' ':' expression
| 'shadow' ':' expression
(* Adaptive Blocks *)
adaptive_block ::= 'adaptive' identifier '{' adaptive_option ( ',' adaptive_option )* '}'
adaptive_option ::= identifier ':' block
(* Implementations *)
impl_block ::= 'impl' type_params? type ( 'for' type )? '{' impl_item* '}'
impl_item ::= function_def
(* Statements *)
statement ::= let_statement
| expression_statement
| item
let_statement ::= 'let' 'mut'? identifier ( ':' type )? '=' expression
expression_statement ::= expression
(* Expressions *)
expression ::= literal
| identifier
| '(' expression ')'
| expression binary_op expression
| unary_op expression
| expression '.' identifier
| expression '[' expression ']'
| expression '(' arg_list? ')'
| if_expression
| match_expression
| block
| for_expression
| while_expression
| adaptive_block
| return_expression
| break_expression
| continue_expression
literal ::= integer | float | string | dimensional_literal | bool_literal
bool_literal ::= 'true' | 'false'
binary_op ::= '+' | '-' | '*' | '/' | '%' | '^'
| '==' | '!=' | '<' | '>' | '<=' | '>='
| '&&' | '||'
| '&' | '|' | '^' | '<<' | '>>'
unary_op ::= '-' | '!' | '&' | '*'
arg_list ::= expression ( ',' expression )*
if_expression ::= 'if' expression block ( 'else' ( block | if_expression ) )?
match_expression ::= 'match' expression '{' match_arm ( ',' match_arm )* '}'
match_arm ::= pattern ( 'if' expression )? '=>' expression
pattern ::= literal
| identifier
| '_'
| identifier '(' pattern_list ')'
| '(' pattern_list ')'
pattern_list ::= pattern ( ',' pattern )*
for_expression ::= 'for' identifier 'in' expression block
while_expression ::= 'while' expression block
return_expression ::= 'return' expression?
break_expression ::= 'break' expression?
continue_expression ::= 'continue'
block ::= '{' statement* expression? '}'Hello World:
fn main() {
print("Hello, Eclexia!");
}
Factorial:
fn factorial(n: Int) -> Int {
if n <= 1 {
1
} else {
n * factorial(n - 1)
}
}
Resource-Aware Computation:
resource energy { budget: 1000J }
fn expensive_compute() @requires(energy: 500J) -> Int {
// Computation...
42
}
fn main() {
let result = expensive_compute();
print(result);
}
Adaptive Execution:
adaptive sort {
fast: { quicksort(data) @requires(time: 10ms) },
slow: { bubblesort(data) @requires(time: 100ms) },
}
Eclexia uses bidirectional type checking. Judgment notation: Γ ⊢ e : τ
Variable:
(x : τ) ∈ Γ
───────────── (Var)
Γ ⊢ x ↑ τ
Integer Literal:
───────────────── (Int)
Γ ⊢ n ↑ Int
Float Literal:
───────────────── (Float)
Γ ⊢ f ↑ Float
String Literal:
────────────────── (String)
Γ ⊢ s ↑ String
Function Application:
Γ ⊢ f ↑ τ₁ → τ₂ Γ ⊢ e ↓ τ₁
─────────────────────────────── (App)
Γ ⊢ f(e) ↑ τ₂
Let Binding:
Γ ⊢ e₁ ↑ τ₁ Γ, x: τ₁ ⊢ e₂ ↑ τ₂
────────────────────────────────── (Let)
Γ ⊢ let x = e₁; e₂ ↑ τ₂
If Expression:
Γ ⊢ cond ↓ Bool Γ ⊢ then ↑ τ Γ ⊢ else ↑ τ
──────────────────────────────────────────────── (If)
Γ ⊢ if cond { then } else { else } ↑ τ
Binary Operation:
Γ ⊢ e₁ ↑ τ₁ Γ ⊢ e₂ ↑ τ₂ τ₁ ~ τ₂ op : τ₁ × τ₂ → τ₃
──────────────────────────────────────────────────────────── (BinOp)
Γ ⊢ e₁ op e₂ ↑ τ₃
Dimension Algebra:
Base dimensions: L (length), M (mass), T (time), I (current), Θ (temperature), N (amount), J (luminosity)
Derived dimensions: Products of powers of base dimensions
Addition Rule:
Γ ⊢ e₁ : Quantity⟨D⟩ Γ ⊢ e₂ : Quantity⟨D⟩
────────────────────────────────────────────── (Add-Dim)
Γ ⊢ e₁ + e₂ : Quantity⟨D⟩
Multiplication Rule:
Γ ⊢ e₁ : Quantity⟨D₁⟩ Γ ⊢ e₂ : Quantity⟨D₂⟩
─────────────────────────────────────────────── (Mul-Dim)
Γ ⊢ e₁ * e₂ : Quantity⟨D₁ × D₂⟩
Division Rule:
Γ ⊢ e₁ : Quantity⟨D₁⟩ Γ ⊢ e₂ : Quantity⟨D₂⟩
─────────────────────────────────────────────── (Div-Dim)
Γ ⊢ e₁ / e₂ : Quantity⟨D₁ / D₂⟩
Example:
let distance : Length = 100m;
let time : Time = 5s;
let speed : Velocity = distance / time; // Type: Length / Time = Velocity
Type Parameters:
fn identity<T>(x: T) -> T { x }
Trait Bounds:
fn max<T: Ord>(a: T, b: T) -> T {
if a > b { a } else { b }
}
Associated Types:
trait Iterator {
type Item;
fn next(&mut self) -> Option<Self::Item>;
}
Subtyping relation S <: T means S can be used where T is expected.
Transitivity:
S <: U U <: T
──────────────── (Sub-Trans)
S <: T
Function Subtyping:
T₁' <: T₁ T₂ <: T₂'
──────────────────────── (Sub-Fun)
(T₁ → T₂) <: (T₁' → T₂')
Arguments are contravariant, returns are covariant.
Resources are declared with dimension, budget, and shadow price function:
resource identifier {
dimension: Dimension,
budget: Expression,
shadow: Expression,
}
Example:
resource energy {
dimension: Energy,
budget: 1000J,
shadow: compute_energy_price(),
}
Functions declare resource requirements:
fn f() @requires(resource: amount) { ... }
Multiple resources:
fn f() @requires(energy: 100J, time: 50ms) { ... }
Shadow prices are computed from dual variables in linear programming:
For binding constraints:
shadow_price = λᵢ (dual variable from LP solver)
For non-binding constraints:
scarcity = usage / budget
shadow_price = base_price * exp(k * scarcity)
Where k controls price sensitivity.
Runtime maintains resource state:
struct ResourceState {
budget: f64,
usage: f64,
shadow_price: f64,
}On function call with @requires(resource: amount):
- Check
usage + amount <= budget - If yes,
usage += amount - Recompute
shadow_pricebased on new usage
Adaptive blocks solve:
Minimize: Σᵢ (cost_i * xᵢ)
Subject to: Σᵢ xᵢ = 1 (choose exactly one)
resource_usage_i * xᵢ <= remaining_budget (for all resources)
xᵢ ∈ {0, 1}
Where cost_i = Σⱼ (shadow_price_j * resource_requirement_ij)
Uses branch-and-bound integer programming.
Eclexia compiles to bytecode executed by a virtual machine.
Instruction Set:
LoadConst <value>- Push constant onto stackLoadLocal <index>- Push local variableStoreLocal <index>- Pop stack, store in localAdd,Sub,Mul,Div- Arithmetic operationsCall <func_id>- Call functionReturn- Return from functionJump <offset>- Unconditional jumpJumpIf <offset>- Conditional jumpConsumeResource <resource_id> <amount>- Deduct resource budget
Example:
fn add(a: Int, b: Int) -> Int {
a + b
}
Compiles to:
LoadLocal 0 // a
LoadLocal 1 // b
Add
Return
Value Stack: For expression evaluation Call Stack: For function calls and local variables Heap: For dynamically-allocated objects (strings, arrays, etc.)
All values are 64-bit:
- Integers: i64
- Floats: f64
- Pointers: 64-bit addresses
- Booleans: 0 (false) or 1 (true)
Runtime maintains global resource table:
struct ResourceTable {
resources: HashMap<ResourceId, ResourceState>,
}On ConsumeResource instruction:
- Look up resource in table
- Check budget constraint
- Update usage
- Recompute shadow price
If budget exceeded, runtime panics with ResourceExhaustionError.
Types:
Option<T>- Optional value (Some or None)Result<T, E>- Fallible operation result (Ok or Err)
Functions:
print(s: String)- Output to stdoutpanic(msg: String)- Abort with error messageassert(condition: Bool, msg: String)- Assert condition or panic
Option Methods:
is_some(self) -> Boolis_none(self) -> Boolunwrap(self) -> Tunwrap_or(self, default: T) -> T
Result Methods:
is_ok(self) -> Boolis_err(self) -> Boolunwrap(self) -> Tunwrap_err(self) -> Eunwrap_or(self, default: T) -> T
Vec - Dynamic array
new() -> Vec<T>push(&mut self, item: T)pop(&mut self) -> Option<T>len(&self) -> Intget(&self, index: Int) -> Option<T>
HashMap<K, V> - Hash table
new() -> HashMap<K, V>insert(&mut self, key: K, value: V)get(&self, key: K) -> Option<V>remove(&mut self, key: K) -> Option<V>contains_key(&self, key: K) -> Bool
HashSet - Hash set
new() -> HashSet<T>insert(&mut self, value: T) -> Boolcontains(&self, value: T) -> Boolremove(&mut self, value: T) -> Bool
Trigonometry:
sin(x: Float) -> Floatcos(x: Float) -> Floattan(x: Float) -> Float
Exponentials:
exp(x: Float) -> Floatlog(x: Float) -> Floatpow(x: Float, y: Float) -> Float
Rounding:
floor(x: Float) -> Floatceil(x: Float) -> Floatround(x: Float) -> Float
Constants:
PI: Float = 3.14159265358979323846E: Float = 2.71828182845904523536
File Operations:
read_file(path: String) -> Result<String, String>write_file(path: String, contents: String) -> Result<(), String>file_exists(path: String) -> Bool
JSON:
read_json(path: String) -> Result<Value, String>write_json(path: String, value: Value) -> Result<(), String>
String Operations:
trim(s: String) -> Stringsplit(s: String, delim: String) -> Vec<String>join(parts: Vec<String>, delim: String) -> Stringto_lowercase(s: String) -> Stringto_uppercase(s: String) -> Stringcontains(s: String, needle: String) -> Boolstarts_with(s: String, prefix: String) -> Boolends_with(s: String, suffix: String) -> Bool
Duration:
from_secs(secs: Float) -> Durationfrom_millis(millis: Int) -> Durationas_secs(self) -> Floatas_millis(self) -> Int
Instant:
now() -> Instantelapsed(self) -> Durationduration_since(self, earlier: Instant) -> Duration
Functions:
sleep(duration: Duration)measure<T>(f: fn() -> T) -> (T, Duration)
Keywords reserved but not yet implemented:
async,await- Asynchronous programmingunsafe- Unsafe operationsmove- Ownership transferref- Reference typesmod- Module systemwhere- Trait constraints
- Type System: Pierce, B. C. (2002). Types and Programming Languages. MIT Press.
- Shadow Pricing: Dantzig, G. B., & Thapa, M. N. (1997). Linear Programming 1: Introduction. Springer.
- Dimensional Analysis: Buckingham, E. (1914). "On Physically Similar Systems; Illustrations of the Use of Dimensional Equations." Physical Review.
- Resource-Aware Computing: Hoffmann, J., & Hofmann, M. (2010). "Amortized Resource Analysis with Polymorphic Recursion and Partial Big-Step Operational Semantics." APLAS.
Document Version: 1.0.0 Eclexia Version: 0.1.0 License: PMPL-1.0-or-later Copyright: 2025 Jonathan D.A. Jewell