bork

module
v0.0.55 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2026 License: MIT

README

bork

Pre-alpha. The language is still changing, and programs may need updating between versions.

bork is a programming language for backend services. Its compiler checks more than types: that a value was validated before it is used, which functions do I/O, that a file or connection is still open, and that every case of a result is handled. Programs compile to a single executable.

Bork bork bork! The name comes from the Swedish Chef. Strict recipes, cheerfully enforced.

Install

bork compiles through Go. Install Go 1.21 or later with automatic toolchain switching enabled (the Go default). Bork needs Go 1.26+ and asks Go to download a suitable toolchain when your installed Go is older. The first install or build may need network access; cached toolchains work offline. With GOTOOLCHAIN=local, install Go 1.26+ yourself. See Go toolchains.

go install github.com/GiGurra/bork/cmd/bork@latest

Prebuilt archives for Linux, macOS and Windows (amd64 and arm64) are available on GitHub Releases, with checksums.txt and the VS Code .vsix. Extract the compiler archive and put bork (bork.exe on Windows) on PATH. Go is still required to compile programs.

On macOS or Linux with Homebrew:

brew install gigurra/tap/bork

The formula installs Go as a runtime dependency. Use brew upgrade bork to update an installation managed by Homebrew; bork upgrade detects Homebrew installations and directs you to that command.

Update explicitly with bork upgrade, or choose a release with bork upgrade v0.4.0. This downloads a release binary, verifies its SHA-256 checksum, and installs it into BORKBIN (shown by bork env BORKBIN). It reports progress and the old and installed versions; use --from-source to build with Go instead. Add that directory to PATH. See upgrades. Interactive commands can offer a quiet daily update notice; disable it with bork env -w BORKUPDATECHECK=off.

Projects can set a minimum compiler with bork 0.4 in bork.mod. Older compilers automatically install and use a suitable release through Go's module proxy. Use BORKTOOLCHAIN=local to disable switching, or BORKTOOLCHAIN=v0.4.2 to pin an exact compiler. bork version and bork env BORKVERSION explain the selection. See compiler versions.

Start a project

bork new hello
cd hello
bork run .
bork test .

Run bork lint . for advisory warnings and safe editor fixes; the language server shows the same warnings. See lint.

Choose --template cli, --template http, or --template lib for other starting points. See creating projects.

Hello, world

Put this in hello.bork:

fn main() {
  println("Hello from bork!")
}
bork run hello.bork      # compile and run
bork build hello.bork    # compile to an executable

The tour continues from here. Read the documentation online. For a single file with top-level statements, use bork script hello.bork; see scripts.

On Linux and macOS, checks and builds automatically cache unchanged compiler results and pure predicate answers. run and script reuse unchanged executables, and unchanged builds, runs and scripts start neither Go nor the compiler on a warm hit, including embeds, cgo and compile-time code. Use --rebuild for an exhaustive rebuild; --fast accepts reuse with untracked external inputs. See the compile cache.

Package values such as MaxRetries = 3 are immutable and pure, computed once on first read, or baked as data when read by comptime. See bindings and package values.

Method chains can span lines with a leading dot, such as .map(...); see methods.

A taste of the language

Records, unions, and exhaustive matching

Values are immutable. Reusing a name in the same block creates a new binding; closures retain captured values, and nested shadowing is forbidden. Unused locals are compile errors: discard explicitly with _. A function that can fail returns a union of its outcomes, written with |, and match must handle every one of them. A value that may be missing is an Option. There is no null and there are no exceptions.

type User = { name: String, email: Option[String] }
type NotFound = { id: Int }

fn findUser(id: Int): User | NotFound {
  if (id == 1) {
    User { name: "Ada", email: Option.None }
  } else {
    NotFound { id: id }
  }
}

fn describe(id: Int): String {
  match (findUser(id)) {
    User { name, email: .Some { value } } => s"$name <$value>"
    User { name } => name
    NotFound { id: missing } => s"no user with id $missing"
  }
}

