Skip to content

Blaise v0.13.0 — Changelog

Latest

Choose a tag to compare

@graemeg graemeg released this 11 Jul 15:00

Changes since v0.12.0 (266 commits: 113 feat, 95 fix, 26 test, 19 docs).

Async runtime & concurrency

  • Stackful fibre foundation: context switch, trampoline, guard-page stacks (L0);
    per-fibre exception state preserved across FiberSwitch.
  • Fibre scheduler: timer heap + run queue, single-worker then N-worker
    multicore
    scheduler over a Chase-Lev work-stealing deque, with a
    persistent worker-thread pool.
  • Structured concurrency: TTaskGroup nursery, fibre-aware synchronisation
    primitives, fibre root exception frame and cancellation.
  • epoll readiness reactor (L2) wired to the scheduler idle-park.
  • Fibre I/O primitives (L3) and a WouldBlock errno-classification leaf.
  • Allocator work supporting the runtime: pointer-width atomics, per-arena MPSC
    remote-free queue + owner drain, widened block headers with owning-arena
    back-pointer, munmap of large foreign frees (P4), abandoned-arena
    reclamation (P5).

Networking stack (stdlib, fibre-native)

  • Net.Tcp over async.io; Net.Tls client/server over an OpenSSL memory-BIO
    provider (L4); Net.Uri URL/URI parser and builder.
  • HTTP/1.1: fibre client (Net.Http.Client, with HTTPS) and a
    fibre-per-connection keep-alive server.
  • WebSockets (RFC 6455): fibre-per-connection server and a masked-frame
    client.
  • Mail: SMTP (AUTH + dot-stuffing), POP3, IMAP4rev1 clients.
  • FTP client and passive-mode server; NNTP client and server.
  • E2E loopback round-trip tests for TLS, HTTP, WebSocket, SMTP, FTP, and NNTP.

Language

  • Anonymous methods / closures (Phases 0–10): reference to types,
    capture-free literals, strong environment-record capture, Self capture +
    method-pointer coercion, block-scoped/per-iteration capture, [Weak Self],
    composition with generics, closure Spawn + closure-argument ABI, a
    Functional type vocabulary, terse -> lambdas with target-typed inference,
    two-phase deferred lambda inference in argument position, generic methods on
    generic classes, and eager LINQ-lite (Where/etc.) + closure Sort on
    TList<T>.
  • Static (class-level) members within a unit and carried across separately
    compiled units: static var, static function, static properties; qualified
    static-var writes (TFoo.X := V); visibility enforcement
    (private/protected/strict) on bare and qualified static access.
  • Custom attributes reified: method-level attributes with constructor
    arguments.
  • Inline assembler: asm … end routine bodies.
  • Units: unit-qualified references (UnitName.Symbol), cross-unit last-wins for
    types/consts/vars, unit-qualified type disambiguation, directed lookup for
    qualified field access.
  • Enums: type-directed resolution of bare enum members; qualified
    TEnum.Member.
  • Types: forward class and interface declarations; named integer subrange as an
    array index type.
  • Lexer: #nnnn / #$hhhh Unicode-codepoint string literals.
  • External lib name directive; link-library deps passed to the linker as
    -l<name>.

Examples

{ closure capturing an outer local }
type TIntFunc = reference to function(X: Integer): Integer;
var
  Add: TIntFunc;
  N: Integer;
begin
  N := 10;
  Add := function(X: Integer): Integer begin Result := X + N end;
  WriteLn(Add(5));                 { 15 }
end.
{ '->' lambda + LINQ-lite }
uses Generics.Collections;
var
  L: TList<Integer>;
  Sum, X: Integer;
begin
  L := TList<>.Create();
  L.Add(1); L.Add(2); L.Add(3); L.Add(4);
  Sum := 0;
  for X in L.Where(x -> x mod 2 = 0) do
    Sum := Sum + X;
  WriteLn(Sum);                    { 6 }
  L.Free();
end.
{ static class-level members }
type
  TCounter = class
    static var Total: Integer;
    static function Next: Integer;
  end;

static function TCounter.Next: Integer;
begin
  TCounter.Total := TCounter.Total + 1;
  Result := TCounter.Total
end;

