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
adze init my_project
cd my_project
# adze init creates hew.toml, main.hew, and .gitignore
hew check main.hew
hew run main.hew
# Interactive REPL
hew evalNeed a lighter source-only scaffold instead? hew init my_project 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.
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.
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
- hew-serialize/ — MessagePack AST serialization
- hew-codegen/ — MLIR middle layer + LLVM backend (Hew dialect ops, lowering, code generation)
- 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/ — Frontend compiled to WASM for in-browser analysis and diagnostics (not full Hew 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 tooling
inputs: 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 check + build hew-wasmUse make playground-manifest-check when you only need to confirm the checked-in manifest is current. Use make playground-check before browser/playground work when you also want the repo-local hew-wasm build (make wasm) that powers browser-side analysis tooling.
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.