Without the last arm, the program does not compile: match is not exhaustive: missing NotFound. More on types and matching.

Facts

A fact is something the compiler has proven about a value. A predicate, declared with pred, is a function that returns a Bool. A parameter can require one with where, and then every caller has to show that it holds.

pred positive(x: Int) { x > 0 }

fn transfer(amount: Int where positive): String {
  s"sent $amount"
}

fn payOut(amount: Int): String {
  if (positive(amount)) { transfer(amount) } else { "nothing to send" }
}

Calling transfer(amount) without the check is a compile error, and so is transfer(0):

transfer requires amount to be positive, but that is not proven for amount
transfer requires amount to be positive, but positive(0) is false

More on facts.

Effects

A function's signature says what it does to the outside world: uses io, net, clock, random, or state. A function that declares nothing is pure, and the compiler holds it to that. Only main and tests may use effects without saying so.

fn greeting(name: String): String {
  s"Hello, $name!"
}

fn greet(name: String) uses io {
  println(greeting(name))
}

Printing inside greeting would be an error: greeting uses io (it calls println), but its signature allows no effects. More on effects.

Scopes and tasks

Files, connections, and tasks belong to a scope. A task is a piece of work that runs concurrently, started with spawn. When the scope ends, its files are closed and its tasks have finished, whether the work succeeded or not. Using a file after its scope has ended is a compile error.

import "bork/fs"

fn size(path: String) uses io: Int | fs.Error {
  scope s {
    fs.ReadAllText(fs.Open(path, s)?)?.byteLength()
  }
}

fn main() {
  sizes = scope s {
    tasks = ["a.txt", "b.txt"].map(path => spawn(s, () => size(path)))
    tasks.map(t => await(t))
  }
  println(sizes)
}

Ctrl+C and SIGTERM cancel root scopes and allow cleanup, then exit with 130 or 143. bork/signal configures shutdown grace, subscriptions, and ignored signals.

The ? returns an error to the caller and keeps the successful value. More on scopes and tasks.

Compile-time evaluation

A comptime block runs while the program compiles, and its result is stored in the executable as plain data.

fn square(n: Int): Int {
  n * n
}

fn main() {
  squares = comptime { range(1, 6).map(square) }
  println(squares)
}

More on compile-time evaluation.

Typed string interpolation

s"..." builds a String. A library can define its own prefix that keeps the inserted values apart from the literal text. sql.SQL sends them to the database as bound parameters, so they are never spliced into the SQL text.

import "bork/sql"

type User = { name: String } derive (Decode)

fn find(db: sql.Connection, name: String) uses io + net: List[User] | sql.Error | DecodeError {
  sql.SQL"SELECT name FROM users WHERE name = $name".Query[User](db)
}

The library also checks the literal while compiling. Writing '$name' in quotes is rejected: SQL hole is inside quoted text or an identifier. More on typed interpolation.

Editor support

The VS Code extension combines syntax highlighting with bork lsp: diagnostics for unsaved edits, types and facts on hover, navigation, completion, formatting and compiler fixes. Install it with bork editor install vscode (use --editor cursor or --editor codium for those editors). See editor setup for other LSP clients. The debugger supports bork source breakpoints and shows records, union variants and options as bork values. The shared tree-sitter grammar provides highlighting, indentation, folds and embedded Go queries. Native packages for Vim, Neovim, Emacs, Helix and Zed are linked from editor setup.

