Skip to content

Loment 0.1.4.5

Choose a tag to compare

@FujoJTOP FujoJTOP released this 13 Oct 01:36
· 623 commits to main since this release
5b4a371

Loment 0.1.4.5

Three things were announced in
v0.1.4.5-pre while they were still
being built; they are in this release, along with the fixes that accumulated since 0.1.4.

This is not an exhaustive changelog — the issue and pull-request numbers below are the index.

Install

Asset
loment-0.1.4.5-linux-x64.tar.gz Linux x86-64. Unpack anywhere; bin/loment is the launcher.
loment-0.1.4.5-windows-x64.zip Windows x86-64. Unzip and run install.cmd.
loment-0.1.4.5-windows-x64-setup.exe Windows x86-64, self-extracting. Double-click.
loment-skill.zip The agent guide (SKILL.md) on its own, for people who want only that.
SHA256SUMS Checksums. The installers verify the payload against this before copying anything.

Installing and running needs no Python, no clang and no WSL — the package is native binaries plus
the standard library. loment run hello.lomt and you are done.


New

LomentGC — reclamation as a ladder

Reclamation in Loment is not one algorithm over one heap. Every alloc site is assigned, at compile
time, to one rung of a ladder, and how much of this program's memory the collector is responsible
for
is a number carried in the artifact:

Rung What it does
L0 static promotion — a provably non-escaping allocation never reaches the heap at all
L1 last-use — the allocator front is returned right after the final use
L2 block epochs — a loop body, or either arm of an if, that allocates and drops returns its whole region at once
L3 mark-sweep with precise roots, triggered by bytes allocated

