Releases: aether-lang-dev/aether
Release list
Aether 0.472.0
What's new in 0.472.0
Fixed
- FreeBSD build break in
fs.mounts.MNT_NODEVwas used unguarded in
the BSDgetmntinfobackend. FreeBSD deprecated that flag and removed the
macro in FreeBSD 10, while macOS and OpenBSD still define it, so the
fallback path had never been compiled anywhere and the break only appeared
on FreeBSD. The flag is now probed with#ifdefrather than keyed on the
platform, so a future removal elsewhere degrades to omitting the option
instead of failing the build. - NetBSD was claimed but never buildable. It sat in the same
getmntinfobranch, but there the call fills astruct statvfsand the
flag field isf_flag, notf_flags, so that body could not have
compiled. NetBSD now falls through to the unsupported branch and reports
the error, matching the module's convention of degrading rather than
fabricating, instead of shipping a shape nobody has built.
Added
make ci-optional-macros, a portability probe, now step 10 ofmake ci. It recompiles the affected sources with each guarded platform macro
forced absent, so both sides of every#ifdefare built on every run.
This reproduces the FreeBSD failure above on any host: verified by
reintroducing the bug and watching the probe fail, then restoring the fix
and watching it pass. Registering a new guarded macro is one line.
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.472.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.472.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.472.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.472.0-windows-x86_64.zip |
|
| FreeBSD | x86_64 | aether-0.472.0-freebsd-x86_64.tar.gz |
cross-built, not tested on FreeBSD |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.472.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/aether-lang-dev/aether#readme
Aether 0.471.0
What's new in 0.471.0
Fixed
- Repository URLs pointed at the pre-rename organisation. Every
github.com/aether-lang-org/...reference (57 across the README, LLM.md,
docs,get.sh, the release workflow, Docker scripts and the Makefile) now
namesaether-lang-dev. They had been resolving only through GitHub's
rename redirect, a silent dependency that breaks the install one-liner,
the release pipeline's crossbuild checkout and every documented clone
command the day it lapses. Each rewritten target was verified to resolve,
including theraw.githubusercontent.comone-liner and the workflow's
repository:field, neither of which is agithub.comURL. The
servirtium-vcrlinks were wrong independently of the rename: that repo
lives in theservirtiumorg and never existed under Aether's (LLM.md
already said so in one place), so those five now point at
servirtium/servirtium-vcr.CHANGELOG-archive.mdkeeps its historical
URLs as written.
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.471.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.471.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.471.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.471.0-windows-x86_64.zip |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.471.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/aether-lang-dev/aether#readme
Aether 0.470.0
What's new in 0.470.0
Fixed
- Benchmark runner reported a negative
cv_pct(#1352). The
coefficient of variation was computed as(best - worst) * 50 / meanin
32-bit int, so for the fastest patterns (skynet and counting run in the
hundreds of millions of msg/sec) the multiply overflowed before the
divide and the result came out negative, on exactly the numbers most
likely to be quoted. Span, mean and CV are now 64-bit, the run
accumulator is too (five runs at 250M already approach the int32
ceiling andBENCH_RUNSis user-settable), and a negative value is
refused rather than published, since a coefficient of variation cannot
be negative.docs/performance-benchmarks.mdstates the guarantee. - Constant folding did not preserve runtime semantics for
int, which
is what let the overflow above hide during development. The folder
evaluates indouble, so(250000000 - 200000000) * 50 / 225000000
folded to11while the same expression overintvariables evaluated
to-7: the literal form looked correct. The fold now wraps exactly as
the runtime does and reports the overflow (newwarning[W1003], with
the exact value, the wrapped value, and how to widen). No code in the
tree trips it. benchmarks/http/baseline_results.txtwas committed containing only a
header (#1353). The harness writes the header, starts the server, then
measures; the server had failed to start,set -eexited, and the stub
was committed. The generated file is removed from the tree and
gitignored (it is machine-specific), and both HTTP harnesses now
preflightwrkbefore building anything, write to a temp file and
publish only on success (so an interrupted run leaves no truncated
artifact), and report the actual cause when the server cannot start
instead of a bare "failed".
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.470.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.470.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.470.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.470.0-windows-x86_64.zip |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.470.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/aether-lang-org/aether#readme
Aether 0.469.0
What's new in 0.469.0
Added
- Per-symbol aliasing in selective imports:
import vg (rect, path as vgpath)binds the exported symbol under the alias and frees the original
name for local use, the standard resolution when exactly one name in an
otherwise-convenient selective import collides. Works for constants as
well as functions, inside a module's own imports (aliases resolve when
that module's bodies merge into a consumer), and alongside module-level
as. The selective-import shadow guard now fires on the alias, the name
the program actually binds, so a localpathbesidepath as vgpathis
legal while a localvgpathis still rejected. Closes #1345. worker.wait()andworker.map(items, f)(#1350).wait()blocks
until every submitted job has completed and been delivered, running the
completions on the calling thread and leaving the pool reusable: the
headless batch join that previously had to be hand-rolled as a
pending()/drain()/sleep()poll, and thatpool_shutdowncould not
provide because it tears down the process-global pool (a second batch
then returned nothing). It blocks on a condition variable, not a poll, and
returns -1 rather than deadlocking when a main-thread poster is installed.
mapis the bounded parallel map over a list, results index-aligned with
the input, concurrency bounded by the pool. Regression:
tests/regression/test_worker_wait_map.ae.string.join(seq, sep): concatenate a*StringSeq's elements with a
separator, the complement ofstring.split_to_seqand a linear-cost
escape from the O(n^2) self-append accumulation trap (two passes, one
exact-size allocation, binary-safe on elements and separator). The trap
itself, and both escapes (std.strbuilderfor piece-by-piece appends,
joinfor an existing sequence), are now documented in the Standard
Library Reference. Closes #1346.
Fixed
- Containers holding one string value could not both be freed (#1349).
list_add_string_owned/map_put_string_ownedare documented as
acquiring their own reference, but they adopted the caller's instead, so
a string literal added through them was libc-freed from.rodataat free
time (malloc's error path aborts, which the reporter saw as a hang), and
two containers each "owning" one pointer freed it twice. The owning
entries now genuinely own: a refcounted string is retained, a plain
pointer is copied. Codegen's escaping-value path moved to new
*_string_adoptedsiblings, so its zero-cost ownership transfer and the
no-per-add-leak property are unchanged. Regression:
tests/regression/test_list_shared_string_free.ae. - Closures returning a parameter truncated pointers. A block closure's
return type is inferred from its body, but the inference only looked in
the parent function's scope, so|x: ptr| { return x }fell back toint
and the emitted C signature truncated a 64-bit pointer. The closure's own
parameters are now consulted first. call(f, ...)on afnparameter truncated pointers. Thecall
builtin is typedintby default and resolved to the real type only when
the callee is a known local closure. In-> ptr fn(...) { return call(f, v) }the enclosing function's declared return type now supplies it, which
is the one case the closure-body resolution cannot see.- Heap-producing calls inside string interpolation leaked their
temporary:"[${string.join(parts, ",")}]"allocated a result that
nothing owned, once per interpolation, in both the printf (print/println)
and the heap-building forms. Interpolation segments that are
heap-producing calls now bind to a drained temp that is freed after the
segment is consumed; bare identifiers keep their owner's free. - A sequence accumulator later passed to
joinleaked its whole spine.
The seq escape walk allowlistsstring_seq_*callees as pure readers, but
thestring.joinwrapper normalises tostring_join, so a
s = seq_cons(x, s)loop feeding a later join was conservatively marked
escaped and every intermediate spine ref leaked. Bothstring_joinand
string_seq_joinare now recognised as non-storing readers.
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.469.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.469.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.469.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.469.0-windows-x86_64.zip |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.469.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/aether-lang-org/aether#readme
Aether 0.468.0
What's new in 0.468.0
See CHANGELOG.md for details.
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.468.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.468.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.468.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.468.0-windows-x86_64.zip |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.468.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/aether-lang-org/aether#readme
Aether 0.467.0
What's new in 0.467.0
Fixed
- A caught panic leaked every allocation made since the
try(#1301).
longjmpskipped the deferred scope-exit frees, so guarded blocks (and
every scheduler-wrapped actor step) leaked whatever they had allocated
before panicking. A thread-local allocation journal now mirrors the armed
deferred frees one-for-one: generated code journals a tracked local when
its flag is armed, the single free choke point forgets on every normal
free, ownership handoffs (return, container/actor/message adoption)
forget at the transfer, andaether_panic()drains the innermost frame's
still-live entries before the jump, freeing exactly the frees the jump
would have skipped. Escaped values are never journaled, so the drain is a
leak-fix by construction, never a use-after-free. Nestedtrydrains
stay frame-local; a panicking actor's step-scoped allocations are
reclaimed before the actor is marked dead; the no-panic hot path shows no
measurable cost on the ping-pong benchmark. Verified 405 leaks to 0 on
the issue's alloc-then-panic matrix. Regressions:
tests/regression/test_panic_unwind_cleanup.ae,
tests/integration/panic_unwind_no_leak/(50000 caught panics, RSS
flat),tests/integration/panic_actor_step_drain/.
Added
fs.mounts()andfs.block_info(dev)(#1118). Mount enumeration
with per-entry source/point/fstype/options accessors: Linux
/proc/self/mountinfo(octal escapes decoded), macOS and the BSDs
getmntinfo(3), Windows drive letters. Block-device size/removable/
transport via the Linux sysfs backend (partitions resolve the removable
flag through their parent disk); other platforms report unsupported
through the error slot rather than fabricating an answer. Regression:
tests/regression/test_std_fs_mounts.ae.
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.467.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.467.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.467.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.467.0-windows-x86_64.zip |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.467.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/aether-lang-org/aether#readme
Aether 0.466.0
What's new in 0.466.0
See CHANGELOG.md for details.
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.466.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.466.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.466.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.466.0-windows-x86_64.zip |
|
| FreeBSD | x86_64 | aether-0.466.0-freebsd-x86_64.tar.gz |
cross-built, not tested on FreeBSD |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.466.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/nicolasmd87/aether#readme
Aether 0.465.0
What's new in 0.465.0
See CHANGELOG.md for details.
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.465.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.465.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.465.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.465.0-windows-x86_64.zip |
|
| FreeBSD | x86_64 | aether-0.465.0-freebsd-x86_64.tar.gz |
cross-built, not tested on FreeBSD |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.465.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/nicolasmd87/aether#readme
Aether 0.464.0
What's new in 0.464.0
See CHANGELOG.md for details.
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.464.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.464.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.464.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.464.0-windows-x86_64.zip |
|
| FreeBSD | x86_64 | aether-0.464.0-freebsd-x86_64.tar.gz |
cross-built, not tested on FreeBSD |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.464.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/nicolasmd87/aether#readme
Aether 0.463.0
What's new in 0.463.0
Fixed
- Actor
?ask answered 0 and leaked a 5s timeout when the handler used
reply <expression>(#1324).reply countparsed but codegen silently
dropped it (an ERROR comment in the generated C), so the ask waited out its
timeout and read 0; the fallback also cast the reply pointer tointptr_t,
emitting a-Wformatwarning.reply <expression>is now a first-class
scalar reply: the handler sends a typed copy through the reply slot, the ask
site derefs it as that type (int, long, float, bool, ptr, string), and the
GCC statement-expression path now matches the MSVC helper's deref semantics.
An unknown message name inreply Name { ... }is a compile error instead of
silently generated nothing. Regression:
tests/regression/test_ask_scalar_reply.ae. - Heap-producing calls in bare
print/printlnargument position leaked
per call (println(string.concat(a, b))). The interpolation form already
freed its temporaries; the direct-argument form never did, for every heap
producer. Both forms now route through owned-print helpers that print and
free in one step; bound identifiers keep their scope-exit free.
Added
string.replace(s, old, new)andstring.replace_all(s, old, new)
(#1331). Non-overlapping left-to-right matches, byte-exact and binary-safe;
newmay be empty (deletion) or longer thanold; emptyoldreturns a
copy unchanged (Go'sstrings.Replaceguard). Single exact-size allocation
regardless of match count; results are heap-tracked likesubstring.
Regression:tests/regression/test_std_string_replace.ae.ae fmtCI gate (#1302).tests/integration/fmt_gate/enforces the
formatter's documented safety properties on every CI run: all checked-in
.aesources understd/,examples/, andtests/are canonically
formatted (ae fmt --check), formatting is idempotent, and a formatted
file's generated C is byte-identical to the original's (modulo#line).
The whole tree was formatted in this change (595 files, whitespace-only);
the IR-preservation property was verified on all 443 compiling program
files before and after: zero differences.
Downloads
| Platform | Architecture | File | Notes |
|---|---|---|---|
| Linux | x86_64 | aether-0.463.0-linux-x86_64.tar.gz |
|
| macOS | x86_64 | aether-0.463.0-macos-x86_64.tar.gz |
|
| macOS | arm64 | aether-0.463.0-macos-arm64.tar.gz |
|
| Windows | x86_64 | aether-0.463.0-windows-x86_64.zip |
|
| FreeBSD | x86_64 | aether-0.463.0-freebsd-x86_64.tar.gz |
cross-built, not tested on FreeBSD |
Quick install
Linux / macOS
# Download the archive for your platform, then:
tar -xzf aether-0.463.0-<platform>.tar.gz
export PATH="$PWD/bin:$PATH"
ae versionWindows
Extract the .zip archive, then run bin\ae.exe version from the extracted folder.
Documentation: https://github.com/nicolasmd87/aether#readme