Releases: atverm/m9c
Release list
M9 0.4.1
The M9 compiler m9c, the runtime libm9rt.a, the standard library as M9 source, the module reference, the compiler's man page and the VS Code extension files. gcc is the only toolchain any of them needs.
One package per distribution, x86-64, each built ON that distribution (the Ubuntu 26.04 one on a real 26.04 machine rather than a VM) from the one source tarball attached here (m9-0.4.1.tar.gz, sha256 bfb8d3f818c873cd4b49f617d28f7f84ed1b08f12066567c19235d277677c27d), then installed there and made to compile and run an M9 program with an empty environment before it was allowed to leave the build machine.
That tarball is the same set of files as this repository -- the compiler, runtime, standard library, gates, man page and module reference -- and the release tooling refuses to cut one that is not, checked both against the list and against an independent deny-list of paths that must never be published.
| distribution | package | install |
|---|---|---|
| Ubuntu 24.04 LTS | m9_0.4.1-1_amd64.ubuntu24.04.deb |
sudo apt install ./m9_0.4.1-1_amd64.ubuntu24.04.deb |
| Ubuntu 26.04 LTS | m9_0.4.1-1_amd64.ubuntu26.04.deb |
sudo apt install ./m9_0.4.1-1_amd64.ubuntu26.04.deb |
| Debian 13 | m9_0.4.1-1_amd64.debian13.deb |
sudo apt install ./m9_0.4.1-1_amd64.debian13.deb |
| Fedora 43 | m9-0.4.1-1.fc43.x86_64.rpm |
sudo dnf install ./m9-0.4.1-1.fc43.x86_64.rpm |
| Rocky 9 (RHEL 9, Alma 9) | m9-0.4.1-1.el9.x86_64.rpm |
sudo dnf install ./m9-0.4.1-1.el9.x86_64.rpm |
| Arch | m9-0.4.1-1-x86_64.pkg.tar.zst |
sudo pacman -U ./m9-0.4.1-1-x86_64.pkg.tar.zst |
What changed since the previous release
- m9c --check: check the module and its imports, print the diagnostics, write NOTHING -- no C, no header, no documentation. The exit code says whether the program exists. Built for editors: bare m9c writes NAME.h/NAME.c beside the file, which inside an editor is the generated-header-shadows trap armed on every save.
- m9lsp, a Language Server Protocol server written in M9, ships as library source (Lsp.m9): build it with
m9c --make -o m9lsp Lspagainst the installed library. It publishes diagnostics on open and save by runningm9c --checkand republishing the compiler's own messages with their positions -- it never lexes M9 itself, so an editor squiggle cannot disagree with the build. Chapter 0 of the tutorial carries Helix and Neovim configuration. - Io gains ReadStdin (one read(2); a stream has no whole, so the whole-file rule stands for files) and Flush (a server's reply must not sit in a buffer while it blocks on the next request).
- m9_cat_extend guards its fast path with integer comparisons: the old pointer comparison between different objects was undefined behaviour, seen as -Wstringop-overflow on
+with a literal left operand under newer gcc. Found by A. Vermeulen reading the runtime. - Release-note bullets are reflowed from the changelog (dpkg's 68-column wrapping is format, not prose), and the arch PKGBUILD's pkgver moved to 0.4.x with the guard that caught it standing.
Each .receipt records the distribution the package was built on, its sha256, the tarball's sha256, the gcc that built it, and the smoke line. Nothing here was modified after it came back from the build machine except the 3 debs' file names, which carry their distribution because they would otherwise be the same name (dpkg reads the control file, not the name).
Chapter 0 of the tutorial (M9Tutorial, tutorial.modula9.net) covers installation from these and from source.
M9 0.4.0
The M9 compiler m9c, the runtime libm9rt.a, the standard library as M9 source, the module reference, the compiler's man page and the VS Code extension files. gcc is the only toolchain any of them needs.
One package per distribution, x86-64, each built ON that distribution (the Ubuntu 26.04 one on a real 26.04 machine rather than a VM) from the one source tarball attached here (m9-0.4.0.tar.gz, sha256 c60fd267cf40ef7998681d8baedf00739047312833a40bde23d7ed509b684cfb), then installed there and made to compile and run an M9 program with an empty environment before it was allowed to leave the build machine.
That tarball is the same set of files as this repository -- the compiler, runtime, standard library, gates, man page and module reference -- and the release tooling refuses to cut one that is not, checked both against the list and against an independent deny-list of paths that must never be published.
| distribution | package | install |
|---|---|---|
| Ubuntu 24.04 LTS | m9_0.4.0-1_amd64.ubuntu24.04.deb |
sudo apt install ./m9_0.4.0-1_amd64.ubuntu24.04.deb |
| Ubuntu 26.04 LTS | m9_0.4.0-1_amd64.ubuntu26.04.deb |
sudo apt install ./m9_0.4.0-1_amd64.ubuntu26.04.deb |
| Debian 13 | m9_0.4.0-1_amd64.debian13.deb |
sudo apt install ./m9_0.4.0-1_amd64.debian13.deb |
| Fedora 43 | m9-0.4.0-1.fc43.x86_64.rpm |
sudo dnf install ./m9-0.4.0-1.fc43.x86_64.rpm |
| Rocky 9 (RHEL 9, Alma 9) | m9-0.4.0-1.el9.x86_64.rpm |
sudo dnf install ./m9-0.4.0-1.el9.x86_64.rpm |
| Arch | m9-0.4.0-1-x86_64.pkg.tar.zst |
sudo pacman -U ./m9-0.4.0-1-x86_64.pkg.tar.zst |
What changed since the previous release
- FRAME POOLS (report par 2.3): every procedure body allocates its intermediates from an implicit arena freed on exit, carried in the err slot rather than the signature, so the C ABI keeps one trailing parameter.
+concatenates strings into the frame -- it no longer allocates from the never-freed HEAP -- and a function can build and RETURN a string: the result lands in the CALLER's arena, with tail calls forwarding the destination.s := s + xin a loop is linear (the arena extends its top allocation in place); the fast path is not a guarantee and DynStr remains the accumulation API, as par 2.3 states. - RETENTION IS DECLARED, CHECKED, AND TRACED (report par 4.1). KEPT, the 61st keyword, follows a parameter's mode and declares that the callee stores the reference somewhere that outlives the call. The checker computes, per procedure, where every store's destination escapes to -- module state, the caller's storage through a parameter, the RETURN value, a callee -- and refuses an undeclared retention naming what it reaches and what to write. The declaration composes upward the way RAISES does: a borrow passed to a KEPT parameter must itself be declared, a concatenation passed to one is refused outright (it dies with the frame), and a borrow laundered through a local copy, an IS SOME or CASE-pattern binder, or a sub-slice is traced to its origin ("borrowed msg (carried by t) reaches module state"). A KEPT parameter never seen retained is reported back as the kept-unseen ledger class, so a signature cannot quietly overstate. The standard library declares its own retentions: about 120 KEPT marks, every one demanded by the checker rather than guessed. Both checkers are held to byte-identical diagnostics and ledgers over the whole corpus (semdiff, 62 probes).
- m9_err is m9_state, because it stopped being only about errors: the per-call slot now carries the RESULT ARENA of the frame-pool machinery -- where
+builds, and where a string-returning function leaves its answer for the caller -- beside the exception it always carried. C drivers written against 0.3.1's m9rt.h must rename the type; the generated C did the same. - A CONST may be declared inside a procedure; a local CONST that shadows a module CONST is refused rather than resolved.
- m9c -g emits #line directives, so gdb breaks, steps and lists in the M9 source rather than the C it became. Implies --keep-c; changes no other flag (not -O0: silently lowering optimisation under a debug flag would be flag-dependent semantics).
- PURE is checked: no write through VAR/OWN, no module-variable write, no allocation from a caller's pool, and -- the rule that carries the weight -- a PURE procedure may call only PURE procedures, which makes "no I/O" true without the checker knowing what I/O is.
- MONITOR fields are reachable only through the bound first parameter, enforced; the check found four programs reaching in from module bodies and improved all four.
- A repeated scalar CASE label is refused at compile time, where it is decided, instead of surfacing as a C error against generated code the author never wrote.
- The public repository now carries everything its gates compare against -- the must-not-compile museum, the checker probes, the parse probes, the benchmark programs, the Modula-2 and Object Pascal reference implementations -- so the differential claims can be re-run from a public checkout rather than taken.
Each .receipt records the distribution the package was built on, its sha256, the tarball's sha256, the gcc that built it, and the smoke line. Nothing here was modified after it came back from the build machine except the 3 debs' file names, which carry their distribution because they would otherwise be the same name (dpkg reads the control file, not the name).
Chapter 0 of the tutorial (M9Tutorial, tutorial.modula9.net) covers installation from these and from source.
m9 0.3.1
The M9 compiler m9c, the runtime libm9rt.a, the standard library as M9 source, the module reference, the compiler's man page and the VS Code extension files. gcc is the only toolchain any of them needs.
One package per distribution, x86-64, each built ON that distribution (the Ubuntu 26.04 one on a real 26.04 machine rather than a VM) from the one source tarball attached here (m9-0.3.1.tar.gz, sha256 2d361163bbcbfffa19c9a1b86ea4db55c98245cf84604ecbd52f7c594ad7c3d6), then installed there and made to compile and run an M9 program with an empty environment before it was allowed to leave the build machine.
That tarball is the same set of files as this repository -- the compiler, runtime, standard library, gates, man page and module reference -- and the release tooling refuses to cut one that is not, checked both against the list and against an independent deny-list of paths that must never be published.
| distribution | package | install |
|---|---|---|
| Ubuntu 24.04 LTS | m9_0.3.1-1_amd64.ubuntu24.04.deb |
sudo apt install ./m9_0.3.1-1_amd64.ubuntu24.04.deb |
| Ubuntu 26.04 LTS | m9_0.3.1-1_amd64.ubuntu26.04.deb |
sudo apt install ./m9_0.3.1-1_amd64.ubuntu26.04.deb |
| Debian 13 | m9_0.3.1-1_amd64.debian13.deb |
sudo apt install ./m9_0.3.1-1_amd64.debian13.deb |
| Fedora 43 | m9-0.3.1-1.fc43.x86_64.rpm |
sudo dnf install ./m9-0.3.1-1.fc43.x86_64.rpm |
| Rocky 9 (RHEL 9, Alma 9) | m9-0.3.1-1.el9.x86_64.rpm |
sudo dnf install ./m9-0.3.1-1.el9.x86_64.rpm |
| Arch | m9-0.3.1-1-x86_64.pkg.tar.zst |
sudo pacman -U ./m9-0.3.1-1-x86_64.pkg.tar.zst |
What changed since the previous release
- TLS is thread-safe: runtime/tlsshim.c shares one SSL_CTX built
under pthread_once instead of re-reading the system CA bundle per
connection, and claims its handle slots under a mutex held for the
bookkeeping only -- never across a handshake, a read or a write.
The four csock TLS procedures are [REENTRANT] rather than
[SERIAL], so concurrent HTTPS overlaps its waiting. The old shim
aborts on a double free under the new gate; the new one is clean
over five runs of eight concurrent fetches, every byte compared
(runtime/test/threads.sh). The handle table grew from 8 to 64. - m9c --make builds in dependency order, computed from the import
GRAPH. A first build from an empty directory used to fail and
succeed on the second run. - A bare main filename names its own directory, so
m9c --make -o p P.m9finds its imports where the file is. - Parse errors carry line, column and a message -- FILE:LINE:COL:
parse: MSG, the shape generator errors already had -- and both
parsers are held to the same wording by a differential. - The checker refuses a reversed NEW ("NEW takes the pool first,
then the type"), which only the generator used to catch. - Hardening reaches m9c: build.sh honours CPPFLAGS and LDFLAGS.
Each .receipt records the distribution the package was built on, its sha256, the tarball's sha256, the gcc that built it, and the smoke line. Nothing here was modified after it came back from the build machine except the 3 debs' file names, which carry their distribution because they would otherwise be the same name (dpkg reads the control file, not the name).
Chapter 0 of the tutorial (M9Tutorial, tutorial.modula9.net) covers installation from these and from source.
m9 0.3.0
The M9 compiler m9c, the runtime libm9rt.a, the standard library as M9 source, the module reference, the language report and the VS Code extension files. gcc is the only toolchain any of them needs. FLEXPART-M9 is not in these packages.
The source tarball m9-0.3.0.tar.gz has been WITHDRAWN from this release (2026-08-30). It was cut with a bare git archive HEAD of the development tree, so it carried far more than this repository does: the project's internal working notes, the CI workflow, and all 51 source files of the FLEXPART port, none of which belong in a public release. It contained no credentials, keys or tokens. The packages below are unchanged and are what this release is for; their receipts still name that tarball's sha256, and are left as they were rather than quietly rewritten.
From v0.3.1 the source tarball is cut from the same list that produces this repository -- 223 files: the compiler, runtime, standard library, gates, man page and module reference -- and the release tooling refuses to build one that is not. Checked twice: that the tarball equals the list, and, because that check alone passes if the list itself is wrong, against an independent deny-list of paths that must never be published.
One package per distribution, x86-64, each built ON that distribution (the Ubuntu 26.04 one on a real 26.04 machine rather than a VM), then installed there and made to compile and run an M9 program with an empty environment before it was allowed to leave the build machine.
| distribution | package | install |
|---|---|---|
| Ubuntu 24.04 LTS | m9_0.3.0_amd64.ubuntu24.04.deb |
sudo apt install ./m9_0.3.0_amd64.ubuntu24.04.deb |
| Ubuntu 26.04 LTS | m9_0.3.0_amd64.ubuntu26.04.deb |
sudo apt install ./m9_0.3.0_amd64.ubuntu26.04.deb |
| Debian 13 | m9_0.3.0_amd64.debian13.deb |
sudo apt install ./m9_0.3.0_amd64.debian13.deb |
| Fedora 43 | m9-0.3.0-1.fc43.x86_64.rpm |
sudo dnf install ./m9-0.3.0-1.fc43.x86_64.rpm |
| Rocky 9 (RHEL 9, Alma 9) | m9-0.3.0-1.el9.x86_64.rpm |
sudo dnf install ./m9-0.3.0-1.el9.x86_64.rpm |
| Arch | m9-0.3.0-1-x86_64.pkg.tar.zst |
sudo pacman -U ./m9-0.3.0-1-x86_64.pkg.tar.zst |
Each .receipt records the distribution the package was built on, its sha256, the tarball's sha256, the gcc that built it, and the smoke line. Nothing here was modified after it came back from the build machine except the two debs' file names, which carry their distribution because they would otherwise be the same name (dpkg reads the control file, not the name).
Chapter 0 of the tutorial (M9Tutorial, tutorial.modula9.net) covers installation from these and from source.