Skip to content

Latest commit

 

History

5,679 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Hew's front-facing blue jay, with swept wings

Hew

A statically-typed, actor-oriented programming language for concurrent and distributed systems.

Website | Documentation | Playground | Tutorial

Install

curl -fsSL https://hew.sh/install | bash

Pre-built binaries for Linux (x86_64, ARM64), macOS (x86_64, ARM64), FreeBSD (x86_64, ARM64), and Windows (x86_64) — plus .deb, .rpm, and Arch packages — are published on the Releases page. Also available via Homebrew, Docker, and system packages.

Quick Start

# Hello world
echo 'fn main() { println("Hello from Hew!"); }' > hello.hew
hew run hello.hew

# Start a new project
hew init my_project
cd my_project
# hew init scaffolds hew.toml + main.hew + a merged .gitignore
hew check main.hew
hew fmt --check main.hew
hew doc main.hew --output-dir doc
hew run main.hew

# Interactive REPL
hew eval

Evaluation & REPL

hew eval can run as an interactive REPL, evaluate a file in REPL context, or evaluate a one-off inline expression. Top-level items (fn, type, enum, actor, impl, trait) persist across REPL inputs so you can define a function then call it later; let/var bindings and bare statements are evaluated fresh each line and do not carry over. (Hew has no struct keyword — type Name { ... } declares a record.)

hew eval
hew eval -f script.hew
hew eval "1 + 2"
hew eval --json -f script.hew

For non-interactive runs, -f - reads from stdin and --target wasm32-wasi uses the WASI eval path.

Use :help inside the REPL to see the command list. Common commands include :help / :h, :session / :show, :items, :type <expr>, :load <file>, :clear / :reset, and :quit / :q.

hew init scaffolds a manifest-first project: hew.toml, a starter main.hew, and a merged .gitignore.

For a reusable package, hew init --lib local_dep creates local_dep/local_dep.hew. The filename matches the package name, so after a consumer adds and installs the dependency, its root is imported directly with import local_dep;.

Package names are module paths. A dotted library such as hew.selfqualtype uses every segment for its installed directory and the final segment for its root file: hew/selfqualtype/selfqualtype.hew, imported with import hew.selfqualtype;. The generated manifest records main = "selfqualtype.hew".

See the Getting Started Guide for more.

Learning Paths

The examples/ directory contains structured learning paths for new users:

  • examples/ux/ — 15 quick-start lessons (hello world through hashmaps), each paired with an .expected output file; ideal for a first 20-minute tour
  • examples/progressive/ — 11 numbered lessons building from variables to actors, also with .expected files
  • examples/playground/ — Topic-grouped snippets covering basics, concurrency, and types, with checked-in metadata in manifest.json

See examples/README.md for the complete directory guide. If you're looking specifically for multi-file/module layouts, start with examples/directory_module_demo/README.md and then examples/multifile/README.md.

When you move from language lessons to library APIs, use std/README.md, the canonical index of shipped stdlib modules.

Sandbox VM

The sandbox VM runs admitted Hew programs in a deterministic browser-hosted runtime with a virtual clock, seeded randomness, logical heap accounting, and page-owned streams. See the public sandbox VM divergence catalog for the accepted differences from native execution and the native-only APIs rejected by the sandbox profile.

Language Basics

println and print are plain function calls, not macros. Coming from Rust, you might reach for println! — in Hew these are ordinary built-in functions written without a ! suffix, auto-imported into every file:

fn main() {
    print("hello ");     // no trailing newline
    println("world");    // appends newline
    println(42);         // works with any type that implements Display
}

To use modules beyond the builtins, add an import statement at the top of your file:

import std.fs;
import std.encoding.json;

fn main() {
    let data = fs.read("config.json") handle error {
        println(f"cannot read config: {error}");
        return;
    };
    let obj = json.parse(data) handle error {
        println(f"invalid config: {error}");
        return;
    };
    match obj.stringify() {
        .Ok(text) => println(text),
        .Err(error) => println(f"cannot encode config: {error}"),
    }
}

json.Value has no Display impl, so print it through stringify() rather than passing the value straight to println.

See std/README.md for the canonical index of shipped stdlib modules.

Multi-file programs & modules

When you compile or typecheck a multi-file program with hew check, hew compile, or hew run, pass one entry .hew file. Imports and directory-form modules pull in the rest, so pass main.hew, not every file in the tree.

hew doc is different: it accepts either one .hew file or a directory tree of .hew files to document.

  • import foo; resolves to the directory-form module at foo/foo.hew or to foo.hew beside the importer — whichever exists. If both exist the import is a hard error (import `foo` is ambiguous: both ... exist); rename or remove one.
  • Other top-level .hew files inside foo/ merge into the same module automatically.
  • Child directories stay separate submodules, so import them explicitly — for example import foo.bar;.
  • Start with examples/directory_module_demo/README.md for the smallest working layout, then examples/multifile/README.md for selective imports and nested module hierarchies.

Module search paths & stdlib discovery

