Contributing to struthio #
Thank you for wanting to help. This file covers what you need to know to make a change and get it accepted. README.md says what struthio is and how it is used.
Where to send changes #
Report issues and send pull requests to the Tangled mirror: https://tangled.org/jcollie.dev/struthio.
Setting up #
Everything is pinned in the Nix flake, Zig 0.17.0 included:
$ git clone https://git.jcollie.dev/jeff/struthio.git
$ cd struthio
$ nix develop
The development shell has zig, reuse, tree-sitter, zon2nix,
kcov and the rest. Without Nix, you need Zig 0.17.0 and nothing else to
build and test the library and the command; zig build fetches the
dependencies named in build.zig.zon.
Before you send a change #
CI runs these, and a change has to pass all of them:
$ reuse lint # every file has a license
$ zig fmt --check --exclude zig-pkg . # Zig is formatted
$ zig build test --summary all # unit, golden, fuzz-seed and server tests
$ zig build check # compiles what nothing else builds
$ zig build fuzz-run -- --iterations 60000
$ nix build # the package; runs the tests in the sandbox
$ nix flake check # the tree-sitter grammar
nix build and nix flake check see only files git knows about. git add a
new file before running them, or the build fails as if the file were missing.
Where things are #
| Path | What |
|---|---|
src/root.zig |
The public API: Program, evalSource, Options, format |
src/Tokenizer.zig, src/Parser.zig, src/ast.zig |
Source to tree; names and @include are resolved here |
src/eval.zig, src/builtins.zig, src/value.zig |
Evaluating the tree, and the built-in functions |
src/host.zig, src/decode.zig |
Reading the context by reflection, and decoding into the caller's type |
src/format.zig |
struthio fmt and outline, with a parser of its own that keeps every token |
src/Diagnostic.zig |
Error messages and positions |
src/main.zig, src/lsp.zig |
The struthio command: fmt and the language server |
tests/golden/ |
Whole programs and what they must evaluate to or fail with |
tests/fuzz.zig, tools/fuzz.zig |
Fuzz targets, and a reproducible loop that drives them |
tree-sitter-struthio/ |
The tree-sitter grammar and editor queries |
Making changes #
Tests #
Every behavior change comes with a test. Unit tests sit at the bottom of the
file they test; src/tests.zig holds tests of the language as a whole.
A golden test is a program in tests/golden/NAME.struthio, with either
NAME.zon (what it must evaluate to) or NAME.err (the diagnostic it must
fail with, as line:column: message). Add it to cases in
tests/golden.zig. A program that evaluates must already be formatted, so
run zig build run -- fmt tests/golden/ on it.
Errors #
Anything a program can get wrong is an error with a Diagnostic, never a
panic. Messages are short and lowercase, say what was found, and point at the
place in the source where the problem is.
The language #
A change to the syntax touches more than the parser. In the same change:
src/Parser.zig, andsrc/format.zig's parser, which has to accept the same programs in the same shapes. A test checks that formatting never changes a program's tree.tree-sitter-struthio/grammar.js, thentree-sitter generatein that directory, and commit what it writes tosrc/.- The queries in
tree-sitter-struthio/queries/, then./helix-queries.sh, and commit what it writes toqueries/helix/. - A corpus test in
tree-sitter-struthio/test/corpus/, run withtree-sitter test. - The language section of
README.md.
nix flake check fails if src/ or queries/helix/ is out of date.
The language must not be able to loop or recurse. A feature that makes it possible for a program to run without finishing will not be accepted.
Fuzzing #
The targets in tests/fuzz.zig run on their seeds as part of
zig build test. To search for problems:
$ zig build fuzz --fuzz # Zig's coverage-guided fuzzer
$ zig build fuzz-run -- --seconds 300 # the loop in tools/fuzz.zig
A crash input saved by either is a bug. Fix it and add the input as a seed.
Dependencies #
When build.zig.zon changes, regenerate the file Nix builds from and commit
it along with the change:
$ zon2nix --17 --nix=build.zig.zon.nix build.zig.zon
Documentation #
The API documentation is generated from doc comments; read it with
zig build docs-serve. A public declaration gets a doc comment. When behavior
changes, update README.md to describe how things are now, not how they
changed.
Licensing #
struthio is MIT licensed and follows REUSE. Every
new file starts with an SPDX header like the ones already in the tree; a
file that cannot hold one goes in REUSE.toml. By sending a change you agree
to license it under the MIT license.
Commits #
The first line is a short summary in the imperative ("Add switch", "Give a float printed as ZON room for all of its digits"). The body explains what changed and why.