mirror of
https://github.com/Nexoniarz/Finch.git
synced 2026-11-03 08:54:25 +00:00
docs: the Polish cheat sheet and engineers' guide rewritten in natural Polish; the engineers' guide matches the Finch compiler
- names from the C++ compiler (declareFns, HelperScope, Fn::borrowParam, mutatingMethods) replaced by the real ones - section 8's subsections numbered 8.x; the map's LLVM type has 7 fields; @W in the index records Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Psc42moPLwP43Cmb9oZqSR
This commit is contained in:
parent
0bf66740df
commit
8495bc718d
3 changed files with 550 additions and 501 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# Ściąga Fincha
|
||||
# Ściąga z Fincha
|
||||
|
||||
Cały Finch na jednej stronie. Wyjaśnienia są w [przewodnikach](../../README.pl.md#dokumentacja).
|
||||
Cały Finch na jednej stronie. Wyjaśnienia znajdziesz w [przewodnikach](../../README.pl.md#dokumentacja).
|
||||
|
||||
> 🇬🇧 English version: [cheatsheet.md](../en/cheatsheet.md)
|
||||
|
||||
|
|
@ -8,39 +8,41 @@ Cały Finch na jednej stronie. Wyjaśnienia są w [przewodnikach](../../README.p
|
|||
|
||||
## Polecenie `finch`
|
||||
|
||||
| Polecenie | Robi |
|
||||
| Polecenie | Co 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 build plik.fch --shared` | zrób bibliotekę (`libplik.so`, `plik.dll`) dla programu w C; jej `export fn` to jej funkcje C |
|
||||
| `finch test plik.fch` | uruchom jego bloki `test "…" { }`, każdy osobno (także z importowanych modułów) |
|
||||
| `finch fmt [--check] [pliki/foldery]` | wcięcia wg `{ }` po 4 spacje, bez spacji na końcach linii, najwyżej jedna pusta linia (`--check`: tylko wypisz, co by zmienił) |
|
||||
| `finch run` / `build` / `test` bez pliku | w folderze z `finch.toml`: jego `entry` |
|
||||
| `finch ir plik.fch` | pokaż LLVM IR |
|
||||
| `finch run plik.fch [argumenty…]` | kompiluje i uruchamia (argumenty trafiają do programu) |
|
||||
| `finch build plik.fch [-o nazwa]` | tworzy program (na Windowsie `nazwa.exe`) |
|
||||
| `finch build plik.fch --shared [-I katalog]` | tworzy bibliotekę (`libplik.so`, `plik.dll`), którą wczyta program w C; jej funkcjami C są funkcje `export fn` (liczby, bool, char, wskaźniki) |
|
||||
| `finch test plik.fch` | uruchamia każdy blok `test "…" { }` osobno (także w importowanych modułach) |
|
||||
| `finch fmt [--check] [pliki/katalogi]` | wcięcia po 4 spacje na każdy poziom `{ }`, bez spacji na końcach linii, najwyżej jedna pusta linia z rzędu (`--check`: tylko wypisuje, co by zmienił) |
|
||||
| `finch run` / `build` / `test` bez pliku | w katalogu z `finch.toml`: plik z pola `entry` |
|
||||
| `finch ir plik.fch` | wypisuje 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` / `arm64` / `macos` / `android` / triple | zbuduj dla innego systemu (`android`: clang z NDK wskazanego przez `ANDROID_NDK_HOME`, zwykle z `--shared`) |
|
||||
| `-g` | informacje dla debuggera (gdb, lldb, Visual Studio) |
|
||||
| `-l bib` | dolinkowuje bibliotekę C (to samo co `link "bib"`) |
|
||||
| `--target windows` / `linux` / `arm64` / `macos` / `android` / triple | buduje na inny system (`android`: clang z NDK wskazanego przez `ANDROID_NDK_HOME`, zwykle z `--shared`) |
|
||||
| `-g` | informacje dla debuggera (gdb, lldb) |
|
||||
| `-O0` | bez optymalizacji |
|
||||
| `--trace` / `--no-trace` | błędy w czasie działania pokazują łańcuch wywołań; włączone dla `run`, `test`, `-g`, `-O0`, wyłączone dla zwykłego `build` (kosztuje szybkość) |
|
||||
| `--cpu native` / `x86-64-v3` / `apple-m1` … | używa wszystkich instrukcji danego procesora (AVX2, AVX-512, NEON); program będzie wtedy wymagał podobnego procesora |
|
||||
| `--trace` / `--no-trace` | błąd w trakcie działania pokazuje ścieżkę wywołań; domyślnie włączone dla `run`, `test`, `-g` i `-O0`, wyłączone dla zwykłego `build` (spowalnia program) |
|
||||
|
||||
Zmienne środowiskowe: `FINCH_PATH` (foldery z modułami), `FINCH_CC` (kompilator C, który linkuje), `FINCH_CXX` (dla plików `.cpp`).
|
||||
Skompilowany kod programu i jego pliki `link "x.c"` zostają w cache (`~/.cache/finch`), dopóki one albo ich nagłówki się nie zmienią.
|
||||
Zmienne środowiskowe: `FINCH_PATH` (katalogi z modułami), `FINCH_CC` (kompilator C, który linkuje), `FINCH_CXX` (dla plików `.cpp`).
|
||||
Skompilowany program i jego pliki z `link "x.c"` zostają w pamięci podręcznej (`~/.cache/finch`), dopóki nie zmienią się one same albo ich nagłówki.
|
||||
|
||||
`finch.toml` (obok kodu; `finch run` w tym folderze nie potrzebuje pliku ani flag):
|
||||
`finch.toml` (obok kodu; wtedy `finch run` nie potrzebuje ani nazwy pliku, ani opcji):
|
||||
|
||||
```toml
|
||||
name = "gra" # co robi finch build
|
||||
name = "gra" # co zbuduje finch build
|
||||
entry = "src/main.fch"
|
||||
paths = ["src"] # foldery z modułami
|
||||
paths = ["src"] # katalogi z modułami
|
||||
include = ["vendor/SDL3/include"] # nagłówki C
|
||||
links = ["SDL3", "native/glue.cpp"] # biblioteki i własne .c / .cpp / .o / .a
|
||||
links = ["SDL3", "native/glue.cpp"] # biblioteki i twoje pliki .c / .cpp / .o / .a
|
||||
libdirs = ["vendor/SDL3/lib"]
|
||||
cflags = ["-DFAST"] # dla własnych plików .c / .cpp
|
||||
cflags = ["-DFAST"] # dla twoich plików .c / .cpp
|
||||
ldflags = ["-Wl,-rpath,."]
|
||||
cpu = "native" # to samo co --cpu native
|
||||
|
||||
[target.windows] # tylko przy budowaniu dla tego systemu (też linux, macos, android, linux-arm64)
|
||||
[target.windows] # tylko przy budowaniu na ten system (są też linux, macos, android, linux-arm64)
|
||||
links = ["ws2_32"]
|
||||
```
|
||||
|
||||
|
|
@ -63,8 +65,8 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
`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.
|
||||
`main` może wyglądać tak: `fn main()`, `fn main() -> int` (zwraca kod wyjścia) albo `fn main([]str args)`.
|
||||
Jedna instrukcja w linii, bez średników, `{` w tej samej linii, warunki bez nawiasów.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -72,12 +74,12 @@ Jedna instrukcja na linijkę, bez średników, `{` w tej samej linijce, bez nawi
|
|||
|
||||
| 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 (też struktur w niej) |
|
||||
| `x := 5` | nowa zmienna, typ wynika z wartości |
|
||||
| `int x = 5` | nowa zmienna z podanym typem |
|
||||
| `int x` | zero / `""` / `[]` / `null` / wartości domyślne struktury (także struktur w jej środku) |
|
||||
| `x = 7` | przypisanie |
|
||||
| `x += 1` `-=` `*=` `/=` `%=` | zmiana |
|
||||
| `const W = 640`, `const f32 G = 9.8` | stała (na najwyższym poziomie pliku; `ksztalty.W` z modułu) |
|
||||
| `const W = 640`, `const f32 G = 9.8` | stała (na najwyższym poziomie pliku; z modułu: `ksztalty.W`) |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -87,15 +89,16 @@ Jedna instrukcja na linijkę, bez średników, `{` w tej samej linijce, bez nawi
|
|||
|---|---|
|
||||
| `int` (= `i64`) | `42`, `-7`, `0xFF`, `1_000_000` |
|
||||
| `float` (= `f64`) | `3.14`, `1e9`, `2.5e-3` |
|
||||
| `bool` | `true` (prawda), `false` (fałsz) |
|
||||
| `bool` | `true`, `false` |
|
||||
| `char` | `'A'`, `'\n'` |
|
||||
| `str` | `"tekst\t\"w cudzysłowie\""`, `"hp \(hp), prędkość \(v, 2)"` (kod w tekście; `, 2` = dwie cyfry po przecinku), `"""` kilka linii `"""` (wcięcie zamykających cudzysłowów znika) |
|
||||
| `i8 i16 i32 i64` | ze znakiem, z rozmiarem |
|
||||
| `u8 u16 u32 u64` | bez znaku, z rozmiarem |
|
||||
| `f32 f64` | zmiennoprzecinkowe |
|
||||
| `str` | `"tekst\t\"w cudzysłowie\""`, `"hp \(hp), prędkość \(v, 2)"` (kod w tekście; `, 2` = dwie cyfry po przecinku), `"""` kilka linii `"""` (wcięcie zamykającego cudzysłowu znika) |
|
||||
| `i8 i16 i32 i64` | liczby całkowite ze znakiem, o podanym rozmiarze |
|
||||
| `u8 u16 u32 u64` | liczby całkowite bez znaku |
|
||||
| `f32 f64` | liczby zmiennoprzecinkowe |
|
||||
| `[]T` | tablica: `[1, 2, 3]`, `[]str imiona` |
|
||||
| `map[K]V` | mapa: `["a": 1]`, `map[str]int ile`, `[:]` |
|
||||
| `ptr[T]`, `ptr` | wskaźnik, wskaźnik bez typu |
|
||||
| `f32x8`, `i8x32`, `f64x4`, `u16x16` … | wektor: N liczb liczonych naraz (SIMD), zob. niżej |
|
||||
| `Nazwa` / `modul.Nazwa` | struktura |
|
||||
|
||||
Znaki specjalne: `\n \t \r \0 \\ \" \'`.
|
||||
|
|
@ -107,11 +110,11 @@ Znaki specjalne: `\n \t \r \0 \\ \" \'`.
|
|||
| Priorytet | Operatory |
|
||||
|---|---|
|
||||
| 5 | `*` `/` `%` `<<` `>>` `&` |
|
||||
| 4 | `+` `-` `\|` `^` (`+` skleja też tekst) |
|
||||
| 4 | `+` `-` `\|` `^` (`+` łączy też teksty) |
|
||||
| 3 | `==` `!=` `<` `<=` `>` `>=` |
|
||||
| 2 | `&&` (i) |
|
||||
| 1 | `\|\|` (lub) |
|
||||
| jednoargumentowe | `-x` `!x` (nie) `~x` |
|
||||
| 2 | `&&` |
|
||||
| 1 | `\|\|` |
|
||||
| jednoargumentowe | `-x` `!x` `~x` |
|
||||
|
||||
`x & 1 == 0` znaczy `(x & 1) == 0`.
|
||||
|
||||
|
|
@ -121,14 +124,14 @@ Znaki specjalne: `\n \t \r \0 \\ \" \'`.
|
|||
|
||||
```c
|
||||
if a > b { … } else if a == b { … } else { … }
|
||||
x := if a > b { a } else { b } // jako wartość: jedna wartość na gałąź, else wymagane
|
||||
x := if a > b { a } else { b } // jako wartość: po jednej wartości w każdej gałęzi, else obowiązkowe
|
||||
while x > 0 { … }
|
||||
for i in 0..10 { … } // 0 … 9
|
||||
for el in lista { … } // każdy element (albo znak str)
|
||||
for el in lista { … } // każdy element (albo znak tekstu)
|
||||
for i, el in lista { … } // razem z indeksem
|
||||
for klucz, wart in m { … } // każdy wpis mapy, w kolejności dodawania
|
||||
for klucz, wartosc in m { … } // każdy wpis mapy, w kolejności dodania
|
||||
break continue return wartosc
|
||||
defer sprzatanie() // uruchomi się na końcu bloku
|
||||
defer sprzatnij() // wykona się, gdy blok się skończy
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -144,48 +147,48 @@ fn przywitaj(str imie) { // bez wyniku
|
|||
}
|
||||
```
|
||||
|
||||
Parametry zachowują się jak kopie. Kolejność w pliku nie ma znaczenia. Przecinek po ostatnim argumencie jest dozwolony.
|
||||
Parametry zachowują się jak kopie. Kolejność funkcji w pliku nie ma znaczenia. Po ostatnim argumencie może stać przecinek.
|
||||
|
||||
---
|
||||
|
||||
## Metody
|
||||
|
||||
```c
|
||||
fn Punkt.przesun(int dx, int dy) { // self to Punkt, na którym wywołano (nie kopia)
|
||||
fn Punkt.przesun(int dx, int dy) { // self to punkt, na którym ją wywołano (nie kopia)
|
||||
self.x += dx
|
||||
self.y += dy
|
||||
}
|
||||
fn Punkt.odleglosc() -> float { … }
|
||||
|
||||
p.przesun(1, 2) lista[0].przesun(1, 1) wsk_na_punkt.przesun(0, 1)
|
||||
p.przesun(1, 2) lista[0].przesun(1, 1) wskaznik_na_punkt.przesun(0, 1)
|
||||
```
|
||||
|
||||
Także na strukturach z C: `fn Vector2.length() -> f32 { … }`.
|
||||
Działają też na strukturach z C: `fn Vector2.length() -> f32 { … }`.
|
||||
|
||||
---
|
||||
|
||||
## Błędy jako wartości
|
||||
|
||||
```c
|
||||
fn parsuj(str s) -> int! { // ! = może się nie udać
|
||||
fn parsuj(str s) -> int! { // ! = może się nie udać
|
||||
if s.len == 0 {
|
||||
return error("pusty")
|
||||
return error("pusty tekst")
|
||||
}
|
||||
return int(s) or { return error("to nie liczba: " + s) }
|
||||
}
|
||||
fn zapisz(str p, str t) -> ! { // może się nie udać, bez wyniku
|
||||
fn zapisz(str p, str t) -> ! { // może się nie udać, bez wyniku
|
||||
try write_file(p, t)
|
||||
}
|
||||
```
|
||||
|
||||
| Kod | Przy porażce |
|
||||
| Kod | Gdy się nie uda |
|
||||
|---|---|
|
||||
| `x := parsuj(s) or 0` | użyj 0 |
|
||||
| `x := parsuj(s) or { print(err); return }` | wykonaj blok (`err`: komunikat) |
|
||||
| `x := try parsuj(s)` | zakończ porażką też bieżącą funkcję |
|
||||
| `fn main() -> !` | porażka wypisuje `error: …`, kod wyjścia 1 |
|
||||
| `x := parsuj(s) or 0` | weź 0 |
|
||||
| `x := parsuj(s) or { print(err); return }` | wykonaj blok (`err` to komunikat) |
|
||||
| `x := try parsuj(s)` | przerwij też bieżącą funkcję z tym samym błędem |
|
||||
| `fn main() -> !` | błąd wypisuje `error: …`, kod wyjścia 1 |
|
||||
|
||||
Funkcje wbudowane, które mogą się nie udać: `int(s)`, `float(s)`, `read_file`, `write_file`, `delete_file`.
|
||||
Wbudowane funkcje, które mogą się nie udać: `int(s)`, `float(s)`, `read_file`, `write_file`, `delete_file`.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -193,9 +196,9 @@ Funkcje wbudowane, które mogą się nie udać: `int(s)`, `float(s)`, `read_file
|
|||
|
||||
| Kod | Znaczenie |
|
||||
|---|---|
|
||||
| `struct P { … }` | definicja (jedno pole na linijkę, `= domyślna` opcjonalnie) |
|
||||
| `struct P { … }` | definicja (jedno pole w linii, `= wartość` opcjonalnie) |
|
||||
| `P(1, 2)` | utworzenie, wszystkie pola po kolei |
|
||||
| `P(x: 1)` | utworzenie po nazwie, reszta domyślna/zero |
|
||||
| `P(x: 1)` | utworzenie przez nazwy pól, reszta domyślna albo zero |
|
||||
| `p.x`, `p.x = 5` | odczyt, zmiana pola |
|
||||
| `b := a` | pełna kopia |
|
||||
|
||||
|
|
@ -203,62 +206,83 @@ Funkcje wbudowane, które mogą się nie udać: `int(s)`, `float(s)`, `read_file
|
|||
|
||||
## Tablice `[]T`
|
||||
|
||||
| Kod | Daje |
|
||||
| Kod | Wynik |
|
||||
|---|---|
|
||||
| `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[i]`, `a[i] = x` | element (zakres jest sprawdzany) |
|
||||
| `a.push(x)` | dodaje na końcu |
|
||||
| `a.pop()` | zdejmuje ostatni i go zwraca |
|
||||
| `a.insert(i, x)` | wstawia na pozycję i |
|
||||
| `a.remove(i)` | usuwa pozycję i i ją zwraca |
|
||||
| `a.clear()` | opróżnia |
|
||||
| `a.resize(n)` | długość n (nowe elementy są zerami) |
|
||||
| `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.sort()` | sortuje (liczby, znaki, teksty) |
|
||||
| `a.reverse()` | odwraca kolejność |
|
||||
| `a.slice(p, k)` | nowa tablica z elementów p … k-1 |
|
||||
| `a.join(sep)` | `[]str` → jeden tekst |
|
||||
| `a.ptr` | adres pierwszego elementu (dla C) |
|
||||
|
||||
---
|
||||
|
||||
## Mapy `map[K]V`
|
||||
|
||||
| Kod | Daje |
|
||||
| Kod | Wynik |
|
||||
|---|---|
|
||||
| `m := ["a": 1, "b": 2]` | mapa (klucze: liczby, char, bool, str) |
|
||||
| `m[k]` | wartość (brak klucza: program się zatrzymuje) |
|
||||
| `m[k] = v` | dodaj / zastąp |
|
||||
| `m[k]` | wartość (brak klucza zatrzymuje program) |
|
||||
| `m[k] = v` | dodaje albo podmienia |
|
||||
| `m[k] += 1`, `m[k].push(x)` | brakujący klucz zaczyna od wartości domyślnej (0, `[]`, …) |
|
||||
| `m.len` | liczba kluczy |
|
||||
| `m.has(k)` | czy jest |
|
||||
| `m.get(k, domyslna)` | wartość albo domyślna |
|
||||
| `m.remove(k)` | bool: czy był |
|
||||
| `m.clear()` | wyczyść |
|
||||
| `m.keys()`, `m.values()` | tablice, w kolejności dodawania |
|
||||
| `m.has(k)` | bool |
|
||||
| `m.get(k, domyslna)` | wartość albo `domyslna` |
|
||||
| `m.remove(k)` | bool: czy klucz był |
|
||||
| `m.clear()` | opróżnia |
|
||||
| `m.keys()`, `m.values()` | tablice, w kolejności dodania |
|
||||
|
||||
---
|
||||
|
||||
## Wektory `f32x8` (SIMD)
|
||||
|
||||
Typy: `f32x4/8/16`, `f64x2/4/8`, `i8x16/32/64`, `i16x8/16/32`, `i32x4/8/16`, `i64x2/4/8` i tak samo `u…`; najwyżej 512 bitów.
|
||||
|
||||
| Kod | Wynik |
|
||||
|---|---|
|
||||
| `f32x8(x)` | `x` w każdym elemencie |
|
||||
| `f32x8(a, b, …, h)` | po jednej liczbie na element |
|
||||
| `f32x8(lista, i)` | `lista[i]` … `lista[i+7]` (z `[]f32` albo `ptr[f32]`) |
|
||||
| `f32x8(v)` | 8-elementowy wektor przeliczony element po elemencie (`f32x8(calkowite)`, `i32x8(ulamki)`) |
|
||||
| `v + w`, `v * 2.0`, `-v` | element po elemencie; zwykła liczba działa na każdy element (`/` tylko dla liczb zmiennoprzecinkowych) |
|
||||
| `& \| ^ << >> ~` | element po elemencie, dla liczb całkowitych |
|
||||
| `v == w`, `v != w` | bool: czy wszystkie elementy są równe / czy któryś się różni |
|
||||
| `v[i]`, `v[i] = x`, `v.len` | jeden element; liczba elementów |
|
||||
| `min(v, w)`, `max`, `abs(v)`, `clamp(v, lo, hi)` | element po elemencie |
|
||||
| `v.sum()`, `v.min()`, `v.max()`, `v.dot(w)` | jedna liczba ze wszystkich elementów |
|
||||
| `v.sqrt()`, `v.floor()`, `v.ceil()`, `v.round()`, `v.fma(b, c)` | każdy element (liczby zmiennoprzecinkowe; `fma` = `v * b + c`) |
|
||||
| `v.store(lista, i)` | zapisuje elementy do `lista[i]` … |
|
||||
|
||||
---
|
||||
|
||||
## Tekst `str`
|
||||
|
||||
| Kod | Daje |
|
||||
| Kod | Wynik |
|
||||
|---|---|
|
||||
| `s.len` | liczba bajtów (ą, ż… to 2) |
|
||||
| `s.len` | liczba bajtów |
|
||||
| `s[i]`, `s[i] = 'x'` | znak |
|
||||
| `a + b` | sklejony tekst |
|
||||
| `"x = \(x)"` | wartość dowolnego kodu w tekście (`\(x, 2)`: liczba z 2 cyframi po przecinku) |
|
||||
| `a + b` | połączony tekst |
|
||||
| `"x = \(x)"` | wartość dowolnego kodu wstawiona w tekst (`\(x, 2)`: liczba z dwiema cyframi po przecinku) |
|
||||
| `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.contains(t)` | bool |
|
||||
| `s.starts_with(t)`, `s.ends_with(t)` | bool |
|
||||
| `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.replace(a, b)` | każde a zamienione na b |
|
||||
| `s.repeat(n)` | tekst n razy |
|
||||
| `s.bytes()` | `[]u8` |
|
||||
| `s.ptr` | `ptr[char]` (dla C; `str` trafia też do parametru `const char *` bez zmian) |
|
||||
| `s.ptr` | `ptr[char]` (dla C; parametr `const char *` przyjmie też samo `str`) |
|
||||
| `==` `!=` `<` `>` | porównanie |
|
||||
|
||||
---
|
||||
|
|
@ -271,41 +295,41 @@ Funkcje wbudowane, które mogą się nie udać: `int(s)`, `float(s)`, `read_file
|
|||
| `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) |
|
||||
| `u8(300)` | `44` (zostają najniższe bity) |
|
||||
| `char(66)` | `'B'` |
|
||||
| `bool(0)` | `false` |
|
||||
| `str(42)`, `str(1.5)`, `str(true)`, `str('c')` | tekst (float: najkrótszy tekst, który jest tą samą liczbą) |
|
||||
| `str(3.14159, 2)` | `"3.14"` (tyle cyfr po kropce) |
|
||||
| `str(42)`, `str(1.5)`, `str(true)`, `str('c')` | tekst (liczba zmiennoprzecinkowa: najkrótszy zapis tej samej liczby) |
|
||||
| `str(3.14159, 2)` | `"3.14"` (tyle cyfr po przecinku) |
|
||||
| `str([1, 2])`, `str(m)`, `str(punkt)` | ten sam tekst, który pokazuje `print` |
|
||||
| `int("x") or 0`, `float(s) or 0.0` | liczba albo wartość zapasowa |
|
||||
| `str(bajty)` | `[]u8` → tekst |
|
||||
| `str(p)` | `char*` z C → tekst |
|
||||
| `ptr(p)`, `ptr(16)` | wskaźnik bez typu, ze wskaźnika albo liczby |
|
||||
| `ptr(p)`, `ptr(16)` | wskaźnik bez typu, ze wskaźnika albo z liczby |
|
||||
| `int(p)` | wskaźnik → adres |
|
||||
|
||||
Automatycznie tylko wtedy, gdy nic nie ginie: mniejsza → większa liczba, dowolna całkowita → float, `f32` → `f64`.
|
||||
Automatycznie tylko wtedy, gdy nic nie ginie: mniejsza liczba → większa, liczba całkowita → zmiennoprzecinkowa, `f32` → `f64`.
|
||||
|
||||
---
|
||||
|
||||
## Funkcje wbudowane
|
||||
|
||||
| Funkcja | Robi |
|
||||
| Funkcja | Co robi |
|
||||
|---|---|
|
||||
| `print(a, b, …)` | wypisz, spacje między, nowa linia na końcu |
|
||||
| `input()`, `input("Pytanie? ")` | wczytaj linijkę |
|
||||
| `print(a, b, …)` | wypisuje wartości oddzielone spacjami i kończy linię |
|
||||
| `input()`, `input("Pytanie? ")` | wczytuje linię |
|
||||
| `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 (kończy też blok `or { }`) |
|
||||
| `min(a, b, …)`, `max(a, b, …)`, `abs(x)`, `clamp(x, od, do)` | dla dowolnych liczb (twoja funkcja o tej nazwie wygrywa) |
|
||||
| `file_exists(sciezka)` | bool |
|
||||
| `delete_file(sciezka)` | bool |
|
||||
| `shell(polecenie)` | uruchamia polecenie, zwraca jego kod wyjścia |
|
||||
| `exit(kod)` | od razu kończy program (kończy też blok `or { }`) |
|
||||
| `min(a, b, …)`, `max(a, b, …)`, `abs(x)`, `clamp(x, lo, hi)` | dla dowolnych liczb (twoja funkcja o tej samej nazwie ma pierwszeństwo) |
|
||||
| `error(komunikat)` | `return error("…")` w funkcji `-> T!` |
|
||||
| `addr(x)` | wskaźnik na x; `addr(fn)` = callback dla C |
|
||||
| `assert(warunek)`, `assert(warunek, "dlaczego")` | zatrzymaj się z błędem, gdy warunek jest fałszywy (w bloku `test`: ten test nie przechodzi) |
|
||||
| `atomic_add(p, n)`, `atomic_sub`, `atomic_load(p)`, `atomic_store(p, n)`, `atomic_swap(p, n)`, `atomic_cas(p, stara, nowa)` | liczba całkowita zmieniana też przez inne wątki, przez jej `ptr` (`addr(licznik)`) |
|
||||
| `addr(x)` | wskaźnik na x; `addr(fn)` = funkcja zwrotna dla C |
|
||||
| `assert(warunek)`, `assert(warunek, "dlaczego")` | zatrzymuje program, gdy warunek jest fałszywy (w bloku `test`: ten test nie przechodzi) |
|
||||
| `atomic_add(p, n)`, `atomic_sub`, `atomic_load(p)`, `atomic_store(p, n)`, `atomic_swap(p, n)`, `atomic_cas(p, stara, nowa)` | liczba całkowita, którą zmieniają też inne wątki, przez jej `ptr` (`addr(licznik)`) |
|
||||
| `new(wartosc)` | wartość na stercie → `ptr[T]` |
|
||||
| `free(p)` | oddaj ją |
|
||||
| `free(p)` | oddaje tę pamięć |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -314,7 +338,7 @@ Automatycznie tylko wtedy, gdy nic nie ginie: mniejsza → większa liczba, dowo
|
|||
| Finch | C |
|
||||
|---|---|
|
||||
| `ptr[int] p` | `int *p` |
|
||||
| `addr(x)` | `&x` (zmienna-struktura podana tam, gdzie idzie `ptr[TaStruktura]`: `pchnij(cialo)` = `pchnij(addr(cialo))`) |
|
||||
| `addr(x)` | `&x` (zmienna-struktura podana tam, gdzie oczekiwany jest `ptr[TaStruktura]`: `push(cialo)` = `push(addr(cialo))`) |
|
||||
| `p.value` | `*p` |
|
||||
| `p.pole` | `p->pole` |
|
||||
| `p[i]` | `p[i]` |
|
||||
|
|
@ -325,23 +349,23 @@ Automatycznie tylko wtedy, gdy nic nie ginie: mniejsza → większa liczba, dowo
|
|||
|
||||
## 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.
|
||||
- Przekazywanie struktury: `fn f(Cialo c)` pracuje na własnej kopii (ta u wywołującego się nie zmienia), `fn f(ptr[Cialo] c)` zmienia tę u wywołującego (`f(cialo)` albo `f(addr(cialo))`), metoda dostaje `self` przez adres, nigdy kopię. Struktura z 256+ bajtami liczb przekazana przez wartość albo w `for x in lista` dostaje ostrzeżenie.
|
||||
- `new(...)` + `free(...)` (często z `defer`) do list wiązanych, drzew, współdzielenia.
|
||||
- Pamięć z C: funkcjami z C (`malloc` / `free`, `fclose`, …).
|
||||
- Tablice, teksty i struktury zwalniają się same na końcu swojego bloku. `free` nie jest potrzebne.
|
||||
- `b := a` kopiuje; wynik funkcji jest przenoszony; `return x` przenosi.
|
||||
- Przekazywanie struktury: `fn f(Cialo c)` pracuje na własnej kopii (struktura wywołującego się nie zmienia), `fn f(ptr[Cialo] c)` zmienia strukturę wywołującego (`f(cialo)` albo `f(addr(cialo))`), metoda dostaje `self` przez adres, nigdy jako kopię. Struktura z co najmniej 256 bajtami liczb, przekazywana przez wartość albo w `for x in lista`, dostaje ostrzeżenie.
|
||||
- `new(...)` z `free(...)` (często razem z `defer`) przydaje się do list wiązanych, drzew i współdzielenia.
|
||||
- Pamięć z C zwalniasz funkcjami 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
|
||||
import ui/przycisk // ui/przycisk.fch: przycisk.rysuj()
|
||||
import ui/przycisk as p // inna nazwa: p.rysuj()
|
||||
import ksztalty // ksztalty.fch obok tego pliku (albo w FINCH_PATH)
|
||||
ksztalty.pole(b) // jego funkcje
|
||||
ksztalty.Pudelko(2, 3) // jego struktury
|
||||
ksztalty.Pudelko inne // w deklaracjach
|
||||
import ui/button // ui/button.fch: button.draw()
|
||||
import ui/button as btn // pod inną nazwą: btn.draw()
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -350,14 +374,14 @@ import ui/przycisk as p // inna nazwa: p.rysuj()
|
|||
|
||||
| Kod | Znaczenie |
|
||||
|---|---|
|
||||
| `import "x.h"` | funkcje, struktury, enumy, liczbowe `#define`, zmienne globalne |
|
||||
| `link "nazwa"` | libnazwa.so / nazwa.lib (najpierw pkg-config) |
|
||||
| `link "plik.c"`, `link "glue.cpp"` | skompiluj własny plik C albo C++ (C++: funkcje w `extern "C"`) |
|
||||
| `addr(mojaFn)` | funkcja Fincha jako callback |
|
||||
| `import "x.h"` | funkcje, struktury, enumy, liczby z `#define`, zmienne globalne |
|
||||
| `link "nazwa"` | libnazwa.so / nazwa.lib (najpierw pyta pkg-config) |
|
||||
| `link "plik.c"`, `link "glue.cpp"` | kompiluje twój plik C albo C++ (w C++ funkcje w `extern "C"`) |
|
||||
| `addr(mojaFn)` | przekazuje funkcję Fincha jako funkcję zwrotną |
|
||||
|
||||
| Typ C | Finch |
|
||||
| Typ w C | W Finchu |
|
||||
|---|---|
|
||||
| `int` / `long long` / `unsigned` | `i32` / `i64` / `u32` (wg rozmiaru) |
|
||||
| `int` / `long long` / `unsigned` | `i32` / `i64` / `u32` (według rozmiaru) |
|
||||
| `float` / `double` | `f32` / `f64` |
|
||||
| `char *` (parametr, wynik) | `str` |
|
||||
| `char *` (pole, za wskaźnikiem) | `ptr[char]` |
|
||||
|
|
@ -365,46 +389,46 @@ import ui/przycisk as p // inna nazwa: p.rysuj()
|
|||
| `T *` | `ptr[T]` |
|
||||
| `void *`, uchwyty | `ptr` |
|
||||
| `T x[N]` (w strukturze) | `[N]T` |
|
||||
| `union U` | `U`: `U u`, `u.pole`, `U(pole: v)`, przez wskaźnik do C (nie przez wartość) |
|
||||
| `#define N 4`, `"tekst"`, `(1u << 3)`, `((Uint64)2)` | stałe (bez makr-funkcji) |
|
||||
| `#define RAYWHITE (Color){ 245, 245, 245, 255 }` | `Color` |
|
||||
| `union U` | `U`: `U u`, `u.pole`, `U(pole: v)`, do C przez wskaźnik (nie przez wartość) |
|
||||
| `#define N 4`, `"tekst"`, `(1u << 3)`, `((Uint64)2)` | stałe (bez makr z parametrami) |
|
||||
| `#define RAYWHITE (Color){ 245, 245, 245, 255 }` | wartość typu `Color` |
|
||||
|
||||
**`char *` to `str`**: funkcja C, która bierze albo zwraca `char *`, bierze albo daje `str` Fincha (bez `.ptr`, bez zamiany); tylko pole `char *` i `char **` zostają `ptr[char]`.
|
||||
C++ i Rust: przez nagłówek C. C++ z `extern "C"` (i `link "x.cpp"`), Rust z `#[no_mangle] pub extern "C" fn` zbudowany jako `staticlib` (`link "target/release/libgra.a"`) i nagłówek (napisze go cbindgen).
|
||||
**`char *` to `str`**: funkcja C, która przyjmuje albo zwraca `char *`, przyjmuje albo zwraca `str` Fincha (bez `.ptr` i bez zamiany); tylko pole `char *` i `char **` zostają jako `ptr[char]`.
|
||||
C++ i Rust: przez nagłówek C. C++ z `extern "C"` (i `link "x.cpp"`), Rust z `#[no_mangle] pub extern "C" fn`, zbudowany jako `staticlib` (`link "target/release/libgra.a"`), z nagłówkiem (może go napisać cbindgen).
|
||||
|
||||
Wynik `char *` z funkcji C to od razu `str`; struktury przez wartość działają w konwencjach System V, Windows x64 i ARM64 Linux (sprawdzone w emulatorach; macOS przez CI).
|
||||
Wynik `char *` funkcji C od razu jest `str`; struktury przez wartość działają w konwencjach wywołań System V, Windows x64 i ARM64 (Linux i macOS).
|
||||
|
||||
---
|
||||
|
||||
## Błędy w czasie działania (program zatrzymuje się z plikiem i linijką)
|
||||
## Błędy w trakcie działania (program kończy się z plikiem i linią)
|
||||
|
||||
| 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 |
|
||||
| `pop() on an empty array` | |
|
||||
| `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` (bez `or`) |
|
||||
| `the key "x" is not in the map` | `m["x"]` |
|
||||
| `assert failed: dlaczego` | `assert(warunek, "dlaczego")` |
|
||||
|
||||
Pod komunikatem wywołania, które do niego doprowadziły (`finch run`, `finch test`, `-g`, `-O0`, `--trace`):
|
||||
Pod komunikatem pojawiają się wywołania, które do niego doprowadziły (`finch run`, `finch test`, `-g`, `-O0`, `--trace`):
|
||||
|
||||
```
|
||||
gra.fch:6: runtime error: index 3 is out of range (the length is 2)
|
||||
in Enemy.next (gra.fch:6)
|
||||
in step (gra.fch:10)
|
||||
in Wrog.nastepny (gra.fch:6)
|
||||
in krok (gra.fch:10)
|
||||
in main (gra.fch:15)
|
||||
```
|
||||
|
||||
## Testy
|
||||
|
||||
```c
|
||||
test "wysokość skoku" { // obok kodu; finch test plik.fch je uruchamia, finch run/build je pomijają
|
||||
g := Gracz()
|
||||
g.skocz()
|
||||
assert(g.y > 0.0, "y to \(g.y)")
|
||||
test "wysokość skoku" { // obok kodu; uruchamia je finch test plik.fch, finch run/build je pomijają
|
||||
p := Gracz()
|
||||
p.skocz()
|
||||
assert(p.y > 0.0, "y wynosi \(p.y)")
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -413,74 +437,55 @@ test "wysokość skoku" { // obok kodu; finch test plik.fch je uruchamia
|
|||
## Edytory
|
||||
|
||||
Kate: `editors/kate/install.sh`, potem włącz wtyczkę **LSP Client**; uruchamianie przez **Build & Run** → `finch run %f`.
|
||||
Każdy edytor z LSP: `finch lsp`.
|
||||
Dowolny edytor z LSP: `finch lsp`.
|
||||
|
||||
### VS Code (rozszerzenie „Finch”)
|
||||
|
||||
| Klawisz / akcja | Robi |
|
||||
| Klawisz / akcja | Co 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+F5` | uruchamia plik |
|
||||
| `Finch: Build This File` | buduje; błędy trafiają do panelu Problems |
|
||||
| `F12` | przejście do definicji |
|
||||
| najechanie kursorem | typ / sygnatura / opis |
|
||||
| `Ctrl+Spacja` | podpowiedzi (po `.`: pola, metody, zawartość modułu) |
|
||||
| `Ctrl+Shift+O` | funkcje i struktury w pliku |
|
||||
| `main`, `fn`, `fnr`, `fnf`, `method`, `struct`, `for`, `foreach`, `forkv`, `map`, `orb`, `if`, `ife`, `while`, `input` + Tab | szablony |
|
||||
| ustawienie `finch.path` | gdzie jest finch / finch.exe |
|
||||
| `main`, `fn`, `fnr`, `fnf`, `method`, `struct`, `for`, `foreach`, `forkv`, `map`, `orb`, `if`, `ife`, `while`, `input` + Tab | gotowe fragmenty kodu |
|
||||
| ustawienie `finch.path` | gdzie leży finch / finch.exe |
|
||||
|
||||
---
|
||||
|
||||
## Enumy i `match`
|
||||
|
||||
```
|
||||
enum Kolor { Czerwony, Zielony } enum Status { Ok = 200, Brak = 404 }
|
||||
k := Kolor.Zielony int(k) Kolor(1) k == Kolor.Czerwony // tylko == i !=; Kolor(7) to błąd
|
||||
enum Kolor { Czerwony, Zielony, Niebieski } enum Status { Ok = 200, NotFound = 404 }
|
||||
k := Kolor.Zielony int(k) Kolor(2) k == Kolor.Czerwony // tylko == i !=; Kolor(7) to błąd
|
||||
fn Kolor.nastepny() -> Kolor { ... } // metody działają
|
||||
|
||||
match k { Czerwony -> ... Zielony -> { ... } else -> ... } // same nazwy wariantów; każdy wariant albo else
|
||||
x := match n { 1, 2 -> "mało" else -> "dużo" } // wyrażenie: gałęzie tego samego typu
|
||||
match k { Czerwony -> ... Zielony, Niebieski -> { ... } else -> ... } // same nazwy wariantów; każdy wariant albo else
|
||||
x := match n { 1, 2 -> "kilka" else -> "dużo" } // wyrażenie: każda gałąź tego samego typu
|
||||
```
|
||||
|
||||
## Typy generyczne
|
||||
|
||||
```
|
||||
fn max[T](T a, T b) -> T { ... } max(3, 9) max[float](1, 2.5) // wynika z argumentów albo zapisane
|
||||
struct Stos[T] { []T elementy } fn Stos[T].dodaj(T x) { ... } // typ zawsze podaje się przy tworzeniu:
|
||||
fn max[T](T a, T b) -> T { ... } max(3, 9) max[float](1, 2.5) // typ wywnioskowany albo podany
|
||||
struct Stos[T] { []T el } fn Stos[T].push(T x) { ... } // typ zawsze idzie z nazwą:
|
||||
s := Stos[int]() Stos[int] t Para[str, int]("wiek", 31) // nigdy samo Stos()
|
||||
```
|
||||
|
||||
## Biblioteka standardowa (`import nazwa`; własny plik o tej nazwie ma pierwszeństwo)
|
||||
## Biblioteka standardowa (`import nazwa`; twój plik o tej samej nazwie ma pierwszeństwo)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `path` | `join(a, b)` `base(p)` `dir(p)` `ext(p)` `stem(p)` `parts(p)` `clean(p)` `is_abs(p)` |
|
||||
| `time` | `now()` `millis()` `sleep(ms)` `date(t)` `local(t)` `format(t, fmt)` `days_in_month(r, m)` |
|
||||
| `proc` | `run(cmd)` `output(cmd)` (błąd z jego wyjściem) `env(nazwa, domyślna)` `pid()` `cwd()` |
|
||||
| `time` | `now()` `millis()` `sleep(ms)` `date(t)` `local(t)` `format(t, wzor)` `days_in_month(r, m)` |
|
||||
| `proc` | `run(polecenie)` `output(polecenie)` (przy błędzie zwraca jego wyjście) `env(nazwa, domyslna)` `pid()` `cwd()` |
|
||||
| `thread` | `spawn(addr(praca), addr(dane))` → `t.join()`; `mutex()` → `m.lock()` `m.unlock()` `m.close()`; `cpus()` (funkcja wątku: `fn praca(ptr arg)`) |
|
||||
| `fs` | `read_bytes(p)` `write_bytes(p, dane)` `exists(p)` `is_dir(p)` `mkdir(p)` `list(folder)` `remove_dir(p)` `data_dir(app)` |
|
||||
| `fs` | `read_bytes(p)` `write_bytes(p, dane)` `exists(p)` `is_dir(p)` `mkdir(p)` `list(katalog)` `remove_dir(p)` `data_dir(aplikacja)` |
|
||||
| `json` | `parse(tekst)` `stringify(v)` `pretty(v)` `new_text/number/bool/null/list/object` `v.get(k)` `v.at(i)` `v.set(k, x)` `v.push(x)` `v.has(k)` `v.str_or(d)` `v.int_or(d)` `v.float_or(d)` `v.bool_or(d)` |
|
||||
|
||||
## 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 |
|
||||
| `enum` | wyliczenie |
|
||||
| `match` | dopasuj |
|
||||
| `defer` | odłóż (na koniec bloku) |
|
||||
| `or` | albo (co zrobić przy porażce) |
|
||||
| `try` | spróbuj (porażkę przekaż dalej) |
|
||||
| `const` | stała |
|
||||
| `export` | wystaw (funkcja dla programu w C) |
|
||||
| `self` | sam (w metodzie: struktura, na której ją wywołano) |
|
||||
| `test` | test (tylko jako `test "nazwa" { }`) |
|
||||
| `as` | jako (tylko w `import x as y`) |
|
||||
| `map` | mapa |
|
||||
`fn return if else while for in break continue true false null import link struct enum match defer or try const export`
|
||||
(`test` i `as` tylko tam, gdzie coś znaczą: `test "nazwa" { }`, `import x as y`)
|
||||
(oraz `self` wewnątrz metod)
|
||||
|
|
|
|||
Loading…
Reference in a new issue