From d2693c5bacc7be73417665e60e3fdf59043d8fb3 Mon Sep 17 00:00:00 2001 From: Nexoniarz Date: Thu, 8 Oct 2026 22:05:02 +0200 Subject: [PATCH] Finch 2.3.0: docs for Windows, LSP and VS Code; cheat sheets (en, pl); portable LSP test Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 2 + CMakeLists.txt | 2 +- README.md | 16 +- README.pl.md | 16 +- docs/en/cheatsheet.md | 305 ++++++++++++++++++++++++++++++++ docs/en/for-beginners.md | 2 +- docs/en/for-engineers.md | 99 ++++++++++- docs/en/for-technicians.md | 71 ++++++-- docs/pl/dla-inzynierow.md | 100 ++++++++++- docs/pl/dla-poczatkujacych.md | 2 +- docs/pl/dla-technikow.md | 72 ++++++-- docs/pl/sciaga.md | 316 ++++++++++++++++++++++++++++++++++ tests/lsp_test.py | 4 +- 13 files changed, 961 insertions(+), 46 deletions(-) create mode 100644 docs/en/cheatsheet.md create mode 100644 docs/pl/sciaga.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d7f271..083eb50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,6 +88,8 @@ jobs: 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 diff --git a/CMakeLists.txt b/CMakeLists.txt index e6e292f..e484a11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -project(finch VERSION 2.0.0 LANGUAGES CXX) +project(finch VERSION 2.3.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/README.md b/README.md index f713172..b81833f 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,11 @@ fn main() { ## Quick start -Linux x86-64, LLVM 21. +**Windows:** download `finch-windows-x64.zip` from the [releases](https://github.com/Nexoniarz/Finch/releases), +install LLVM 21 and Visual Studio Build Tools (C++), and see the +[install steps](docs/en/for-technicians.md#windows). **VS Code:** install the `finch-lang` `.vsix` from the same release. + +**Linux** x86-64, LLVM 21: ```sh git clone https://github.com/Nexoniarz/Finch.git @@ -75,6 +79,7 @@ Pick the guide that fits you: | **Beginners** | Never programmed: students, seniors, anyone curious | [for-beginners.md](docs/en/for-beginners.md) | [dla-poczatkujacych.md](docs/pl/dla-poczatkujacych.md) | | **Technicians** | Know computers, new to programming: install, whole language, C libraries, troubleshooting | [for-technicians.md](docs/en/for-technicians.md) | [dla-technikow.md](docs/pl/dla-technikow.md) | | **Engineers** | Everything: lexer, grammar, AST, type rules, IR lowering, libclang import, ABI, internals | [for-engineers.md](docs/en/for-engineers.md) | [dla-inzynierow.md](docs/pl/dla-inzynierow.md) | +| **Cheat sheet** | Every function, method, operator and command on one page | [cheatsheet.md](docs/en/cheatsheet.md) | [sciaga.md](docs/pl/sciaga.md) | ## The language at a glance @@ -125,9 +130,11 @@ Pick the guide that fits you: - [x] Finch modules (`import name`) - [x] Debug info (`-g`) - [x] Bootstrap: a Finch compiler written in Finch that builds itself -- [ ] Methods on structs, maps, `match` +- [x] Windows: `finch.exe`, `.exe` programs, the Microsoft x64 ABI; cross-building from Linux (`--target windows`) +- [x] Language server (`finch lsp`) and a VS Code extension +- [ ] Maps, methods on structs, `match` - [ ] Error values instead of stopping the program -- [ ] More platforms (ARM64, macOS) +- [ ] More platforms (macOS, ARM64) ## Layout @@ -136,7 +143,8 @@ src/ compiler: lexer, parser, AST, codegen, C import + ABI, driver (C++17 runtime/ the small C runtime linked into every program boot/ the Finch compiler written in Finch (~3k lines) examples/ example programs -tests/ run/ (golden output), fail/ (expected errors), run.sh, boot.sh +editors/ the VS Code extension +tests/ run/ (golden output), fail/ (expected errors), run.sh, boot.sh, windows.sh, lsp_test.py docs/ en/ and pl/ guides for three audiences ``` diff --git a/README.pl.md b/README.pl.md index 45f0212..be57269 100644 --- a/README.pl.md +++ b/README.pl.md @@ -51,7 +51,11 @@ fn main() { ## Szybki start -Linux x86-64, LLVM 21. +**Windows:** pobierz `finch-windows-x64.zip` z [wydań](https://github.com/Nexoniarz/Finch/releases), +zainstaluj LLVM 21 i Visual Studio Build Tools (C++), a potem przejdź przez +[kroki instalacji](docs/pl/dla-technikow.md#windows). **VS Code:** zainstaluj plik `.vsix` `finch-lang` z tego samego wydania. + +**Linux** x86-64, LLVM 21: ```sh git clone https://github.com/Nexoniarz/Finch.git @@ -75,6 +79,7 @@ Wybierz przewodnik dla siebie: | **Początkujący** | Nigdy nie programowałeś: uczniowie, seniorzy, ciekawscy | [dla-poczatkujacych.md](docs/pl/dla-poczatkujacych.md) | [for-beginners.md](docs/en/for-beginners.md) | | **Technicy** | Znasz komputery, programowanie jest nowe: instalacja, cały język, biblioteki C, problemy | [dla-technikow.md](docs/pl/dla-technikow.md) | [for-technicians.md](docs/en/for-technicians.md) | | **Inżynierowie** | Wszystko: lekser, gramatyka, AST, reguły typów, tłumaczenie na IR, import przez libclang, ABI, wnętrze | [dla-inzynierow.md](docs/pl/dla-inzynierow.md) | [for-engineers.md](docs/en/for-engineers.md) | +| **Ściąga** | Każda funkcja, metoda, operator i polecenie na jednej stronie | [sciaga.md](docs/pl/sciaga.md) | [cheatsheet.md](docs/en/cheatsheet.md) | ## Język w pigułce @@ -125,9 +130,11 @@ Wybierz przewodnik dla siebie: - [x] Moduły Fincha (`import nazwa`) - [x] Informacje dla debuggera (`-g`) - [x] Bootstrap: kompilator Fincha napisany w Finchu, który buduje sam siebie -- [ ] Metody w strukturach, mapy, `match` +- [x] Windows: `finch.exe`, programy `.exe`, ABI Microsoft x64; budowanie na Windowsa z Linuksa (`--target windows`) +- [x] Serwer języka (`finch lsp`) i rozszerzenie VS Code +- [ ] Mapy, metody w strukturach, `match` - [ ] Błędy jako wartości zamiast zatrzymywania programu -- [ ] Więcej platform (ARM64, macOS) +- [ ] Więcej platform (macOS, ARM64) ## Struktura @@ -136,7 +143,8 @@ src/ kompilator: lekser, parser, AST, codegen, import C + ABI, sterownik runtime/ mały runtime w C dołączany do każdego programu boot/ kompilator Fincha napisany w Finchu (ok. 3 tys. linii) examples/ przykładowe programy -tests/ run/ (wzorcowe wyjście), fail/ (oczekiwane błędy), run.sh, boot.sh +editors/ rozszerzenie VS Code +tests/ run/ (wzorcowe wyjście), fail/ (oczekiwane błędy), run.sh, boot.sh, windows.sh, lsp_test.py docs/ przewodniki en/ i pl/ dla trzech grup odbiorców ``` diff --git a/docs/en/cheatsheet.md b/docs/en/cheatsheet.md new file mode 100644 index 0000000..8cb36c5 --- /dev/null +++ b/docs/en/cheatsheet.md @@ -0,0 +1,305 @@ +# Finch Cheat Sheet + +Everything in Finch on one page. For explanations, see the [guides](../../README.md#documentation). + +> 🇵🇱 Polska wersja: [sciaga.md](../pl/sciaga.md) + +--- + +## The `finch` command + +| Command | Does | +|---|---| +| `finch run file.fch [args…]` | compile and run (args go to the program) | +| `finch build file.fch [-o name]` | make a program (`name.exe` on Windows) | +| `finch ir file.fch` | print the LLVM IR | +| `finch lsp` | the language server (editors use it) | +| `finch version` | version | +| `-l lib` | link a C library (like `link "lib"`) | +| `--target windows` / `linux` / triple | build for another system | +| `-g` | debug info (gdb, lldb, Visual Studio) | +| `-O0` | no optimizations | + +Environment: `FINCH_PATH` (folders with modules), `FINCH_CC` / `CC` (the C compiler that links). + +--- + +## A file + +```c +import "stdio.h" // a C header +import shapes // a Finch module: shapes.fch +link "m" // a C library, or "mine.c" / ".o" / ".a" + +struct Point { + int x + int y = 0 // default value +} + +fn main() { + print("Hello") +} +``` + +`main` can be `fn main()`, `fn main() -> int` (exit code) or `fn main([]str args)`. +One statement per line, no semicolons, `{` on the same line, no brackets around conditions. + +--- + +## Variables + +| Code | Meaning | +|---|---| +| `x := 5` | new variable, type inferred | +| `int x = 5` | new variable, type written | +| `int x` | zero / `""` / `[]` / `null` / the struct's defaults | +| `x = 7` | assign | +| `x += 1` `-=` `*=` `/=` `%=` | update | + +--- + +## Types + +| Type | Example | +|---|---| +| `int` (= `i64`) | `42`, `-7`, `0xFF`, `1_000_000` | +| `float` (= `f64`) | `3.14` | +| `bool` | `true`, `false` | +| `char` | `'A'`, `'\n'` | +| `str` | `"text\t\"quoted\""` | +| `i8 i16 i32 i64` | signed, sized | +| `u8 u16 u32 u64` | unsigned, sized | +| `f32 f64` | floats | +| `[]T` | array: `[1, 2, 3]`, `[]str names` | +| `ptr[T]`, `ptr` | pointer, untyped pointer | +| `Name` / `module.Name` | a struct | + +Escapes: `\n \t \r \0 \\ \" \'`. + +--- + +## Operators + +| Priority | Operators | +|---|---| +| 5 | `*` `/` `%` `<<` `>>` `&` | +| 4 | `+` `-` `\|` `^` (`+` also joins text) | +| 3 | `==` `!=` `<` `<=` `>` `>=` | +| 2 | `&&` | +| 1 | `\|\|` | +| unary | `-x` `!x` `~x` | + +`x & 1 == 0` means `(x & 1) == 0`. + +--- + +## Control flow + +```c +if a > b { … } else if a == b { … } else { … } +while x > 0 { … } +for i in 0..10 { … } // 0 … 9 +for item in list { … } // every element (or char of a str) +break continue return value +defer cleanup() // runs when the block ends +``` + +--- + +## Functions + +```c +fn add(int a, int b) -> int { + return a + b +} +fn greet(str name) { // no result + print("Hi", name) +} +``` + +Parameters behave like copies. Order in the file doesn't matter. A comma after the last argument is allowed. + +--- + +## Structs + +| Code | Meaning | +|---|---| +| `struct P { … }` | define (one field per line, `= default` optional) | +| `P(1, 2)` | create, all fields in order | +| `P(x: 1)` | create by name, the rest default/zero | +| `p.x`, `p.x = 5` | read, change a field | +| `b := a` | a full copy | + +--- + +## Arrays `[]T` + +| Code | Gives | +|---|---| +| `a.len` | number of elements | +| `a[i]`, `a[i] = x` | element (checked) | +| `a.push(x)` | add at the end | +| `a.pop()` | remove the last, give it back | +| `a.insert(i, x)` | put at position i | +| `a.remove(i)` | remove position i, give it back | +| `a.clear()` | empty it | +| `a.resize(n)` | length n (new elements are zero) | +| `a.find(x)` | index or -1 | +| `a.contains(x)` | bool | +| `a.sort()` | sort (numbers, chars, str) | +| `a.reverse()` | reverse | +| `a.slice(s, e)` | new array of s … e-1 | +| `a.join(sep)` | `[]str` → one str | +| `a.ptr` | address of the first element (for C) | + +--- + +## Text `str` + +| Code | Gives | +|---|---| +| `s.len` | bytes | +| `s[i]`, `s[i] = 'x'` | char | +| `a + b` | joined text | +| `s.sub(a, b)` | part a … b-1 | +| `s.find(t)` | position or -1 | +| `s.contains(t)` | bool | +| `s.starts_with(t)`, `s.ends_with(t)` | bool | +| `s.split(sep)` | `[]str` | +| `s.trim()` | no spaces at the ends | +| `s.upper()`, `s.lower()` | A–Z / a–z | +| `s.replace(a, b)` | every a → b | +| `s.repeat(n)` | n times | +| `s.bytes()` | `[]u8` | +| `s.ptr` | `ptr[char]` (for C) | +| `==` `!=` `<` `>` | compare | + +--- + +## Conversions + +| Code | Result | +|---|---| +| `int(3.9)` | `3` | +| `int("42")` | `42` (stops the program if it isn't a number) | +| `int('A')` | `65` | +| `float(7)`, `float("2.5")` | `7`, `2.5` | +| `u8(300)` | `44` (keeps the low bits) | +| `char(66)` | `'B'` | +| `bool(0)` | `false` | +| `str(42)`, `str(1.5)`, `str(true)`, `str('c')` | text | +| `str(bytes)` | `[]u8` → text | +| `str(p)` | C `char*` → text | +| `ptr(p)`, `ptr(16)` | untyped pointer, from a pointer or a number | +| `int(p)` | pointer → address | + +Automatic only when nothing is lost: smaller → bigger number, any int → float, `f32` → `f64`. + +--- + +## Built-in functions + +| Function | Does | +|---|---| +| `print(a, b, …)` | print, spaces between, newline at the end | +| `input()`, `input("Question? ")` | read a line | +| `read_file(path)` | file → str | +| `write_file(path, text)` | str → file, `true` if it worked | +| `file_exists(path)` | bool | +| `delete_file(path)` | bool | +| `shell(command)` | run a command, its exit code | +| `exit(code)` | stop the program now | +| `addr(x)` | pointer to x; `addr(fn)` = C callback | +| `new(value)` | value on the heap → `ptr[T]` | +| `free(p)` | give it back | + +--- + +## Pointers + +| Finch | C | +|---|---| +| `ptr[int] p` | `int *p` | +| `addr(x)` | `&x` | +| `p.value` | `*p` | +| `p.field` | `p->field` | +| `p[i]` | `p[i]` | +| `null` | `NULL` | +| `ptr` | `void *` | + +--- + +## Memory + +- Arrays, text and structs free themselves at the end of their block. No `free` needed. +- `b := a` copies; a call's result moves; `return x` moves. +- `new(...)` + `free(...)` (often with `defer`) for linked lists, trees, sharing. +- C memory: C's own functions (`malloc` / `free`, `fclose`, …). + +--- + +## Modules + +```c +import shapes // shapes.fch next to this file (or in FINCH_PATH) +shapes.area(b) // its functions +shapes.Box(2, 3) // its structs +shapes.Box other // in declarations +``` + +--- + +## C + +| Code | Meaning | +|---|---| +| `import "x.h"` | functions, structs, enums, `#define` numbers, globals | +| `link "name"` | libname.so / name.lib (pkg-config first) | +| `link "file.c"` | compile your own C file | +| `addr(myFn)` | pass a Finch function as a callback | + +| C type | Finch | +|---|---| +| `int` / `long long` / `unsigned` | `i32` / `i64` / `u32` (by size) | +| `float` / `double` | `f32` / `f64` | +| `char *` (parameter, result) | `str` | +| `char *` (field, behind a pointer) | `ptr[char]` | +| `struct X` | `X` | +| `T *` | `ptr[T]` | +| `void *`, handles | `ptr` | +| `T x[N]` (in a struct) | `[N]T` | + +--- + +## Runtime errors (the program stops with file and line) + +| Message | Cause | +|---|---| +| `division by zero` | `/` or `%` by 0 | +| `index 5 is out of range (the length is 3)` | `a[5]` | +| `pop() on an empty array` | | +| `used .value on a null pointer` | `.value` / `.field` / `[i]` through `null` | +| `can't turn "x" into int` | `int("x")` | +| `can't read the file "…"` | `read_file` | + +--- + +## VS Code (extension "Finch") + +| Key / action | Does | +|---|---| +| ▶ / `Ctrl+F5` | run the file | +| `Finch: Build This File` | build; errors go to Problems | +| `F12` | go to definition | +| hover | type / signature / docs | +| `Ctrl+Space` | completion (after `.`: fields, methods, module members) | +| `Ctrl+Shift+O` | functions and structs in the file | +| `main`, `fn`, `fnr`, `struct`, `for`, `foreach`, `if`, `ife`, `while`, `input` + Tab | snippets | +| setting `finch.path` | where finch / finch.exe is | + +--- + +## Keywords + +`fn return if else while for in break continue true false null import link struct defer` diff --git a/docs/en/for-beginners.md b/docs/en/for-beginners.md index f37b34b..a0a7e4c 100644 --- a/docs/en/for-beginners.md +++ b/docs/en/for-beginners.md @@ -77,7 +77,7 @@ To check it works, type: ./build/finch version ``` -You should see something like `finch 2.0.0`. +You should see something like `finch 2.3.0`. --- diff --git a/docs/en/for-engineers.md b/docs/en/for-engineers.md index 03d2f35..ab83d9e 100644 --- a/docs/en/for-engineers.md +++ b/docs/en/for-engineers.md @@ -38,7 +38,10 @@ For the language from a user's point of view, see the [technicians' guide](for-t 20. [Semantics vs. C](#20-semantics-vs-c) 21. [Function reference](#21-function-reference) 22. [Extending the compiler](#22-extending-the-compiler) -23. [Known limitations](#23-known-limitations) +23. [Targets and Windows](#23-targets-and-windows) +24. [The language server](#24-the-language-server) +25. [The VS Code extension](#25-the-vs-code-extension) +26. [Known limitations](#26-known-limitations) --- @@ -874,12 +877,102 @@ emission in `arithOp`/`compare`, an explanation in `badOperands`. --- -## 23. Known limitations +## 23. Targets and Windows + +`src/target.h` holds `g_target`: the LLVM triple, `windows` / `msvc` / `cross` flags, the C compiler (`cc`) +and the executable suffix. `setTarget()` picks the C compiler: `FINCH_CC`, else `CC` (not when +cross-compiling), else `x86_64-w64-mingw32-gcc` for `--target windows` from Linux, `clang` on Windows, +`cc` on Unix. Everything platform-dependent goes through it: + +- **Headers:** libclang parses with `--target=` (so `long` is 32 bits on Windows and the right + headers are used) and, on Windows, `-D_USE_MATH_DEFINES`. Include folders come from ` -E -v`. +- **Processes:** `capture()` / `runCommand()` wrap `popen` / `system` (`_popen` on Windows) and decode exit + statuses (POSIX `WIFEXITED`/signals, or Windows exit codes and NTSTATUS crashes like `0xC0000005`). + `shellQuote()` quotes for `sh` (`'…'`) or `cmd.exe` (`"…"`); a command line handed to `cmd /c` that + starts with a quote gets one extra pair of quotes. +- **Linking:** no `-lm` with MSVC; `.exe` names; the runtime cache key includes the triple and the C compiler. + MSVC linker messages (`LNK2019 unresolved external symbol`, `LNK1104`/`LNK1181 cannot open file`) are + translated like GNU ld's. +- **Running:** a Windows program built on Linux runs with `wine`. +- **Debug info:** CodeView for MSVC targets, DWARF elsewhere. +- **Runtime:** no `getline` or `sys/wait.h` on Windows; `stdin`/`stdout`/`stderr` are macros there, so + `finch_std_stream(i)` gives them to Finch when a header has no `extern` variable for them. +- **Printing pointers** is the same everywhere: `null` or `0x…`. + +### The Microsoft x64 calling convention + +`classify()` switches on `g_target.windows`. A struct of exactly 1, 2, 4 or 8 bytes travels as **one +integer** of that size, even if it holds floats (`{float, float}` → `i64`). Any other struct is +**Indirect**: the caller copies it to its own stack and passes the copy's address (no `byval`: the callee +receives a plain pointer). Results of 1/2/4/8 bytes come back in `rax` as an integer; anything else +through a hidden `sret` pointer. Each argument takes one slot, so there is no register counting. +`cThunk()` mirrors this for callbacks. + +`tests/windows.sh` builds every test with `--target windows`, runs it with Wine and compares the output: +all of them pass, including `c_structs` (which then exercises the Microsoft rules against a C library built +with MinGW). CI additionally builds `finch.exe` with MSVC on Windows Server and runs `tests/run.sh` there. + +### Building finch.exe + +CI uses Visual Studio 2022, Ninja and the official `clang+llvm-21.x-x86_64-pc-windows-msvc` package +(static libraries, `/MT`, so `CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`). Two Windows details in +`CMakeLists.txt`: that package names the DIA SDK library at the path of the machine LLVM was built on, so +it is redirected to the installed Visual Studio; and the embedded runtime is written as several raw +string pieces, because MSVC limits one literal to 16 KB. LLVM is initialized with the native target only, +so the static build doesn't pull in every backend. + +--- + +## 24. The language server + +`finch lsp` (`src/lsp.cpp`) speaks LSP over stdin/stdout with `llvm::json`. On `didOpen`/`didChange` +it runs the real front end on the document: `Loader` (with the open documents' text as overrides), +`importHeaders` (cached per set of imports, since reading headers is the slow part), and `generate()` +without optimizing or emitting. Two switches make the compiler usable inside a server: + +- `g_throwErrors`: `failAt()` throws `FinchError{file, line, col, msg}` instead of printing and exiting. + The server publishes it as a diagnostic (for the right file, also inside an imported module) and clears + diagnostics that disappeared. +- `g_index`: while generating code, `Codegen::note()` records a `SymRef` for every name it resolves + (variables, parameters, fields, functions, constructors, C functions and constants, built-ins, methods, + module members): its span, a markdown hover, and the definition position. `define()` and + `declareStructs()` add `FnInfo` / `StructIndex`; `addVar()` adds `VarInfo` with the enclosing function's + line range. Positions of names come from `namePos` fields the parser records. + +Requests use that index: + +| Request | From | +|---|---| +| hover, definition | the `SymRef` under the cursor | +| completion | keywords, types, built-ins, variables of the enclosing function, functions, structs, imported modules, C names matching the typed prefix; after `name.`: struct fields (also through `ptr[T]`), array/str methods, or a module's members | +| signatureHelp | scans back to the unmatched `(`, counts top-level commas, looks up the Finch / C / built-in signature | +| documentSymbol | functions and structs (with fields) of the file | + +Half-typed code (`p.`, `add(1, `) doesn't compile, so the server keeps the **last successful** analysis of +each document and merges its functions, structs and variables in for completion and signature help. +`tests/lsp_test.py` drives the server like an editor and checks every feature. + +`src/builtins_doc.h` is the single description of built-ins and methods, used for hover, completion and +signature help (and mirrored by the cheat sheets). + +--- + +## 25. The VS Code extension + +`editors/vscode` is a plain JavaScript extension: `extension.js` starts `finch lsp` through +`vscode-languageclient` (path from the `finch.path` setting) and adds **Run** / **Build** as +`ProcessExecution` tasks (no shell quoting, the `$finch` problem matcher turns `file:line:col: error:` +lines into Problems). `syntaxes/finch.tmLanguage.json` is the TextMate grammar, tested by `npm test` with +`vscode-textmate` + `vscode-oniguruma` (the engine VS Code itself uses); +`language-configuration.json` gives comments, brackets, auto-closing and indentation; `snippets/` the +templates. CI packages it with `vsce` into `finch-lang.vsix`. + +## 26. Known limitations - No methods on structs, generics, maps, `match`, closures, error values (`int("x")`, `read_file` panic). - Strings are bytes: `.len`, `s[i]`, `upper()` are not Unicode-aware. - Dangling pointers (`addr` of a local that went away, use after `free`) are not detected. - Shift amounts and float→int conversions are not range-checked (LLVM poison, as in C). - C: unions and bit-field structs by value, function-like macros, `long double`. -- One target tested: Linux x86-64 (the ABI code is System V x86-64 specific). +- Two systems: Linux and Windows, both x86-64 (System V and Microsoft x64 ABIs). No macOS or ARM yet. - The self-hosted compiler has no C imports, sized integers or `defer`, and doesn't free memory. diff --git a/docs/en/for-technicians.md b/docs/en/for-technicians.md index 76b9b26..b29128f 100644 --- a/docs/en/for-technicians.md +++ b/docs/en/for-technicians.md @@ -29,10 +29,11 @@ compiler works inside. For that, see the [guide for engineers](for-engineers.md) 16. [Modules](#16-modules) 17. [Using C libraries](#17-using-c-libraries) 18. [Errors](#18-errors) -19. [Debugging](#19-debugging) -20. [Troubleshooting](#20-troubleshooting) -21. [Project layout and tests](#21-project-layout-and-tests) -22. [Current limits](#22-current-limits) +19. [Editor: VS Code](#19-editor-vs-code) +20. [Debugging](#20-debugging) +21. [Troubleshooting](#21-troubleshooting) +22. [Project layout and tests](#22-project-layout-and-tests) +23. [Current limits](#23-current-limits) --- @@ -59,7 +60,24 @@ messages that tell you how to fix the problem. ## 2. Installing -Finch currently runs on **Linux, x86-64**. It has been tested with **LLVM 21**. +Finch runs on **Linux and Windows, x86-64**, and is built with **LLVM 21**. + +### Windows + +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`. + +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). + +### Linux + 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) @@ -70,7 +88,7 @@ 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.0.0 (LLVM 21.x) +./build/finch version # finch 2.3.0 (LLVM 21.x) ``` ### Option B: your distribution's packages @@ -91,6 +109,16 @@ cmake -S . -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-21/lib/cmake/llvm ninja -C build ``` +### Building Windows programs on Linux + +With the MinGW-w64 cross compiler installed (`x86_64-w64-mingw32-gcc`; on Nix +`pkgsCross.mingwW64.buildPackages.gcc`): + +```sh +finch build game.fch --target windows # game.exe +finch run game.fch --target windows # runs it with Wine, if installed +``` + ### Putting `finch` on your PATH (optional) ```sh @@ -667,7 +695,18 @@ Instead of undefined behavior (as in C), Finch stops with a message and exit cod --- -## 19. Debugging +## 19. Editor: VS Code + +The **Finch** extension (`editors/vscode`, also attached to each release as a `.vsix` file) gives you: +highlighting, errors as you type, completion (also fields and methods after `.`), types on hover, +go to definition (F12), an outline of the file, parameter hints, snippets, and a ▶ **Run** button +(`Ctrl+F5`). Errors from **Finch: Build This File** appear in the Problems panel. + +Install: Extensions → `…` → *Install from VSIX…* → pick `finch-lang-*.vsix`. The extension runs `finch` +from your PATH; if it is somewhere else, set **Finch: Path** in the settings. Other editors that speak the +Language Server Protocol (Neovim, Helix, Zed, Emacs, Sublime) can use `finch lsp` directly. + +## 20. Debugging ```sh finch build game.fch -g -O0 -o game @@ -680,11 +719,12 @@ gdb ./game ``` `-g` adds debug info (lines, functions, variables, struct fields). `-O0` keeps every variable -visible; without it the optimizer may remove some. +visible; without it the optimizer may remove some. On Windows, `-g` writes CodeView, which the +Visual Studio debugger and WinDbg read. --- -## 20. Troubleshooting +## 21. Troubleshooting | Problem | Solution | |---|---| @@ -695,12 +735,14 @@ visible; without it the optimizer may remove some. | `can't find the module 'x'` | Put `x.fch` next to the importing file, or set `FINCH_PATH`. | | `couldn't build the Finch runtime` | No working C compiler. Install gcc or clang, or set `CC`. | | A library is not found when the program starts | It was linked from a folder the system doesn't search. Run inside the same `nix-shell`, or install it system-wide. | +| Windows: `finch` can't link (`LNK…` errors about `libcmt`, `kernel32`) | Install Visual Studio Build Tools with *Desktop development with C++*. | +| Windows: `finch.exe` doesn't start (missing `libclang.dll`) | Keep `libclang.dll` next to `finch.exe`. | | `clang` inside `nix-shell` can't find `stdio.h` | You have an old `shell.nix`: `llvmPackages.clang` must be listed before `llvmPackages.libclang`. | | A program never ends | A loop condition never becomes false. Press Ctrl+C. | --- -## 21. Project layout and tests +## 22. Project layout and tests ``` Finch/ @@ -713,7 +755,8 @@ Finch/ │ ├── 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 -├── docs/ this documentation (en, pl) +├── editors/vscode/ the VS Code extension +├── docs/ this documentation (en, pl), including the cheat sheet ├── shell.nix the Nix development environment └── CMakeLists.txt ``` @@ -722,11 +765,13 @@ Finch/ tests/run.sh # → 59 passed, 0 failed 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/windows.sh # every test built for Windows and run with Wine +python3 tests/lsp_test.py # the language server ``` --- -## 22. Current limits +## 23. Current limits Finch 2.0 is a complete small language, but not a finished one. Not there yet: @@ -734,6 +779,6 @@ Finch 2.0 is a complete small language, but not a finished one. Not there yet: - Error values: errors in `int("x")` or `read_file` stop the program. Check first (`file_exists`). - Unicode-aware text: `.len`, `s[i]` and `upper()` work on bytes / ASCII. - Threads. -- Platforms other than Linux x86-64. +- Platforms other than Linux and Windows on x86-64 (macOS, ARM). See the [roadmap in the README](../../README.md#roadmap). diff --git a/docs/pl/dla-inzynierow.md b/docs/pl/dla-inzynierow.md index 80a9460..bf076b5 100644 --- a/docs/pl/dla-inzynierow.md +++ b/docs/pl/dla-inzynierow.md @@ -38,7 +38,10 @@ Język z perspektywy użytkownika opisuje [przewodnik dla techników](dla-techni 20. [Semantyka a C](#20-semantyka-a-c) 21. [Spis funkcji](#21-spis-funkcji) 22. [Rozbudowa kompilatora](#22-rozbudowa-kompilatora) -23. [Znane ograniczenia](#23-znane-ograniczenia) +23. [Platformy i Windows](#23-platformy-i-windows) +24. [Serwer języka](#24-serwer-języka) +25. [Rozszerzenie VS Code](#25-rozszerzenie-vs-code) +26. [Znane ograniczenia](#26-znane-ograniczenia) --- @@ -886,12 +889,103 @@ przed wyskokiem z zasięgów. --- -## 23. Znane ograniczenia +## 23. Platformy i Windows + +`src/target.h` trzyma `g_target`: triple LLVM, flagi `windows` / `msvc` / `cross`, kompilator C (`cc`) +i rozszerzenie plików wykonywalnych. `setTarget()` wybiera kompilator C: `FINCH_CC`, potem `CC` (nie przy +kompilacji krzyżowej), potem `x86_64-w64-mingw32-gcc` dla `--target windows` z Linuksa, `clang` na +Windowsie, `cc` na Uniksie. Przez tę warstwę idzie wszystko, co zależy od platformy: + +- **Nagłówki:** libclang parsuje z `--target=` (więc `long` ma 32 bity na Windowsie i używane są + właściwe nagłówki), a na Windowsie z `-D_USE_MATH_DEFINES`. Katalogi nagłówków pochodzą z ` -E -v`. +- **Procesy:** `capture()` / `runCommand()` opakowują `popen` / `system` (`_popen` na Windowsie) i dekodują + kody wyjścia (POSIX `WIFEXITED`/sygnały albo kody Windowsa i wyjątki NTSTATUS, np. `0xC0000005`). + `shellQuote()` cytuje dla `sh` (`'…'`) albo `cmd.exe` (`"…"`); linia polecenia dla `cmd /c`, która + zaczyna się od cudzysłowu, dostaje dodatkową parę cudzysłowów. +- **Linkowanie:** bez `-lm` przy MSVC; nazwy `.exe`; klucz cache runtime'u obejmuje triple i kompilator C. + Komunikaty linkera MSVC (`LNK2019 unresolved external symbol`, `LNK1104`/`LNK1181 cannot open file`) są + tłumaczone tak jak komunikaty GNU ld. +- **Uruchamianie:** program dla Windowsa zbudowany na Linuksie uruchamia się przez `wine`. +- **Informacje dla debuggera:** CodeView dla celów MSVC, DWARF w pozostałych. +- **Runtime:** na Windowsie nie ma `getline` ani `sys/wait.h`; `stdin`/`stdout`/`stderr` są tam makrami, + więc `finch_std_stream(i)` udostępnia je Finchowi, gdy nagłówek nie ma dla nich zmiennej `extern`. +- **Wypisywanie wskaźników** jest wszędzie takie samo: `null` albo `0x…`. + +### Konwencja wywołań Microsoft x64 + +`classify()` rozgałęzia się po `g_target.windows`. Struktura o rozmiarze dokładnie 1, 2, 4 albo 8 bajtów +idzie jako **jedna liczba całkowita** tego rozmiaru, nawet jeśli zawiera floaty (`{float, float}` → `i64`). +Każda inna struktura jest **pośrednia (Indirect)**: wywołujący kopiuje ją na swój stos i przekazuje adres +kopii (bez `byval`: funkcja dostaje zwykły wskaźnik). Wyniki 1/2/4/8-bajtowe wracają w `rax` jako liczba; +wszystko inne przez ukryty wskaźnik `sret`. Każdy argument zajmuje jedno miejsce, więc nie ma liczenia +rejestrów. `cThunk()` robi to samo w drugą stronę dla callbacków. + +`tests/windows.sh` buduje każdy test z `--target windows`, uruchamia go w Wine i porównuje wynik: przechodzą +wszystkie, łącznie z `c_structs` (który wtedy sprawdza reguły Microsoftu na bibliotece C zbudowanej MinGW). +CI dodatkowo buduje `finch.exe` przez MSVC na Windows Server i uruchamia tam `tests/run.sh`. + +### Budowanie finch.exe + +CI używa Visual Studio 2022, Ninja i oficjalnego pakietu `clang+llvm-21.x-x86_64-pc-windows-msvc` +(biblioteki statyczne, `/MT`, więc `CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`). Dwa szczegóły Windowsa +w `CMakeLists.txt`: ten pakiet podaje ścieżkę do biblioteki DIA SDK z maszyny, na której zbudowano LLVM, +więc jest ona przekierowywana na zainstalowane Visual Studio; a osadzony runtime jest zapisywany jako +kilka surowych napisów, bo MSVC ogranicza jeden literał do 16 KB. LLVM jest inicjalizowany tylko z +natywnym backendem, żeby budowanie statyczne nie wciągało wszystkich architektur. + +--- + +## 24. Serwer języka + +`finch lsp` (`src/lsp.cpp`) mówi protokołem LSP przez stdin/stdout, używając `llvm::json`. Przy +`didOpen`/`didChange` uruchamia na dokumencie prawdziwy front-end: `Loader` (z tekstem otwartych +dokumentów jako nadpisaniem plików), `importHeaders` (w cache na zestaw importów, bo czytanie nagłówków +jest najwolniejsze) i `generate()` bez optymalizacji i emisji. Dwa przełączniki pozwalają użyć +kompilatora wewnątrz serwera: + +- `g_throwErrors`: `failAt()` rzuca `FinchError{file, line, col, msg}` zamiast wypisywać i kończyć proces. + Serwer publikuje to jako diagnostykę (dla właściwego pliku, także wewnątrz importowanego modułu) i czyści + diagnostyki, które zniknęły. +- `g_index`: podczas generowania kodu `Codegen::note()` zapisuje `SymRef` dla każdej rozwiązywanej nazwy + (zmienne, parametry, pola, funkcje, konstruktory, funkcje i stałe C, funkcje wbudowane, metody, elementy + modułów): jej zakres, opis w markdownie i pozycję definicji. `define()` i `declareStructs()` dokładają + `FnInfo` / `StructIndex`; `addVar()` dokłada `VarInfo` z zakresem linii otaczającej funkcji. Pozycje nazw + pochodzą z pól `namePos`, które zapisuje parser. + +Zapytania korzystają z tego indeksu: + +| Zapytanie | Źródło | +|---|---| +| hover, definition | `SymRef` pod kursorem | +| completion | słowa kluczowe, typy, funkcje wbudowane, zmienne otaczającej funkcji, funkcje, struktury, importowane moduły, nazwy z C pasujące do wpisanego początku; po `nazwa.`: pola struktury (także przez `ptr[T]`), metody tablic/tekstów albo zawartość modułu | +| signatureHelp | cofa się do niezamkniętego `(`, liczy przecinki na najwyższym poziomie i szuka sygnatury Fincha / C / wbudowanej | +| documentSymbol | funkcje i struktury (z polami) z pliku | + +Kod w trakcie pisania (`p.`, `add(1, `) się nie kompiluje, więc serwer trzyma **ostatnią udaną** analizę +każdego dokumentu i dołącza z niej funkcje, struktury i zmienne do podpowiedzi. `tests/lsp_test.py` +steruje serwerem tak jak edytor i sprawdza każdą funkcję. + +`src/builtins_doc.h` to jedyny opis funkcji wbudowanych i metod, używany przy hover, podpowiedziach +i podpowiedziach parametrów (i odwzorowany w ściągach). + +--- + +## 25. Rozszerzenie VS Code + +`editors/vscode` to zwykłe rozszerzenie w JavaScripcie: `extension.js` uruchamia `finch lsp` przez +`vscode-languageclient` (ścieżka z ustawienia `finch.path`) i dodaje **Run** / **Build** jako zadania +`ProcessExecution` (bez cytowania dla powłoki; matcher `$finch` zamienia linie `plik:linia:kol: error:` +w wpisy w Problems). `syntaxes/finch.tmLanguage.json` to gramatyka TextMate, testowana przez `npm test` +z `vscode-textmate` + `vscode-oniguruma` (tym samym silnikiem, którego używa VS Code); +`language-configuration.json` daje komentarze, nawiasy, automatyczne domykanie i wcięcia; `snippets/` +szablony. CI pakuje je przez `vsce` do `finch-lang.vsix`. + +## 26. Znane ograniczenia - Brak metod w strukturach, typów generycznych, map, `match`, domknięć i błędów jako wartości (`int("x")`, `read_file` robią panic). - Teksty to bajty: `.len`, `s[i]`, `upper()` nie znają Unicode. - Wiszące wskaźniki (`addr` zmiennej, która zniknęła, użycie po `free`) nie są wykrywane. - Wielkość przesunięć i konwersje float→int nie są sprawdzane (poison w LLVM, jak w C). - C: unie i struktury z polami bitowymi przez wartość, makra-funkcje, `long double`. -- Testowana jedna platforma: Linux x86-64 (kod ABI jest specyficzny dla System V x86-64). +- Dwa systemy: Linux i Windows, oba x86-64 (ABI System V i Microsoft x64). Jeszcze bez macOS i ARM. - Kompilator samohostujący nie ma importu C, liczb z rozmiarem ani `defer` i nie zwalnia pamięci. diff --git a/docs/pl/dla-poczatkujacych.md b/docs/pl/dla-poczatkujacych.md index 7422f78..aac09b0 100644 --- a/docs/pl/dla-poczatkujacych.md +++ b/docs/pl/dla-poczatkujacych.md @@ -77,7 +77,7 @@ Jeśli ostatnia linijka skończy się bez słowa `error`, Finch jest gotowy. ./build/finch version ``` -Powinieneś zobaczyć coś w stylu `finch 2.0.0`. +Powinieneś zobaczyć coś w stylu `finch 2.3.0`. --- diff --git a/docs/pl/dla-technikow.md b/docs/pl/dla-technikow.md index 4f4f6d9..20302b8 100644 --- a/docs/pl/dla-technikow.md +++ b/docs/pl/dla-technikow.md @@ -29,10 +29,11 @@ kompilator działa w środku. Do tego służy [przewodnik dla inżynierów](dla- 16. [Moduły](#16-moduły) 17. [Biblioteki z C](#17-biblioteki-z-c) 18. [Błędy](#18-błędy) -19. [Debugowanie](#19-debugowanie) -20. [Rozwiązywanie problemów](#20-rozwiązywanie-problemów) -21. [Struktura projektu i testy](#21-struktura-projektu-i-testy) -22. [Obecne ograniczenia](#22-obecne-ograniczenia) +19. [Edytor: VS Code](#19-edytor-vs-code) +20. [Debugowanie](#20-debugowanie) +21. [Rozwiązywanie problemów](#21-rozwiązywanie-problemów) +22. [Struktura projektu i testy](#22-struktura-projektu-i-testy) +23. [Obecne ograniczenia](#23-obecne-ograniczenia) --- @@ -59,8 +60,24 @@ i komunikaty błędów, które mówią, jak problem naprawić. ## 2. Instalacja -Finch działa obecnie na **Linuksie x86-64**. Testowany był z **LLVM 21**. -Z innymi wersjami LLVM prawdopodobnie się nie skompiluje, bo API C++ LLVM zmienia się między wydaniami. +Finch działa na **Linuksie i Windowsie, x86-64**, i jest budowany z **LLVM 21**. + +### Windows + +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`. + +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). + +### Linux + +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) @@ -70,7 +87,7 @@ 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.0.0 (LLVM 21.x) +./build/finch version # finch 2.3.0 (LLVM 21.x) ``` ### Opcja B: pakiety z twojej dystrybucji @@ -91,6 +108,16 @@ cmake -S . -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-21/lib/cmake/llvm ninja -C build ``` +### Budowanie programów na Windowsa pod Linuksem + +Z zainstalowanym kompilatorem krzyżowym MinGW-w64 (`x86_64-w64-mingw32-gcc`; na Niksie +`pkgsCross.mingwW64.buildPackages.gcc`): + +```sh +finch build gra.fch --target windows # gra.exe +finch run gra.fch --target windows # uruchamia ją w Wine, jeśli jest zainstalowane +``` + ### Dodanie `finch` do PATH (opcjonalnie) ```sh @@ -669,7 +696,18 @@ Zamiast niezdefiniowanego zachowania (jak w C) Finch zatrzymuje się z komunikat --- -## 19. Debugowanie +## 19. Edytor: VS Code + +Rozszerzenie **Finch** (`editors/vscode`, dołączane też do każdego wydania jako plik `.vsix`) daje: +podświetlanie składni, błędy na bieżąco, podpowiedzi (także pola i metody po `.`), typy po najechaniu +myszą, idź do definicji (F12), konspekt pliku, podpowiedzi parametrów, szablony i przycisk ▶ **Run** +(`Ctrl+F5`). Błędy z **Finch: Build This File** trafiają do panelu Problems. + +Instalacja: Rozszerzenia → `…` → *Install from VSIX…* → wybierz `finch-lang-*.vsix`. Rozszerzenie uruchamia +`finch` z PATH; jeśli jest gdzie indziej, ustaw **Finch: Path** w ustawieniach. Inne edytory obsługujące +Language Server Protocol (Neovim, Helix, Zed, Emacs, Sublime) mogą używać `finch lsp` bezpośrednio. + +## 20. Debugowanie ```sh finch build gra.fch -g -O0 -o gra @@ -682,11 +720,12 @@ gdb ./gra ``` `-g` dodaje informacje dla debuggera (linijki, funkcje, zmienne, pola struktur). `-O0` zostawia wszystkie -zmienne widoczne; bez niego optymalizator może część z nich usunąć. +zmienne widoczne; bez niego optymalizator może część z nich usunąć. Na Windowsie `-g` zapisuje format +CodeView, który czyta debugger Visual Studio i WinDbg. --- -## 20. Rozwiązywanie problemów +## 21. Rozwiązywanie problemów | Problem | Rozwiązanie | |---|---| @@ -697,12 +736,14 @@ zmienne widoczne; bez niego optymalizator może część z nich usunąć. | `can't find the module 'x'` | Połóż `x.fch` obok importującego pliku albo ustaw `FINCH_PATH`. | | `couldn't build the Finch runtime` | Brak działającego kompilatora C. Zainstaluj gcc lub clang albo ustaw `CC`. | | Biblioteka nie znajduje się przy starcie programu | Zlinkowano ją z folderu, którego system nie przeszukuje. Uruchamiaj w tym samym `nix-shell` albo zainstaluj ją systemowo. | +| Windows: `finch` nie linkuje (błędy `LNK…` o `libcmt`, `kernel32`) | Zainstaluj Visual Studio Build Tools z *Desktop development with C++*. | +| Windows: `finch.exe` się nie uruchamia (brak `libclang.dll`) | Trzymaj `libclang.dll` obok `finch.exe`. | | `clang` w `nix-shell` nie widzi `stdio.h` | Masz stary `shell.nix`: `llvmPackages.clang` musi być przed `llvmPackages.libclang`. | | Program nigdy się nie kończy | Warunek pętli nigdy nie staje się fałszywy. Naciśnij Ctrl+C. | --- -## 21. Struktura projektu i testy +## 22. Struktura projektu i testy ``` Finch/ @@ -715,7 +756,8 @@ Finch/ │ ├── 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 -├── docs/ ta dokumentacja (en, pl) +├── editors/vscode/ rozszerzenie VS Code +├── docs/ ta dokumentacja (en, pl), łącznie ze ściągą ├── shell.nix środowisko deweloperskie Nix └── CMakeLists.txt ``` @@ -724,11 +766,13 @@ Finch/ tests/run.sh # → 59 passed, 0 failed 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/windows.sh # każdy test zbudowany na Windowsa i uruchomiony w Wine +python3 tests/lsp_test.py # serwer języka ``` --- -## 22. Obecne ograniczenia +## 23. Obecne ograniczenia Finch 2.0 to kompletny mały język, ale nie skończony. Jeszcze nie ma: @@ -736,6 +780,6 @@ Finch 2.0 to kompletny mały język, ale nie skończony. Jeszcze nie ma: - Błędów jako wartości: błąd w `int("x")` albo `read_file` zatrzymuje program. Sprawdzaj wcześniej (`file_exists`). - Tekstu świadomego Unicode: `.len`, `s[i]` i `upper()` działają na bajtach / ASCII. - Wątków. -- Platform innych niż Linux x86-64. +- Platform innych niż Linux i Windows na x86-64 (macOS, ARM). Plan rozwoju jest w [README](../../README.pl.md#plan-rozwoju). diff --git a/docs/pl/sciaga.md b/docs/pl/sciaga.md new file mode 100644 index 0000000..a90241b --- /dev/null +++ b/docs/pl/sciaga.md @@ -0,0 +1,316 @@ +# Ściąga Fincha + +Cały Finch na jednej stronie. Wyjaśnienia są w [przewodnikach](../../README.pl.md#dokumentacja). + +> 🇬🇧 English version: [cheatsheet.md](../en/cheatsheet.md) + +--- + +## Polecenie `finch` + +| Polecenie | Robi | +|---|---| +| `finch run plik.fch [argumenty…]` | skompiluj i uruchom (argumenty trafiają do programu) | +| `finch build plik.fch [-o nazwa]` | zrób program (`nazwa.exe` na Windowsie) | +| `finch ir plik.fch` | pokaż LLVM IR | +| `finch lsp` | serwer języka (korzystają z niego edytory) | +| `finch version` | wersja | +| `-l lib` | dolinkuj bibliotekę C (jak `link "lib"`) | +| `--target windows` / `linux` / triple | zbuduj dla innego systemu | +| `-g` | informacje dla debuggera (gdb, lldb, Visual Studio) | +| `-O0` | bez optymalizacji | + +Zmienne środowiskowe: `FINCH_PATH` (foldery z modułami), `FINCH_CC` / `CC` (kompilator C, który linkuje). + +--- + +## Plik + +```c +import "stdio.h" // nagłówek C +import ksztalty // moduł Fincha: ksztalty.fch +link "m" // biblioteka C albo "moje.c" / ".o" / ".a" + +struct Punkt { + int x + int y = 0 // wartość domyślna +} + +fn main() { + print("Cześć") +} +``` + +`main` to `fn main()`, `fn main() -> int` (kod wyjścia) albo `fn main([]str args)`. +Jedna instrukcja na linijkę, bez średników, `{` w tej samej linijce, bez nawiasów wokół warunków. + +--- + +## Zmienne + +| Kod | Znaczenie | +|---|---| +| `x := 5` | nowa zmienna, typ zgadnięty | +| `int x = 5` | nowa zmienna, typ podany | +| `int x` | zero / `""` / `[]` / `null` / wartości domyślne struktury | +| `x = 7` | przypisanie | +| `x += 1` `-=` `*=` `/=` `%=` | zmiana | + +--- + +## Typy + +| Typ | Przykład | +|---|---| +| `int` (= `i64`) | `42`, `-7`, `0xFF`, `1_000_000` | +| `float` (= `f64`) | `3.14` | +| `bool` | `true` (prawda), `false` (fałsz) | +| `char` | `'A'`, `'\n'` | +| `str` | `"tekst\t\"w cudzysłowie\""` | +| `i8 i16 i32 i64` | ze znakiem, z rozmiarem | +| `u8 u16 u32 u64` | bez znaku, z rozmiarem | +| `f32 f64` | zmiennoprzecinkowe | +| `[]T` | tablica: `[1, 2, 3]`, `[]str imiona` | +| `ptr[T]`, `ptr` | wskaźnik, wskaźnik bez typu | +| `Nazwa` / `modul.Nazwa` | struktura | + +Znaki specjalne: `\n \t \r \0 \\ \" \'`. + +--- + +## Operatory + +| Priorytet | Operatory | +|---|---| +| 5 | `*` `/` `%` `<<` `>>` `&` | +| 4 | `+` `-` `\|` `^` (`+` skleja też tekst) | +| 3 | `==` `!=` `<` `<=` `>` `>=` | +| 2 | `&&` (i) | +| 1 | `\|\|` (lub) | +| jednoargumentowe | `-x` `!x` (nie) `~x` | + +`x & 1 == 0` znaczy `(x & 1) == 0`. + +--- + +## Sterowanie + +```c +if a > b { … } else if a == b { … } else { … } +while x > 0 { … } +for i in 0..10 { … } // 0 … 9 +for el in lista { … } // każdy element (albo znak str) +break continue return wartosc +defer sprzatanie() // uruchomi się na końcu bloku +``` + +--- + +## Funkcje + +```c +fn dodaj(int a, int b) -> int { + return a + b +} +fn przywitaj(str imie) { // bez wyniku + print("Cześć", imie) +} +``` + +Parametry zachowują się jak kopie. Kolejność w pliku nie ma znaczenia. Przecinek po ostatnim argumencie jest dozwolony. + +--- + +## Struktury + +| Kod | Znaczenie | +|---|---| +| `struct P { … }` | definicja (jedno pole na linijkę, `= domyślna` opcjonalnie) | +| `P(1, 2)` | utworzenie, wszystkie pola po kolei | +| `P(x: 1)` | utworzenie po nazwie, reszta domyślna/zero | +| `p.x`, `p.x = 5` | odczyt, zmiana pola | +| `b := a` | pełna kopia | + +--- + +## Tablice `[]T` + +| Kod | Daje | +|---|---| +| `a.len` | liczba elementów | +| `a[i]`, `a[i] = x` | element (z kontrolą zakresu) | +| `a.push(x)` | dodaj na końcu | +| `a.pop()` | zabierz ostatni i go oddaj | +| `a.insert(i, x)` | wstaw na pozycję i | +| `a.remove(i)` | usuń pozycję i i ją oddaj | +| `a.clear()` | wyczyść | +| `a.resize(n)` | długość n (nowe elementy to zera) | +| `a.find(x)` | indeks albo -1 | +| `a.contains(x)` | bool | +| `a.sort()` | posortuj (liczby, znaki, str) | +| `a.reverse()` | odwróć | +| `a.slice(s, e)` | nowa tablica z s … e-1 | +| `a.join(sep)` | `[]str` → jeden str | +| `a.ptr` | adres pierwszego elementu (dla C) | + +--- + +## Tekst `str` + +| Kod | Daje | +|---|---| +| `s.len` | liczba bajtów (ą, ż… to 2) | +| `s[i]`, `s[i] = 'x'` | znak | +| `a + b` | sklejony tekst | +| `s.sub(a, b)` | fragment a … b-1 | +| `s.find(t)` | pozycja albo -1 | +| `s.contains(t)` | czy zawiera | +| `s.starts_with(t)`, `s.ends_with(t)` | czy zaczyna / kończy się | +| `s.split(sep)` | `[]str` | +| `s.trim()` | bez spacji na końcach | +| `s.upper()`, `s.lower()` | A–Z / a–z | +| `s.replace(a, b)` | każde a → b | +| `s.repeat(n)` | n razy | +| `s.bytes()` | `[]u8` | +| `s.ptr` | `ptr[char]` (dla C) | +| `==` `!=` `<` `>` | porównanie | + +--- + +## Zamiana typów + +| Kod | Wynik | +|---|---| +| `int(3.9)` | `3` | +| `int("42")` | `42` (zatrzymuje program, jeśli to nie liczba) | +| `int('A')` | `65` | +| `float(7)`, `float("2.5")` | `7`, `2.5` | +| `u8(300)` | `44` (zostawia najniższe bity) | +| `char(66)` | `'B'` | +| `bool(0)` | `false` | +| `str(42)`, `str(1.5)`, `str(true)`, `str('c')` | tekst | +| `str(bajty)` | `[]u8` → tekst | +| `str(p)` | `char*` z C → tekst | +| `ptr(p)`, `ptr(16)` | wskaźnik bez typu, ze wskaźnika albo liczby | +| `int(p)` | wskaźnik → adres | + +Automatycznie tylko wtedy, gdy nic nie ginie: mniejsza → większa liczba, dowolna całkowita → float, `f32` → `f64`. + +--- + +## Funkcje wbudowane + +| Funkcja | Robi | +|---|---| +| `print(a, b, …)` | wypisz, spacje między, nowa linia na końcu | +| `input()`, `input("Pytanie? ")` | wczytaj linijkę | +| `read_file(sciezka)` | plik → str | +| `write_file(sciezka, tekst)` | str → plik, `true`, jeśli się udało | +| `file_exists(sciezka)` | czy plik istnieje | +| `delete_file(sciezka)` | usuń plik | +| `shell(polecenie)` | uruchom polecenie, jego kod wyjścia | +| `exit(kod)` | zakończ program od razu | +| `addr(x)` | wskaźnik na x; `addr(fn)` = callback dla C | +| `new(wartosc)` | wartość na stercie → `ptr[T]` | +| `free(p)` | oddaj ją | + +--- + +## Wskaźniki + +| Finch | C | +|---|---| +| `ptr[int] p` | `int *p` | +| `addr(x)` | `&x` | +| `p.value` | `*p` | +| `p.pole` | `p->pole` | +| `p[i]` | `p[i]` | +| `null` | `NULL` | +| `ptr` | `void *` | + +--- + +## Pamięć + +- Tablice, teksty i struktury zwalniają się same na końcu swojego bloku. Bez `free`. +- `b := a` kopiuje; wynik wywołania jest przenoszony; `return x` przenosi. +- `new(...)` + `free(...)` (często z `defer`) do list wiązanych, drzew, współdzielenia. +- Pamięć z C: funkcjami z C (`malloc` / `free`, `fclose`, …). + +--- + +## Moduły + +```c +import ksztalty // ksztalty.fch obok tego pliku (albo w FINCH_PATH) +ksztalty.pole(b) // jego funkcje +ksztalty.Pudlo(2, 3) // jego struktury +ksztalty.Pudlo inne // w deklaracjach +``` + +--- + +## C + +| Kod | Znaczenie | +|---|---| +| `import "x.h"` | funkcje, struktury, enumy, liczbowe `#define`, zmienne globalne | +| `link "nazwa"` | libnazwa.so / nazwa.lib (najpierw pkg-config) | +| `link "plik.c"` | skompiluj własny plik C | +| `addr(mojaFn)` | funkcja Fincha jako callback | + +| Typ C | Finch | +|---|---| +| `int` / `long long` / `unsigned` | `i32` / `i64` / `u32` (wg rozmiaru) | +| `float` / `double` | `f32` / `f64` | +| `char *` (parametr, wynik) | `str` | +| `char *` (pole, za wskaźnikiem) | `ptr[char]` | +| `struct X` | `X` | +| `T *` | `ptr[T]` | +| `void *`, uchwyty | `ptr` | +| `T x[N]` (w strukturze) | `[N]T` | + +--- + +## Błędy w czasie działania (program zatrzymuje się z plikiem i linijką) + +| Komunikat | Przyczyna | +|---|---| +| `division by zero` | `/` albo `%` przez 0 | +| `index 5 is out of range (the length is 3)` | `a[5]` | +| `pop() on an empty array` | `pop()` na pustej tablicy | +| `used .value on a null pointer` | `.value` / `.pole` / `[i]` przez `null` | +| `can't turn "x" into int` | `int("x")` | +| `can't read the file "…"` | `read_file` | + +--- + +## VS Code (rozszerzenie „Finch”) + +| Klawisz / akcja | Robi | +|---|---| +| ▶ / `Ctrl+F5` | uruchom plik | +| `Finch: Build This File` | zbuduj; błędy trafiają do panelu Problems | +| `F12` | idź do definicji | +| najechanie myszą | typ / sygnatura / opis | +| `Ctrl+Spacja` | podpowiedzi (po `.`: pola, metody, zawartość modułu) | +| `Ctrl+Shift+O` | funkcje i struktury w pliku | +| `main`, `fn`, `fnr`, `struct`, `for`, `foreach`, `if`, `ife`, `while`, `input` + Tab | szablony | +| ustawienie `finch.path` | gdzie jest finch / finch.exe | + +--- + +## Słowa kluczowe + +| Słowo | Po polsku | +|---|---| +| `fn` | funkcja | +| `return` | zwróć | +| `if` / `else` | jeżeli / w przeciwnym razie | +| `while` | dopóki | +| `for` … `in` | dla … w | +| `break` / `continue` | przerwij / kontynuuj | +| `true` / `false` / `null` | prawda / fałsz / nic | +| `import` / `link` | zaimportuj / dolinkuj | +| `struct` | struktura | +| `defer` | odłóż (na koniec bloku) | diff --git a/tests/lsp_test.py b/tests/lsp_test.py index a07db44..aec0e9f 100755 --- a/tests/lsp_test.py +++ b/tests/lsp_test.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """Talks to `finch lsp` like an editor would and checks the answers.""" -import json, os, subprocess, sys, tempfile +import json, os, pathlib, subprocess, sys, tempfile FINCH = os.environ.get("FINCH", os.path.join(os.path.dirname(__file__), "..", "build", "finch")) failures = 0 @@ -76,7 +76,7 @@ def pos(line_no, text): # 0-based position of `text` in a 1-based line d = tempfile.mkdtemp() path = os.path.join(d, "demo.fch") open(path, "w").write(src) -uri = "file://" + path +uri = pathlib.Path(path).resolve().as_uri() td = {"uri": uri} c = Client()