Markdown 194 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="300">
</picture>
<h3>A small systems language that compiles to Zig — now compiling itself, and, in time, <a href="https://github.com/ajhahnde/FlashOS">FlashOS</a></h3>
<p>
<a href="https://github.com/ajhahnde/Flash/actions/workflows/test.yml"><img src="https://img.shields.io/github/actions/workflow/status/ajhahnde/Flash/test.yml?branch=main&style=flat-square&label=ci" alt="CI"></a>
<img src="https://img.shields.io/badge/version-v0.6.1-f59e0b?style=flat-square" alt="Version">
<img src="https://img.shields.io/badge/bootstrap-fixpoint-f59e0b?style=flat-square" alt="Bootstrap fixpoint">
<img src="https://img.shields.io/badge/status-pre--alpha-f59e0b?style=flat-square" alt="Status">
<img src="https://img.shields.io/badge/zig-0.16.0-lightgrey?style=flat-square" alt="Zig 0.16.0">
<img src="https://img.shields.io/badge/license-Apache--2.0-lightgrey?style=flat-square" alt="License">
</p>
<p>
<b>README</b> ·
<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> ·
<a href="SETUP.md"><b>Setup</b></a> ·
<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>
---
## About
Flash is a statically typed, freestanding-capable systems language. Its
compiler, `flashc`, is written in Flash itself — self-hosted as of v0.5.0 —
and, in its first incarnation, lowers Flash source to Zig source rather
than to machine code. The Zig toolchain then performs code generation,
linking, and alignment-sensitive lowering. A frozen, handwritten-Zig seed
compiler stays in-tree so a clean clone bootstraps with nothing but a Zig
toolchain: the seed builds the compiler from its Flash sources, that
compiler rebuilds itself, and the build asserts both generations emit
byte-identical code.
This "Tier 0" strategy exists for one reason: Flash is being built to
rewrite a real, working operating system —
[FlashOS](https://github.com/ajhahnde/FlashOS), an AArch64 bare-metal kernel
— without regressing its boot contract or its test suite at any step.
Emitting Zig lets Flash and Zig sources coexist module by module, so the
migration is incremental rather than a rewrite.
Flash is an independent side project. FlashOS is its first consumer, not a
dependency.
## Why
FlashOS is roughly 26,000 lines of Zig today. The aim is not to replace Zig
for its own sake, but to own the entire stack — language, compiler, kernel,
and shell — end to end, in the same spirit that drove the original C→Zig
port. Flash is the language layer of that ambition.
## Approach
| Stage | Today | Plan |
| :------------ | :------------------------------------------------------------------------------------------- | :------------------------------------------------------- |
| Backend | Flash → Zig (transpile) | optionally Flash → LLVM IR, or a native AArch64 backend |
| Type checking | native binding/mutability checks + compile-time evaluation; the rest leans on Zig downstream | full native checker |
| Self-hosting | done —`flashc` is written in Flash (v0.5.0) | retire the Zig seed with the native backend |
The frontend (lexer, parser, AST, sema) is reused unchanged if the backend
is later swapped; only lowering is replaced. See [VISION.md](VISION.md).
## Status
Pre-alpha. v0.6.0 is released: the low-level language register an
operating system needs is complete, and Flash has the seed of its own
standard library. The compiler has been **self-hosted** since v0.5.0 —
the maintained `flashc` source is Flash (`selfhost/`), the handwritten
Zig compiler under `src/` is the frozen bootstrap seed, and `zig build fixpoint` certifies on every build that the generation chain stays
closed. On that footing, the v1 syntax surface (frozen at v0.4.0,
growing additively only) gained its booked systems forms: wrapping
compound assignment (`+%=` `-%=` `*%=`), array repetition (`**`),
`export`/`extern` variables, `linksection(…)`, `packed`/`extern` struct
layouts, `callconv` in function types, pointer captures (`|*x|`),
labeled loops, `align(N)` in pointer types and on bindings, and
`errdefer |err|` capture. And `std/` is born: the `core` module lands
memory primitives, the `List(T)` dynamic array, comptime-checked
formatting and integer parsing, integer bounds, and an arena allocator —
all pure Flash, with the self-hosted compiler itself running on them.
See the [changelog](CHANGELOG.md) for what has landed.
## Building
Requires Zig 0.16.0 exactly (pinned; see `.zigversion`). Full steps in
[SETUP.md](SETUP.md).
```sh
zig build # build flashc (the stage0 bootstrap seed) into zig-out/bin
zig build test # run the host unit + integration suite (includes test-flash, test-selfhost, test-std, test-lsp, and test-driver)
zig build test-flash # transpile and run the .flash test suite (tests/flash/)
zig build test-selfhost # transpile and run the self-hosted compiler's test suite (selfhost/)
zig build test-std # transpile and run the standard library's test suite (std/)
zig build test-lsp # transpile and run the language server's test suite (tools/lsp/)
zig build test-driver # assert the build driver's file outputs, exit codes, and flag composition
zig build stage1 # build flashc-stage1 — the compiler built from the Flash sources
zig build stage2 # build flashc-stage2 — stage1 rebuilding the compiler from the same sources
zig build diff-corpus # assert flashc and flashc-stage1 behave byte-identically over the corpus
zig build fixpoint # assert stage1 and stage2 emit byte-identical Zig, deterministically
zig build lsp # build flashd, the Flash language server (editor wiring in editors/)
# transpile a Flash program to Zig (lowered source on stdout, or -o FILE):
zig-out/bin/flashc examples/hello.flash
# transpile a whole source tree, mirroring relative paths (src/**.flash -> gen/**.zig):
zig-out/bin/flashc build src gen
# reformat a .flash file in place (--check reports without writing):
zig-out/bin/flashc fmt examples/hello.flash
# inspect the token stream, or print the version:
zig-out/bin/flashc --dump-tokens examples/clear.flash
zig-out/bin/flashc --version
```
## Tutorial
An interactive, browser-based tutorial — twelve chapters beside a live code
editor — is hosted at
[ajhahnde.github.io/Flash](https://ajhahnde.github.io/Flash/). Reading and
loading examples into the editor are fully static; for live Flash → Zig
transpilation run the bundled dev server (`cd tutorial && npm install && npm start`).
For the full syntax and semantics in one document see the
[Language Reference](REFERENCE.md); for small, copyable patterns —
allocators, error handling, casts, bit work, JSON — see the
[Cookbook](COOKBOOK.md).
## Layout
```
selfhost/ the compiler — flashc written in Flash (support.flash is the std shim)
std/ the Flash standard library — the `core` module, written in Flash
src/ the frozen bootstrap seed — the handwritten Zig compiler (bugfixes only)
tests/ integration tests over the example sources
examples/ sample .flash programs (hello, clear, and /bin coreutil ports;
register/ holds post-bootstrap grammar samples)
editors/ VS Code + Neovim syntax grammars and the language-server wiring
tutorial/ interactive web tutorial (GitHub Pages + local dev server)
assets/ logo
tools/ host-side build tooling (the diff-corpus and fixpoint harnesses)
and tools/lsp/ — flashd, the Flash language server, written in Flash
.github/ CI + Pages workflows
```
## AI assistance
The prose docs in this repo (README, CHANGELOG, REFERENCE, COOKBOOK,
VISION) and the tutorial are LLM-drafted under my review. They're kept honest by the
build, not by trust: every behavioral claim maps to something CI runs.
- `zig build test` — the compiler test suite (lexer → parser → sema → lower)
- `zig build diff-corpus` — asserts the Zig seed (stage0) and the
self-hosted compiler (stage1) behave identically
- `zig build fixpoint` — asserts stage1 and stage2 emit byte-identical
Zig, i.e. the compiler reproduces itself exactly
All three run on every push. If a doc claims the bootstrap closes, the
fixpoint gate is what proves it.
The docs are also kept current automatically: a contract-literal drift
check verifies the version, the Zig pin, and the `zig build` target
names quoted in these files against the live tree, so a stale copy is
caught rather than shipped.
Source code (`src/*.zig`, `selfhost/*.flash`, `std/`, `tools/`) is
authored by me.
## License
Apache-2.0. See [LICENSE.md](LICENSE.md).
## See also
- **[FlashOS](https://github.com/ajhahnde/FlashOS)** — the operating system Flash is written in.
- **[eeco](https://github.com/ajhahnde/eeco)** — self-maintaining workflow ecosystem.
- **[the-way-out](https://github.com/ajhahnde/the-way-out)** — top-down pixel-art escape-room shooter.
- **[Theria](https://github.com/ajhahnde/Theria)** — 2.5D MOBA built in Godot 4.
---
[Next: Vision →](VISION.md)