Changelog

What's changed

A record of all notable changes to code-lang. The project follows a rolling development model — breaking changes will be noted explicitly once v1.0 stabilizes.

v0.3.0

June 2026

In dev
Toolchain
  • code-lang-fmt check — validate .cl files for parse errors, exits 1 on failure
  • code-lang-fmt lint — run UnusedImport and ShadowedBinding rules with optional --fix
  • cargo-dist release pipeline — pushes a git tag and GitHub Actions builds native binaries for Linux x64/ARM, macOS ARM, and Windows
  • install.sh — curl | sh installs both code-lang and code-lang-fmt into ~/.code-lang/bin on Linux and macOS
  • install.ps1 — equivalent one-liner installer for Windows PowerShell
  • ci.yml — GitHub Actions CI runs build, test, clippy -D warnings, and rustfmt --check on every push and pull request
  • ci.sh — local mirror of CI so you can run all four checks before pushing

v0.2.2

June 2026

Release
Language
  • null keyword — write null as a literal value in any expression
  • let x; — uninitialized declaration defaults to null (no more required initializer)
  • ?? null coalescing operator — 'a ?? b' returns b only when a is null
  • typeof keyword — 'typeof expr' returns the type name as a string
  • Array destructuring in let/const — 'let [a, b] = arr' binds elements by position
  • Hash destructuring in let/const — 'let { x, y } = hash' extracts keys by name, 'let { x: alias } = hash' renames
  • Default function parameters — 'fn(name, greeting = "hi")' uses the default when the argument is omitted
Bug fixes
  • Struct self-methods with zero extra args no longer panic — 'point.get_x()' works correctly
  • Array index assignment now bounds-checks — out-of-range index returns an error instead of silently doing nothing
  • Importing a .cl file that fails at runtime now surfaces the error instead of swallowing it
Safety
  • Float operations (sqrt, log, pow, trig) return a clean error on NaN or Infinity instead of propagating IEEE 754 special values
  • Number parsing in the lexer no longer panics on malformed literals — emits ILLEGAL token instead

v0.2.1

June 2026

Release
Language
  • String interpolation — embed expressions directly in strings with ${...} syntax
  • for-in loops — iterate arrays with 'for (i in arr)' and hashes with 'for (k, v in hash)'
  • switch statement — pattern matching with 'switch (subject) { pattern => body }', compared with ==
  • Enum types — define named variant sets with 'enum Direction { North, South, East, West }' and access via 'Direction.North'
Errors
  • is_error(val) global builtin — test whether a value is an error without importing anything
  • Errors stored in let/const are recoverable values — only bare expression statements propagate errors
  • Module member errors now name the module: 'fmt has no member x', 'utils has no public member x'

v0.2.0

June 2026

Release
Errors
  • All errors now show the source line with a caret pointing to the exact column
  • break and continue outside a loop now report the correct line/column
  • import errors now point to the import statement location
  • Hint messages added for common mistakes — type mismatches, undefined variables, arity errors, and more
  • REPL now checks for parse errors before evaluating, preventing confusing partial-AST results
  • Parse errors in imported .cl files are surfaced with the file name
Safety
  • Recursion depth limit of 500 — infinite recursion now gives a clean error instead of a segfault
  • Integer arithmetic (+ - * **) now uses checked operations — overflow produces a clear error
  • Float operations that produce NaN or Infinity now return an error
  • Function calls enforce arity — wrong argument count is an error, not silent truncation
Standard library
  • arrays.map, filter, reduce, find, any, all — higher-order functions that accept user-defined functions
  • fmt.format(template, ...args) — printf-style string formatting with %s %d %f %%
  • math.log2, math.sign, math.gcd, math.lcm
  • strings.lines, strings.is_empty, strings.pad_left, strings.pad_right
  • hash.get(h, key, default) — safe key access with a fallback value

v0.1.0-dev

June 2026

In dev
Language
  • Tree-walking interpreter rewritten from Go to Rust
  • First-class functions, closures, and recursion
  • Structs with default field values and dot-notation access
  • Module and import system for stdlib and .cl files
  • Control flow: if / elseif / else, while, for, break, continue
  • Operators: arithmetic (** //), comparison, logical (&& ||), compound assignment, prefix/postfix ++/--
  • Types: Integer, Float, String, Char, Boolean, Array, Hash, Null, Function, Struct, Module
Standard library
  • fmt — print, eprint, input, typeof, to_int, to_float, to_str, clear
  • math — PI, E, sqrt, abs, pow, floor, ceil, round, log, sin, cos, tan, min, max, clamp
  • strings — to_upper, to_lower, split, join, contains, replace, trim, reverse, to_chars, from_chars, parse_int, parse_float
  • arrays — 20 functions including push, pop, slice, sort, zip, flatten, unique
  • hash — keys, values, entries, has_key, merge, delete, len
  • fs — read_file, write_file, append_file, read_lines, exists, list_dir, mkdir, copy, rename, remove
  • path — join, basename, dirname, stem, extension, absolute, is_absolute
  • os — args, platform, arch, get_env, set_env, get_wd, hostname, exit
  • time — now, unix, sleep, since, format, year/month/day/hour/minute/second
  • json — parse, stringify
  • rand — int, float, choice, shuffle
  • http — get, post, post_json (blocking, returns status/body/ok)
Errors
  • All errors carry line and column from the call site
  • Error output shows source line with caret pointer
  • Parse errors surface to the user before evaluation begins
  • Non-zero exit code on any error in script mode
REPL
  • Persistent history across sessions (~/.code_lang_history)
  • exit, exit(), and quit all exit cleanly
  • Errors print to stderr without crashing the session

Subscribe to releases on GitHub.

Install guide →