Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Changelog

All notable changes to Korrin are recorded here. The format follows Keep a Changelog. Korrin is pre-1.0 and uses 0.MINOR.PATCH; while the major version is 0, any release may contain breaking changes, which are called out under Changed / Removed.

Unreleased

Milestone 5 is complete: packaging (git-based dependencies, no central registry) and a community package index. Milestone 4 is complete: a real language server for VS Code. Milestone 3 is complete: a bytecode compiler and virtual machine, alongside the tree-walking interpreter rather than replacing it. Milestone 2 is complete: string interpolation, methods on the built-in types, exceptions, modules, and the first standard-library modules (math, io). Milestone 1's entries are further below.

Added — Milestone 5

  • Packages. A bare import "name" now also checks installed dependencies, alongside the built-in module table it already checked (ADR 0032). A package is a git repository, pinned by tag, branch, or commit in a new korrin.toml manifest, resolved into a new korrin.lock, and checked out locally under .korrin/packages/ — no central registry or hosting of any kind (ADR 0031).

    # korrin.toml
    [package]
    name = "app"
    version = "0.1.0"
    
    [dependencies]
    greet = { git = "https://github.com/alice/korrin-greet", tag = "v1.0.0" }
    

    A package's own dependencies must be empty — packages are leaf-only in this milestone, so there is no dependency-graph solver and no risk of a name collision beyond what TOML already forbids. A dependency name that collides with a built-in module is refused at add/install time, not silently shadowed. See specification §12.

  • korrin pkg, new subcommands on the existing korrin binary: add <git-url> [--tag|--branch|--rev] [--name], remove <name>, install, update [name], list. Implemented by the new korrin-pkg library crate — manifest/lockfile parsing (toml_edit) and git access by shelling out to the installed git binary, not a linked git library (ADR 0033).

  • A community package index, korrin-packages/: a second static site alongside this one, listing packages from one JSON file per submission under data/packages/. Submitting a package is a pull request, not a form — there is no submission backend (ADR 0034).

