Blaise v0.10.0 (alpha) โ€” Mandatory `()`, Native Backend, Threads & Incremental Compilation ๐ŸŽ‰ ยท graemeg blaise ยท Discussion #82

4 min read Original article โ†—

Hey everyone! We're thrilled to announce Blaise v0.10.0 โ€” our biggest release yet, packing in a native x86-64 backend, thread support, incremental separate compilation, and a language-level clarity win that makes Blaise code unambiguous at a glance.

Let's dive in! ๐Ÿš€


๐Ÿ”ง Mandatory () on Zero-Argument Calls

The headline language change: Blaise now requires parentheses on every call, even with zero arguments.

// โœ… The Blaise way
F := TFoo.Create();
Obj.Free();
X := GetCurrentDir();

// โŒ No longer accepted
F := TFoo.Create;
Obj.Free;
X := GetCurrentDir;

No more guessing whether Foo is a variable read or a function call โ€” Foo is always a read, Foo() is always a call. This eliminates the classic Pascal ambiguity between Result assignment and recursion, makes grep a reliable way to find call sites, and let us delete the entire IsNoArgFuncCall machinery from the compiler internals. Three latent codegen bugs were flushed out in the process. ๐Ÿ›โ†’๐Ÿฆ‹

We also added proper procedure-field invocation: Obj.Handler() dispatches through the stored code pointer, while Obj.Handler reads the field value.

For the full rationale, see the separate announcement post.

๐Ÿ–ฅ๏ธ Native x86-64 Backend

Blaise now ships with a direct x86-64 code generator alongside the QBE backend. Milestones M1 through M8 are complete:

  • Integer and float arithmetic, control flow, for/while/repeat loops
  • Records, static arrays, dynamic arrays, open arrays
  • Full class system: method dispatch, vtables, constructors, destructors
  • ARC retain/release for strings, classes, and interfaces
  • Interface dispatch through itab
  • Exception handling (try/except/finally)
  • String operations at parity with the QBE backend
  • Var/out parameters and inherited calls
  • Generics support (monomorphised classes, records, interfaces, free routines)
  • For-in and case statements

The native backend is invoked with --backend native or --target linux-x86_64. It produces ELF .o files directly โ€” no external assembler needed. ๐Ÿ’ช

๐Ÿงต Thread Support

Blaise gains first-class threading capabilities:

  • threadvar declarations for thread-local storage
  • Atomic ARC โ€” reference counting is now thread-safe via atomic increment/decrement
  • Mutex-protected weak reference table โ€” weak refs work correctly across threads
  • Per-thread memory allocator via threadvar โ€” reduces lock contention
  • Thread-local exception globals โ€” each thread gets its own exception frame chain
  • TThread.Create(False) now correctly joins on Free() via ARC

All of this is exercised through e2e tests that spawn real threads. ๐Ÿงช

โšก Incremental Separate Compilation

The compiler now supports incremental per-unit compilation, a major step towards fast rebuild cycles:

  • .bif (Blaise Interface File) format โ€” a compact serialisation of a unit's public interface, embedded inside the .o file
  • --incremental flag: only recompile units whose source has changed; reuse cached .o + .bif for unchanged deps
  • Parallel incremental compilation via worker threads โ€” multiple units build concurrently
  • Warm incremental recompile resolves all EImportError crashes that previously occurred when reusing stale interface data

The .bif format covers constants, types (simple, record, class, interface, generic templates), routines, global variables, inline bodies, and calling convention directives.

๐Ÿ“ฆ Language & Standard Library

  • Diamond operator โ€” var L: TList<Integer> := TList<>.Create() infers the type argument from the left-hand side
  • Exit(Value) shorthand โ€” 305 sites across the compiler dogfood this feature
  • not on integers โ€” bitwise complement for Integer, Byte, Word, SmallInt, Int64
  • Set-valued constants โ€” const X = [a, b] and set literals as set of arguments
  • out parameter mode tracked distinctly from var
  • Calling convention directives (cdecl, stdcall) preserved on routine declarations
  • WriteLn prints True/False for Boolean values
  • Unsigned 32-bit values print correctly in WriteLn
  • TStringList.Text / LoadFromFile preserve verbatim lines (no more trimming)

๐Ÿ› ๏ธ Compiler Improvements

  • --dump-ast flag โ€” prints the fully resolved AST after semantic analysis, invaluable for diagnosing codegen issues
  • Unit-prefix symbol mangling โ€” free routines, classes, and address-of expressions are mangled with their owning unit name, enabling true multi-unit builds without symbol collisions
  • Per-unit symbol cache for fast uses-chain retrieval
  • Layered symbol lookup โ€” current-unit symbols shadow uses-chain, matching Delphi/FPC semantics

๐ŸŽฏ Kanban Tool

The built-in TUI Kanban board (tools/kanban/) gained several improvements:

  • CLI mode for non-interactive task creation
  • UTC datetime storage with local display
  • External file change detection and merge
  • Rounded box-drawing corners and coloured borders

๐Ÿ“Š By the Numbers

  • 2627 tests passing โœ…
  • 262,202 lines of verified QBE IR at fixpoint
  • 130+ commits since v0.9.0
  • FIXPOINT_OK โ€” self-hosting verified โœ…

Grab the release from the GitHub Releases page and see the changelog for the full list of changes.

We'd love to hear your thoughts โ€” drop a comment, open an issue, or just say hello! ๐Ÿ‘‹

Onwards to v0.11.0! ๐Ÿ™Œ


Built with โค for the Pascal community.