Every std.* module, including the implicit prelude, resolves from one standard-library root: HEW_STD (the path to the std/ directory itself) when it is set, and otherwise the std shipped with the running binary: <exe_dir>/../share/hew/std (FHS packages, Homebrew, Docker), then <exe_dir>/../std (release tarball, Windows zip), then the checkout a development binary was built from while it is still in that build's output. No shipped layout needs HEW_STD. A std/ beside the source file or in the current directory is never the standard library.

hew.toml does not configure the std root. Use HEW_STD when you need a different standard library, for example to run one checkout's std with a binary built from another.

To browse shipped stdlib modules, generate docs for the stdlib tree:

hew doc std/ --output-dir doc/std

This writes a browsable index page for the modules under std/. The canonical module list also lives in std/README.md.

For import-resolution problems, see docs/troubleshooting.md.

Wire Types

Wire types define versioned serialization schemas for use with actors and distributed protocols. Each field carries an explicit numeric tag (@1, @2, …) that is the field's stable identity across schema versions. You can safely add new tagged fields or rename existing ones; decoders that encounter an unknown tag skip it. Never reuse a tag number for a different field.

#[wire]
type UserMessage {
    name: string @1,
    age:  i32    @2,
    // Adding a new @3 field later is backwards-compatible; reusing @1 is not.
}

See examples/playground/types/wire_types.hew for a runnable example.

Actor calls and concurrency

An actor call waits for its handler to finish, including a handler with no return value. Handle the completion outcome with match, ? or handle. fork creates a task; await joins a task or a vector of tasks. Ordinary calls can suspend without an await prefix.

actor Counter {
    var count: i64 = 0,
    receive fn add(n: i64) { count = count + n; }
    receive fn total() -> i64 { count }
}
fn main() {
    let counter = spawn Counter();
    counter.add(42) handle error {
        println(f"update failed: {error}");
        return;
    };
    match counter.total() {
        .Ok(value) => println(value),
        .Err(error) => println(f"query failed: {error}"),
    }
    close(counter);
}

Use mailbox(target, on_full: ...) for submission-only delivery and policy(target, on_full: .Wait) or the .Reject policy to choose completion-call admission. The intended rejected-call contract returns a sealed request for typed retry or redirection. That request recovery remains implementation work; the current reason-only rejection is not the final API.

Distributed actors share the call contract, with transport and liveness errors visible to callers. The native cutover still needs distributed acceptance and unified remote-handle integration; do not infer network parity from a local example. See the actor guide and distributed protocol reference.

Architecture

The compiler is a Rust pipeline: frontend → HIR/MIR → codegen-rs LLVM emission. hew-codegen-rs is the sole backend and is linked into the hew binary as a normal Cargo dependency.

source.hew → Lexer → Parser → Type Checker → HIR → MIR → LLVM IR/object
               (hew-lexer) (hew-parser) (hew-types) (hew-hir/hew-mir)
                                                       │
                                                       ▼
                               hew-codegen-rs (Rust/Inkwell)
                                                       │
                                                       ▼
                               hew links object + libhew.a → executable

Detailed diagrams: See docs/diagrams.md for Mermaid diagrams of the compilation pipeline, actor/supervisor state machines, runtime architecture, and wire format.

Repository Structure

Compiler

  • hew-cli/ — Compiler driver (hew binary)
  • hew-lexer/ — Tokenizer
  • hew-parser/ — Recursive-descent + Pratt precedence parser
  • hew-types/ — Bidirectional type checker with Hindley-Milner inference; warnings carry source-module attribution so diagnostics in multi-module programs identify which module triggered each warning
  • hew-hir/, hew-mir/ — High-level and middle-level intermediate representations of the typed program
  • hew-codegen-rs/ — LLVM-backed code generation via inkwell (the compiler backend, embedded in the hew binary)
  • hew-runtime/ — Pure Rust actor runtime (libhew_runtime.a) with node mesh networking, QUIC transport, SWIM cluster membership, and cross-node actor registry; also compiles for WASM targets
  • hew-cabi/ — C ABI bridge for stdlib FFI bindings

Package Manager & Tooling

  • hew-pkg/ — Package-manager library behind the hew subcommands (init, add, install, publish, search)
  • hew-lsp/ — Language server (tower-lsp)
  • hew-observe/ — Runtime observability TUI (hew-observe)
  • hew-wasm/ — Analysis-only diagnostics frontend compiled to WASM (lexer/parser/type-checker for in-browser editor tooling); the full browser execution runtime is a v0.6.0 deliverable

Standard Library & Build Support

  • std/ — Standard library modules (.hew source files + Rust FFI crates)

Distribution

  • editors/ — Editor support (Emacs, Nano, Sublime)
  • installers/ — Package installers (Homebrew, Debian, RPM, Arch, Alpine, Nix, Docker) plus install-time shell completion generation
  • examples/ — Example programs and benchmarks
  • scripts/ — Development scripts
  • docs/ — Language specification and API references

Documentation

Full documentation at hew.sh/docs

Building from Source

Prerequisites