Added — Milestone 4

  • korrin-lsp, a Language Server Protocol implementation for Korrin: live diagnostics, hover, and go-to-definition, over stdio, synchronous with no async runtime. (ADR 0026, 0027, 0028, 0029.)

    Diagnostics are the same lex/parse/resolve checks korrin run performs, shown live as you type instead of after the fact. Hover, over a builtin function or a str/list/map method, is pulled directly from docs/spec/08-builtins.md, embedded into the binary at compile time. Go to definition resolves a local variable, parameter, function, class, or import alias to where it was bound, within the current file (reaching into an imported file is not yet supported).

    Install with cargo install --path crates/korrin-lsp.

  • A real VS Code extension, in editors/vscode/: the existing syntax-highlighting grammar now starts korrin-lsp and shows what it sends, plus Korrin: Run File / Korrin: Run File (bytecode VM) commands that run the active file in an integrated terminal. (ADR 0030 — this is also where Node and TypeScript enter the repository's tooling, scoped to this one directory.)

Added — Milestone 3

  • A bytecode compiler and virtual machine. Korrin now has a second execution engine. A program is compiled once into flat instruction sequences, one per function, and run by a VM that finds local variables by slot instead of by name. It is roughly 1.7x faster on call-heavy code and 1.5x on local-variable-heavy loops, and about 15% slower on a tight loop over module globals, where slots buy nothing and its operand stack still costs something. (ADR 0022, 0023, 0025.)

    korrin run --vm file.kor runs a program through it; korrin::run_vm and run_file_vm are the embedding equivalents. The interpreter remains what korrin run and korrin::run use.

  • korrin bytecode file.kor prints the compiled instructions, one chunk per function, alongside the existing korrin tokens and korrin ast.

  • The tree-walking interpreter is now a permanent differential-testing oracle. Every golden program, every runnable specification example, and every module fixture runs under both engines on each build, and their output must match byte for byte. (ADR 0024.)

  • New E04xx diagnostics for the bytecode's operand-width limits (E0401 through E0404): more than 65 535 locals or constants, or more than 255 arguments. Reaching one takes a generated program.

Changed — Milestone 3

  • Name resolution is lexical. The nearest-binding rule is unchanged — assigning to a name an outer scope already binds still updates that outer binding, with no keyword — but "does an outer binding exist?" is now answered from the enclosing program text rather than from the live scope chain. This is what makes local variables compilable to slots. The two engines differ only for a program that reads an outer name after a call that would have created it and before the text that does. (ADR 0022.)

  • Native functions no longer name an execution engine. Builtins, built-in methods, and standard-library functions receive &mut dyn Host instead of &mut Interpreter, where Host is the four capabilities any engine offers them: output, command-line arguments, a line of input, and a call back into Korrin. One implementation of each now serves both the tree-walking interpreter and the bytecode VM. (ADR 0021.)

    For embedders this changes the public NativeFnPtr and NativeMethodFn types, and moves Interpreter::call_value onto the Host trait. No Korrin program behaves differently.

  • The input builtin reads through Host::read_line rather than reaching for std::io::stdin() directly, which also makes it testable for the first time.

Added — Milestone 2

  • String interpolation. Every string literal is a template: "hi {name}" splices the str() value of each { expr } hole, evaluated left to right. {{ / }} are literal braces. Holes are full expressions and need no escaping for nested strings ("{m["k"]}"). (ADR 0015, specification §1.7 and §4.2.)

  • Methods on str, list, and map. The . operator now works on the built-in types. New vocabulary:

    • str: len, upper, lower, trim, split, replace, find, contains, starts_with, ends_with, slice, repeat.
    • list: len, push, pop, insert, remove_at, index_of, contains, slice, reverse, sort, join.
    • map: len, keys, values, has, get, remove, pairs.

    (ADR 0016, specification §8.2–8.4.)

  • Exceptions. raise <value> unwinds until a try: / except [name]: / finally: catches it, or it reaches the top level as E0312. Any value may be raised; Error(message?) is the built-in exception type, with .message and .code. Built-in runtime faults (E0301E0313) are now catchable — an except binds them as an Error carrying the faulting code. finally runs on every exit path, including return / break / continue. (ADR 0017, specification §5.10–5.11 and §9.6.)

  • Keywords try, except, finally, raise (19 → 23). Parser error E0107 for a try with no clause, or a dangling except / finally.

  • Modules. import "./util" runs a Korrin file (resolved relative to the importing file, .kor implied) and binds a module objecttype() is "module", members are mod.name, top-level _names are private. import "./x" as y renames. Modules load once and are cached; importing the same module twice yields the same object. A circular import is E0315; a module that will not resolve, read, or compile is E0314. import "math" (no ./) loads a built-in module. New korrin::run_file API; korrin run resolves relative imports against the file's directory. (ADR 0018, specification §11.)

  • math standard-library module. import "math": sqrt, pow, floor, ceil, round, abs, min, max, and the constants pi and e. (ADR 0019, specification §11.4.)

  • io standard-library module. import "io": read_file(path), write_file(path, text), and args() (command-line arguments). Failures raise a catchable E0316. korrin run script.kor a b c passes a b c to io.args(). New Interpreter::set_args. (ADR 0020, specification §11.5.)

  • Keywords import, as (23 → 25). Parser error E0108 for a malformed import or a stray as.

Changed — Milestone 2

  • Breaking: a literal { in a string must now be written {{. No existing Korrin code, spec example, or guide example was affected.

  • Breaking: the collection built-in functions are removed in favour of methods (ADR 0016):

    RemovedReplacement
    len(x)x.len()
    append(xs, v)xs.push(v)
    pop(xs)xs.pop()
    keys(m) / values(m)m.keys() / m.values()
    has(m, k)m.has(k)
    get(m, k, default?)m.get(k, default?)
    remove(m, k)m.remove(k)

    print, type, str, int, float, bool, range, and input remain functions.

Added — Milestone 1

  • Project scaffold: Cargo workspace (korrin library + korrin-cli binary), toolchain pin, CI, lint configuration.

  • Documentation backbone: ADR process and the initial decision records (0000–0013), specification and guide skeletons, contributor docs.

  • span module: byte-offset Span and Spanned<T>.

  • diagnostics module: Diagnostic, ErrorCode, Severity, SourceMap, and ariadne-backed rendering.

  • lexer module: full tokenizer with the indentation state machine (INDENT/DEDENT/NEWLINE), bracket-aware and operator-aware newline suppression, all literal forms, and local error recovery. Specification section 01 (lexical structure) written to match.

  • ast module: expression and statement node types, all span-carrying, plus an S-expression dump for debugging and tests.

  • parser module: recursive-descent statements + Pratt-parsed expressions, non-associative comparisons, error recovery that reports multiple problems. the grammar (specification section 02) and sections 04, 05 written to match.

  • resolver module: static validation pass (return/break/continue/super placement, duplicate parameters, self-inheritance).

  • interpreter module: tree-walking evaluator — values, environments, the nearest-binding rule, closures, classes with single inheritance and super, checked integer arithmetic, on-demand stack growth with a recursion backstop.

  • builtins module: print, len, type, str, int, float, bool, range, input, and the collection functions append, pop, keys, values, has, get, remove. Specification section 08 written to match.

  • korrin::run embedding API and Interpreter for REPL use.

  • korrin binary: run, tokens, and ast subcommands, plus an interactive REPL with multi-line input and expression echo.

  • Runnable example programs under crates/korrin/examples/.

  • CI-enforced documentation harnesses: tests/spec.rs executes every runnable example in the specification and the guide, tests/builtins.rs checks builtin/spec agreement both ways, tests/adr.rs checks ADR structure, index completeness, and numbering.

  • Golden end-to-end program corpus (tests/programs/), property tests (tests/properties.rs: the front end never panics), and CLI black-box tests.

  • The complete specification (sections 01–10) and the learn-by-example guide.

  • mdBook skeleton (docs/book.toml, docs/SUMMARY.md) for the eventual site.

  • VS Code syntax-highlighting extension (editors/vscode/) and a workspace .vscode/settings.json that falls back to Python highlighting for .kor.

  • playground.kor — a runnable scratch file for experimenting.

  • branding/ — the Korrin mark, wordmark, favicon, and usage notes.

  • korrin-web/ — the website: a static landing page plus the full guide, specification, and design notes rendered from docs/ by mdBook (themed to the Korrin identity). scripts/deploy-site.sh builds and deploys it to Cloudflare Pages.

Changed — Milestone 1

  • self is no longer a keyword; it is a conventional identifier (the name of a method's first parameter). The reserved-word count is now 19. See ADR 0006.
  • Scoping is function-level, not block-level: a name first assigned inside an if / while / for body stays visible afterwards. See ADR 0011.
  • The grammar moved from a standalone korrin.ebnf file into specification §2 — one source, and it renders in the documentation site.