Install, CI, seeds and docs for the compiler written in Finch

bootstrap/install.sh and a share/finch lookup for the runtime and std; an ARM64 Linux seed; bootstrap/README.md;
CI builds from the seed on x64 and ARM64 and runs every test on Windows (Wine) and ARM64 (qemu); README, install and
layout sections of the guides (EN+PL) no longer talk about CMake; editors know enum, match and export.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015f73FesGZGYPkmDvUcj6QX
This commit is contained in:
Nexoniarz 2026-10-25 21:53:50 +01:00
commit 81df9f8c3e
15 changed files with 125197 additions and 30152 deletions

View file

@ -1,14 +1,15 @@
name: CI
# The compiler is written in Finch. It is built from bootstrap/<system>.ll, its own LLVM IR (see bootstrap/README.md),
# then from itself. Linux x86-64 and ARM64 have seeds; macOS and Windows machines can't build the compiler yet
# (programs for them are built from Linux with --target, and tested here under Wine and qemu).
on:
push:
branches: [main, "ci/**"]
tags: ["v*"]
pull_request:
env:
LLVM_VERSION: 21.1.8
jobs:
linux:
strategy:
@ -21,77 +22,57 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install LLVM 21, libclang, tools
- name: Install clang 21, libclang, tools
run: |
wget -q https://apt.llvm.org/llvm.sh
sudo bash llvm.sh 21
sudo apt-get install -y llvm-21-dev libclang-21-dev ninja-build valgrind
sudo apt-get install -y libclang-21-dev pkg-config valgrind
echo "/usr/lib/llvm-21/bin" >> $GITHUB_PATH
- name: Build
- name: Build the compiler (seed, then itself, and the two must agree)
run: |
cmake -S . -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-21/lib/cmake/llvm -DCMAKE_BUILD_TYPE=Release
ninja -C build
export FINCH_LIBCLANG="-L/usr/lib/llvm-21/lib -lclang-21"
bootstrap/build.sh
build/finch version
- name: Tests
- name: Tests (programs, refusals, -g, a shared library, the language server)
run: tests/run.sh
- name: Shared library
run: tests/shared.sh
- name: Tests under valgrind
if: matrix.arch == 'x64'
run: MEMCHECK=1 tests/run.sh
- name: Self-hosting
run: tests/boot.sh
- name: Language server
run: python3 tests/lsp_test.py
- name: Package
run: |
mkdir -p dist/finch && cp build/finch README.md LICENSE dist/finch/ && cp -r examples dist/finch/
mkdir -p dist/finch && cp build/finch README.md LICENSE dist/finch/ && cp -r runtime std examples dist/finch/
tar -czf finch-linux-${{ matrix.arch }}.tar.gz -C dist finch
- uses: actions/upload-artifact@v4
with:
name: finch-linux-${{ matrix.arch }}
path: finch-linux-${{ matrix.arch }}.tar.gz
macos:
runs-on: macos-15
cross:
name: programs for ${{ matrix.target }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
target: [windows, arm64]
steps:
- uses: actions/checkout@v4
- name: Install LLVM 21
- name: Install clang 21, libclang, cross compilers and emulators
run: |
brew install llvm@21 ninja
echo "$(brew --prefix llvm@21)/bin" >> $GITHUB_PATH
- name: Build
wget -q https://apt.llvm.org/llvm.sh
sudo bash llvm.sh 21
sudo apt-get install -y libclang-21-dev pkg-config gcc-mingw-w64-x86-64 wine64 gcc-aarch64-linux-gnu qemu-user libc6-arm64-cross
echo "/usr/lib/llvm-21/bin" >> $GITHUB_PATH
- name: Build the compiler
run: |
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR="$(brew --prefix llvm@21)/lib/cmake/llvm"
ninja -C build
build/finch version
- name: Tests
run: CC=/usr/bin/clang tests/run.sh
- name: Self-hosting
run: CC=/usr/bin/clang tests/boot.sh
- name: Language server
run: python3 tests/lsp_test.py
- name: Apple frameworks
export FINCH_LIBCLANG="-L/usr/lib/llvm-21/lib -lclang-21"
bootstrap/build.sh
- name: Run every test on the other system
run: |
cat > fw.fch <<'EOF'
import "CoreFoundation/CoreFoundation.h"
link "CoreFoundation.framework"
fn main() {
print(CFAbsoluteTimeGetCurrent() > 0.0)
}
EOF
out=$(CC=/usr/bin/clang build/finch run fw.fch)
echo "$out"
test "$out" = "true"
- name: Package
run: |
mkdir -p dist/finch && cp build/finch README.md LICENSE dist/finch/ && cp -r examples dist/finch/
tar -czf finch-macos-arm64.tar.gz -C dist finch
- uses: actions/upload-artifact@v4
with:
name: finch-macos-arm64
path: finch-macos-arm64.tar.gz
if [ "${{ matrix.target }}" = windows ]; then
FINCH_CC=x86_64-w64-mingw32-gcc tests/cross.sh windows
else
FINCH_CC=aarch64-linux-gnu-gcc QEMU_LD_PREFIX=/usr/aarch64-linux-gnu tests/cross.sh arm64
fi
vscode:
runs-on: ubuntu-24.04
@ -112,51 +93,3 @@ jobs:
with:
name: finch-vscode
path: editors/vscode/finch-lang.vsix
windows:
runs-on: windows-2022
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- name: Cache LLVM
id: cache-llvm
uses: actions/cache@v4
with:
path: C:/llvm
key: llvm-${{ env.LLVM_VERSION }}-x86_64-pc-windows-msvc
- name: Download LLVM ${{ env.LLVM_VERSION }}
if: steps.cache-llvm.outputs.cache-hit != 'true'
run: |
curl -sSL -o llvm.tar.xz "https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVM_VERSION/clang+llvm-$LLVM_VERSION-x86_64-pc-windows-msvc.tar.xz"
mkdir -p /c/llvm
tar -xf llvm.tar.xz -C /c/llvm --strip-components=1
rm llvm.tar.xz
- name: Build finch.exe
run: |
echo "C:/llvm/bin" >> $GITHUB_PATH
export PATH="/c/llvm/bin:$PATH"
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR=C:/llvm/lib/cmake/llvm \
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_C_COMPILER=cl -DCMAKE_CXX_COMPILER=cl
ninja -C build
cp /c/llvm/bin/libclang.dll build/
build/finch.exe version
- name: Tests
run: |
export PATH="/c/llvm/bin:$PATH"
tests/run.sh
- name: Language server
run: python tests/lsp_test.py
- name: Package
run: |
mkdir -p dist/finch
cp build/finch.exe build/libclang.dll dist/finch/
cp README.md LICENSE dist/finch/
cp -r examples dist/finch/
cd dist && 7z a -tzip finch-windows-x64.zip finch > /dev/null
- uses: actions/upload-artifact@v4
with:
name: finch-windows-x64
path: dist/finch-windows-x64.zip

View file

@ -48,38 +48,33 @@ fn main() {
```
- **Any C library, directly.** `import "raylib.h"` + `link "raylib"`, and you can call it, structs by value
and callbacks included. Headers are read by libclang, so there is nothing to declare by hand.
- **Written in itself, too.** `boot/` is a Finch compiler written in Finch that compiles itself to a
byte-identical result. It handles the whole language except C import and `link` (sized numbers,
methods, `defer`, errors as values, maps and `for k, v` all work); `tests/boot.sh` shows what is left.
- **Written in itself.** The compiler is Finch code, and nothing else: `src/*.fch`, about 8.6k lines. It is built from a
seed (its own LLVM IR, `bootstrap/`) and then from itself, and the two come out identical. Its first version, in C++,
is kept on the `before-bootstrap` branch.
## Quick start
Ready builds are in the [releases](https://github.com/Nexoniarz/Finch/releases):
| System | Download | Also needs |
|---|---|---|
| Windows x64 | `finch-windows-x64.zip` | LLVM 21, Visual Studio Build Tools (C++); [steps](docs/en/for-technicians.md#windows) |
| macOS (Apple Silicon) | `finch-macos-arm64.tar.gz` | `brew install llvm@21`; [steps](docs/en/for-technicians.md#macos) |
| Linux x64 / ARM64 | `finch-linux-x64.tar.gz` / `finch-linux-arm64.tar.gz` | LLVM 21 libraries, a C compiler; [steps](docs/en/for-technicians.md#linux) |
Editors: **Kate** (`editors/kate/install.sh`), **VS Code** (the `finch-lang` `.vsix` from the release), or any
editor with LSP support (`finch lsp`).
**Building it yourself** (Linux or macOS, LLVM 21):
**Building it** (Linux x86-64 or ARM64; needs `clang` and libclang, LLVM 21):
```sh
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell # or install LLVM 21 + libclang + cmake + ninja yourself
cmake -S . -B build -G Ninja
ninja -C build
nix-shell # or install clang + libclang (LLVM 21) + pkg-config yourself
bootstrap/build.sh # the compiler is build/finch: built from the seed, then from itself
./build/finch run examples/hello.fch
./build/finch build examples/tour.fch -o tour && ./tour
tests/run.sh # 74 passed, 0 failed
tests/boot.sh # the compiler written in Finch builds itself
tests/run.sh # every program, every refusal, -g, a shared library, the language server
```
Ready builds of the compiler are in the [releases](https://github.com/Nexoniarz/Finch/releases) (Linux x64 and ARM64:
unpack, keep `runtime/` and `std/` next to `finch`). **Programs for Windows, ARM64 and macOS** are built from Linux with
`--target windows|arm64|macos` (see the [guide](docs/en/for-technicians.md#3-the-finch-command)); the compiler itself does not run on
macOS or Windows yet (it needs a seed made with that system's headers: see [bootstrap/README.md](bootstrap/README.md)).
Editors: **Kate** (`editors/kate/install.sh`), **VS Code** (the `finch-lang` `.vsix` from the release), or any
editor with LSP support (`finch lsp`).
## Documentation
Pick the guide that fits you:
@ -156,12 +151,14 @@ Pick the guide that fits you:
## Layout
```
src/ compiler: lexer, parser, AST, codegen, C import + ABI, language server, driver (C++17, ~7k lines)
src/ the compiler, in Finch: lexer, parser, AST, code generation (to LLVM IR as text), C import (libclang) and
the C calling conventions, the language server, the driver
std/ the standard library, in Finch: json, path, time, proc
runtime/ the small C runtime linked into every program
boot/ the Finch compiler written in Finch (~3k lines)
bootstrap/ build.sh and the seeds: the compiler's own LLVM IR, one per system
examples/ example programs
editors/ VS Code extension, Kate highlighting and LSP setup
tests/ run/ (golden output), fail/ (expected errors), run.sh, boot.sh, cross.sh, lsp_test.py
tests/ run/ new/ (golden output), fail/ new/fail/ (expected errors), run.sh, cross.sh, shared.sh, lsp_test.py
docs/ en/ and pl/ guides for three audiences
```

View file

@ -48,37 +48,33 @@ fn main() {
```
- **Każda biblioteka C, bezpośrednio.** Piszesz `import "raylib.h"` i `link "raylib"`, i możesz z niej korzystać,
także ze struktur przekazywanych przez wartość i z callbacków. Nagłówki czyta libclang, więc nie trzeba niczego deklarować ręcznie.
- **Napisany także w sobie.** `boot/` to kompilator Fincha napisany w Finchu, który kompiluje sam siebie
do identycznego co do bajtu wyniku.
- **Napisany w sobie.** Kompilator to kod w Finchu i nic więcej: `src/*.fch`, ok. 8,6 tys. linii. Buduje się go z ziarna
(własny kod LLVM IR, `bootstrap/`), potem z samego siebie, a oba wyniki są identyczne. Pierwsza wersja, w C++,
jest w gałęzi `before-bootstrap`.
## Szybki start
Gotowe wersje są w [wydaniach](https://github.com/Nexoniarz/Finch/releases):
| System | Plik | Potrzebuje też |
|---|---|---|
| Windows x64 | `finch-windows-x64.zip` | LLVM 21, Visual Studio Build Tools (C++); [kroki](docs/pl/dla-technikow.md#windows) |
| macOS (Apple Silicon) | `finch-macos-arm64.tar.gz` | `brew install llvm@21`; [kroki](docs/pl/dla-technikow.md#macos) |
| Linux x64 / ARM64 | `finch-linux-x64.tar.gz` / `finch-linux-arm64.tar.gz` | biblioteki LLVM 21, kompilator C; [kroki](docs/pl/dla-technikow.md#linux) |
Edytory: **Kate** (`editors/kate/install.sh`), **VS Code** (plik `.vsix` `finch-lang` z wydania) albo każdy
edytor obsługujący LSP (`finch lsp`).
**Samodzielne budowanie** (Linux albo macOS, LLVM 21):
**Budowanie** (Linux x86-64 lub ARM64; potrzebny `clang` i libclang, LLVM 21):
```sh
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell # albo zainstaluj samodzielnie LLVM 21 + libclang + cmake + ninja
cmake -S . -B build -G Ninja
ninja -C build
nix-shell # albo zainstaluj samodzielnie clang + libclang (LLVM 21) + pkg-config
bootstrap/build.sh # kompilator to build/finch: z ziarna, potem z samego siebie
./build/finch run examples/hello.fch
./build/finch build examples/tour.fch -o tour && ./tour
tests/run.sh # 74 passed, 0 failed
tests/boot.sh # kompilator napisany w Finchu buduje sam siebie
tests/run.sh # każdy program, każda odmowa, -g, biblioteka współdzielona, serwer języka
```
Gotowe kompilatory są w [wydaniach](https://github.com/Nexoniarz/Finch/releases) (Linux x64 i ARM64: rozpakuj, zostaw
`runtime/` i `std/` obok `finch`). **Programy dla Windowsa, ARM64 i macOS** buduje się z Linuksa przez
`--target windows|arm64|macos`; sam kompilator nie działa jeszcze na macOS ani Windowsie (potrzebuje ziarna
zrobionego z nagłówkami tego systemu: patrz [bootstrap/README.md](bootstrap/README.md)).
Edytory: **Kate** (`editors/kate/install.sh`), **VS Code** (plik `.vsix` `finch-lang` z wydania) albo dowolny
edytor z obsługą LSP (`finch lsp`).
## Dokumentacja
Wybierz przewodnik dla siebie:
@ -155,12 +151,14 @@ Wybierz przewodnik dla siebie:
## Struktura
```
src/ kompilator: lekser, parser, AST, codegen, import C + ABI, serwer języka, sterownik (C++17, ok. 7 tys. linii)
src/ kompilator, w Finchu: lekser, parser, AST, generowanie kodu (do LLVM IR jako tekst), import C (libclang)
i konwencje wywołań C, serwer języka, sterownik
std/ biblioteka standardowa, w Finchu: json, path, time, proc
runtime/ mały runtime w C dołączany do każdego programu
boot/ kompilator Fincha napisany w Finchu (ok. 3 tys. linii)
bootstrap/ build.sh i ziarna: własny LLVM IR kompilatora, po jednym na system
examples/ przykładowe programy
editors/ rozszerzenie VS Code, podświetlanie i konfiguracja LSP dla Kate
tests/ run/ (wzorcowe wyjście), fail/ (oczekiwane błędy), run.sh, boot.sh, cross.sh, lsp_test.py
tests/ run/ new/ (wzorcowe wyjście), fail/ new/fail/ (oczekiwane błędy), run.sh, cross.sh, shared.sh, lsp_test.py
docs/ przewodniki en/ i pl/ dla trzech grup odbiorców
```

39
bootstrap/README.md Normal file
View file

@ -0,0 +1,39 @@
# The seed
Finch's compiler is written in Finch. To build it you need something that already runs Finch: the **seed**, which is
the compiler's own LLVM IR, one file per system:
| File | System | Checked |
|---|---|---|
| `linux-x86_64.ll` | Linux x86-64 | built and tested here and in CI |
| `linux-aarch64.ll` | Linux ARM64 | made with the ARM64 cross compiler; CI builds and tests it on an ARM64 runner |
`bootstrap/build.sh` compiles the seed with `clang` (and the runtime, and libclang) into `build/finch0`; `finch0` builds
`src/` into `finch1`; `finch1` builds `src/` again into `build/finch`; the two must make the same IR, or the script stops.
## Why one per system
The seed includes how this system's C compiler passes structs by value, because the compiler calls libclang with
`CXCursor`, `CXType` and `CXString` (the calling convention is different on x86-64, on ARM64 and on Windows). So a seed
made for one system doesn't run on another, and a seed needs the target system's C headers to be made.
## When to make a new one
When the compiler's own source starts to use a feature that the committed seed doesn't have, `build.sh` fails at the first
step. Make the seed from a working compiler:
```sh
bootstrap/build.sh seed # writes bootstrap/<this system>.ll
```
For another system, from a machine that has that system's headers and a cross compiler (what `tests/cross.sh` uses):
```sh
FINCH_CC=aarch64-linux-gnu-gcc build/finch ir src/main.fch --target arm64 > bootstrap/linux-aarch64.ll
```
## macOS and Windows
There is no seed for them yet: it needs Apple's or Microsoft's headers, which can't be had on Linux. Until there is one,
programs for macOS and Windows are built from Linux with `--target macos|windows`, and the compiler's older C++ version
(branch `before-bootstrap`) is the way to get a compiler that runs there.

14
bootstrap/install.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/sh
# Installs the compiler you built (bootstrap/build.sh) under a prefix:
# bootstrap/install.sh /usr/local (needs sudo)
# bootstrap/install.sh ~/.local
# finch goes to <prefix>/bin; the runtime and the standard library go to <prefix>/share/finch, where finch looks for them.
set -eu
cd "$(dirname "$0")/.."
prefix=${1:-/usr/local}
[ -x build/finch ] || { echo "install: run bootstrap/build.sh first" >&2; exit 1; }
mkdir -p "$prefix/bin" "$prefix/share/finch"
cp build/finch "$prefix/bin/finch"
rm -rf "$prefix/share/finch/runtime" "$prefix/share/finch/std"
cp -r runtime std "$prefix/share/finch/"
echo "installed: $prefix/bin/finch ($("$prefix/bin/finch" version))"

95038
bootstrap/linux-aarch64.ll Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -63,8 +63,7 @@ these lines one by one, pressing **Enter** after each:
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell
cmake -S . -B build -G Ninja
ninja -C build
bootstrap/build.sh
```
If the last line finishes without the word `error`, Finch is ready.
@ -77,7 +76,7 @@ To check it works, type:
./build/finch version
```
You should see something like `finch 2.4.0`.
You should see something like `Finch 2.4.0`.
---

View file

@ -63,78 +63,40 @@ messages that tell you how to fix the problem.
## 2. Installing
Finch runs on **Linux** (x86-64 and ARM64), **macOS** (Apple Silicon and Intel) and **Windows** (x86-64),
and is built with **LLVM 21**. Each [release](https://github.com/Nexoniarz/Finch/releases) has a ready
`finch` for Windows, Linux x86-64, Linux ARM64 and macOS ARM64.
The Finch compiler is written in Finch (see the [engineers' guide](for-engineers.md)). It runs on **Linux**
(x86-64 and ARM64) and builds programs for **Linux, Windows and macOS**. It needs **clang 21** and **libclang**
(LLVM 21) to read C headers and to compile its output.
### Windows
The compiler does not run on macOS or Windows yet; it needs a seed made with that system's headers
([bootstrap/README.md](../../bootstrap/README.md) says why). Until then, build your Windows and macOS programs from Linux
with `--target` (below), or use the older C++ compiler from the `before-bootstrap` branch.
1. Download **`finch-windows-x64.zip`** from the [releases](https://github.com/Nexoniarz/Finch/releases)
and unpack it, for example to `C:\finch`. It contains `finch.exe` and `libclang.dll`.
2. Install **LLVM 21** (`LLVM-21.x.x-win64.exe` from the
[LLVM releases](https://github.com/llvm/llvm-project/releases)) and tick *Add LLVM to the system PATH*.
Finch uses its `clang` to link programs.
3. Install **Visual Studio Build Tools 2022** with *Desktop development with C++*: it provides the Windows
libraries every program is linked with.
4. Add `C:\finch` to your PATH, open a new terminal, and run `finch version`.
### Option A: a ready build (Linux)
Programs are normal `.exe` files. To build from source on Windows instead, follow `.github/workflows/ci.yml`
(Visual Studio 2022 + the `clang+llvm-21.x-x86_64-pc-windows-msvc` package from LLVM's releases).
Download `finch-linux-x64.tar.gz` or `finch-linux-arm64.tar.gz` from the
[releases](https://github.com/Nexoniarz/Finch/releases) and unpack it. Keep `runtime/` and `std/` next to the `finch` file
(or install it, below). You also need `clang` 21 and its libclang library:
### macOS
| Distribution | Packages |
|---|---|
| Debian / Ubuntu | `clang-21 libclang-21-dev` from [apt.llvm.org](https://apt.llvm.org), `pkg-config` |
| Fedora | `clang clang-devel pkgconf` |
| Arch | `clang pkgconf` |
| Nix | `nix-shell` in the repository gives all of it |
```sh
brew install llvm@21 # Finch's LLVM; programs are linked with Apple's clang
```
Then either unpack **`finch-macos-arm64.tar.gz`** from the releases (it uses Homebrew's `llvm@21`),
or build it yourself (Xcode command line tools: `xcode-select --install`):
```sh
git clone https://github.com/Nexoniarz/Finch.git && cd Finch
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR="$(brew --prefix llvm@21)/lib/cmake/llvm"
ninja -C build
./build/finch version
```
Apple frameworks link with `link "Cocoa.framework"` (`-framework Cocoa`), and their headers import as usual:
`import "OpenGL/gl.h"`.
### Linux
The ready `finch-linux-x64.tar.gz` / `finch-linux-arm64.tar.gz` need LLVM 21's libraries
(Debian/Ubuntu: `libllvm21 libclang1-21` from [apt.llvm.org](https://apt.llvm.org)) and a C compiler (`cc`).
Building it yourself works the same on x86-64 and ARM64 (Raspberry Pi 4/5, Graviton, …).
Other LLVM versions will likely fail to compile, because LLVM's C++ API changes between releases.
### Option A: Nix (recommended, nothing to install by hand)
### Option B: build it yourself
```sh
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell # downloads LLVM, libclang, clang, cmake, ninja, pkg-config
cmake -S . -B build -G Ninja
ninja -C build
./build/finch version # finch 2.4.0 (LLVM 21.x)
nix-shell # clang, libclang, pkg-config (or install them with your distribution)
bootstrap/build.sh # build/finch
./build/finch version
```
### Option B: your distribution's packages
You need: a C/C++ compiler, CMake ≥ 3.20, Ninja (or Make), LLVM 21 development files,
libclang 21 development files, and optionally `pkg-config`.
| Distribution | Packages (names can differ slightly by version) |
|---|---|
| Debian / Ubuntu | `build-essential cmake ninja-build pkg-config llvm-21-dev libclang-21-dev` |
| Fedora | `gcc-c++ cmake ninja-build pkgconf llvm-devel clang-devel` |
| Arch | `base-devel cmake ninja pkgconf llvm clang` |
These have not been tested; if CMake cannot find LLVM, point it there:
```sh
cmake -S . -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-21/lib/cmake/llvm
ninja -C build
```
`bootstrap/build.sh` compiles the seed (`bootstrap/<system>.ll`, the compiler's own LLVM IR) into a first compiler, builds
`src/` with it, builds `src/` again with the result and checks the two are identical. If libclang isn't where the linker
looks, tell it: `FINCH_LIBCLANG="-L/usr/lib/llvm-21/lib -lclang-21" bootstrap/build.sh`.
### Building for another system
@ -160,12 +122,13 @@ On Nix the compilers are `pkgsCross.mingwW64.buildPackages.gcc` and
### Putting `finch` on your PATH (optional)
```sh
sudo cp build/finch /usr/local/bin/
sudo bootstrap/install.sh # /usr/local/bin/finch, and /usr/local/share/finch/{runtime,std}
bootstrap/install.sh ~/.local # or into your own folder
finch version
```
At run time Finch needs a C compiler (`cc`). It is used to link programs, and once to build
Finch's small runtime library, which is kept in `~/.cache/finch`. Set `CC` to use a different one.
At run time Finch needs `clang` (it compiles each program's IR and links it). The small runtime library is built once and
kept in `~/.cache/finch`. `FINCH_CC` names a different compiler to link with; `FINCH_PATH` adds folders to look for modules in.
---
@ -938,28 +901,27 @@ Visual Studio debugger and WinDbg read.
```
Finch/
├── src/ the compiler (C++)
├── runtime/ finch_rt.c: the small runtime (text, arrays, input, files)
├── boot/ the Finch compiler written in Finch (see the engineers' guide)
├── src/ the compiler, in Finch (lexer, parser, gen: LLVM IR as text, cimport: libclang, lsp, main ...)
├── std/ the standard library, in Finch: json, path, time, proc
├── runtime/ finch_rt.c: the small runtime (text, arrays, maps, input, files)
├── bootstrap/ build.sh, install.sh and the seeds (the compiler's own IR, one per system)
├── examples/ hello, tour, types, structs, todo, guess, c_import, window, opengl, vulkan, raylib, llvm
├── tests/
│ ├── run/ programs + the exact output they must print (.out), input (.in)
│ ├── fail/ programs that must fail, with the expected error in line 1
│ ├── run/ new/ programs + the exact output they must print (.out), input (.in)
│ ├── fail/ new/fail/ programs that must fail, with the expected error in line 1
│ ├── run.sh the test runner (MEMCHECK=1 also checks memory with valgrind)
│ └── boot.sh builds the self-hosted compiler with itself and compares
│ ├── cross.sh every test built for Windows / ARM64 and run under Wine / QEMU
│ └── lsp_test.py the language server, talked to like an editor does
├── editors/ the VS Code extension (vscode/), Kate highlighting and LSP setup (kate/)
├── docs/ this documentation (en, pl), including the cheat sheet
├── shell.nix the Nix development environment
└── CMakeLists.txt
└── shell.nix the Nix development environment
```
```sh
tests/run.sh # → 74 passed, 0 failed
tests/run.sh # programs, refusals, -g builds, a shared library, the language server
MEMCHECK=1 tests/run.sh # the same under valgrind: no leaks, no bad memory access
tests/boot.sh # the self-hosting check (needs clang)
tests/cross.sh windows # every test built for Windows and run with Wine
tests/cross.sh arm64 # every test built for ARM64 Linux and run with QEMU
python3 tests/lsp_test.py # the language server
```
---

View file

@ -63,8 +63,7 @@ i wpisz te linijki po kolei, naciskając **Enter** po każdej:
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell
cmake -S . -B build -G Ninja
ninja -C build
bootstrap/build.sh
```
Jeśli ostatnia linijka skończy się bez słowa `error`, Finch jest gotowy.

View file

@ -63,77 +63,40 @@ i komunikaty błędów, które mówią, jak problem naprawić.
## 2. Instalacja
Finch działa na **Linuksie** (x86-64 i ARM64), **macOS** (Apple Silicon i Intel) i **Windowsie** (x86-64),
i jest budowany z **LLVM 21**. Każde [wydanie](https://github.com/Nexoniarz/Finch/releases) ma gotowy
`finch` dla Windowsa, Linuksa x86-64, Linuksa ARM64 i macOS ARM64.
Kompilator Fincha jest napisany w Finchu (zobacz [przewodnik dla inżynierów](dla-inzynierow.md)). Działa na **Linuksie**
(x86-64 i ARM64) i buduje programy dla **Linuksa, Windowsa i macOS**. Potrzebuje **clanga 21** i **libclang** (LLVM 21),
żeby czytać nagłówki C i kompilować to, co wygeneruje.
### Windows
Kompilator nie działa jeszcze na macOS ani Windowsie: potrzebuje ziarna zrobionego z nagłówkami tego systemu
([bootstrap/README.md](../../bootstrap/README.md) tłumaczy dlaczego). Do tego czasu programy na Windows i macOS buduj z Linuksa
przez `--target` (niżej) albo użyj starszego kompilatora w C++ z gałęzi `before-bootstrap`.
1. Pobierz **`finch-windows-x64.zip`** z [wydań](https://github.com/Nexoniarz/Finch/releases) i rozpakuj,
np. do `C:\finch`. W środku są `finch.exe` i `libclang.dll`.
2. Zainstaluj **LLVM 21** (`LLVM-21.x.x-win64.exe` z [wydań LLVM](https://github.com/llvm/llvm-project/releases))
i zaznacz *Add LLVM to the system PATH*. Finch używa jego `clang` do linkowania programów.
3. Zainstaluj **Visual Studio Build Tools 2022** z pakietem *Desktop development with C++*: dostarcza biblioteki
Windowsa, z którymi linkowany jest każdy program.
4. Dodaj `C:\finch` do PATH, otwórz nowy terminal i wpisz `finch version`.
### Opcja A: gotowa wersja (Linux)
Programy to zwykłe pliki `.exe`. Żeby zbudować Fincha ze źródeł na Windowsie, idź za `.github/workflows/ci.yml`
(Visual Studio 2022 + pakiet `clang+llvm-21.x-x86_64-pc-windows-msvc` z wydań LLVM).
Pobierz `finch-linux-x64.tar.gz` albo `finch-linux-arm64.tar.gz` z [wydań](https://github.com/Nexoniarz/Finch/releases)
i rozpakuj. Zostaw `runtime/` i `std/` obok pliku `finch` (albo zainstaluj, niżej). Potrzebny jest też `clang` 21
z biblioteką libclang:
### macOS
| Dystrybucja | Pakiety |
|---|---|
| Debian / Ubuntu | `clang-21 libclang-21-dev` z [apt.llvm.org](https://apt.llvm.org), `pkg-config` |
| Fedora | `clang clang-devel pkgconf` |
| Arch | `clang pkgconf` |
| Nix | `nix-shell` w repozytorium daje wszystko |
```sh
brew install llvm@21 # LLVM dla Fincha; programy linkuje clang od Apple
```
Potem rozpakuj **`finch-macos-arm64.tar.gz`** z wydań (korzysta z `llvm@21` z Homebrew)
albo zbuduj go sam (narzędzia wiersza poleceń Xcode: `xcode-select --install`):
```sh
git clone https://github.com/Nexoniarz/Finch.git && cd Finch
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR="$(brew --prefix llvm@21)/lib/cmake/llvm"
ninja -C build
./build/finch version
```
Frameworki Apple linkuje się przez `link "Cocoa.framework"` (`-framework Cocoa`), a ich nagłówki importuje
się normalnie: `import "OpenGL/gl.h"`.
### Linux
Gotowe `finch-linux-x64.tar.gz` / `finch-linux-arm64.tar.gz` potrzebują bibliotek LLVM 21
(Debian/Ubuntu: `libllvm21 libclang1-21` z [apt.llvm.org](https://apt.llvm.org)) i kompilatora C (`cc`).
Samodzielne budowanie wygląda tak samo na x86-64 i ARM64 (Raspberry Pi 4/5, Graviton, …).
Z innymi wersjami LLVM Finch prawdopodobnie się nie skompiluje, bo API C++ LLVM zmienia się między wydaniami.
### Opcja A: Nix (zalecana, nic nie instalujesz ręcznie)
### Opcja B: zbuduj sam
```sh
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell # pobiera LLVM, libclang, clang, cmake, ninja, pkg-config
cmake -S . -B build -G Ninja
ninja -C build
./build/finch version # finch 2.4.0 (LLVM 21.x)
nix-shell # clang, libclang, pkg-config (albo zainstaluj z dystrybucji)
bootstrap/build.sh # build/finch
./build/finch version
```
### Opcja B: pakiety z twojej dystrybucji
Potrzebujesz: kompilatora C/C++, CMake ≥ 3.20, Ninja (albo Make), plików deweloperskich LLVM 21
i libclang 21, a opcjonalnie `pkg-config`.
| Dystrybucja | Pakiety (nazwy mogą się nieco różnić zależnie od wersji) |
|---|---|
| Debian / Ubuntu | `build-essential cmake ninja-build pkg-config llvm-21-dev libclang-21-dev` |
| Fedora | `gcc-c++ cmake ninja-build pkgconf llvm-devel clang-devel` |
| Arch | `base-devel cmake ninja pkgconf llvm clang` |
Ta opcja nie była testowana. Jeśli CMake nie znajduje LLVM, wskaż mu katalog:
```sh
cmake -S . -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-21/lib/cmake/llvm
ninja -C build
```
`bootstrap/build.sh` kompiluje ziarno (`bootstrap/<system>.ll`, własny LLVM IR kompilatora) do pierwszego kompilatora,
buduje nim `src/`, buduje `src/` jeszcze raz wynikiem i sprawdza, że oba są identyczne. Jeśli libclang nie leży tam, gdzie
szuka linker: `FINCH_LIBCLANG="-L/usr/lib/llvm-21/lib -lclang-21" bootstrap/build.sh`.
### Budowanie na inny system
@ -159,13 +122,14 @@ Na Niksie te kompilatory to `pkgsCross.mingwW64.buildPackages.gcc` i
### Dodanie `finch` do PATH (opcjonalnie)
```sh
sudo cp build/finch /usr/local/bin/
sudo bootstrap/install.sh # /usr/local/bin/finch oraz /usr/local/share/finch/{runtime,std}
bootstrap/install.sh ~/.local # albo do własnego katalogu
finch version
```
Podczas pracy Finch potrzebuje kompilatora C (`cc`). Używa go do linkowania programów i jednorazowo
do zbudowania swojej małej biblioteki uruchomieniowej, którą trzyma w `~/.cache/finch`.
Inny kompilator wskażesz zmienną `CC`.
Podczas działania Finch potrzebuje `clanga` (kompiluje IR każdego programu i go linkuje). Mała biblioteka uruchomieniowa
budowana jest raz i trzymana w `~/.cache/finch`. `FINCH_CC` wskazuje inny kompilator do linkowania; `FINCH_PATH` dodaje
katalogi, w których szukać modułów.
---
@ -941,28 +905,27 @@ CodeView, który czyta debugger Visual Studio i WinDbg.
```
Finch/
├── src/ kompilator (C++)
├── runtime/ finch_rt.c: mała biblioteka uruchomieniowa (teksty, tablice, wejście, pliki)
├── boot/ kompilator Fincha napisany w Finchu (zobacz przewodnik dla inżynierów)
├── src/ kompilator, w Finchu (lekser, parser, gen: LLVM IR jako tekst, cimport: libclang, lsp, main ...)
├── std/ biblioteka standardowa, w Finchu: json, path, time, proc
├── runtime/ finch_rt.c: mała biblioteka uruchomieniowa (teksty, tablice, mapy, wejście, pliki)
├── bootstrap/ build.sh, install.sh i ziarna (własny IR kompilatora, po jednym na system)
├── examples/ hello, tour, types, structs, todo, guess, c_import, window, opengl, vulkan, raylib, llvm
├── tests/
│ ├── run/ programy + dokładny wynik (.out) i wejście (.in)
│ ├── fail/ programy, które muszą się nie udać, z oczekiwanym błędem w 1. linijce
│ ├── run/ new/ programy + dokładny wynik (.out) i wejście (.in)
│ ├── fail/ new/fail/ programy, które muszą się nie udać, z oczekiwanym błędem w 1. linijce
│ ├── run.sh uruchamia testy (MEMCHECK=1 sprawdza też pamięć valgrindem)
│ └── boot.sh buduje kompilator samohostujący nim samym i porównuje
│ ├── cross.sh każdy test zbudowany na Windows / ARM64 i uruchomiony w Wine / QEMU
│ └── lsp_test.py serwer języka, obsługiwany jak przez edytor
├── editors/ rozszerzenie VS Code (vscode/), podświetlanie i konfiguracja LSP dla Kate (kate/)
├── docs/ ta dokumentacja (en, pl), łącznie ze ściągą
├── shell.nix środowisko deweloperskie Nix
└── CMakeLists.txt
└── shell.nix środowisko deweloperskie Nix
```
```sh
tests/run.sh # → 74 passed, 0 failed
tests/run.sh # programy, odmowy, buildy z -g, biblioteka współdzielona, serwer języka
MEMCHECK=1 tests/run.sh # to samo pod valgrindem: bez wycieków i złych dostępów do pamięci
tests/boot.sh # sprawdzenie samohostowania (wymaga clanga)
tests/cross.sh windows # każdy test zbudowany na Windowsa i uruchomiony w Wine
tests/cross.sh arm64 # każdy test zbudowany na Linuksa ARM64 i uruchomiony w QEMU
python3 tests/lsp_test.py # serwer języka
```
---

View file

@ -11,6 +11,8 @@
<list name="keywords">
<item>fn</item>
<item>struct</item>
<item>enum</item>
<item>export</item>
</list>
<list name="control">
<item>if</item>
@ -24,6 +26,7 @@
<item>defer</item>
<item>or</item>
<item>try</item>
<item>match</item>
</list>
<list name="imports">
<item>import</item>

View file

@ -156,5 +156,43 @@
"}"
],
"description": "Every key and value of a map (or index and element of an array)"
},
"enum": {
"prefix": "enum",
"body": [
"enum ${1:Name} {",
"\t${2:First},",
"\t${3:Second}",
"}"
],
"description": "An enum: a type with a few named values"
},
"match": {
"prefix": "match",
"body": [
"match ${1:value} {",
"\t${2:pattern} -> $0",
"\telse -> ",
"}"
],
"description": "match: pick what to do from a value"
},
"generic function": {
"prefix": "fng",
"body": [
"fn ${1:name}[${2:T}](${3:T x}) -> ${2:T} {",
"\t$0",
"}"
],
"description": "A function that works for any type"
},
"generic struct": {
"prefix": "structg",
"body": [
"struct ${1:Name}[${2:T}] {",
"\t$0",
"}"
],
"description": "A struct that holds any type"
}
}

View file

@ -74,7 +74,7 @@
]
},
"struct": {
"match": "\\b(struct)\\s+([A-Za-z_][A-Za-z0-9_]*)",
"match": "\\b(struct|enum)\\s+([A-Za-z_][A-Za-z0-9_]*)",
"captures": {
"1": {
"name": "storage.type.struct.finch"
@ -117,7 +117,7 @@
},
{
"name": "keyword.control.finch",
"match": "\\b(if|else|while|for|in|break|continue|return|defer|or|try)\\b"
"match": "\\b(if|else|while|for|in|break|continue|return|defer|or|try|match)\\b"
},
{
"name": "storage.type.function.finch",
@ -125,7 +125,11 @@
},
{
"name": "storage.type.struct.finch",
"match": "\\bstruct\\b"
"match": "\\b(struct|enum)\\b"
},
{
"name": "storage.modifier.finch",
"match": "\\bexport\\b"
},
{
"name": "constant.language.finch",

View file

@ -216,7 +216,7 @@ fn main([]str args) -> int {
} else if tg.darwin {
loader.os = "macos"
}
for cand in [dirOf(args[0]) + "/../std", dirOf(args[0]) + "/std", "std"] {
for cand in [dirOf(args[0]) + "/../std", dirOf(args[0]) + "/std", dirOf(args[0]) + "/../share/finch/std", "std"] {
if loader.std.len == 0 && file_exists(cand + "/path.fch") {
loader.std = cand
}
@ -276,6 +276,9 @@ fn main([]str args) -> int {
if !file_exists(rt) {
rt = dirOf(args[0]) + "/runtime/finch_rt.c"
}
if !file_exists(rt) {
rt = dirOf(args[0]) + "/../share/finch/runtime/finch_rt.c"
}
if !file_exists(rt) && file_exists("runtime/finch_rt.c") {
rt = "runtime/finch_rt.c"
}