Dependency Version Purpose
Rust and Cargo rust-toolchain.toml pin (including Clippy and rustfmt) Compiler, runtime and package manager
LLVM 22.1.x Native/WASM object emission through inkwell/llvm-sys
C compiler GCC or Clang; MSVC environment on Windows Native linking and C header checks
GNU Make GNU implementation Build and test entry points
Python 3.12+ Makefile gates and repository scripts
Git and Bash Available on PATH Source checkout and shell helpers

Install on Ubuntu/Debian:

# Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# LLVM 22 development libraries
sudo mkdir -p /etc/apt/keyrings
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key \
  | sudo tee /etc/apt/keyrings/llvm.asc >/dev/null
echo "deb [signed-by=/etc/apt/keyrings/llvm.asc] http://apt.llvm.org/noble/ llvm-toolchain-noble-22 main" \
  | sudo tee /etc/apt/sources.list.d/llvm.list >/dev/null
sudo apt-get update
sudo apt-get install -y llvm-22-dev clang-22 make gcc git python3

Install on macOS:

# Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# LLVM 22 development libraries
brew install llvm

# Repository scripts and Makefile gates
brew install python@3.12

Build

make          # Build the usable developer toolchain
make release  # Build the optimized install/package toolchain
make preflight     # Unconditional, fail-fast pre-PR gate
make test     # Run Rust workspace tests against the known-failure ratchet
make lint     # Run Rust lint, source contracts and Hew formatting

The default toolchain pairs the release-lib compiler with its linkable libhew archive, builds debug support binaries, and publishes WASI plus any native cross-architecture archive supported by the host toolchain. On Linux, the opposite architecture is included when its multiarch sysroot is installed; on macOS, the opposite Darwin architecture is included. The same non-LTO cross archive is reused by tests, assembly, installation, and packaging.

See the Makefile header for all targets.

The standard pre-PR gate runs the same Make-owned lint and test groups as Linux CI and fails fast after the first failed command. make ci-preflight remains as a compatibility alias for the same gate.

Browser / Playground Validation

The browser runtime provides deterministic execution for its admitted subset. The current native cutover changes actor calls, suspension, ownership and collections; browser and WASM parity for that surface remains pending. Existing sandbox capabilities are not proof that a current native program runs there. See the capability reference.

This repo carries the analysis-side browser tooling (hew-wasm) plus the sandbox bytecode emission crate (hew-sandbox-wasm); the downstream browser app and the hew-sandbox-vm TypeScript worker are in hew-lang/playground.

make baselines                  # regenerate deterministic generated metadata
make playground-manifest-check  # cheap freshness check for manifest.json only
make playground-check           # repo-local preflight: manifest freshness + curated analyze smoke + build hew-wasm
make playground-wasi-check      # focused manifest-driven WASI runtime preflight
make sandbox-parity             # full Node VM plus Rust native/sandbox parity suite

Use make playground-manifest-check when you only need to confirm the checked-in manifest is current. Use make playground-check for the repo-local browser/tooling slice: curated hew-wasm analysis smoke plus the repo-local hew-wasm build (make wasm) that powers browser-side diagnostics tooling. Use make playground-wasi-check in codegen-capable environments when you also want the focused manifest-driven WASI runtime proof. The hew-wasm crate in this repo is analysis-only; the sandbox VM execution target and downstream browser app live in hew-lang/playground.

Development tools

Install these when developing Hew, in addition to the build prerequisites:

Dependency Version / install Purpose
ShellCheck 0.11.0 release Shell-script lint; CI installs the version selected in ci.yml
actionlint Release binaries or platform package manager Validate GitHub Actions workflows before pushing
clang-format LLVM installation or platform package manager Check generated C headers

After setting up or changing your environment, run:

make check-requirements

This checks tool availability and the required Rust, LLVM, Python and ShellCheck versions. It is an explicit diagnostic, not a prerequisite of builds, lint or tests. Normal commands trust the configured environment. Structural lint provisions its pinned ast-grep and Hew grammar through the existing Make targets.

Workflow-specific test tools

These are needed for the indicated workflows; they are outside make check-requirements:

Dependency Version / install Purpose
cargo-nextest cargo install cargo-nextest --locked --version 0.9.120 Rust test execution (make test)
wasmtime v47.0.2 release WASI tests (make playground-wasi-check and WASI cases in make test)
wasm32-wasip1 target rustup target add wasm32-wasip1 WASI runtime archives
wasm32-unknown-unknown target rustup target add wasm32-unknown-unknown Browser/sandbox modules
wasm-pack cargo install wasm-pack --locked --version 0.13.1 Browser and sandbox bindings
Node.js and npm Node.js 24 Browser, sandbox and grammar checks
Mosquitto clients Platform package manager (mosquitto-clients on Ubuntu) MQTT broker end-to-end checks
cargo-fuzz cargo install cargo-fuzz Parser fuzzing (hew-parser/fuzz/)

License

Hew is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-MIT and LICENSE-APACHE for details.

About

A statically-typed, actor-oriented programming language for concurrent and distributed systems.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

10 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages