Skip to content

jamesc/beamtalk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3,042 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CI API Docs Rust coverage Erlang coverage

A live, interactive Smalltalk-like language for the BEAM VM

Beamtalk brings Smalltalk's legendary live programming experience to Erlang's battle-tested runtime. While inspired by Smalltalk's syntax and philosophy, Beamtalk makes pragmatic choices for modern development (see Syntax Rationale). Write code in a running system, hot-reload modules without restarts, and scale to millions of concurrent actors.

// Spawn an actor with state
counter := Counter spawn

// Send messages (sync by default)
counter increment
counter increment
value := counter getValue // => 2


// Send an async message
counter increment!  // => ok
// Cascades - multiple messages to same receiver
Transcript show: "Hello"; cr; show: "World"

// Map literals
config := #{#host => "localhost", #port => 8080}

…and a live, browser-based IDE attached to the running system — system browser, live method editing, and a workspace eval pane (the LiveView IDE):

The Beamtalk LiveView IDE — system browser, method editor, live bindings, and a workspace eval pane, all attached to a running workspace


Why Beamtalk?

Feature Benefit
Interactive-first REPL and live workspace, not batch compilation
Hot code reload Edit and reload modules in running systems
Actor model Actors are BEAM processes with independent fault isolation
Gradual typing Opt-in typed classes with inference through generics, unions, FFI, and narrowing
Reflection Inspect any actor's state and methods at runtime
Runs on BEAM Compiles to Core Erlang; deploy to existing OTP infrastructure
Native Erlang FFI Call any OTP function with typed specs and Result-shaped error coercion

What's New in 0.4

  • Type system grows teeth. typed classes flow types through generics, unions, narrowing predicates, FFI calls, and method-local type variables; beamtalk type-coverage reports per-file coverage and the LSP shows why a chain decayed to Dynamic.
  • Real package manager. [dependencies] in beamtalk.toml (path / git / hex), beamtalk.lock, beamtalk deps add, and qualified pkg@Class names — including native .erl inside packages, compiled via a vendored rebar3.
  • Result everywhere it counts. FFI {ok, T} | {error, R} coerces to typed Result(T, E) at the boundary, and supervisor lifecycle calls return Result instead of raising.
  • Live-edit save model. Method-level edits patch memory and append to a workspace ChangeLog; Workspace flush splices the body back into the .bt file atomically, with external-edit conflict detection.

See CHANGELOG.md for the full list, including named actor registration, the internal modifier, auto-chained initialize, and class crash recovery.


Key Features

Actors as Objects

Every Beamtalk actor is a BEAM process with its own state and mailbox:

Actor subclass: Counter
  state: value = 0

  increment => self.value := self.value + 1
  decrement => self.value := self.value - 1
  getValue => self.value

Pattern Matching

Match expressions with pattern arms:

status match: [
  #ok -> "success"
  #error -> "failure"
  _ -> "unknown"
]

// Variable binding in patterns
42 match: [n -> n + 1]  // => 43

Collections

Rich collection types written in Beamtalk itself:

list := #(1, 2, 3)
list collect: [:x | x * 2]    // => #(2, 4, 6)

dict := #{#name => "Alice", #age => 30}
dict at: #name                 // => Alice

Live Code Reloading

Redefine methods on running actors — state is preserved:

// In the REPL: redefine a method on a running class
Counter >> increment => self.value := self.value + 10

// Existing actors immediately use the new code
c increment  // now adds 10 instead of 1

Getting Started

Install from Release

The quickest way to get started — downloads a prebuilt binary for your platform:

curl -fsSL https://jamesc.github.io/beamtalk/install.sh | sh

This installs to ~/.beamtalk/bin/. You can customise the location:

curl -fsSL https://jamesc.github.io/beamtalk/install.sh | sh -s -- --prefix /usr/local

Prerequisite: Erlang/OTP 27+ must be installed with erl on PATH.

Installing Erlang/OTP

macOS (Homebrew):

brew install erlang

Ubuntu/Debian:

sudo apt install erlang

Windows: Download the installer from erlang.org.

Version manager (any platform): asdf with asdf-erlang:

asdf plugin add erlang
asdf install erlang 27.0
asdf global erlang 27.0

After installation, start the REPL:

beamtalk repl

Build from Source

Prerequisites for building from source
  • Rust (latest stable) — rustup.rs
  • Erlang/OTP 27+ with erl and erlc on PATH
  • rebar3 — Erlang build tool (rebar3.org)
  • Just — command runner (cargo install just)
  • Node.js LTS (optional) — only for building the VS Code extension
# Clone and build
git clone https://github.com/jamesc/beamtalk.git
cd beamtalk
just build

# Start the REPL
just repl

# Run tests
beamtalk test              # Run BUnit TestCase tests
just test-stdlib           # Run compiled expression tests
just test-repl-protocol    # Run REPL TCP-protocol tests

# Run full CI checks
just ci

Install from Source

# Install to /usr/local (may need sudo)
just install

# Install to a custom prefix
just install PREFIX=$HOME/.local

# Uninstall
just uninstall PREFIX=$HOME/.local

The install layout follows the OTP convention (PREFIX/lib/beamtalk/lib/<app>/ebin/), so beamtalk repl and beamtalk build work correctly from any directory when the binary is on PATH.

After installing, verify your environment:

beamtalk doctor

VS Code Extension (Local Dev)

For local extension development (debug LSP, no .vsix packaging):

just build-vscode

Then in VS Code, run Developer: Install Extension from Location... and select editors/vscode.

If your stdlib source files are outside the project root, set:

{
  "beamtalk.stdlib.sourceDir": "/opt/beamtalk/stdlib/lib"
}

beamtalk.stdlib.sourceDir can be absolute (including outside the project) or relative to the Beamtalk project root (directory containing beamtalk.toml). See editors/vscode/README.md for full extension configuration.

LiveView IDE

A browser-based, Smalltalk-style live IDE that attaches to a running Beamtalk workspace over Erlang distribution (the Attach topology) — Phoenix runs as its own BEAM node and calls the same workspace functions the REPL uses, so what you see in the browser is the live system, not a snapshot (pictured at the top).

What's in the cockpit:

  • System Browser — a four-pane Smalltalk navigator (classes → protocols → methods → source) over the live image, including stdlib and runtime classes.
  • Method editor — open any method as an editable tab with CodeMirror syntax highlighting; Compile redefines it on the running system (live code reload), with Senders / Implementors navigation and Save All to Disk.
  • Workspace — a Do it / Print it / Inspect it eval pane returning live Erlang terms (not JSON), backed by a per-session workspace that persists state across evals, plus a live Transcript.
  • Bindings & Inspector — workspace variables update live as you eval, and the Inspector follows a reference through the object graph and can track a live actor.

It ships on its own release lane — a self-contained release archive and a Docker image (ghcr.io/jamesc/beamtalk-ide) — separate from the toolchain bundle.

REPL Usage

New to Beamtalk? See the REPL Tutorial for a complete beginner's guide!

Beamtalk v0.4.0
Type :help for available commands, :exit to quit.

> message := "Hello, Beamtalk!"
"Hello, Beamtalk!"

> 2 + 3 * 4
14

> :load "examples/getting-started/src/hello.bt"
nil

> Hello new greeting
│ Hello, World!
a Hello

Load Files

> :load "examples/getting-started/src/counter.bt"
nil

Development Setup

The fastest path is the devcontainer: open the repo in VS Code with the Dev Containers extension, click Reopen in Container, then run just ci. Everything — Rust, Erlang/OTP, rebar3, Just, the GitHub CLI, and the editor extensions — comes pre-configured.

Prefer a local toolchain? Install Rust, the BEAM tools via mise (mise install reads the pinned .tool-versions), and cargo install just, then just ci.

CONTRIBUTING.md has the full guide — devcontainer details, GitHub/SSH commit-signing setup, the test layers, commit conventions, and the PR workflow. For AI agent contributors, see AGENTS.md.


Project Status

Active development — the compiler core is working with an interactive REPL.

What Works Now

  • REPL — Interactive evaluation with variable persistence, :sync, :interrupt, parallel :test
  • Lexer & Parser — Full expression parsing with error recovery
  • Core Erlang codegen — Compiles to BEAM bytecode via erlc
  • Actors & Supervision — Spawn actors with state, sync/async messages, futures, OTP supervision with Result-shaped lifecycle, named registration
  • Field assignments — Actor state mutations via :=
  • Method dispatch — Full message routing (unary, binary, keyword)
  • Pattern matchingmatch: expressions with literal, variable, and constructor patterns
  • Hot code reloading — Redefine classes/methods on running actors via >>; class crash recovery preserves dispatch tables
  • Type systemtyped classes, generics, protocols, unions, control-flow narrowing, FFI inference, Never, Self class, local annotations
  • Package managerbeamtalk.toml [dependencies] (path/git/hex), beamtalk.lock, qualified pkg@Class names, beamtalk deps
  • Native Erlang in packagesnative/*.erl compiled via vendored rebar3; EUnit runs through beamtalk test
  • Standard library — Boolean, Block, Integer, Float, String, Character, Collections, Result, Printable, Package, Tracing
  • Class system — Inheritance, super, sealed, internal access control, class-side methods, abstract classes, auto-chained initialize
  • Cascades, map literals, comprehensions, exception handling
  • LSP — Completions (incl. FFI), hover with type/Dynamic-reason, go-to-definition, find references, workspace symbols, diagnostics
  • Testing — SUnit-style TestCase, parallel runner, BUnit + EUnit integration
  • Toolingbeamtalk doctor, beamtalk type-coverage, beamtalk gen-native, beamtalk generate stubs, MCP server, VS Code extension
  • LiveView IDE — browser-based Smalltalk cockpit (system browser, live method editing, Workspace + Transcript, Bindings, Inspector) attached to a running workspace over Erlang distribution

Documentation

📚 Documentation Index — Start here for a guided tour 🌐 API Reference — Standard library API docs (auto-generated) 📖 Documentation Site — Full docs including language features, principles, and architecture

Core Documents

Architecture

Tooling & Vision


Examples & Standard Library

Examples (examples/)

Simple programs demonstrating language features:

cargo run -- repl
> :load "examples/getting-started/src/hello.bt"

Standard Library (stdlib/src/)

Foundational classes implementing "everything is a message":

Class Description
Actor Base class for all actors
Block First-class closures
True / False Boolean control flow
Integer / Float Numeric types
String / Character UTF-8 text and characters
List / Tuple Ordered collections
Set / Dictionary Unordered collections
Nil Null object pattern
TestCase SUnit-style test framework

See stdlib/src/README.md for full documentation.


Repository Structure

beamtalk/
├── crates/
│   ├── beamtalk-core/       # Lexer, parser, AST, codegen, type checker
│   ├── beamtalk-cli/        # Command-line interface & REPL
│   ├── beamtalk-lsp/        # Language server (LSP)
│   └── beamtalk-repl-protocol/ # Shared REPL response types
├── stdlib/src/              # Standard library (.bt files)
├── runtime/                 # Erlang runtime (actors, REPL backend)
├── stdlib/test/             # BUnit test cases (TestCase classes)
├── tests/
│   ├── repl-protocol/       # REPL TCP-protocol tests
│   └── parity/              # Cross-surface parity tests
├── docs/                    # Design documents & ADRs
├── examples/                # Example programs
└── editors/vscode/          # VS Code extension

The compiler is written in Rust and generates Core Erlang, which compiles to BEAM bytecode via erlc.


Inspiration

Beamtalk combines ideas from:

  • Smalltalk/Newspeak — Live programming, message-based syntax, reflection (inspiration, not strict compatibility)
  • Erlang/BEAM — Actors, fault tolerance, hot code reload, distribution
  • Elixir — Protocols, comprehensions, with blocks
  • Gleam — Result types, exhaustive pattern matching
  • Dylan — Sealing, conditions/restarts, method combinations
  • TypeScript — Compiler-as-language-service architecture

Contributing

We welcome contributions! See CONTRIBUTING.md for how to get started — covering dev setup, running tests, PR guidelines, and where to help.

For AI agent contributors, see AGENTS.md for detailed development guidelines.

We use Linear for issue tracking (project prefix: BT).


License

Licensed under the Apache License, Version 2.0. See LICENSE for details.

About

BeamTalk: Where actors don't just run—they evolve.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors