Skip to content

M9 0.19.0

Choose a tag to compare

@atverm atverm released this 09 Oct 13:11

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.19.0.tar.gz, sha256 5972d0860218d51273fddf3b30e4b6213195b41e026409d984d21295060d1583), 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.19.0-1_amd64.ubuntu24.04.deb sudo apt install ./m9_0.19.0-1_amd64.ubuntu24.04.deb
Ubuntu 26.04 LTS m9_0.19.0-1_amd64.ubuntu26.04.deb sudo apt install ./m9_0.19.0-1_amd64.ubuntu26.04.deb
Debian 13 m9_0.19.0-1_amd64.debian13.deb sudo apt install ./m9_0.19.0-1_amd64.debian13.deb
Fedora 43 m9-0.19.0-1.fc43.x86_64.rpm sudo dnf install ./m9-0.19.0-1.fc43.x86_64.rpm
Rocky 9 (RHEL 9, Alma 9) m9-0.19.0-1.el9.x86_64.rpm sudo dnf install ./m9-0.19.0-1.el9.x86_64.rpm
Arch m9-0.19.0-1-x86_64.pkg.tar.zst sudo pacman -U ./m9-0.19.0-1-x86_64.pkg.tar.zst

Windows — experimental

m9-0.19.0-windows-x86_64.zip (sha256 631c8502480a38952ef3ecbe3c120448957bb8ab49bbbc4824ac8c05dad09790) is one folder with everything in it: its own gcc (a subset of the MSYS2 UCRT64 toolchain, measured by tracing real builds), the compiler's bootstrap C, the standard library and tools as M9 source, the tutorial as pages, and an install.bat that compiles the compiler on your own machine — the same "gcc is the only toolchain" claim as above, with the gcc in the box. Unpack it anywhere and run install.bat from a terminal; it says what it will do and asks before it touches your PATH or your VS Code extensions.

Experimental means experimental. It is the same compiler as the Linux one — the runtime carries _WIN32 paths beside the POSIX ones and the generated C never names a platform — but it is verified under wine and on one Windows machine, where Linux is tested across six distributions. Two of the tutorial's twenty-nine examples do not work there yet: chapter 14 (netCDF resolves paths through its own Windows converter) and chapter 17 (it runs sort and uniq). The rest, zarr over TLS and the threaded chapters included, runs.

macOS — experimental

brew tap atverm/m9 && brew install m9

installs this release on a Mac from the same source tarball, built there with Homebrew's gcc, and with OpenSSL, blosc and netCDF from Homebrew, so a program that opens an https URL, reads a zarr chunk or writes a netCDF file links on the first try. m9-0.19.0.rb (sha256 3f02d282750228519d6eb09c5c99e6e05a54b0aa9564786b02e54fe59d0ae770) is the formula the tap carries; its receipt records the Mac it was installed and smoke-tested on (26.5.1 arm64, gcc-16 (Homebrew GCC 16.2.0) 16.2.0).

Experimental means experimental. It is the same compiler — every macOS difference in the runtime and the driver is under __APPLE__ or macos and the generated C never names a platform — verified on one Apple-silicon Mac, where Linux is tested across six distributions; Intel Macs are untested. The whole tutorial runs there, zarr over TLS and the threaded chapters included.

What changed since the previous release

  • Io's text files are UTF-8: Io.ReadFile decodes (strictly -- a file that is not UTF-8 raises ValueRange), Io.WriteFile and the new Io.AppendFile encode every Unicode scalar, and a PATH is UTF-8 in every Io call (Grib.Open's too). Until now one CHAR was one octet and WriteFile refused a scalar past 255, while the console was UTF-8: nothing in Io wrote text, and a UTF-8 file read and printed came out double-encoded (cp-kernel, on 0.18.0). NOT SOURCE COMPATIBLE for a program that held octets as CHARs through ReadFile/WriteFile: it reads and writes them through ReadFileBytes/WriteFileBytes with DynStr.Bytes/Chars (the tutor's cell sources, three sites). HttpServer serves a file whose name is not ASCII from the right path now.
  • m9c --make treats a missing generated header as stale: a build directory whose .h files were deleted but whose objects stayed failed on a fresh module's missing header.
  • A FOR "C" unit names what it links: UNSAFE DEFINITION MODULE FOR "C" cnc LINK "netcdf" ; -- a library name, a linker word as it is (-l:libblosc.so.1; -lblosc where ld64 or mingw links), a shim source beside the runtime (pgshim.c) -- and m9c puts the closure's words on every link it supplies: the flagless -o, --so, --run and --cell. NetCDF, Grib, ZarrStore and Pg name theirs, so a program importing one links with no flag and runs under m9c --run; the tutorial's build recipes are m9c -o. A line taken over after -- still names everything itself. LINK is the 62nd keyword.
  • A string literal beyond ASCII compiles: the source is UTF-8 and a literal holds scalars ('déjà' is four CHARs, 'é' fits a CHAR). It was non-ASCII string literal unsupported yet.
  • IndexError carries (index, length : I64) -- the index and the length as the check saw them -- and | IndexError (i, n) : binds two typed I64s. The predeclared exceptions bound nothing until now.
  • ADR (x) has a type, C.Ptr, which fits a C.ConstPtr or C.MutPtr parameter and nothing else; every ADR argument of every foreign call was passed over by the checker until now (the review pages' last passed-over class, 225 sites, is at zero).
  • Windows: every path is UTF-8 -- the runtime converts to UTF-16 and opens with the wide calls -- so a file whose name is not ASCII is found there too.
  • macOS: m9test's and m9c's gates run there (the linker's words).
  • cp-kernel's issues on 0.18.0 (github.com/atverm/m9c/issues 1-12): a CONST built with + over string and CHAR literals is one literal (it passed the checker and the generator refused it), and a CONST form the generator cannot emit is refused by the checker by name (#1); a FOR inside a FOR over the same control variable is refused (#3, it compiled and ran wrong); Text.Compare orders two strings by code point, Sort.Strs's order (#5); Fmt's page points at Io.ParseI64 (#6); Http.GetToFile writes nothing on a status other than 200 (#7, a 404 page used to land in dest); Io.MkDirs makes the missing parents (#9); m9c --json lists an exception's payload as params (#11); #2 (literals beyond ASCII) and #12 (the link line) are the entries above.
  • cp-kernel's second batch (issues 13-19): a CASE over an enumeration may spell its labels qualified -- Store.Fs -- and is held total like the bare spelling (#13, the generator refused it); Zip.CrcAt reads a member's CRC-32 from the central directory (#14); Zip.Crc32Update carries a CRC-32 over pieces, zlib.crc32 (b, crc) (#15); Fmt.Hex (v, width), lower case, a negative v as its 64-bit pattern (#16); Http.NewForm/FormField/FormBytes/FormBody/FormType build a multipart/form-data body whose boundary occurs in no part (#17); Io.WriteBytes puts octets on standard output through the buffer Write uses (#18); Text.ToBase64Url/FromBase64Url, base64url without padding (#19).

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.