Metel Language Changelog
Changelog
v0.6.4
Module system technical debt. Shipped by Sprint 15 (sprint/15).
Internal improvements:
TypeDefinitionRegistryis now used as the cross-module type accumulator incheck_graph, replacing theVec<Decl>approach that cloned raw AST nodes; cross-module struct field type references now resolve correctly even when the field type comes from an indirect dependency (ADR-0032, METEL-3)InferContext::newacceptsimported_schemesdirectly, enforcing the dual-registration invariant (inference + construction passes both see imported names) at the type level (ADR-0022, METEL-6)declared_namesmap added toResolvedNamesduring name resolution, replacing an O(n) AST scan inbuild_import_schemesfor T0009/T0003 distinction (METEL-4)resolve_path_rootextracted tosrc/module_paths.rsas a single shared implementation for bothmodule_loaderandname_resolver; fixed a regression where theNamepath root incorrectly doubled the module name segment (ADR-0023, METEL-7)StdPrelude::schemes()/ evaluator builtin parity assertion added as a compile-time-checked test (ADR-0027, METEL-5)
Compatibility:
- No language-visible changes.
v0.6.3
Module system - feature complete. Shipped by Sprint 14 (sprint/14).
Bug fixes:
returnandbreakare now valid as bare match arm bodies without enclosing braces:arm => return value(#226)- Diamond module dependencies (same physical file reachable via two different logical paths) no longer fail with T0003; the name resolver now dereferences path aliases to their canonical form (#228)
Internal improvements:
?operator desugared in a pre-pass (path_normalizer::desugar_propagate_error) rather than carried through inference and construction;Expr::PropagateErrorno longer exists after normalization (ADR-0030, #214)Type::PerhapsandType::Resultconvenience variants removed from theTypeenum; both types are now represented uniformly asType::Named("Perhaps", ...)andType::Named("Result", ...)(#150)- Per-module isolated runtime environments validated with cross-module closure-capture and mutual-recursion tests (#189)
- All aspect method dispatch key construction routed through
ImplMethodKey::to_env_key(), eliminating ad-hoc format strings in the evaluator (#209)
Compatibility:
- No language-visible changes except the match arm body fix (#226), which is purely additive.
v0.6.2
Evaluator normalization. Shipped by Sprint 13 (sprint/13).
Internal improvements:
Value::PerhapsandValue::Resultdedicated variants removed; allPerhapsandResultvalues now use the generalValue::Enum { name, variant, fields }representation, eliminating special-case dispatch throughout the evaluator (ADR-0028, #205)evaluate_graphnow initialises each module in its own isolatedEnvironmentseeded with builtins and cross-linked via theimported_namestable populated bycheck_graph; replaces the flat-merge strategy from v0.5.0 (ADR-0029, #210)
Compatibility:
- No language-visible changes. All existing programs produce identical output.
v0.6.1
Type system cleanup and std::core virtual module. Shipped by Sprint 12 (sprint/12).
Internal improvements:
- Unified
TypeDefinitionRegistryreplaces four separate flat maps (struct_env,method_env,enum_env, aspect impls) in the type inference and construction passes; a single registry instance is now the source of truth for all type and impl data (#133) ImplMethodKeyenum replaces flat string concatenation for impl method dispatch keys in the evaluatorStdPrelude::default()is the single source of truth for all built-in function schemes, eliminating the previous divergence between the inference and construction registries
New language features:
std::corevirtual module:Perhaps,Result,Display,Iterable,From, and all built-in functions are available in every module without any explicit import (#201,#202)- Glob import tiers: the runtime auto-imports
std::coreatStdtier (lowest priority); userimport path::*declarations useUsertier and silently win overStdtier without a conflict error (#206)
Compatibility:
- All existing programs are unaffected;
std::corenames that were previously available globally continue to work without import statements
v0.6.0
Module semantics. Shipped by Sprint 11 (sprint/11).
Enforced module semantics (previously deferred from v0.5.0):
- Visibility enforcement:
pubis required for a declaration to be importable; private items produce a compile-time error (T0009) when referenced from another module - Import scoping: only names brought in scope by
importare accessible; accessing an undeclared name is a compile-time error (T0003) - Alias resolution:
import mod::name as aliasmakesaliascallable and removesnamefrom scope - Import conflict detection: two imports binding the same local name produce a compile-time error (T0011); explicit imports silently win over conflicting glob imports
- Glob visibility filtering:
import mod::*now includes onlypubitems from the source module; private items are excluded - Re-export propagation: names re-exported via
exportare part of the facade module's public API and importable by consumers without importing the underlying module directly pubdeclarations require complete type annotations (T0010): every parameter and the return type must be annotated on apub fun
Internal improvements:
- Name resolver wired into the type-checking pipeline (
load_root -> resolve -> normalize -> check_graph -> evaluate_graph) - Flat-merge compatibility shim (ADR-0019) and last-segment fallback (ADR-0020) removed
root::,self::, andsuper::path roots now compute correct module paths in both the loader and name resolver
Compatibility:
- Single-file programs and programs using only
pubitems across module boundaries are unaffected - Programs that imported private items or relied on global declaration visibility will need
pubannotations added
v0.5.0
Module system. Shipped by Sprint 9 (sprint/9).
New language features:
- Multi-file programs: each
.mlnfile is a module; the module graph is built fromimportdeclarations import path::Name;both loads the referenced file and bringsNameinto scope- Import forms: single name, alias (
as), group ({A, B}), glob (*), module handle export path::Name;re-exports a name from a submodule into the current module's public APIpubonfun,struct,enum, andaspectmarks declarations as externally accessible- Absolute and relative path roots:
root::,std::,self::,super:: - Fully-qualified paths valid in type and expression position without a preceding
import - Circular imports detected at load time with a full chain in the error message
- Facade modules:
parser.mlnalongsideparser/directory - no specialmod.mlnfile - File-to-module mapping via
::->/with no special cases
Shipped in v0.6.1:
std::coreauto-import and standard library core types (#150, #201, #202)
Compatibility:
- Single-file programs with no
importorexportdeclarations remain valid without modification
v0.4.2
Evaluator refactor, test restructure, and keyword cleanup. Shipped by Sprint 8 (sprint/8).
Breaking changes:
Perhaps::Noperenamed toPerhaps::None; the standalonenopekeyword is nowNone
v0.4.1
Technical debt, bug fixes, and internal cleanup. Shipped by Sprint 7 (sprint/7).
Bug fixes:
TypeErrorCode::T0005("Invalid operand types") is now emitted for arithmetic operators (+,-,*,/,%) applied to non-numeric types (e.g.true + falseis now a type error)- Unary negation (
-) on non-numeric types is now a type error - Ordering comparisons (
<,<=,>,>=) on non-comparable types (non-Int, non-Float, non-String) are now type errors Pattern::Nopelatent bug eliminated -nopevalues are now exclusivelyValue::Perhaps(None), so the pattern can no longer silently miss theValue::Enum { name: "Perhaps", variant: "Nope" }form
Internal improvements:
Value::YoloResultrenamed toValue::Result;PerhapsandResultvalues are now first-class runtime variants - no longer stored asValue::Enum- Large enum variants boxed in
Decl,Stmt,TypedDecl,TypedStmt(stack frame sizes reduced from 896-1040 bytes to 8 bytes) - Dead utility methods removed (
Program::new,Type::is_numeric,Type::is_unit); reserved fields annotated with#[allow(dead_code)] - All clippy style/idiom warnings resolved
v0.4.0
Aspects and upgraded builtins. Shipped by Sprint 6 (sprint/6).
New language features:
- Aspect declarations -
aspect Foo { fun method(self) -> T; } impl Aspect for Typeblocks with method dispatch via.method()syntaxIterable<T>aspect - user-defined types usable infor-inloopsFrom<S>aspect -ascast desugars toT::from(value); user-defined casts for any type pairDisplayaspect -.to_string()onInt,Float,Bool,String;print/printlnpolymorphic via Display?operator now supports cross-type error coercion: if the function's error typeE2implementsFrom<E1>,?callsE2::from(e)automatically
Builtin changes:
print(v)andprintln(v)are now polymorphic (<T: Display>) - accept any Display typeInt::from(f: Float)andFloat::from(n: Int)built-in From impls replace the hardcodedasspecial case- Deprecated:
print_int,println_int,print_float,println_float,int_to_string,float_to_string,bool_to_string(use.to_string()and polymorphicprint/println)
Bug fixes:
- Keyword-prefix identifiers (
break_sum,return_value,let_x) now parse correctly as identifiers - Multiple
impl From<X> for Yblocks with different source types now dispatch independently
v0.3.0
Generics and type-inference improvements. Shipped by Sprint 5 (sprint/5).
New language features:
- User-defined generic functions -
fun id<T>(x: T) -> T- monomorphised at each call site - User-defined generic structs -
struct Box<T> { value: T },struct Pair<A, B> { ... } - User-defined generic enums -
enum Maybe<T> { Some { value: T }, None {} } - Let-polymorphism - unannotated
let-bound closures are generalised to polymorphic schemes (let id = fun(x) { x }works atInt,Bool, andStringin the same scope) - Braceless
ifbody -if (c) exprandif (c) a else b(RFC-0022) structandenumdeclarations are allowed inside function bodies
Type-inference improvements:
expected_typropagates into match arm bodies - bare[]andnoperesolve without ascription when the surrounding return type is known- Callee parameter types propagate into argument construction -
find(words, nope)resolves without ascription when the parameter type isPerhaps<String> - Lvalue path assignment -
obj.field = valandarr[i] = valwork on non-bare receivers (e.g.get_foo().bar = 1)
v0.2.0
Evaluator improvements, DX features, and language quality fixes. Shipped by Sprint 3 (sprint/3).
New language features:
- Type ascription operator
:-[] : Int[]guides type inference without runtime cost (RFC-0021) - Shorthand struct field initialisation -
Point { x, y }desugars toPoint { x: x, y: y } - Trailing commas allowed in function parameter lists and argument lists
New built-in functions:
assert(cond: Bool)- panics with"assertion failed"ifcondisfalseassert_msg(cond: Bool, msg: String)- panics withmsgifcondisfalsedbg<T>(v: T) -> T- prints[dbg] <value>to stderr and returns the value unchangedprint_int(n: Int),println_int(n: Int)- print anIntwithout/with newlineprint_float(f: Float),println_float(f: Float)- print aFloatwithout/with newline
Bug fixes:
- Arrays now have value semantics - binding an array to a new variable produces an independent copy
- Error spans now report
file:line:colinstead of raw byte offsets - Complex expressions (field access, calls) are now valid array index operands
Developer experience:
- Runtime panics now include a call-stack trace showing function name and call site
v0.1.0
Initial language version. Implemented by the tree-walk interpreter.
Features included:
- Primitive types:
Int,Float,Bool,String,() - Variables:
let(immutable),mut(mutable), lexical scoping,fun/type hoisting - Functions: first-class values, closures with mutable capture,
?operator (exact error type match only) - Structs: literals, field access, methods (
impl),mut self, associated functions - Enums: unit and struct-like variants,
implblocks - Built-in generic types:
Perhaps<T>,Result<T, E>,Array<T>/T[](as special cases; user-defined generics are v0.3.0) - Exhaustive pattern matching: all pattern kinds (see Pattern Kinds)
- Control flow:
if/else,while,for,for-in(arrays and ranges only),loop,break/continue,return - Type casting:
asforInt <-> Float - Never type (
!) - Tuples
- Built-in functions (see Built-in Functions)
Not included (v0.3.0+):
- User-defined generic functions and types (see Generics)
- User-defined aspects and
impl Aspect for Type(see Aspects) From-based?coercion across different error types (see The ? Operator)- User-defined
Iterable<T>implementations (see For-In)