A statically-typed, actor-oriented programming language for concurrent and distributed systems.
Website | Documentation | Playground | Tutorial
curl -fsSL https://hew.sh/install.sh | bashPre-built binaries for Linux (x86_64) and macOS (x86_64, ARM) are available on the Releases page. Also available via Homebrew, Docker, and system packages.
# 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 creates main.hew + README.md (no hew.toml)
hew check main.hew
hew fmt --check main.hew
hew doc main.hew --output-dir doc
hew run main.hew
# Interactive REPL
hew evalhew eval can run as an interactive REPL, evaluate a file in REPL context, or
evaluate a one-off inline expression. The REPL remembers top-level items and
let/var bindings across inputs.
hew eval
hew eval -f script.hew
hew eval "1 + 2"
hew eval --json -f script.hewFor 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, :bindings, :type <expr>,
:load <file>, :clear / :reset, and :quit / :q.
hew init is the source-only scaffold: it writes main.hew +
README.md, but no hew.toml.
See the Getting Started Guide for more.
The examples/ directory contains structured learning paths for new users:
examples/ux/— 15 quick-start lessons (hello world through hashmaps), each paired with an.expectedoutput file; ideal for a first 20-minute tourexamples/progressive/— 11 numbered lessons building from variables to actors, also with.expectedfilesexamples/playground/— Topic-grouped snippets covering basics, concurrency, and types, with checked-in metadata inmanifest.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.
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");
let obj = json.parse(data);
println(obj);
}
See std/README.md for the canonical index of shipped stdlib modules.
When you compile or typecheck a multi-file program with hew check,
hew build, 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;prefers the directory-form module atfoo/foo.hew, then falls back tofoo.hewbeside the importer.- Other top-level
.hewfiles insidefoo/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.mdfor the smallest working layout, thenexamples/multifile/README.mdfor selective imports and nested module hierarchies.
Hew resolves imported modules in this order, and the first match wins:
HEWPATH(colon-separated entries; each entry is the parent directory that containsstd/)HEW_STD(the path to thestd/directory itself; Hew uses its parent as a search root)- The installed
<prefix>/share/hewtree beside thehewbinary - A development fallback to the repo root when
std/exists two levels above the binary
hew.toml does not configure module search paths. Use HEWPATH or HEW_STD
when you need Hew to search a non-default stdlib or module root.
To browse shipped stdlib modules, generate docs for the stdlib tree:
hew doc std/ --output-dir doc/stdThis writes a browsable index page for the modules under std/. The canonical
module list also lives in std/README.md.
For the current wildcard-import warning caveat, see
docs/troubleshooting.md.
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.
Actors communicate across nodes with the same syntax used locally. The runtime handles transport, registry gossip, and remote dispatch transparently.
// server node
Node::set_transport("quic");
Node::start("127.0.0.1:9000");
let counter = spawn Counter;
Node::register("counter", counter);
// client node (separate process)
Node::set_transport("quic");
Node::start("127.0.0.1:9001");
Node::connect("127.0.0.1:9000");
let counter: Counter = Node::lookup("counter");
counter.increment(42); // remote message — same syntax as local
See examples/quic_mesh/ for a complete two-process QUIC mesh demo.
The compiler has three layers: Rust frontend → embedded MLIR middle layer → LLVM backend.
source.hew → Lexer → Parser → Type Checker → MessagePack Serialize
(hew-lexer) (hew-parser) (hew-types) (hew-serialize)
│
▼ in-process C API
hew (Rust + C++): hew_codegen_compile_msgpack
│
▼
MLIRGen → Hew dialect → LLVM dialect → LLVM IR → .o
hew (Rust): cc .o + libhew.a → executable
Detailed diagrams: See
docs/diagrams.mdfor Mermaid sequence diagrams, state machines, and architecture visuals covering the full compilation pipeline, MLIR lowering stages, actor lifecycle, message flow, runtime layers, and wire protocol format.
- hew-cli/ — Compiler driver (
hewbinary) - 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-serialize/ — MessagePack AST serialization
- hew-codegen/ — MLIR middle layer + LLVM backend (Hew dialect ops, lowering, code generation); built as a C++ library and embedded inside the
hewbinary — not a separately shipped executable - hew-astgen/ — Generates C++ msgpack deserialization from AST definitions
- 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
- adze-cli/ — Package manager (
adzebinary) — init, install, publish, search - hew-lsp/ — Language server (tower-lsp)
- hew-observe/ — Runtime observability TUI (
hew-observe) - hew-wasm/ — Analysis-only frontend compiled to WASM for in-browser diagnostics and editor tooling (not browser runtime/codegen/execution)
- std/ — Standard library modules (
.hewsource files + Rust FFI crates)
- 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
Full documentation at hew.sh/docs
- Local troubleshooting guide:
docs/troubleshooting.md - Website source: github.com/hew-lang/hew.sh
| Dependency | Version | Purpose |
|---|---|---|
| Rust | stable (latest) | Frontend compiler, runtime, package manager |
| LLVM | 22.1 | MLIR code generation and LLVM backend |
| MLIR | (bundled with LLVM 22) | Hew dialect and lowering passes |
| CMake | >= 3.20 | Builds the embedded C++ MLIR backend |
| Ninja | any | CMake build generator |
| clang/clang++ | any (LLVM 22 preferred) | C/C++ compilation of the MLIR backend |
Install on Ubuntu/Debian:
# Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# LLVM 22 + MLIR
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 cmake ninja-build \
llvm-22-dev libmlir-22-dev mlir-22-tools clang-22Install on macOS:
# Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# LLVM 22 + MLIR + build tools
brew install llvm ninja cmakemake # Build everything (debug)
make release # Build everything (optimized)
make ci-preflight # Dispatch a conservative local preflight from your current diff
make test # Run Rust + native codegen tests
make lint # cargo clippySee the Makefile header for all targets.
Use make ci-preflight ARGS="--dry-run" to inspect the selected commands before
running them. The first slice stays conservative: known docs/parser/types/CLI
diffs get narrower checks, and everything else falls back to broader local
preflight commands.
This repo does not build the downstream browser app or a full in-browser Hew
runtime. The repo-local browser/playground slice here is analysis-only tooling:
hew-wasm plus the curated
examples/playground/manifest.json
consumed by downstream browser tooling.
make playground-manifest # regenerate examples/playground/manifest.json
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 preflightUse 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 analysis tooling. Use make playground-wasi-check in codegen-capable environments when you also want the focused manifest-driven WASI runtime proof. Browser coverage remains analysis-only; this repo does not claim downstream browser execution exists.
These are only needed for specific workflows:
| Dependency | Install | Purpose |
|---|---|---|
| wasmtime | curl https://wasmtime.dev/install.sh -sSf | bash |
Run WASM tests (make test-wasm) |
| wasm32-wasip1 target | rustup target add wasm32-wasip1 |
Build WASM runtime (make wasm-runtime) |
| wasm-pack | cargo install wasm-pack |
Build browser analysis bindings (make wasm, make playground-check) |
| Python 3 | system package manager | Playground manifest + other scripts (scripts/) |
| Java 21 + ANTLR4 | system package manager | Grammar validation (make grammar) |
| cargo-fuzz | cargo install cargo-fuzz |
Parser fuzzing (hew-parser/fuzz/) |
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.