The cursor now costs nothing for a byte inside an escape sequence and one cell fewer for a plain glyph: the grid is the truth, so the old cursor cell is repainted after the byte, and not at all when a glyph has just been drawn over it. __fortify_panic says "r8169: rtl_open.cold+0x..." through ldlsd's module list, so a photograph of the screen is enough, and exits instead of spinning on a core and holding /dev/netdev. docs/plan/finch.md: only integrating Finch is later; finishing it is not. The self-hosting gap measured against Finch's own bootstrap test. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015f73FesGZGYPkmDvUcj6QX
93 lines
4.8 KiB
Markdown
93 lines
4.8 KiB
Markdown
# Finch, for SchOS's own programs
|
|
|
|
**Two things, and only one of them is later.**
|
|
|
|
- *Bringing Finch into SchOS* (below) is **later** — behind [1.0.md](1.0.md)'s
|
|
freeze like everything else here that is not named there.
|
|
- *Finishing Finch itself*, and making it fully self-hosting, is work on the
|
|
Finch repository and does not touch this tree. It can proceed now; see
|
|
[the gap](#the-self-hosting-gap).
|
|
|
|
Finch is the author's own language: <https://pandor.pl/git/nexoniarz/Finch>
|
|
(GitHub mirror: `Nexoniarz/Finch`). The plan is to write SchOS's own
|
|
applications and tools in it, in place of C, and so leave behind what C does
|
|
badly: silent narrowing, signed/unsigned mixing, undefined behaviour on an
|
|
out-of-range index, a forgotten `free`.
|
|
|
|
## What it is today (version 2.4.0)
|
|
|
|
Measured from the repository, not from its README alone:
|
|
|
|
- **LLVM front end**, C-like syntax, no semicolons, no headers, no preprocessor.
|
|
It compiles through LLVM's `-O2` pipeline to native code; there is no
|
|
garbage collector.
|
|
- **Values, not references:** lists, text and structs copy on assignment and
|
|
are freed at the end of their block. Out-of-range indexes, division by zero
|
|
and null pointers stop with a runtime error rather than undefined behaviour.
|
|
- **Errors as values** (`int(s) or 0`, `try read_file(p)`), maps, methods,
|
|
modules.
|
|
- **C interop through libclang:** `import "foo.h"` plus `link "foo"` calls any C
|
|
library, structs by value and callbacks included. That is the way in to
|
|
everything SchOS already has — musl, the `/dev/*` interfaces, Alpine's
|
|
libraries.
|
|
- **Targets:** Linux, macOS, Windows, on x86-64 and ARM64 (`src/target.cpp`;
|
|
the System V, AAPCS64 and Microsoft x64 ABIs are in `src/abi.cpp`).
|
|
- **Tooling:** a language server (`finch lsp`), VS Code and Kate support, 74
|
|
tests.
|
|
- **Self-hosting:** `boot/` is a Finch compiler written in Finch (about 3,100
|
|
lines, against about 5,900 for the C++ one in `src/`, language server included) that builds itself to a
|
|
byte-identical result — `tests/boot.sh`.
|
|
|
|
## What SchOS would need to do
|
|
|
|
1. **A `schos` target.** `finch` picks a triple, a C compiler and a linker per
|
|
target. SchOS runs unmodified Alpine binaries and Alpine's musl
|
|
(see [alpine.md](alpine.md)), so the first target is **the existing
|
|
`x86_64-unknown-linux-musl`**, and a Finch program built on the host should
|
|
run on SchOS before anything in Finch is made SchOS-specific. Test that
|
|
before writing a line of target code.
|
|
2. **The compiler on SchOS.** Needs LLVM 21 and libclang, both of which Alpine
|
|
packages. That is a question of apk and memory, not of SchOS.
|
|
3. **`boot/` as the SchOS-hosted compiler.** The C++ compiler needs LLVM's C++
|
|
libraries; the one in `boot/` is the candidate for being the compiler that
|
|
ships in the image, once it emits through LLVM's C API or a smaller
|
|
back end.
|
|
4. **Bindings** for SchOS's own interfaces (`/dev/pci`, `/dev/netdev`,
|
|
schinit's job protocol, the framebuffer) — generated by the C importer from
|
|
the headers in `include/uapi/`, so they are not hand-written and cannot
|
|
drift from the kernel.
|
|
|
|
## The self-hosting gap
|
|
|
|
"Rewrite it in Finch itself" is mostly done: `boot/` compiles itself. What it
|
|
does **not** yet do is stated by its own test, `tests/boot.sh`, which skips
|
|
every test that uses a feature `boot/` lacks. Counting mentions in the two
|
|
sources confirms it (`boot/` vs `src/`):
|
|
|
|
| Feature | `boot/` | `src/` | Needed for |
|
|
|---|---|---|---|
|
|
| maps | 0 | 185 | `codegen_map.cpp` (242 lines) to port |
|
|
| errors as values (`or`, `try`) | few | hundreds | most real programs |
|
|
| methods on user types | 17 | 87 | partial |
|
|
| `defer` | 2 | 31 | partial |
|
|
| sized numbers (`u8`..`u64`, `i8`..`i32`, `f32`, `f64`) | none | throughout | kernel-facing code |
|
|
| enums | 0 | 14 | |
|
|
| C import (`import "x.h"`, `link`) | none | `cimport.cpp`, 373 lines on libclang | **the way into every C library, SchOS's included** |
|
|
| target and ABI layer (AArch64, macOS, Windows) | 0 | `target.cpp`, `abi.cpp` | non-Linux-x86 targets |
|
|
| language server | 0 | `lsp.cpp`, 580 lines | editors |
|
|
|
|
So "finishing" has a concrete order: **errors as values and maps first** (they
|
|
are what the rest uses), then sized numbers and `defer`, then C import — which
|
|
needs libclang bindings, so it needs C import's own simpler form first — and
|
|
the target layer last. `tests/boot.sh` is the measure: the list of skipped
|
|
tests shrinks to nothing.
|
|
|
|
The scratch files `note.txt` and `notatka.txt` in the repository are not
|
|
Finch's and can go.
|
|
|
|
## Rules
|
|
|
|
- Inference, not an instruction: the kernel stays in C. Finch is for
|
|
applications and tools; the user said "our apps or stuff like that".
|
|
- No new capability starts until [the register of unfinished work](1.0.md#the-freeze-and-the-register-of-unfinished-work)
|
|
is empty; the SchOS half of this document is a plan, not an exception to that.
|