Markdown 227 lines
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="assets/flash_logo_dark.png">
<img src="assets/flash_logo_light.png" alt="Flash" width="240">
</picture>
<h1>Setup</h1>
<p><i>From clone to running compiler in two commands.</i></p>
<p>
<a href="README.md"><b>README</b></a> ·
<a href="VISION.md"><b>Vision</b></a> ·
<a href="https://ajhahnde.github.io/Flash/"><b>Tutorial</b></a> ·
<a href="REFERENCE.md"><b>Reference</b></a> ·
<a href="COOKBOOK.md"><b>Cookbook</b></a> ·
<b>Setup</b> ·
<a href="VERSIONING.md"><b>Versioning</b></a> ·
<a href="CHANGELOG.md"><b>Changelog</b></a> ·
<a href="LICENSE.md"><b>License</b></a>
</p>
</div>
---
How to build and run the Flash compiler (`flashc`).
## Requirements
- **Zig 0.16.0**, exactly. The version is hard-pinned (see `.zigversion`)
and the build fails fast on any other version. Install from
[ziglang.org/download](https://ziglang.org/download/) or with a version
manager (zigup / zvm / anyzig).
## Build
```sh
git clone https://github.com/ajhahnde/Flash.git
cd Flash
zig build
```
The `flashc` binary lands in `zig-out/bin/flashc`.
## Run
```sh
# version
zig-out/bin/flashc --version
# inspect the token stream
zig-out/bin/flashc --dump-tokens examples/clear.flash
# reformat a .flash file in place (--check reports without writing)
zig-out/bin/flashc fmt examples/hello.flash
# transpile a .flash file to Zig (lowered source on stdout)
zig build run -- examples/hello.flash
# the same, written to a file instead of stdout
zig-out/bin/flashc examples/hello.flash -o hello.zig
# transpile a whole source tree: every .flash under src/ lands in gen/ as a
# .zig twin mirroring its relative path; the first compile error stops the
# build with a non-zero exit
zig-out/bin/flashc build src gen
```
Compile errors print the offending source line with a `^` caret under the
exact spot (and a `~` tail when the error spans more than one character):
```
flashc: broken.flash:2:9: error: unknown name 'nope'
_ = nope.sys.write()
^~~~
```
Pass `--plain-diagnostics` (any argument position) to get the bare
one-line `file:line:col: error: message` form instead — handy for
grep-style tooling that keys on one diagnostic per line.
### Tracing Zig errors back to Flash source
The emitted Zig is compiled by the Zig toolchain, so a type error caught
there is reported against the *generated* file. Pass `--anchors` (any
argument position) and every lowered top-level constant and function is
prefixed with a comment naming the Flash line it came from:
```sh
zig-out/bin/flashc --anchors examples/hello.flash > hello.zig
```
```zig
// hello.flash:12
export fn main(...) callconv(.c) noreturn {
```
A Zig error inside that function now reads back to `hello.flash:12` by
eye. The comment names the file only (no directories), and without the
flag the emitted bytes are unchanged.
## Using Flash in your own project
Flash compiles to readable Zig, so a Flash project is a Zig project with one
extra step: transpile the Flash sources, then let `zig build` compile the
result. A minimal layout:
```
my-project/
├── build.zig — ordinary Zig build script (below)
├── src/ — your .flash sources
└── gen/ — the transpiled .zig twins (generated, ignorable)
```
`flashc build src gen` keeps `gen/` mirrored to `src/`, and this `build.zig`
wires the two steps together so `zig build` does both:
```zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
// Transpile every .flash file under src/ into gen/. Point the first
// argument at your flashc binary (here: on PATH).
const transpile = b.addSystemCommand(&.{ "flashc", "build", "src", "gen" });
// Compile the generated Zig as an ordinary executable.
const exe = b.addExecutable(.{
.name = "my-app",
.root_module = b.createModule(.{
.root_source_file = b.path("gen/main.zig"),
.target = target,
.optimize = optimize,
}),
});
exe.step.dependOn(&transpile.step);
b.installArtifact(exe);
}
```
A compile error in any Flash source stops the transpile step non-zero, so
`zig build` halts with the Flash diagnostic — file, line, and caret —
before the Zig compiler ever runs. For errors the Zig toolchain catches in
the generated code, add `--anchors` to the `flashc build` command line and
each generated declaration carries a comment naming its Flash origin.
## Test
```sh
zig build test
```
Runs the per-module unit tests (lexer, parser, semantic checker, lowering, and
the formatter), the integration suite (`tests/`), the build-driver harness
(`zig build test-driver` — file outputs, exit codes, and flag composition),
and the Flash-source test suite together. The latter can also run on its own:
```sh
zig build test-flash
```
This transpiles each `.flash` file under `tests/flash/` with the freshly
built `flashc` and runs the emitted Zig `test` blocks — Flash code testing
itself through its own `test "name" { }` form.
## Self-hosting
The compiler's maintained source is Flash, under `selfhost/`. By convention
the handwritten Zig compiler under `src/` is *stage0* — the frozen bootstrap
seed that keeps a clean clone buildable with nothing but a Zig toolchain —
the compiler built from the Flash sources is *stage1* (`flashc-stage1`), and
the compiler stage1 builds from those same sources is *stage2*
(`flashc-stage2`). Six build steps drive and certify the bootstrap:
```sh
# build flashc-stage1: stage0 transpiles every selfhost module and the
# result is compiled as the self-hosted compiler
zig build stage1
# build flashc-stage2: the same composition, with stage1 as the transpiler —
# the self-hosted compiler compiling its own sources
zig build stage2
# transpile each selfhost module and run its Flash test blocks
# (also part of `zig build test`)
zig build test-selfhost
# transpile each standard-library module (std/) and run its Flash test
# blocks (also part of `zig build test`)
zig build test-std
# transpile each language-server module (tools/lsp/) and run its Flash
# test blocks (also part of `zig build test`)
zig build test-lsp
# build flashd, the Flash language server (diagnostics over stdio; see
# editors/nvim/README.md for the editor wiring)
zig build lsp
# run flashc and flashc-stage1 over every example, probe, and test source
# and assert byte-identical transpile, --dump-tokens, and fmt behaviour
zig build diff-corpus
# the bootstrap fixpoint: assert stage1 and stage2 emit byte-identical Zig
# over every selfhost source and example, deterministically across runs
zig build fixpoint
```
## Shell helpers (optional)
`flash.env.zsh` provides a `flash` verb dispatcher. Source it from your
shell profile:
```sh
echo "[[ -f $PWD/flash.env.zsh ]] && source $PWD/flash.env.zsh" >> ~/.zshrc
# then, from anywhere:
# flash build | flash test | flash tokens examples/clear.flash | flash clean
```
---
[← Prev: Reference](REFERENCE.md) · [Next: Versioning →](VERSIONING.md)