All four rungs are implemented twice — the reference compiler (tools/lomentc.py) and the
self-hosted one (loment/selfhost/) — and the two must agree byte for byte (#109, #110, #143, #157).
The tiers choose gc_manual / choose gc_auto / choose gc_auto_alpha select how far down the
ladder a unit is allowed to go. Potato v10 carries gc_ladder = {l0, l1, l2, l3, total_sites},
and two independent validators check the arithmetic (l0 + l1 + l2 + l3 == total_sites) without
reading a single line of source (#172).

The gc_auto_alpha policy is no longer one fixed threshold: it follows the live set (#200) and
collects generationally — a 1024-entry card table, a write barrier at every store8 site, and
minor / major levels (#230). The difference that matters between the tiers is not throughput but
the ceiling: on loment/examples/gc_heap/ — the repository's first program that really builds on
the heap (#264) — the same linked-list walk runs to completion under gc_auto and gc_auto_alpha
and exhausts the arena under gc_manual. Numbers in docs/210 §7.

Networking, on both targets

The same .lomt source opens a socket on Linux and on Windows, from the same output bytes. On
ELF the calls are the Linux syscalls directly; on PE the runtime dispatches 29 syscall numbers —
eight for files and processes, and the whole network surface through ws2_32: the sockets plus
poll, select, sendmsg / recvmsg, socketpair and epoll_* (#191 and the batches in
docs/217). As of this release no networking syscall is left
unimplemented
on either target. syscall7 fills all six argument registers, so address-carrying
UDP — sendto / recvfrom, where the sixth argument is the socklen_t — is writable in the
language (#199). tools/loment_pe_test.py walks the whole surface by having a program connect to
itself.

lompi, the package manager

lompi moves to 0.2.0 Alpha and fetches by itself: lompi fetch reads the registry over a
raw socket instead of printing a git clone for you to run (#267). What it cannot do is HTTPS or
hostnames — there is no TLS and no resolver in the toolchain, so http:// with an IPv4 literal is
the whole fetchable surface (docs/236). Along the way the store
argument became optional, instance identity stopped re-reading the store, and --opt reached the
packaging path (#183, #188).

Two smaller features

  • register <name> { ... } — declare a loment subcommand from source instead of hand-placing
    a loment-<name> executable on PATH (#208).
  • The escape hatch, end to end — loment build --opt, a pre-optimized kernel object, and
    lompi obj, for the cases where the native toolchain's lack of an optimizer is the thing in your
    way (docs/212, #179, #195).

Fix

  • The Windows installer works. (#117) — 0.1.4's
    self-extracting setup.exe unpacked and exited having installed nothing: it launched install.cmd
    by bare file name, and where NoDefaultCurrentDirectoryInExePath is set, cmd cannot resolve
    that. The launch command now carries the unpack directory. The 0.1.4 asset itself is not being
    rebuilt
    — that would change the bytes under a version number already in the wild — so 0.1.4 users
    should stay on the zip until they move here.
  • The installers now name a shadowing lompi / loment. They only ever append to PATH
    (deliberately: an installer should not reorder a machine it does not own), so a copy installed
    earlier by hand wins silently — you type lompi version and get the older build with nothing
    explaining why. Both scripts now resolve the names after installing and print the path that is
    actually in front, without removing it.
  • lomelf can link an L0-promoted product. An alloca used as a plain SSA value was not
    recognised, so a unit whose alloc sites were all promoted to the stack could not be linked at all
    (#239, #257). The same fix moved the write barrier
    to follow "does this unit need a heap", which had been emitting a reference to an arena that
    L0-promotion had removed.
  • Two IR bugs that made array-subscript artifacts invalid LLVM (#177), and a release-manifest
    ordering bug that made every pull request look conflicted (#138).
  • Entry points are correctly aligned: stackrealign is now emitted on _start, whose stack is 8
    bytes off the SysV convention (#206). Binary operators are typed by the expected type rather than
    by their operands (#204), and loment fmt refuses a file written in a non-native surface grammar
    instead of destroying it (#115, #203).
  • The surface-grammar translators, in batches. About thirty issues fixed in the C, Python and
    other choose write grammar paths — silent drops, silently-wrong values, and files that failed to
    compile with a generic error instead of saying what was unsupported: the issues are #74,
    #115–#137 and #145–#155, and one language server crash (#142); the batches that fixed them are
    #171, #180 and #201. (docs/211 is how they were found: a
    pure-Loment project written in each surface grammar.)
  • Two flaky criteria were made deterministic (#190, #261); flaky checks turn unrelated pull
    requests red and cost every contributor time.

What else

Not in this release.

  • choose hosted — the dimension for artifacts that link real libc and shared libraries — is
    refused by a release build, by name (docs/222 sec 4.5,
    docs/219 sec 8c, #207, #258). The capability is in the development
    channel; calling libc from a 0.1.4.5 build is not offered.
  • The vm dimension is in main and is refused by a release build the same way — it is a
    gate, not a feature, and an extension module's bytecode does not exist yet.
  • The development side is not self-hosted. The toolchain compiles and runs with no Python at run
    time, but the reference implementation (tools/lomentc.py and friends) and the Python test suites
    are still in the repository (docs/189). "The repository contains
    only Loment" is not yet true.
  • There is no networking library and no admission gate. std has no net module — you write the
    syscalls yourself — and a unit that declares excluded "network: ..." is not stopped from calling
    socket, because the capability check compares domain names and never looks at behaviour
    (docs/218).

Known bugs, still open. The ones most likely to be met, with their issue numbers:

  • #164 — free checks neither ownership nor
    double-free, so freeing twice puts one region both at the frontier and on the free list, and two
    live allocations alias. Also #165: the Rust
    backend lowers free to a no-op.
  • #265 — a function with 11 or more parameters makes
    the self-hosted compiler die with SIGILL, silently, where the reference implementation accepts it.
  • #163 — lompi truncates any source file larger
    than 256 KiB, and the content-hash identity covers only the truncated part.
  • #226 — a flat expression of ~250 terms makes
    check die with a RecursionError instead of a diagnostic.
  • #149 — check does not check the bodies of
    modules brought in by use, so a library can ship with a body type error and every consumer checks
    clean. #139: two files that declare the same
    module name pass check and then produce IR with two define i32 @f.
  • #262 — both language servers ignore the
    choose write grammar declaration, so a valid file in a non-native grammar reports false
    diagnostics.
  • #237,
    #236,
    #235,
    #234,
    #218 — the same program can compute different
    numbers depending on which surface grammar it is written in: integer widths, block scope, and a
    bool parameter that cannot be called.
  • #205,
    #224 — two places where the reference compiler
    emits invalid or wrongly-typed LLVM (pointer comparison; bool arithmetic).
  • #160–#162,
    #167,
    #168,
    #159,
    #166 — capability-audit bounds, unchecked input
    parsing in lomelf and lomt_from.py, dependency paths with no containment check, and a VS Code
    extension that declares no untrusted-workspace capability.
  • #266 — one networking criterion is still flaky.

Two version numbers inside lompi. The package manager reports lompi 0.2.0; the standard
library it ships and installs is the bundle stamped 0.1.0 (lompi list shows std 0.1.0 and
host 0.1.0). They are different axes — the library bundle did not change in this release — but the
two numbers sitting next to each other is a fair thing to trip over (docs/170).

The language surface is frozen (docs/158 says what changing it
costs); the implementation is not. What 0.1.4 included, listed item by item and audited, is in
docs/202.