Learn more

  • Documentation: the tour, a page for each part of the language, and the command-line reference.
  • Integer bases: hex, binary, octal, arbitrary radix, and checked parsing.
  • Standard packages: files, HTTP, JSON, SQL, time, and more.
  • Typed CLI applications: proven options, field docs, configurable flag/environment mappings, and reusable metadata policies.
  • Package API documentation: run bork doc, with --all for a module or --html for a standalone page; standard and cached pinned libraries work too.
  • Dependency tooling: pin Go and bork libraries in bork.mod with bork deps; commit bork.sum and generated go.mod.
  • Library and consumer example: publish, pin and upgrade a Bork library, with an offline proxy test. Scripts accept Bork libraries through bork:require; editor navigation keeps cached sources read-only.
  • Examples: runnable programs, from wc to an HTTP service.
  • Contributing and design notes: the grammar, requirements, and design documents.

License

MIT

Directories

Path Synopsis
cmd
bork command
Command bork is the bork compiler and toolchain.
Command bork is the bork compiler and toolchain.
bork-playground command
Command bork-playground exposes compiler operations inside a Web Worker.
Command bork-playground exposes compiler operations inside a Web Worker.
internal
apidoc
Package apidoc renders checked package APIs without changing source files.
Package apidoc renders checked package APIs without changing source files.
check
Package check type-checks a parsed bork package.
Package check type-checks a parsed bork package.
childproc
Package childproc runs a program in the foreground on behalf of a bork command, the way a shell would.
Package childproc runs a program in the foreground on behalf of a bork command, the way a shell would.
describe
Package describe adapts source positions to typed compiler queries.
Package describe adapts source positions to typed compiler queries.
diag
Package diag holds source positions and compiler diagnostics.
Package diag holds source positions and compiler diagnostics.
doccomment
Package doccomment gives compiler documentation and editor hover one comment model.
Package doccomment gives compiler documentation and editor hover one comment model.
driver
Package driver runs the compiler pipeline: load sources, parse, check, generate Go, and build with the Go toolchain.
Package driver runs the compiler pipeline: load sources, parse, check, generate Go, and build with the Go toolchain.
format
Package format normalizes bork source whitespace without changing its layout.
Package format normalizes bork source whitespace without changing its layout.
gen
Package gen lowers a checked bork package to Go source.
Package gen lowers a checked bork package to Go source.
gen/cmd/genstdvalidators command
genstdvalidators derives compiler-owned artifacts from embedded standard code.
genstdvalidators derives compiler-owned artifacts from embedded standard code.
gotoolchain
Package gotoolchain applies the compiler's minimum Go version to subprocesses.
Package gotoolchain applies the compiler's minimum Go version to subprocesses.
lsp
Package lsp implements bork's stdio language server.
Package lsp implements bork's stdio language server.
manifest
Package manifest reads compiler requirements without loading program sources.
Package manifest reads compiler requirements without loading program sources.
modcache
Package modcache identifies shared Go dependency sources for editing tools.
Package modcache identifies shared Go dependency sources for editing tools.
playground
Package playground exposes the compiler's process-free operations to browsers.
Package playground exposes the compiler's process-free operations to browsers.
prelude
Package prelude holds the built-in types and functions that every bork package can use.
Package prelude holds the built-in types and functions that every bork package can use.
project
Package project scaffolds projects from the toolchain's bundled templates.
Package project scaffolds projects from the toolchain's bundled templates.
std
Package std holds bork's standard packages, imported as "bork/name" (import "bork/http").
Package std holds bork's standard packages, imported as "bork/name" (import "bork/http").
stdvalidators
Package stdvalidators executes generated, pinned standard-library intrinsics.
Package stdvalidators executes generated, pinned standard-library intrinsics.
syntax
Package syntax contains bork's lexer, syntax tree, and parser.
Package syntax contains bork's lexer, syntax tree, and parser.
testutil
Package testutil provides isolated compiler fixtures for toolchain tests.
Package testutil provides isolated compiler fixtures for toolchain tests.
toolchain
Package toolchain selects and caches immutable compiler installations.
Package toolchain selects and caches immutable compiler installations.
toolenv
Package toolenv resolves and persists the compiler's user settings.
Package toolenv resolves and persists the compiler's user settings.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL