Skip to content

Releases: Lord1Egypt/Heh

Heh 𓁨 v1.0.4

Choose a tag to compare

@github-actions github-actions released this 04 Aug 14:46
6cef69c

What's Changed

  • release: Heh v1.0.4 security and static-correctness hardening by @Lord1Egypt in #37
  • fix: release builds without an absent lockfile by @Lord1Egypt in #38

Full Changelog: v1.0.3...v1.0.4

Heh 𓁨 v1.0.3 β€” builds on the Rust it promises

Choose a tag to compare

@Lord1Egypt Lord1Egypt released this 02 Aug 13:41
a59905e

Heh 𓁨 v1.0.3

A correctness and infrastructure release. No language change.

  • Fixed: the crate did not build on the Rust version it claimed to support.
    Cargo.toml promises rust-version = "1.70", but the code used
    std::iter::repeat_n (stable only since 1.82) and compared ExitCode
    values. Anyone on Rust 1.70–1.81 running cargo install heh-lang hit a
    compile error. Both are replaced, and the claim is now proven on every PR by
    a CI job that builds with a real 1.70 toolchain.
  • CI runs the full suite on macOS and Windows as well as Linux β€” release
    binaries ship for all three, and only one had ever been tested. Doing so
    found three Windows-only harness bugs (CRLF in byte-exact fixtures, CRLF from
    CPython in the arithmetic differential, and malformed file:// URLs), all
    fixed. .gitattributes now pins LF for sources and fixtures.
  • CI also enforces cargo clippy -- -D warnings; the tree is clippy-clean.
  • Documentation pruned from 18 markdown files to 6: the agent handoff kit and
    per-release notes files were scaffolding for a build that is finished. Their
    content lives on in AGENTS.md and CHANGELOG.md. Fixed a dangling
    docs/agent/TASK_MENU.md reference in heh --help.

Install

cargo install heh-lang     # the crate is heh-lang; the command is heh

Or download a binary below β€” linux x86_64, Windows x86_64, macOS arm64 and
x86_64. Checksums in SHA256SUMS.txt.

License

MIT Β© Mohamed Mounir (Lord1Egypt)

Heh 𓁨 v1.0.2 β€” roughly twice as fast

Choose a tag to compare

@Lord1Egypt Lord1Egypt released this 02 Aug 13:06
aae0bb4

Heh 𓁨 v1.0.2

A performance release. The frozen v1.0 language surface is unchanged β€” programs
behave exactly as before, just faster.

Roughly twice as fast

Three costs sat on the interpreter's hot path.

Integers now use a machine word until they need more. Every integer used to
allocate a heap vector of limbs, so a loop counter cost an allocation per step.
SPEC Β§5.1's implementation note asks for "a machine-word fast path with
automatic promotion to a bignum, so ordinary arithmetic runs at native speed" β€”
that is now what happens. Semantics are unchanged: integers are still
unbounded, and 2 ** 200 is still exact.

Interpreter-internal maps use a fast hasher. Variable lookup was running
SipHash β€” cryptographic strength, on nearly every instruction. std/hash
(SHA-256) is untouched and still a real hash.

Binding a name no longer allocates. Variable names are refcounted, so
binding a loop variable is a pointer bump instead of a string copy β€” two
million fewer allocations in a two-million-iteration loop.

benchmark v1.0.1 v1.0.2 vs CPython
fib 104ms 72ms 0.35x β†’ 0.62x
loop_sum 751ms 373ms 0.27x β†’ 0.57x
strings 58ms 41ms 0.91x β†’ 1.15x
maps 205ms 108ms 0.38x β†’ 0.51x
bigint 11ms 10ms 3.00x

Heh is now faster than CPython on string work and on arbitrary-precision
arithmetic, and roughly half its speed on loop-heavy code. The original design
target was β‰₯5Γ— CPython, and this release still does not meet it β€” see below.

Integer arithmetic is now verified against CPython

tests/bignum_vs_python.rs runs every binary operator over 23 operands chosen
to sit exactly on the machine-word and limb boundaries β€” about 13,000
comparisons against CPython, whose integers are also unbounded and whose //
and % sign rules the spec adopts by name.

It caught a real bug in the first draft of the fast path: 1 // -2 returned
1 instead of -1. That test is now part of the suite.

Also fixed

sys.rand.bytes and sys.rand.int read only the lowest limb of their
arguments, so large values silently produced wrong bounds. They now use the
whole value and reject out-of-range input.

What is still slow, and why

Local variables are still looked up by name through a chain of scopes on
every access. A mature VM assigns each local a frame slot at compile time and
indexes an array instead. Doing that here needs a resolver pass that handles
shadowing across block scopes, match arm bindings, narrowing rebinds, and
closure capture β€” a subsystem rather than a patch, and exactly the kind of
change that ships subtle scoping bugs when rushed. It is the remaining path
toward the original performance target.

Install

cargo install heh-lang     # the crate is heh-lang; the command is heh

Or download a binary below β€” linux x86_64, Windows x86_64, macOS arm64 and
x86_64. Checksums in SHA256SUMS.txt.

License

MIT Β© Mohamed Mounir (Lord1Egypt)

Heh 𓁨 v1.0.1 β€” VM by default, clean recursion faults, four platforms

Choose a tag to compare

@Lord1Egypt Lord1Egypt released this 02 Aug 11:02
7de72b7

Heh 𓁨 v1.0.1

A patch release. The frozen v1.0 language surface is unchanged β€” this is
entirely implementation work, plus the first crates.io publish.

The bytecode VM is now the default, and covers the whole language

heh run executes on the bytecode VM; --tree-walk selects the reference
tree-walking evaluator. The VM previously punted three construct families back
to the tree-walker. It now encodes all of them:

  • Closures become the same function value a named function is, capturing
    the live scope.
  • Optional narrowing gets real block scopes, including the case where a
    break or continue jumps out of a narrowed block.
  • Field and index assignment (p.x = v, l[i] = v, and nesting). Compound
    forms duplicate the container and index rather than re-evaluating the index,
    so an index expression's side effects cannot run twice.

Both engines share one call path and one set of field/index accessors, so they
cannot drift. Output remains byte-identical across the entire conformance
corpus, enforced by a differential test.

Runaway recursion is a fault, not a crash

Deep recursion used to abort the process with fatal runtime error: stack overflow and a core dump. SPEC Β§7.3 says a fault stops the program with a
diagnostic
. Programs now run on a dedicated 256 MB stack with a call-depth
limit of 10,000, and both engines report E0202 identically. Legitimate deep
recursion β€” 9,000 frames β€” works fine.

Performance, honestly

benches/run.sh runs five benchmarks, each paired with an equivalent CPython
program whose answer must match before a timing is reported.

benchmark VM tree-walk CPython VM vs tree-walk VM vs CPython
fib 112ms 254ms 37ms 2.27x 0.33x
loop_sum 714ms 967ms 223ms 1.35x 0.31x
strings 52ms 56ms 53ms 1.08x 1.02x
maps 206ms 208ms 58ms 1.01x 0.28x
bigint 10ms 11ms 31ms 1.10x 3.10x

The VM beats the tree-walker on every benchmark, and beats CPython only on
arbitrary-precision arithmetic. The original design target was β‰₯5Γ— CPython, and
this release does not meet it. The reason is structural rather than a
matter of tuning: every variable access is a string-keyed hash lookup up a
scope chain, and every integer heap-allocates, with no machine-word fast path β€”
something SPEC Β§5.1 explicitly invites an implementation to add. That is the
next performance milestone; the measurement harness now exists to prove it.

Also fixed

  • heh fmt mangled a closure nested inside a function, emitting a body at the
    wrong indentation that would not re-parse.

Install

cargo install heh-lang     # the crate is heh-lang; the command is heh

The crate is published as heh-lang because heh was taken on crates.io
in 2022 by an unrelated project. The installed command is still heh.

Or download a binary below β€” linux x86_64, Windows x86_64, macOS arm64 and
x86_64. Checksums in SHA256SUMS.txt.

License

MIT Β© Mohamed Mounir (Lord1Egypt)

Heh 𓁨 v1.0.0 β€” the language is frozen

Choose a tag to compare

@Lord1Egypt Lord1Egypt released this 01 Aug 20:29
85b9747

Heh 𓁨 v1.0.0 β€” the language is frozen

Heh is a small programming language designed to stop changing. Nineteen
keywords, a spec that fits in eight printed pages against a hundred-page
budget, and a NEVER list fixed on day one. This release freezes the surface:
after v1.0, code that runs today runs unchanged forever.

What Heh is

  • Easier than Python. Indentation blocks, inference everywhere except
    function boundaries, one obvious way to do things.
  • Infinite by nature. int is arbitrary-precision β€” overflow does not
    exist. 2 ** 200 and factorial(1000) are exact, with nothing to import.
    Ranges may be unbounded: for i in 0.. runs until you break.
  • Secure by default. All I/O flows from a single Sys value handed to
    main. A function that never receives it cannot touch the filesystem,
    network, clock, or environment. Any capability can be revoked from the
    command line (--deny-net), and revocation fails closed.
  • Reliable. Static types, errors as values (ok / err / try), no
    null, no exceptions, exhaustive match.
  • Immortal. One binary, zero crates β€” Rust standard library only.
    No package registry: dependencies are vendored into your repo and pinned by
    SHA-256 in heh.lock, verified on every run.

Getting it

git clone https://github.com/Lord1Egypt/Heh && cd Heh
cargo build --release          # target/release/heh β€” the whole toolchain
echo 'sys.print("Heh lives forever 𓁨")' > hello.heh
./target/release/heh run hello.heh

The toolchain

heh run Β· heh check Β· heh test Β· heh fmt Β· heh get Β· heh ast Β·
heh tokens β€” one binary, no configuration files, no options to argue about.
The formatter is canonical and comment-preserving. heh run --vm executes on
the bytecode VM, which is byte-identical to the tree-walking evaluator across
the entire conformance corpus.

Standard library

Eight pure modules β€” math, json, fmt, time, regex (RE2-style, no
backtracking), csv, hash (SHA-256, CRC32), debug β€” plus builtin methods
on str, list, and map. Anything effectful lives on Sys instead. The
complete frozen surface is in docs/STDLIB.md.

What v1.0 does not have

  • No raw sockets. A socket is a handle with a lifetime, and Heh has no
    resource-lifecycle construct; committing to one at the freeze would be a
    permanent decision made in a hurry. sys.net.get covers HTTP request and
    response work. Sockets remain a candidate addition against the page budget.
  • No concurrency. When it arrives it will be structured and colorless β€”
    async/await function coloring is on the NEVER list.
  • Everything else on the NEVER list (SPEC Β§1.2), permanently: null, exceptions,
    integer overflow, eval, classes, macros, operator overloading, global
    mutable state, a package server, implicit coercion.

Conformance

tests/corpus/ is the definition: an implementation that passes it is Heh.
The corpus grows and never shrinks. The spec, not the implementation, is
authoritative β€” where they disagreed during the v1.0 audit, the implementation
was fixed.

License

MIT Β© Mohamed Mounir (Lord1Egypt)