Targets & toolchain

  • FreeBSD x86_64 target: self-hosting, byte-identical native fixpoint on
    FreeBSD, bidirectional Linux⇄FreeBSD cross-compilation with no external tools;
    target-driven OS defines, per-target RTL unit list, syscall leaves, libc-free
    threads/TLS, and freestanding _start. FreeBSD fixpoint + full suite run in
    CI under emulation.
  • RTL unification: RTL units relocated into the compiler tree (dotted-flat
    names); RTL built from source on every link path; the internal assembler
    assembles the Pascal RTL; blaise_rtl.a dropped from all self-host link
    lines. IsUnmangledUnit recognises the runtime. prefix.
  • libc-free static Linux binaries: direct-syscall kernel leaf, tiered
    freestanding libc leaves, clone/futex threads, static TLS + mutex stubs; a
    fully static binary links and runs.
  • Internal assembler gained SSE2 + AVX2/VEX encoders, lock prefix,
    xadd/neg, xchgq/cmpxchgq (REX.W), unsuffixed mnemonics,
    mem-indirect jmp, endbr64/hlt/syscall; strips @PLT.
  • Internal linker ships its own _start (drops system CRT), honours
    --target's TLinkTarget, resolves duplicate globals via the canonical
    symbol table, resolves absolute 32-bit relocations in static mode.
  • BLAISE_BACKEND selects the backend when --backend is absent.

Codegen & ARC (fixes)

  • GH #174: bare RTL class/interface/global symbols (typeinfo, vtable,
    _FieldCleanup, methods, itab, impllist, unit globals) now emitted weak
    in both backends, so the --no-incremental archive and whole-program QBE
    links no longer collide.
  • Float value width matched to slot/param width at store + spill sites;
    unsigned 32-bit values zero-extended into 64-bit slots; scalar RHS
    widened/converted on pointer-deref store.
  • Record-return ABI: sret buffer for discarded record-returning method calls;
    record-returning property getters use sret; inherited record-by-value returns
    thread the sret pointer; self-assigned record method no longer aliases Self.
  • itab dispatch of a record-returning method fixed on both backends; itab ref
    for a non-virtual inherited interface method (#130 bug3).
  • ARC: release string transients passed to Write/WriteLn; release
    static-array-of-interface elements at scope exit; nested-proc capture of
    outer var-param records/arrays; native ARC of managed fields on record copy;
    statement-scoped deferred class-release (BUG-003, both backends);
    discarded class-returning call result released.
  • Native: @threadvar TLS address; call-site 16-byte alignment under pinned
    pushes; spill implicit-Self args beyond six registers; record/aggregate
    threadvars via TLS; honour owning unit for module globals.
  • Empty loop body no longer crashes the compiler (#150); mandatory parentheses
    on statement-position calls (#148); parentheses required on inherited calls.

Semantic

  • Reject colliding same-named generic declarations across units (GH #171).
  • Thread method Self into classic nested routines (BUG-008).
  • Reject non-lvalue var/out actuals at every call form (BUG-011).
  • Warn when a for-in loop variable is written (BUG-001).
  • Reject class methods declared but never implemented; reject unsupported
    memory-builtin forms with a native unknown-proc fall-through guard (BUG-035).
  • Scope same-named nested routines to their enclosing body; tolerate
    implementation-section circular dependencies.

Debugging (OPDF)

  • recRuntimeHelper records for RTL release routines; complete recProperty
    layout (method-name strings); recPrimitive for Double/Single; pointer
    type record for PChar; escape string-constant values in the recConstant
    .ascii line; shared CodegenMangle for class vtable symbol names.

stdlib

  • Security.Crypto: SHA-256, MD5, HMAC-SHA256, ConstantTimeEqual (plus
    existing SHA-1/Base64).
  • Xml read/write (Types/Parser/Reader/Writer).
  • Generics.Collections: release managed elements in TList;
    TObjectList.Remove(AObject).
  • SysUtils.SameFileName; StrToInt/StrToInt64 raise EConvertError on
    invalid input.

Tooling / CI

  • Separate-compilation .bif interface fixes: round-trip external-name linkage
    of free routines (IFACE v9), serialise the overload directive; unit-cache
    validation keyed on a hash of the compiler binary (BUG-007).
  • Typed [TestCase] parameterised tests + attribute vocabulary in
    blaise.testing; bif-coverage builds by default.
  • CI builds vendored QBE for E2E; FreeBSD fixpoint + full suite job.

Verification

  • Self-hosting fixpoint: 498,507 lines of QBE IR, byte-for-byte stable.
  • All four fixpoints green: FIXPOINT_OK, NATIVE_FIXPOINT_OK, NATIVE_INTERNAL_OK,
    WARMCACHE_FIXPOINT_OK.
  • 4275 tests passing (Linux and FreeBSD).