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 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: on:
push: push:
branches: [main, "ci/**"] branches: [main, "ci/**"]
tags: ["v*"] tags: ["v*"]
pull_request: pull_request:
env:
LLVM_VERSION: 21.1.8
jobs: jobs:
linux: linux:
strategy: strategy:
@ -21,77 +22,57 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install LLVM 21, libclang, tools - name: Install clang 21, libclang, tools
run: | run: |
wget -q https://apt.llvm.org/llvm.sh wget -q https://apt.llvm.org/llvm.sh
sudo bash llvm.sh 21 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 echo "/usr/lib/llvm-21/bin" >> $GITHUB_PATH
- name: Build - name: Build the compiler (seed, then itself, and the two must agree)
run: | run: |
cmake -S . -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-21/lib/cmake/llvm -DCMAKE_BUILD_TYPE=Release export FINCH_LIBCLANG="-L/usr/lib/llvm-21/lib -lclang-21"
ninja -C build bootstrap/build.sh
build/finch version build/finch version
- name: Tests - name: Tests (programs, refusals, -g, a shared library, the language server)
run: tests/run.sh run: tests/run.sh
- name: Shared library
run: tests/shared.sh
- name: Tests under valgrind - name: Tests under valgrind
if: matrix.arch == 'x64' if: matrix.arch == 'x64'
run: MEMCHECK=1 tests/run.sh run: MEMCHECK=1 tests/run.sh
- name: Self-hosting
run: tests/boot.sh
- name: Language server
run: python3 tests/lsp_test.py
- name: Package - name: Package
run: | 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 tar -czf finch-linux-${{ matrix.arch }}.tar.gz -C dist finch
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
with: with:
name: finch-linux-${{ matrix.arch }} name: finch-linux-${{ matrix.arch }}
path: finch-linux-${{ matrix.arch }}.tar.gz path: finch-linux-${{ matrix.arch }}.tar.gz
macos: cross:
runs-on: macos-15 name: programs for ${{ matrix.target }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
target: [windows, arm64]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install LLVM 21 - name: Install clang 21, libclang, cross compilers and emulators
run: | run: |
brew install llvm@21 ninja wget -q https://apt.llvm.org/llvm.sh
echo "$(brew --prefix llvm@21)/bin" >> $GITHUB_PATH sudo bash llvm.sh 21
- name: Build 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: | run: |
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR="$(brew --prefix llvm@21)/lib/cmake/llvm" export FINCH_LIBCLANG="-L/usr/lib/llvm-21/lib -lclang-21"
ninja -C build bootstrap/build.sh
build/finch version - name: Run every test on the other system
- 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
run: | run: |
cat > fw.fch <<'EOF' if [ "${{ matrix.target }}" = windows ]; then
import "CoreFoundation/CoreFoundation.h" FINCH_CC=x86_64-w64-mingw32-gcc tests/cross.sh windows
link "CoreFoundation.framework" else
FINCH_CC=aarch64-linux-gnu-gcc QEMU_LD_PREFIX=/usr/aarch64-linux-gnu tests/cross.sh arm64
fn main() { fi
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
vscode: vscode:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
@ -112,51 +93,3 @@ jobs:
with: with:
name: finch-vscode name: finch-vscode
path: editors/vscode/finch-lang.vsix 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 - **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. 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 - **Written in itself.** The compiler is Finch code, and nothing else: `src/*.fch`, about 8.6k lines. It is built from a
byte-identical result. It handles the whole language except C import and `link` (sized numbers, seed (its own LLVM IR, `bootstrap/`) and then from itself, and the two come out identical. Its first version, in C++,
methods, `defer`, errors as values, maps and `for k, v` all work); `tests/boot.sh` shows what is left. is kept on the `before-bootstrap` branch.
## Quick start ## Quick start
Ready builds are in the [releases](https://github.com/Nexoniarz/Finch/releases): **Building it** (Linux x86-64 or ARM64; needs `clang` and libclang, LLVM 21):
| 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):
```sh ```sh
git clone https://github.com/Nexoniarz/Finch.git git clone https://github.com/Nexoniarz/Finch.git
cd Finch cd Finch
nix-shell # or install LLVM 21 + libclang + cmake + ninja yourself nix-shell # or install clang + libclang (LLVM 21) + pkg-config yourself
cmake -S . -B build -G Ninja bootstrap/build.sh # the compiler is build/finch: built from the seed, then from itself
ninja -C build
./build/finch run examples/hello.fch ./build/finch run examples/hello.fch
./build/finch build examples/tour.fch -o tour && ./tour ./build/finch build examples/tour.fch -o tour && ./tour
tests/run.sh # 74 passed, 0 failed tests/run.sh # every program, every refusal, -g, a shared library, the language server
tests/boot.sh # the compiler written in Finch builds itself
``` ```
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 ## Documentation
Pick the guide that fits you: Pick the guide that fits you:
@ -156,12 +151,14 @@ Pick the guide that fits you:
## Layout ## 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 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 examples/ example programs
editors/ VS Code extension, Kate highlighting and LSP setup 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 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ć, - **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. 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 - **Napisany w sobie.** Kompilator to kod w Finchu i nic więcej: `src/*.fch`, ok. 8,6 tys. linii. Buduje się go z ziarna
do identycznego co do bajtu wyniku. (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 ## Szybki start
Gotowe wersje są w [wydaniach](https://github.com/Nexoniarz/Finch/releases): **Budowanie** (Linux x86-64 lub ARM64; potrzebny `clang` i libclang, LLVM 21):
| 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):
```sh ```sh
git clone https://github.com/Nexoniarz/Finch.git git clone https://github.com/Nexoniarz/Finch.git
cd Finch cd Finch
nix-shell # albo zainstaluj samodzielnie LLVM 21 + libclang + cmake + ninja nix-shell # albo zainstaluj samodzielnie clang + libclang (LLVM 21) + pkg-config
cmake -S . -B build -G Ninja bootstrap/build.sh # kompilator to build/finch: z ziarna, potem z samego siebie
ninja -C build
./build/finch run examples/hello.fch ./build/finch run examples/hello.fch
./build/finch build examples/tour.fch -o tour && ./tour ./build/finch build examples/tour.fch -o tour && ./tour
tests/run.sh # 74 passed, 0 failed tests/run.sh # każdy program, każda odmowa, -g, biblioteka współdzielona, serwer języka
tests/boot.sh # kompilator napisany w Finchu buduje sam siebie
``` ```
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 ## Dokumentacja
Wybierz przewodnik dla siebie: Wybierz przewodnik dla siebie:
@ -155,12 +151,14 @@ Wybierz przewodnik dla siebie:
## Struktura ## 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 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 examples/ przykładowe programy
editors/ rozszerzenie VS Code, podświetlanie i konfiguracja LSP dla Kate 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 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 git clone https://github.com/Nexoniarz/Finch.git
cd Finch cd Finch
nix-shell nix-shell
cmake -S . -B build -G Ninja bootstrap/build.sh
ninja -C build
``` ```
If the last line finishes without the word `error`, Finch is ready. If the last line finishes without the word `error`, Finch is ready.
@ -77,7 +76,7 @@ To check it works, type:
./build/finch version ./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 ## 2. Installing
Finch runs on **Linux** (x86-64 and ARM64), **macOS** (Apple Silicon and Intel) and **Windows** (x86-64), The Finch compiler is written in Finch (see the [engineers' guide](for-engineers.md)). It runs on **Linux**
and is built with **LLVM 21**. Each [release](https://github.com/Nexoniarz/Finch/releases) has a ready (x86-64 and ARM64) and builds programs for **Linux, Windows and macOS**. It needs **clang 21** and **libclang**
`finch` for Windows, Linux x86-64, Linux ARM64 and macOS ARM64. (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) ### Option A: a ready build (Linux)
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`.
Programs are normal `.exe` files. To build from source on Windows instead, follow `.github/workflows/ci.yml` Download `finch-linux-x64.tar.gz` or `finch-linux-arm64.tar.gz` from the
(Visual Studio 2022 + the `clang+llvm-21.x-x86_64-pc-windows-msvc` package from LLVM's releases). [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 ### Option B: build it yourself
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)
```sh ```sh
git clone https://github.com/Nexoniarz/Finch.git git clone https://github.com/Nexoniarz/Finch.git
cd Finch cd Finch
nix-shell # downloads LLVM, libclang, clang, cmake, ninja, pkg-config nix-shell # clang, libclang, pkg-config (or install them with your distribution)
cmake -S . -B build -G Ninja bootstrap/build.sh # build/finch
ninja -C build ./build/finch version
./build/finch version # finch 2.4.0 (LLVM 21.x)
``` ```
### Option B: your distribution's packages `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
You need: a C/C++ compiler, CMake ≥ 3.20, Ninja (or Make), LLVM 21 development files, looks, tell it: `FINCH_LIBCLANG="-L/usr/lib/llvm-21/lib -lclang-21" bootstrap/build.sh`.
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
```
### Building for another system ### Building for another system
@ -160,12 +122,13 @@ On Nix the compilers are `pkgsCross.mingwW64.buildPackages.gcc` and
### Putting `finch` on your PATH (optional) ### Putting `finch` on your PATH (optional)
```sh ```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 finch version
``` ```
At run time Finch needs a C compiler (`cc`). It is used to link programs, and once to build At run time Finch needs `clang` (it compiles each program's IR and links it). The small runtime library is built once and
Finch's small runtime library, which is kept in `~/.cache/finch`. Set `CC` to use a different one. 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/ Finch/
├── src/ the compiler (C++) ├── src/ the compiler, in Finch (lexer, parser, gen: LLVM IR as text, cimport: libclang, lsp, main ...)
├── runtime/ finch_rt.c: the small runtime (text, arrays, input, files) ├── std/ the standard library, in Finch: json, path, time, proc
├── boot/ the Finch compiler written in Finch (see the engineers' guide) ├── 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 ├── examples/ hello, tour, types, structs, todo, guess, c_import, window, opengl, vulkan, raylib, llvm
├── tests/ ├── tests/
│ ├── run/ programs + the exact output they must print (.out), input (.in) │ ├── run/ new/ programs + the exact output they must print (.out), input (.in)
│ ├── fail/ programs that must fail, with the expected error in line 1 │ ├── 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) │ ├── 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/) ├── editors/ the VS Code extension (vscode/), Kate highlighting and LSP setup (kate/)
├── docs/ this documentation (en, pl), including the cheat sheet ├── docs/ this documentation (en, pl), including the cheat sheet
├── shell.nix the Nix development environment └── shell.nix the Nix development environment
└── CMakeLists.txt
``` ```
```sh ```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 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 windows # every test built for Windows and run with Wine
tests/cross.sh arm64 # every test built for ARM64 Linux and run with QEMU 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 git clone https://github.com/Nexoniarz/Finch.git
cd Finch cd Finch
nix-shell nix-shell
cmake -S . -B build -G Ninja bootstrap/build.sh
ninja -C build
``` ```
Jeśli ostatnia linijka skończy się bez słowa `error`, Finch jest gotowy. 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 ## 2. Instalacja
Finch działa na **Linuksie** (x86-64 i ARM64), **macOS** (Apple Silicon i Intel) i **Windowsie** (x86-64), Kompilator Fincha jest napisany w Finchu (zobacz [przewodnik dla inżynierów](dla-inzynierow.md)). Działa na **Linuksie**
i jest budowany z **LLVM 21**. Każde [wydanie](https://github.com/Nexoniarz/Finch/releases) ma gotowy (x86-64 i ARM64) i buduje programy dla **Linuksa, Windowsa i macOS**. Potrzebuje **clanga 21** i **libclang** (LLVM 21),
`finch` dla Windowsa, Linuksa x86-64, Linuksa ARM64 i macOS ARM64. ż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, ### Opcja A: gotowa wersja (Linux)
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`.
Programy to zwykłe pliki `.exe`. Żeby zbudować Fincha ze źródeł na Windowsie, idź za `.github/workflows/ci.yml` Pobierz `finch-linux-x64.tar.gz` albo `finch-linux-arm64.tar.gz` z [wydań](https://github.com/Nexoniarz/Finch/releases)
(Visual Studio 2022 + pakiet `clang+llvm-21.x-x86_64-pc-windows-msvc` z wydań LLVM). 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 ### Opcja B: zbuduj sam
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)
```sh ```sh
git clone https://github.com/Nexoniarz/Finch.git git clone https://github.com/Nexoniarz/Finch.git
cd Finch cd Finch
nix-shell # pobiera LLVM, libclang, clang, cmake, ninja, pkg-config nix-shell # clang, libclang, pkg-config (albo zainstaluj z dystrybucji)
cmake -S . -B build -G Ninja bootstrap/build.sh # build/finch
ninja -C build ./build/finch version
./build/finch version # finch 2.4.0 (LLVM 21.x)
``` ```
### Opcja B: pakiety z twojej dystrybucji `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
Potrzebujesz: kompilatora C/C++, CMake ≥ 3.20, Ninja (albo Make), plików deweloperskich LLVM 21 szuka linker: `FINCH_LIBCLANG="-L/usr/lib/llvm-21/lib -lclang-21" bootstrap/build.sh`.
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
```
### Budowanie na inny system ### Budowanie na inny system
@ -159,13 +122,14 @@ Na Niksie te kompilatory to `pkgsCross.mingwW64.buildPackages.gcc` i
### Dodanie `finch` do PATH (opcjonalnie) ### Dodanie `finch` do PATH (opcjonalnie)
```sh ```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 finch version
``` ```
Podczas pracy Finch potrzebuje kompilatora C (`cc`). Używa go do linkowania programów i jednorazowo Podczas działania Finch potrzebuje `clanga` (kompiluje IR każdego programu i go linkuje). Mała biblioteka uruchomieniowa
do zbudowania swojej małej biblioteki uruchomieniowej, którą trzyma w `~/.cache/finch`. budowana jest raz i trzymana w `~/.cache/finch`. `FINCH_CC` wskazuje inny kompilator do linkowania; `FINCH_PATH` dodaje
Inny kompilator wskażesz zmienną `CC`. katalogi, w których szukać modułów.
--- ---
@ -941,28 +905,27 @@ CodeView, który czyta debugger Visual Studio i WinDbg.
``` ```
Finch/ Finch/
├── src/ kompilator (C++) ├── src/ kompilator, w Finchu (lekser, parser, gen: LLVM IR jako tekst, cimport: libclang, lsp, main ...)
├── runtime/ finch_rt.c: mała biblioteka uruchomieniowa (teksty, tablice, wejście, pliki) ├── std/ biblioteka standardowa, w Finchu: json, path, time, proc
├── boot/ kompilator Fincha napisany w Finchu (zobacz przewodnik dla inżynierów) ├── 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 ├── examples/ hello, tour, types, structs, todo, guess, c_import, window, opengl, vulkan, raylib, llvm
├── tests/ ├── tests/
│ ├── run/ programy + dokładny wynik (.out) i wejście (.in) │ ├── run/ new/ programy + dokładny wynik (.out) i wejście (.in)
│ ├── fail/ programy, które muszą się nie udać, z oczekiwanym błędem w 1. linijce │ ├── 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) │ ├── 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/) ├── editors/ rozszerzenie VS Code (vscode/), podświetlanie i konfiguracja LSP dla Kate (kate/)
├── docs/ ta dokumentacja (en, pl), łącznie ze ściągą ├── docs/ ta dokumentacja (en, pl), łącznie ze ściągą
├── shell.nix środowisko deweloperskie Nix └── shell.nix środowisko deweloperskie Nix
└── CMakeLists.txt
``` ```
```sh ```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 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 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 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"> <list name="keywords">
<item>fn</item> <item>fn</item>
<item>struct</item> <item>struct</item>
<item>enum</item>
<item>export</item>
</list> </list>
<list name="control"> <list name="control">
<item>if</item> <item>if</item>
@ -24,6 +26,7 @@
<item>defer</item> <item>defer</item>
<item>or</item> <item>or</item>
<item>try</item> <item>try</item>
<item>match</item>
</list> </list>
<list name="imports"> <list name="imports">
<item>import</item> <item>import</item>

View file

@ -156,5 +156,43 @@
"}" "}"
], ],
"description": "Every key and value of a map (or index and element of an array)" "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": { "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": { "captures": {
"1": { "1": {
"name": "storage.type.struct.finch" "name": "storage.type.struct.finch"
@ -117,7 +117,7 @@
}, },
{ {
"name": "keyword.control.finch", "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", "name": "storage.type.function.finch",
@ -125,7 +125,11 @@
}, },
{ {
"name": "storage.type.struct.finch", "name": "storage.type.struct.finch",
"match": "\\bstruct\\b" "match": "\\b(struct|enum)\\b"
},
{
"name": "storage.modifier.finch",
"match": "\\bexport\\b"
}, },
{ {
"name": "constant.language.finch", "name": "constant.language.finch",

View file

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