burn / docs

Introduction

Changelog

Every release of Burn, newest first. Versions are explained in Burn standards; releases can be downloaded from GitHub or installed with burnup.

26.1.0-experimental-9

Your editor explains the language: hover over a keyword or a built-in type to see what it does, and go to its definition to read more. ash init asks for a new project step by step.

  • Editors explain the language itself: hovering over a keyword (def, struct, fun, match, unsafe, …) or a built-in type (int, string, uint8, Future, … and their other names such as String or byte) shows what it does with an example and a link to the documentation, and going to its definition (Ctrl+click) opens language.md at its section. The text lives in lib/doc/language.md, which the compiler embeds like the built-in functions and burn sources writes next to them. Words in strings are left alone.
  • ash init without a name asks step by step: the package name, an app, a library or a workspace, what an app builds to, the directory and whether to create a git repository, each with a suggestion, then shows what it will create (packages).
  • The README is shorter, and this changelog moved from the Burn repository to the documentation.

26.1.0-experimental-8

The JIT: bvm compiles the functions and loops a program spends its time in to x86-64 or arm64 machine code while it runs, so burn run and burni get close to native speed on hot code.

  • The JIT runs on arm64 too, on Linux and on Macs with Apple silicon: compiler/src/bvm/jit_arm64.bn writes arm64 machine code with the same frames, on-stack replacement, values in registers and inline fast paths as on x86-64. The parts both processors share moved to jitbase.bn, and the x86-64 code generator to jit_x86.bn. Under qemu, fib(32) takes 0.35 s instead of 10.9 s.
  • Fixed: a method that overrides one of its parent struct's and uses a global, without a declared return type, failed with "x is used before it is declared". Overriding signatures are now compared after every body is checked.
  • The JIT keeps values in registers and compiles more inline. While it compiles a function it tracks what each operand stack slot holds (a constant, a local's value or the value in rax) and writes it to memory only when a jump, a call or a jump target needs it there, so a + b * 2 is a few register instructions instead of a load and a store per step. Comparisons followed by a branch become one cmp and conditional jump; division and remainder use idiv (falling back to the runtime only for 0 and -1); writes to arrays of plain values and retain and release are inline, calling the runtime only when an object dies, is shared between threads or was freed. A loop with % over 50 million numbers takes 0.17 s instead of 1.1 s (as fast as native code), fib(32) 31 ms instead of 45 ms, and a sieve over arrays 0.9 s instead of 1.3 s. The runtime gives the JIT the address of its "other threads run" flag (burn_rt_mt_cell).
  • bvm has a JIT: functions that are called often and loops that turn often are compiled to x86-64 machine code while the program runs (compiler/src/bvm/jit.bn), so burn run and burni get close to native speed on hot code: fib(32) takes 45 ms instead of 1.4 s, and a loop over 30 million numbers 0.1 s instead of 3.7 s. Compiled code keeps the interpreter's frames, with every operand stack slot at a fixed offset, so interpreted and compiled functions call each other freely, and a hot loop moves from the interpreter into compiled code in the middle of a call (on-stack replacement). Runtime errors, exit, the REPL's recovery and stack overflows work the same in compiled code. BURN_JIT=0 turns it off and BURN_JIT_THRESHOLD sets how many calls or loop turns make code hot (1000). On arm64 bvm still interprets.
  • The less common instructions of bvm (division, floats, records, arrays, host functions, tasks) run in one function, burn_bvm_slow, which the interpreter and compiled code share.

26.1.0-experimental-7

No Rust: the compiler, the command line, bvm and the runtime are written in Burn, the toolchain is a native executable that builds itself in under a minute, and building Burn needs only a C compiler, starting from assembly seeds in the repository.

  • The inline assembly of the runtime assembles with clang too (mul and div take a register, and f32ToBits loads its argument whole), so the macOS seeds and toolchains build on Intel Macs.
  • No Rust is left in the repository: the bvm crate (bvm/, with its runtime core bvm/runtime, the Rust tests and bvm/runtime.bvm), Cargo.toml, Cargo.lock, rustfmt.toml, lib/runtime (the runtime functions the Rust bvm linked into programs) and compiler/src/bin/genrt.bn are gone. compiler/src/vm/runtime.bn now names the runtime functions itself, and releases check their tag against compiler/src/version.bn.
  • The end-to-end tests are written in Burn: tests/run.bn and tests/e2e/ replace bvm/tests/burn.rs, and sh scripts/test.sh builds a toolchain (or takes one with --toolchain) and runs them in parallel, in about 30 seconds. Language server tests send their messages in one batch and pick the answers by id. CI builds, tests and smoke-tests the toolchain without cargo.
  • Ember, the example language built on bvm, is written in Burn: examples/bvm/ember/ember.bn builds bvm modules with the compiler's own module types and runs them with the bvm written in Burn, giving the same output as bvm/examples/ember.rs, which is gone.
  • Burn builds without Rust. The repository keeps seeds instead of the bytecode boot compiler: compiler/boot/<platform>.tar.xz holds the compiler (compiler/src/main.bn) and its runtime as assembly for linux-x86_64, linux-aarch64, macos-x86_64 and macos-aarch64 (1.3 MB each). scripts/bootstrap.sh assembles the seed of this platform with cc, lets it build the compiler and lets the result build itself until two stages are identical, in about 30 seconds; --update replaces all four seeds. scripts/package.sh builds the toolchain from there with only a C compiler, tar and xz, in under a minute, and the end-to-end tests build their toolchain with it. compiler/boot/compiler.bvmc is gone.
  • Native executables leave out the code they never use: every function is in a section of its own on Linux, and the linker drops the sections nothing refers to (--gc-sections). Hello world is 219 KB instead of 408 KB.
  • --no-std executables link the runtime written in Burn, like all others; the Rust no-std runtime (libburn_core.a) is gone, and scripts/native-runtime.sh no longer needs rustc. --no-std still keeps the standard library out of a program, but its executables are no longer smaller than others.
  • The toolchain is a native executable written in Burn: bin/burn is compiler/src/bin/burn.bn compiled to native code, the command line when it is started as burn, burni, burnc or burn-lsp, and bvm written in Burn when it is started as bvm (a link to it). Building a program no longer runs the compiler on a bytecode interpreter. compiler/src/cli/host.bn provides what bvm provided before (paths, files, other programs, the terminal, and linking, writing and running bytecode) in Burn, and the toolchain no longer ships share/burn/burn.bvm or share/burn/compiler.bvm. The compiler entry compiler/src/main.bn writes native assembly with build --target asm and --target runtime, which is how scripts/package.sh and the tests build the toolchain after the bootstrap.
  • Building is much faster now that the compiler runs as native code: the toolchain builds itself in about 25 seconds instead of 8 minutes on bvm, burn check of the compiler takes 10 seconds instead of a minute, the 32 test programs build as native executables in 5 seconds, and the end-to-end test suite runs in about 3 minutes instead of 40.
  • The cycle collector backs off when it finds nothing: after a collection that frees no objects, it waits twice as long before the next one (resetting when one frees something, and always collecting when the heap nears its limit). Programs that keep a large, acyclic graph of objects alive, like the compiler, no longer spend most of their time in it.
  • The native code generators append their output in place: text built with function calls (out += adrText(...), slow paths) went through a full string copy each time, which made generating a large program quadratic. On arm64, slow paths of very long functions are placed inside the function every 30000 instructions, so conditional branches (which reach 1 MB) always reach them, and the reference count check uses b.ne instead of tbnz (which reaches 32 KB).
  • The test suite no longer checks bvm's tiering statistics (BVM_STATS, BVM_HOT), which belong to the Rust bvm that no longer runs Burn programs.
  • The runtime written in Burn has a panic mode for the REPL and the language server: burn_rt_try calls a function and returns when it hits a runtime error or calls exit, instead of stopping the program, and an async task that fails gives its default value. It also gives the program's path, the platform, file modification times and burn_flush.
  • Executables that run bytecode use bvm written in Burn. burn build app.bar -o app (and .bvm, .bvmc) links the bytecode with libburn_launcher.a, which scripts/native-runtime.sh builds from compiler/src/bin/launcher.bn. A native program that imports bytecode libraries is now compiled to bytecode, linked with its libraries and run the same way, so it behaves exactly as on bvm, mixins included. The Rust libburn_bvm.a is gone. burn build --target asm writes the assembly of a program without linking it.
  • bvm written in Burn is complete as a command: compiler/src/bvm/tool.bn has every command of bvm (run, asm, dis, check, link, pack, list, unpack, runtime, version, help) with the same output, and archive.bn reads and writes .bar archives byte for byte like archive.rs, with the resource host function for their modules. compiler/src/version.bn holds the toolchain version.
  • bvm written in Burn assembles text: compiler/src/bvm/assemble.bn turns bvm assembly into a module like bvm asm, with the same error messages. Assembling what bvm dis prints gives back the same bytes, for the boot compiler and the command line too. compiler/src/bin/bvm.bn asm writes it, and run, dis and link accept assembly files as well.
  • bvm written in Burn links: compiler/src/bvm/link.bn merges modules like bvm link (equal types become one, external functions are bound to their definitions, several entries run one after another) and mixin.bn applies @Inject, @Overwrite and @Redirect. Modules with mixins are linked when they load. compiler/src/bin/bvm.bn link writes the same module as bvm link.
  • bvm written in Burn runs bytecode: compiler/src/bvm/interp.bn is an interpreter for bvm modules, with verify.bn checking them first and types.bn adding a module's types after those of the program it runs in, so both share one runtime. Instructions are prepared once into fixed-size records with resolved targets, and common sequences are fused. Every test case gives the same output on it as on bvm. compiler/src/bin/bvm.bn run <module> runs a module with it.
  • Native code tests x is T without calling the runtime when T is a record that nothing extends, such as an enum variant: decoding the boot compiler takes half the time.
  • BURN_SYMBOLS=1 makes native builds name every function in the assembly, for debuggers and profilers.
  • The runtime written in Burn: lib/rt is a complete replacement for the Rust runtime of native executables (memory and the cycle collector, strings, arrays, maps, printing and runtime errors, number formatting, files, directories, processes, JSON, HTTP, async tasks and the stack overflow handler), built with burn build --target runtime lib/rt/runtime.bn. It calls libc through @Extern, so the same code works on Linux and macOS, x86-64 and arm64. It is the runtime native executables link against now: scripts/native-runtime.sh builds it into libburn_runtime.a with the toolchain's own burn. Native programs that run bytecode (bytecode libraries, executables made from .bvm and .bar files) still link bvm and its Rust runtime, now kept in libburn_bvm.a, until bvm is written in Burn too. Executables get smaller: hello world is 400 KB instead of 460 KB.
  • __cfun(f), in unsafe code, is the address of f, a function with a body marked @Extern, for C code to call: a qsort comparator, a thread's start function or a signal handler. It is 0 on bvm and in JavaScript.
  • burn build --target runtime lib.bn -o lib.s compiles Burn code into a native runtime library: assembly without main and without a type table, whose @Extern functions are the C symbols it provides and whose top-level code runs when something calls burn_<name>_init, named after the file (burn_runtime_init for runtime.bn), so several runtime libraries link into one program. @Extern("name") on a top-level var gives its 8 bytes a C symbol, which compiled code and C can read and write. Its globals are its own (burn_<name>_globals), so it links next to any native program. It may only use the types every program has (numbers, bool, string, any, [string], [int], [any] and {string: any}), because its code runs with the type table of the program it is linked into. This is how the runtime moves from Rust to Burn.
  • __addr(value), in unsafe code, gives the address of a value that lives in memory (a string, an array, a struct, …) as an int, without changing its reference count. The runtime written in Burn uses it to read string literals as bytes.
  • __str(address), in unsafe code, is the string object at address as a string, with one more reference: the runtime written in Burn uses it to work with strings it built from raw bytes.
  • Calling C from native code: @Extern("strlen") fun strlen(s: int): int, a function without a body, is the C function strlen. Native executables call it with the platform's C calling convention (x86-64 System V and arm64 AAPCS), so Burn can use libc and any C library that is linked in. Parameters and results are numbers and bools: int, sized integers (widened from what C returns), float (a C double) and bool, up to 6 integer and 8 float parameters; memory is passed as an int address. Calling one needs unsafe code. On bvm and in JavaScript, calling one is a runtime error that names the C function. When the symbol differs on macOS, name it too: @Extern("__errno_location", macos: "__error").
  • C calling Burn: a function with a body marked @Extern("name") is also visible to C under that symbol, so C code can call it, for example as a qsort comparator. It keeps the registers C expects to survive and takes its arguments from C's registers.
  • Native executables read and write raw memory without calling the runtime: Memory.load8/16/32/64, loadFloat and the matching stores compile to single load and store instructions on x86-64 and arm64 (a loop of stores and loads runs about 1.5 times as fast). alloc, resize, free, copy and fill still go through the runtime.

26.1.0-experimental-6

Modules: import aliases and imports inside functions and blocks.

  • Local imports: import works inside functions, methods and blocks, and what it imports is only visible there, until the block ends (lambdas inside see it too). import "std/math" inside a function makes sqrt available in that function only, and import "std/math" as M inside an if names the module M only in that branch. The module itself is loaded and initialized once, before the file that imports it, like any other import. Bytecode libraries can still only be imported at the top level.
  • Import aliases: import "std/memory" as Mem loads a module without bringing its names into the file; they are used through the alias instead, as Mem.Memory.alloc(16), in expressions, types (Geo.Vec2 v, [Geo.Vec2]), new Geo.Point(), struct literals, enum variants and match patterns (Tok.Token.Word(w)), generic types (new C.Stack<int>()) and the functions of the standard library (M.sqrt(2.0)). Aliases work in import lists too (import ( "std/math" as M, "utils" )), and two aliases for the same module are fine. Errors name the module behind an alias and suggest close names (`M` (the module `std/math`) has no public name `sqrtt`), a name used without the alias it needs gets did you mean Mem.Memory?, and an alias may not reuse a name the file declares or name two modules. The language server completes the names of a module after Alias. and the members after Alias.Type., and hover and go to definition work through aliases.

26.1.0-experimental-5

Low-level code: unsafe blocks and functions, inline assembly for every target and raw memory. Native executables for arm64, and Burn builds itself without a released Burn.

  • std/memory: raw memory for unsafe code. Memory.alloc, resize and free manage blocks of bytes addressed by plain ints, load8/16/32/64, loadFloat, store8/16/32/64 and storeFloat read and write little-endian numbers at any address, and copy and fill work on ranges of bytes. Every function is an unsafe fun, so it can only be called in unsafe code. It works on bvm, in native executables (x86-64 and arm64) and in JavaScript (a heap in an ArrayBuffer), through one new runtime function, Mem.
  • The compiler uses inline assembly itself: floatToBits and floatFromBits in compiler/src/vm/bits.bn, which turn float constants into their bits for bvm and native code, read the bits straight from the value with bvm, x86_64 and arm64 sections, and keep the arithmetic version as the else fallback. Its output is the same as before.
  • Burn builds Burn without a released Burn. The repository keeps a compiled copy of the compiler, compiler/boot/compiler.bvmc (bvm bytecode), and scripts/bootstrap.sh lets bvm run it to build compiler/src, then lets the result build itself until two stages are identical. Building, testing and releasing only need Rust: cargo builds bvm, and bvm runs the compiler written in Burn. stage0 is gone: compiler/STAGE0, .github/actions/stage0, the CI job that built the compiler with it, BURN_STAGE0 and scripts/package.sh --stage0. scripts/bootstrap.sh --update replaces the boot compiler, so the compiler's own sources can use new language features right after they land.
  • unsafe blocks and functions, and inline assembly. unsafe { ... } marks code that the compiler cannot check, and unsafe fun makes a function that can only be called (or used as a value) in an unsafe block. An asm { ... } block in unsafe code holds assembly for each target in its own section: x86_64 and arm64 (Intel syntax and GNU syntax, passed to the assembler as written), bvm (bvm instructions, checked by the compiler for unknown instructions, labels and stack balance) and js (JavaScript), plus an optional else section with Burn code for every other target. {name} in the code stands for a variable of type int, uint64 or float: it is copied in before the code and back after it, so locals, parameters, globals and variables that closures capture all work. A native or JavaScript build fails when an asm block has no section for its target and no else; on bvm, reaching such a block is a runtime error. burn fmt leaves the code of the sections as written.
  • The documentation moved to its own repository, burnlang/docs, together with a website built with SvelteKit (https://s42yt.github.io/burn-docs/). docs/ is gone from this repository, and the README links to the website.
  • Fixed: a match on a top-level variable rejected patterns that bind names (is string s, Token.Word(w)) with "a binding needs a subject stored in a variable"; they now work like in functions.
  • Native executables for 64-bit ARM: Macs with Apple silicon (M1 and later) and Linux on arm64 build and run native executables, with the same features as on x86-64 (--no-std, bytecode libraries and their mixins, executables that run .bvmc and .bar files). The arm64 code generator is compiler/src/native/arm64.bn; burn dump --asm prints its assembly on those machines.
  • Cross-compiling: BURN_PLATFORM (linux-x86_64, macos-x86_64, linux-aarch64, macos-aarch64) builds native executables for another platform, with BURN_RUNTIME_DIR pointing at a runtime built for it (TARGET=<rust triple> scripts/native-runtime.sh <dir>) and BURN_CC at a linker for it.
  • CI runs the whole test suite on macOS with Apple silicon, and the Linux suite cross-compiles every test program to arm64 and runs it under qemu.
  • Docs: new pages for functions and closures, errors, testing, JavaScript, the REPL and eval, and for std/math, std/strings, std/fs, std/process and std/json (they replace the "more modules" page); every page has its own place in the order.
  • Docs: a complete language reference, with new pages for variables, constants and scope; operators (with the full precedence table and how equality works); control flow; strings and text; match; enums; generics; and every way to extend types and objects (method syntax, interfaces, inheritance, functions on one object, generated members, mixins). The types page explains which values are copied and which are shared, and the structs page covers calling a parent's method, interface rules, and equality and printing of objects.
  • Docs: a new section, How Burn works, explains what happens in the background: the journey of burn app.bn with burn dump for every stage; the lexer, parser, module loader and type checker (inference, smart casts, generics, the IR); how every kind of value is laid out in memory, how closures capture variables and how method calls are dispatched; the ownership pass, reference counting, the cycle collector, threads and the heap limit; how bvm verifies, interprets and optimizes programs and reports runtime errors; the machine code, startup and linking of native executables; and how the toolchain, the standard library, packages, the language server and the bootstrap fit together.
  • Docs: the async page covers futures (awaiting twice, Future<void>, awaiting outside async functions), how tasks run and end, sharing data between tasks and what each backend does; the modules page covers name clashes between modules, initialization order with import cycles, and a table of the standard library modules.
  • Docs: diagrams (SVG, in docs/images/) for the compiler pipeline, what burn app.bn does, values and heap object layouts, struct inheritance, maps, closures, dispatch tables, reference counting, cycle collection, async tasks, the x86-64 stack frame, optimizing while running, the toolchain, the bootstrap, smart casts, values and references, module initialization order and the ways to extend types.

26.1.0-experimental-4

Native executables and JavaScript are back, generated by the compiler written in Burn.

  • Fixed: a program run by burn, burni or burn run could crash with a segmentation fault when its cycle collector reached objects of the command line itself, which have a different type table (it happened running ash on the interpreter). Each program now keeps its own buffer of possible cycle roots, and so does the REPL session.
  • Native executables are back, generated by the compiler written in Burn (compiler/src/native/): burn build and burnc make a standalone x86-64 executable again by default (Linux and macOS, linked with cc or BURN_CC), burn run --native compiles and runs one, --no-strip keeps symbols, --no-std makes small ones, burn build app.bar or app.bvmc makes an executable that runs bytecode, and burn dump --asm prints the assembly, which is the same as the Rust compiler wrote. Programs that import bytecode libraries embed them, with their mixins. burn.toml defaults to target = "native" again, and burn init to a native app (--workspace: native, js and bvm).
  • Toolchains ship the runtime that native executables link against in share/burn/lib, built by scripts/native-runtime.sh.
  • JavaScript is back: burn build --target js (and burnc --target js, target = "js" in burn.toml, burn init --target js) compiles a program to one JavaScript file for Node.js, and burn dump --js prints it. The backend is ported to Burn (compiler/src/js/js.bn) and writes the same JavaScript as the Rust compiler did; its runtime is lib/js/prelude.js.

26.1.0-experimental-3

The release that ships the compiler written in Burn.

  • The compiler written in Rust (crates/burn) is removed. Burn is now written in Burn: the compiler, the command line, the REPL, the formatter, burn doc and the language server all run on bvm, and the compiler builds itself. Only bvm and its runtime core stay in Rust.

  • bin/burn is bvm: started as burn, burni, burnc or burn-lsp, it runs the command line written in Burn from share/burn/burn.bvm. Commands and output are the same as before.

  • Programs build to bvm bytecode (.bvmc, the default) or runnable archives (.bar). The native x86-64 and JavaScript backends belonged to the compiler written in Rust and are gone with it, and so are burn run --native, --target native/js, --no-strip, --compiler and BURN_CC. burn.toml defaults to target = "bvm", and projects that still say "native" or "js" build bytecode.

  • burnfmt runs lib/tools/fmt.bn on bvm.

  • Building Burn needs a released Burn to start from (stage0, named in compiler/STAGE0): scripts/package.sh --stage0 <burn> and cargo test (with BURN_STAGE0 or burn on PATH) let it compile the compiler written in Burn once. The end-to-end tests moved to bvm/tests/burn.rs and run against that toolchain.

  • The runtime moves to Burn part by part. Its core (memory, values, collections and the system) becomes part of bvm, and the functions built on it are written in Burn in lib/runtime/, compiled to bvm/runtime.bvm, which bvm links into every Burn program it runs. The first are contains, replace, split, startsWith, endsWith and repeat on strings, and min/max on ints, then trim, isInt, toInt (also with a radix) and toString with a radix, then parseJSON and abs/pow on ints. Functions written in Burn raise runtime errors with the new built-in __fail(message, loc).

  • The burn command line is written in Burn (compiler/src/bin/burn.bn). bvm runs it when it is started as burn, burni, burnc or burn-lsp, with host functions to run, check and write modules. Running, checking, building and testing programs and projects, eval, fmt, fix, repl, doc, lsp, sources, burni, burnc and dump work and behave exactly like the Rust burn, burn init creates bvm projects (--target bvm or bar), and programs import bytecode libraries and packages (.bvmc), which are rebuilt when their sources change; toolchains ship it as share/burn/burn.bvm.

  • burn.toml accepts target = "bar": burn build makes a runnable archive.

  • The declarations of the built-in functions, the search script and the style sheet of burn doc move from crates/burn/src/doc/ to lib/doc/.

  • The repository is reorganised: bvm, which stays in Rust, moves from crates/bvm to bvm/ at the root. The runtime core moves with it, from crates/burn-runtime to bvm/runtime (the crate bvm-runtime, which bvm re-exports as bvm::runtime).

  • The formatter moves from tools/burnfmt/burnfmt.bn to lib/tools/fmt.bn. lib/tools/ holds tools written in Burn that work both as commands and as libraries: import "tools/fmt" gives programs format(src), and burnfmt is built from the same file.

  • Projects have a standard layout:

    • src/ is the source root, and its folders are packages.
    • src/bin/ holds extra programs (burn run --bin), tests/ holds tests (burn test), and examples/ holds examples (burn run --example).
    • @/path imports from the project's source root, and <package>/path imports from another package's src/.
    • A folder with a mod.bn can be imported as a module.
  • Workspaces: a [workspace] with members builds several projects together, like Gradle multi-projects or Cargo workspaces.

    • burn init <name> --workspace creates the multi-target layout: a common library and one app per target (native, js, bvm).
    • Members are named under the workspace (github.com/you/game/common), import each other directly and share one burn.lock.
    • At the root, burn build/check/test cover every member, and -p <member> picks one.
  • Self-hosting: the lexer, the parser, the diagnostic renderer, the burn.toml reader, the module loader, the whole checker, the ownership pass and bvm code generation are ported to Burn (compiler/), and the compiler builds itself: scripts/bootstrap.sh (run by CI with stage0) checks that the compiler built by the Burn compiler rebuilds itself into the same bvm module. burn compiler/src/main.bn build <file.bn> compiles a program to bvm assembly that burn <file.bvm> runs.

  • The toolchain ships the compiler written in Burn as share/burn/compiler.bvm (built by itself when the toolchain is packaged), and --compiler burn makes burn run, burn check and burn build --target bvm use it. They produce output identical to the Rust compiler's, checked by burn dump --tokens, --ast, --diagnostics, --toml, --project, --modules, --decls, --checked, --owned, --index and --bvm on every Burn file in the repository and on project fixtures.

  • Docs: Burn standards explains how to name packages, files and code, how to lay out a project and workspace, and the conventions for imports, visibility, formatting, errors, tests and releases, with semantic versions for packages and the yearly versions (YY.RELEASE.PATCH) Burn releases use, with a table of every Burn release and how the next ones are numbered.

  • Fixed: when several names were equally close to a misspelled one, "did you mean" (and burn fix) picked one at random on each run; it now picks the first in alphabetical order.

  • Fixed: the "used before it is initialized" error could name a different chain of calls on each run when functions were called through values, and a use after destroy could point at a different destroy when there were several; both are now the same on every run.

  • Fixed: a pattern binding named like a function (Kind.Big(digits) with a fun digits in scope) was compared against the function instead of binding a new name.

  • Fixed: a stray non-ASCII symbol made the lexer loop forever, and an unknown escape before a multi-byte character crashed it.

26.1.0-experimental-2

The last release whose compiler is written in Rust. It is the stage0 compiler that bootstraps the compiler written in Burn (compiler/STAGE0).