Finch 1.0.0

A small, fast programming language on LLVM with C-like syntax.

- Lexer, recursive-descent parser, single-pass type checker + LLVM IR codegen, O2 pipeline
- Types: int/float/bool/char/str, sized i8..u64/f32/f64, pointers ptr[T] with addr()/.value/null
- Functions (fn ... -> T), if/else, while, for..in, break/continue, Go-style operator precedence
- Implicit conversions only when lossless; literals adapt to their target type
- Runtime checks for division by zero, MIN/-1 and null .value
- C interop: import "header.h" via libclang, link "lib" with pkg-config, link-error advice
- Human-readable errors with source excerpts
- Test suite (34 tests), examples, docs for beginners/technicians/engineers in English and Polish

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Nexoniarz 2026-10-08 17:10:45 +02:00
commit 0591cd20f3
73 changed files with 8066 additions and 0 deletions

650
docs/en/for-beginners.md Normal file
View file

@ -0,0 +1,650 @@
# Finch for Beginners
**Never written a program before? This guide is for you.**
No experience needed, and no math beyond what you learned in primary school.
Take it slowly, one section at a time, and type every example yourself: that is how it sticks.
> 🇵🇱 Polska wersja: [dla-poczatkujacych.md](../pl/dla-poczatkujacych.md)
---
## Contents
1. [What is a program?](#1-what-is-a-program)
2. [Getting Finch ready](#2-getting-finch-ready)
3. [Your first program](#3-your-first-program)
4. [Showing things on the screen](#4-showing-things-on-the-screen)
5. [Boxes with names: variables](#5-boxes-with-names-variables)
6. [Kinds of values](#6-kinds-of-values)
7. [Doing math](#7-doing-math)
8. [Making decisions: if](#8-making-decisions-if)
9. [Repeating things: loops](#9-repeating-things-loops)
10. [Your own commands: functions](#10-your-own-commands-functions)
11. [When something goes wrong](#11-when-something-goes-wrong)
12. [Small projects to try](#12-small-projects-to-try)
13. [Cheat sheet](#13-cheat-sheet)
14. [Words you will hear](#14-words-you-will-hear)
---
## 1. What is a program?
A computer is very fast, but it does not think. It only does exactly what it is told,
one step at a time.
A **program** is a list of those steps, written down. Like a recipe:
> 1. Take two eggs.
> 2. Break them into a bowl.
> 3. Stir.
A **programming language** is the way we write that recipe so the computer understands it.
**Finch** is one of those languages. It was made to be small and simple, so you
can learn it quickly.
The computer reads your program from top to bottom, line by line.
---
## 2. Getting Finch ready
Finch runs on **Linux** computers. If a teacher, parent or friend has already set it up
for you, skip to the next section.
Otherwise, open the **Terminal** program (a window where you type commands) and type
these lines one by one, pressing **Enter** after each:
```sh
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell
cmake -S . -B build -G Ninja
ninja -C build
```
If the last line finishes without the word `error`, Finch is ready.
(If your computer does not have `nix-shell`, ask someone to follow the
[guide for technicians](for-technicians.md#2-installing). It explains the other way.)
To check it works, type:
```sh
./build/finch version
```
You should see something like `finch 1.0.0`.
---
## 3. Your first program
1. Open any text editor (for example *Text Editor*, *Kate*, *gedit* or *VS Code*).
2. Type exactly this:
```c
fn main() {
print("Hello!")
}
```
3. Save it in the `Finch` folder as **`hello.fn`**. The `.fn` at the end tells everyone it is a Finch program.
4. In the Terminal, type:
```sh
./build/finch run hello.fn
```
You will see:
```
Hello!
```
🎉 **You have just written and run a program.**
### What did we write?
```text
fn main() { ← "here starts the main part of my program"
print("Hello!") ← "show the text Hello! on the screen"
} ← "the main part ends here"
```
- `fn main()` is where every Finch program **starts**. Each program has exactly one `main`.
- The curly brackets `{` and `}` hold everything that belongs to `main`, like the two covers of a book.
- `print(...)` shows something on the screen.
- Text always goes inside double quotes: `"Hello!"`.
The spaces at the start of `print` are not required, but they make it easy to see
what is inside the brackets. Always add them. It is a good habit.
---
## 4. Showing things on the screen
`print` can show text and numbers. Put a comma between things, and Finch adds a space for you:
```c
fn main() {
print("I am", 10, "years old")
print("2 + 2 =", 2 + 2)
print()
print("The line above is empty")
}
```
Shows:
```
I am 10 years old
2 + 2 = 4
The line above is empty
```
Every `print` starts a new line. `print()` with nothing inside makes an empty line.
### Notes for yourself: comments
Anything after `//` is ignored by the computer. Use it to leave notes:
```c
// This program says hi
fn main() {
print("Hi") // this shows Hi
}
```
---
## 5. Boxes with names: variables
Imagine a box with a label on it. You can put something in the box and later look
at what is inside by reading the label. In programming that box is called a **variable**.
```c
fn main() {
age := 10
print(age)
}
```
`age := 10` means: *"make a new box, label it `age`, and put 10 in it."*
You can change what is in the box later, using just `=`:
```c
fn main() {
score := 0
print("Score:", score)
score = 5
print("Score:", score)
score = score + 1
print("Score:", score)
}
```
```
Score: 0
Score: 5
Score: 6
```
`score = score + 1` reads as: *"take what is in `score`, add 1, and put the result back into `score`."*
There is a shorter way to write the same thing: `score += 1`.
**Remember:**
- `:=` makes a **new** box. You use it only once per name.
- `=` puts a new value into a box **that already exists**.
### Naming your boxes
Names can use the English letters `a`–`z` and `A`–`Z`, digits and `_`, but cannot start with a digit:
`age`, `total_points`, `player2` are fine. `2player` is not.
Letters like `é`, `ü` or `ż` cannot be used in names, only inside text in quotes: `print("Zürich")` is fine.
Pick names that say what is inside: `price` is better than `p`.
---
## 6. Kinds of values
Finch keeps track of what *kind* of thing is in each box. The kind is called a **type**.
These are the ones you will use most:
| Type | What it holds | Examples |
|---------|------------------------------|--------------------------|
| `int` | whole numbers | `0`, `42`, `-7` |
| `float` | numbers with a decimal point | `3.14`, `0.5`, `-2.0` |
| `str` | text | `"Hello"`, `"Ola"` |
| `bool` | yes or no | `true`, `false` |
| `char` | a single letter or sign | `'A'`, `'z'`, `'?'` |
Finch figures out the type by itself when you use `:=`:
```c
name := "Ola" // str
age := 10 // int
height := 1.42 // float
likes_cats := true // bool
```
You can also write the type yourself, in front of the name:
```c
int age = 10
str name = "Ola"
```
Both ways do the same thing. Use the one you like.
**A box keeps its type.** If `age` holds whole numbers, you cannot put text in it later.
Finch will stop and tell you, which helps you catch mistakes early.
---
## 7. Doing math
| Sign | Meaning | Example | Result |
|------|----------------------------|----------|--------|
| `+` | add | `7 + 2` | `9` |
| `-` | subtract | `7 - 2` | `5` |
| `*` | multiply | `7 * 2` | `14` |
| `/` | divide | `7 / 2` | `3` |
| `%` | what is left after dividing | `7 % 2` | `1` |
**Careful with dividing whole numbers:** `7 / 2` gives `3`, not `3.5`, because both are
whole numbers, so the answer is a whole number too (the part after the dot is dropped).
If you want `3.5`, use a decimal number: `7.0 / 2`.
Multiplication and division happen before adding and subtracting, just like at school.
Use brackets to change the order:
```c
print(2 + 3 * 4) // 14
print((2 + 3) * 4) // 20
```
`%` is handy to check if a number is even: an even number divided by 2 leaves nothing,
so `n % 2` is `0`.
You **cannot divide by zero**. If your program tries, it stops and tells you which line did it.
---
## 8. Making decisions: if
Programs can choose what to do. `if` means *"only do this when something is true"*.
```c
fn main() {
temperature := 25
if temperature > 20 {
print("It's warm, wear a t-shirt")
}
}
```
Add `else` for *"otherwise, do this"*:
```c
if temperature > 20 {
print("It's warm")
} else {
print("Take a jacket")
}
```
And `else if` for more choices. Finch checks them from top to bottom and does only
the **first** one that is true:
```c
if temperature > 25 {
print("Hot!")
} else if temperature > 15 {
print("Nice")
} else {
print("Cold")
}
```
### Comparing things
| Sign | Means |
|------|-----------------------------|
| `==` | is equal to |
| `!=` | is not equal to |
| `<` | is smaller than |
| `>` | is bigger than |
| `<=` | is smaller than or equal to |
| `>=` | is bigger than or equal to |
⚠️ **One `=` puts a value in a box. Two `==` ask "are these equal?"**
You can compare text too: `if name == "Ola" { ... }`.
### Joining questions
- `&&` means **and**: both must be true. `if age > 6 && age < 12 { ... }`
- `||` means **or**: at least one must be true. `if day == "Sat" || day == "Sun" { ... }`
- `!` means **not**: it flips true and false. `if !raining { ... }`
---
## 9. Repeating things: loops
Computers never get bored. A **loop** repeats the same steps many times.
### Counting with `for`
```c
fn main() {
for i in 1..6 {
print("Number", i)
}
}
```
```
Number 1
Number 2
Number 3
Number 4
Number 5
```
`for i in 1..6` means: *"count with `i` from 1, up to but **not including** 6"*.
So `0..10` gives you ten numbers: 0, 1, 2 … 9.
### Repeating while something is true: `while`
```c
fn main() {
count := 3
while count > 0 {
print(count)
count -= 1
}
print("Go!")
}
```
```
3
2
1
Go!
```
⚠️ Make sure the loop can end. If `count` never went down, the loop would run forever.
If that happens, press **Ctrl + C** in the Terminal to stop it.
### Stopping early and skipping
- `break` leaves the loop right away.
- `continue` skips the rest of this round and goes to the next one.
```c
for i in 1..100 {
if i == 5 {
break // stop when we reach 5
}
print(i) // prints 1 2 3 4
}
```
---
## 10. Your own commands: functions
When you do the same thing in many places, give it a name. That named block is a **function**.
You already know one: `main`.
```c
fn say_hello(str name) {
print("Hello,", name)
}
fn main() {
say_hello("Ola")
say_hello("Tom")
}
```
```
Hello, Ola
Hello, Tom
```
`str name` in brackets means: *"this function needs one piece of text, and inside it
we call that text `name`."* The thing you put in brackets when using it is passed in.
### Functions that give back an answer
Write `->` and the type of the answer, and use `return` to give it back:
```c
fn add(int a, int b) -> int {
return a + b
}
fn main() {
result := add(2, 3)
print(result) // 5
}
```
It does not matter where in the file you put your functions, above or below `main`.
---
## 11. When something goes wrong
Everyone makes mistakes when programming, even experts, every day.
Finch tries hard to explain what went wrong in plain words. Example:
```c
fn main() {
age := 10
print(agee)
}
```
```
hello.fn:3:11: error: there is no variable named 'agee'
3 | print(agee)
| ^
```
How to read it:
- `hello.fn` is the file,
- `3` is the **line** number,
- `11` is how far into the line (the **column**),
- then the explanation, and the line itself with a `^` pointing at the problem.
Here we simply misspelled `age`.
### Common mistakes
| Finch says | What it means | Fix |
|---|---|---|
| `there is no variable named 'x'` | The name is misspelled, or you never made that box | Check spelling. Create it with `x := ...` |
| `a variable named 'x' already exists here` | You used `:=` twice for the same name | Use `=` the second time |
| `'x' must be int, but this is str` | Wrong kind of value for that box | Put the right kind of value in |
| `put each statement on its own line` | Two commands on one line | Press Enter between them |
| `this '{' is never closed` | A `}` is missing | Add the `}` |
| `a condition must be bool` | `if` needs a yes/no question | Compare something: `if x > 0` |
| `runtime error: division by zero` | You divided by 0 while the program ran | Check the number before dividing |
---
## 12. Small projects to try
Try writing each one yourself first. Look at the solution only if you get stuck.
### Project 1: Times table
Show the 7 times table, from 7 × 1 to 7 × 10.
<details><summary>Solution</summary>
```c
fn main() {
for i in 1..11 {
print("7 x", i, "=", 7 * i)
}
}
```
</details>
### Project 2: Even or odd
For every number from 1 to 10, show whether it is even or odd.
<details><summary>Solution</summary>
```c
fn main() {
for n in 1..11 {
if n % 2 == 0 {
print(n, "is even")
} else {
print(n, "is odd")
}
}
}
```
</details>
### Project 3: Celsius to Fahrenheit
Show a table from 0 °C to 100 °C, every 10 degrees. Formula: `F = C * 9 / 5 + 32`.
<details><summary>Solution</summary>
```c
fn to_fahrenheit(float c) -> float {
return c * 9 / 5 + 32
}
fn main() {
for c in 0..11 {
celsius := float(c * 10)
print(celsius, "C =", to_fahrenheit(celsius), "F")
}
}
```
`float(...)` turns a whole number into a decimal number.
</details>
### Project 4: Fizz Buzz
Count from 1 to 20. For numbers divisible by 3 say `Fizz`, by 5 say `Buzz`,
by both say `FizzBuzz`, otherwise say the number.
<details><summary>Solution</summary>
```c
fn main() {
for n in 1..21 {
if n % 15 == 0 {
print("FizzBuzz")
} else if n % 3 == 0 {
print("Fizz")
} else if n % 5 == 0 {
print("Buzz")
} else {
print(n)
}
}
}
```
</details>
### Project 5: Biggest of three
Write a function `biggest(int a, int b, int c) -> int` that gives back the largest number.
<details><summary>Solution</summary>
```c
fn biggest(int a, int b, int c) -> int {
if a >= b && a >= c {
return a
}
if b >= c {
return b
}
return c
}
fn main() {
print(biggest(4, 9, 2)) // 9
}
```
</details>
---
## 13. Cheat sheet
```c
// a comment
fn main() { // the program starts here
print("text", 42) // show things
x := 5 // new box (type guessed)
int y = 10 // new box (type written)
x = 7 // change a box
x += 1 // add 1 to x
if x > 5 { // decide
print("big")
} else if x > 0 {
print("small")
} else {
print("zero or less")
}
for i in 0..10 { // count 0 to 9
print(i)
}
while x > 0 { // repeat while true
x -= 1
}
}
fn add(int a, int b) -> int { // your own command
return a + b
}
```
---
## 14. Words you will hear
| Word | Meaning |
|---|---|
| **program** | A list of steps for the computer |
| **code** | The text of a program |
| **run** | Make the computer do the steps |
| **compile** | Translate your code into something the computer can run. `finch run` does this for you |
| **variable** | A named box holding a value |
| **type** | The kind of value: number, text, yes/no… |
| **function** | A named group of steps you can use again |
| **loop** | Steps that repeat |
| **condition** | A yes/no question, like `x > 5` |
| **error** | A message saying something is wrong, and where |
| **bug** | A mistake in a program |
---
**What next?** When this all feels easy, move on to the
[guide for technicians](for-technicians.md). It covers every part of Finch.

1131
docs/en/for-engineers.md Normal file

File diff suppressed because it is too large Load diff

541
docs/en/for-technicians.md Normal file
View file

@ -0,0 +1,541 @@
# Finch for Technicians
**For people who know their way around a computer, but little or no programming.**
This guide covers installing Finch, using the `finch` tool, the whole language, using
C libraries, and fixing common problems. It does not cover how the compiler works inside.
For that, see the [guide for engineers](for-engineers.md).
> 🇵🇱 Polska wersja: [dla-technikow.md](../pl/dla-technikow.md)
---
## Contents
1. [What Finch is](#1-what-finch-is)
2. [Installing](#2-installing)
3. [The finch command](#3-the-finch-command)
4. [How a Finch file looks](#4-how-a-finch-file-looks)
5. [Variables](#5-variables)
6. [Types](#6-types)
7. [Operators](#7-operators)
8. [Control flow](#8-control-flow)
9. [Functions](#9-functions)
10. [Pointers](#10-pointers)
11. [Using C libraries](#11-using-c-libraries)
12. [Errors](#12-errors)
13. [Troubleshooting](#13-troubleshooting)
14. [Project layout and tests](#14-project-layout-and-tests)
15. [Current limits](#15-current-limits)
---
## 1. What Finch is
Finch is a **compiled** programming language. The `finch` tool translates your `.fn`
file into a real program (a native executable, like the ones made from C), using the
**LLVM** compiler toolkit, the same backend that powers clang, Rust and Swift.
What that gives you:
- **Speed close to C.** There is no interpreter, virtual machine or garbage collector.
- **Small, standalone programs** that you can copy and run.
- **Direct access to C libraries.** `import "stdio.h"` and call anything in it.
The design rules: one way to do each thing, C-like syntax without C's traps, and error
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**.
Other LLVM versions will likely fail to compile, because LLVM's C++ API changes between releases.
### Option A: Nix (recommended, nothing to install by hand)
```sh
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell # downloads LLVM, libclang, cmake, ninja, pkg-config
cmake -S . -B build -G Ninja
ninja -C build
./build/finch version # finch 1.0.0 (LLVM 21.x)
```
### Option B: your distribution's packages
You need: a C/C++ compiler, CMake ≥ 3.20, Ninja (or Make), LLVM 21 development files,
libclang 21 development files, and optionally `pkg-config`.
| Distribution | Packages (names can differ slightly by version) |
|---|---|
| Debian / Ubuntu | `build-essential cmake ninja-build pkg-config llvm-21-dev libclang-21-dev` |
| Fedora | `gcc-c++ cmake ninja-build pkgconf llvm-devel clang-devel` |
| Arch | `base-devel cmake ninja pkgconf llvm clang` |
If CMake cannot find LLVM, point it there:
```sh
cmake -S . -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-21/lib/cmake/llvm
ninja -C build
```
### Putting `finch` on your PATH (optional)
```sh
sudo cp build/finch /usr/local/bin/
finch version
```
Finch needs a working C compiler (`cc`) at run time. It uses it as the **linker** that
turns compiled code into a program. Set the `CC` environment variable to use a different one.
---
## 3. The finch command
```
finch run <file.fn> compile and run right away
finch build <file.fn> [-o name] compile into a program (default name: the file's name)
finch ir <file.fn> print the LLVM IR (for the curious)
finch version show the version
options:
-l <lib> link a C library, same as link "lib" in the file
-O0 skip optimizations
```
Examples:
```sh
finch run hello.fn # prints the output
finch build game.fn -o mygame # creates ./mygame
./mygame
finch run window.fn -l glfw # with a C library
```
`finch run` passes on your program's exit code. If the program crashes, it tells you
how (for example `the program crashed: Segmentation fault`).
---
## 4. How a Finch file looks
```c
// comments start with two slashes
/* or span
several lines */
import "math.h" // C headers (optional), always at the top
link "m" // C libraries to link (optional)
fn main() { // the program starts here
print("Hello")
}
```
Rules worth knowing:
- **One statement per line.** There are no semicolons. To split a long expression,
break the line **after** an operator (`a +⏎ b`) or anywhere inside brackets `( )`.
- **Curly braces are always required** after `if`, `else`, `for`, `while`, and the opening
`{` goes on the same line.
- **No brackets around conditions:** `if x > 5 {`, not `if (x > 5) {`.
- Functions can be in any order in the file.
- `main` is either `fn main()` or `fn main() -> int` (returns the exit code).
---
## 5. Variables
```c
x := 5 // new variable, type inferred (int)
int y = 10 // new variable, type written explicitly
int z // no value: starts at zero ("" for str, null for pointers)
x = 7 // assign
x += 1 // also -= *= /= %=
```
- A name can be declared **once** in a function. Finch does not allow reusing a name in an
inner block (no "shadowing"), because that is a common source of confusion.
- Variables exist from their declaration to the end of the `{ }` block they are in.
- Names: ASCII letters, digits and `_`, not starting with a digit. Non-ASCII letters are allowed only inside strings. Type names (`int`, `u8`, …) and
keywords are reserved.
**Keywords:** `fn return if else while for in break continue true false null import link`
---
## 6. Types
### Everyday types
| Type | Holds | Example |
|---------|-------|---------|
| `int` | whole number, 64-bit (same as `i64`) | `42`, `-7`, `0xFF`, `1_000_000` |
| `float` | decimal number, 64-bit (same as `f64`) | `3.14` |
| `bool` | `true` or `false` | |
| `char` | one byte-sized character | `'A'`, `'\n'` |
| `str` | text (a C string) | `"hello\tworld"` |
String and char escapes: `\n` new line, `\t` tab, `\r`, `\0`, `\\`, `\"`, `\'`.
### Sized types (for files, hardware, C libraries)
| Signed | Range | Unsigned | Range |
|---|---|---|---|
| `i8` | −128 … 127 | `u8` | 0 … 255 |
| `i16` | −32 768 … 32 767 | `u16` | 0 … 65 535 |
| `i32` | about ±2.1 billion | `u32` | 0 … about 4.29 billion |
| `i64` | about ±9.2 × 10¹⁸ | `u64` | 0 … about 1.8 × 10¹⁹ |
`f32` is a 32-bit decimal number (about 7 significant digits), `f64` a 64-bit one (about 15–16).
### Pointers
`ptr[T]` points to a value of type `T`. Plain `ptr` points to "something" with unknown
type, like `void*` in C. See [Pointers](#10-pointers).
### Conversions
Finch converts automatically **only when nothing can be lost**:
| From | To | Automatic? |
|---|---|---|
| a smaller whole number | a bigger one of the same signedness (`i8`→`i32`, `u8`→`u64`) | ✅ |
| unsigned | a strictly bigger signed (`u8`→`i16`, `u32`→`i64`) | ✅ |
| any whole number | `float` / `f32` | ✅ |
| `f32` | `f64` | ✅ |
| `null` | any pointer | ✅ |
| any pointer, `str` | `ptr` | ✅ |
| `ptr` | any `ptr[T]` | ✅ |
| anything else | | ❌ write it: `type(value)` |
**Number literals adapt.** A number written in the code fits into any type that can hold it:
`u8 b = 200` works, `u8 b = 300` is an error (`the number 300 doesn't fit in u8`).
The same applies to constants imported from C headers.
**Explicit conversions** use the type name like a function:
```c
int(3.99) // 3 (cuts off the fraction)
int(-3.99) // -3
float(7) / 2 // 3.5
u8(300) // 44 (keeps the lowest 8 bits)
i8(200) // -56
int('A') // 65
char(66) // 'B'
bool(0) // false (any non-zero number is true)
ptr(text) // a str as an untyped pointer
str(p) // a pointer as a str
```
**Fixed-size numbers wrap around**, like real hardware: a `u8` holding 255 plus 1 becomes 0.
Calculations happen in the type of the values involved, so `u8(250) + 10` is `4`, not `260`.
Convert first if you need more room: `int(x) + 10`.
---
## 7. Operators
### By priority (higher binds tighter)
| Priority | Operators | Meaning |
|---|---|---|
| 5 | `*` `/` `%` `<<` `>>` `&` | multiply, divide, remainder, shift left/right, bitwise AND |
| 4 | `+` `-` `\|` `^` | add, subtract, bitwise OR, bitwise XOR |
| 3 | `==` `!=` `<` `<=` `>` `>=` | comparisons |
| 2 | `&&` | logical AND |
| 1 | `\|\|` | logical OR |
Unary (in front of a value): `-x` negate, `!x` logical NOT, `~x` flip all bits.
> **Different from C, on purpose:** bit operators bind tighter than comparisons, so
> `flags & 4 != 0` means `(flags & 4) != 0`. In C it silently means something else.
Notes:
- `/` on whole numbers rounds toward zero: `7 / 2` is `3`, `-7 / 2` is `-3`. `%` takes the sign of the left side.
- Dividing by zero **stops the program** with `runtime error: division by zero` and the line number.
If the zero is written in the code, it is a compile error instead.
- `&&` and `||` only evaluate the right side if needed.
- Text (`str`) can be compared with `==` and `!=` (it compares the contents). `<` and `>` do not work on text.
- Pointers can be compared with `==` and `!=`, including against `null`.
- Bit operators need whole numbers. For `bool` use `&&` and `||`.
- `>>` on signed numbers keeps the sign (`-16 >> 2` is `-4`). On unsigned numbers it fills with zeros.
---
## 8. Control flow
```c
if x > 10 {
...
} else if x > 0 {
...
} else {
...
}
while count > 0 {
count -= 1
}
for i in 0..10 { // i = 0, 1, …, 9 (the end is not included)
if i == 3 { continue }
if i == 8 { break }
}
```
- A condition must be a `bool`. `if x {` with a number is an error; write `if x != 0 {`.
- In `for i in a..b`, both ends are whole numbers evaluated **once** before the loop starts.
`i` is an `int` and cannot be changed inside the loop.
- `while true { ... }` loops until a `break` or `return`.
- Code after `return`, `break` or `continue` in the same block is an error, because it can never run.
---
## 9. Functions
```c
fn name(type1 param1, type2 param2) -> return_type {
...
return value
}
fn no_result(str message) { // no "->": returns nothing
print(message)
}
```
- Parameters are copies. Changing a parameter does not change the caller's variable.
Use a pointer for that (see below).
- A function with `-> type` must return a value on every path. Finch checks this.
- A function cannot be defined inside another function.
- Built-in names you cannot reuse: `print`, `addr`, and all type names.
### Built-in functions
| Function | What it does |
|---|---|
| `print(a, b, ...)` | Prints all values separated by spaces, then a new line. Works with every type. |
| `addr(x)` | Gives a pointer to variable `x`. |
| `int(x)`, `u8(x)`, `float(x)`, … | Converts types (see [Conversions](#conversions)). |
---
## 10. Pointers
A pointer holds the **address** of a value: where it lives in memory. Finch uses words
instead of C's `*` and `&`:
| C | Finch | Meaning |
|---|---|---|
| `int *p` | `ptr[int] p` | p points to an int |
| `&x` | `addr(x)` | the address of x |
| `*p` | `p.value` | the value p points to |
| `NULL` | `null` | points nowhere |
| `void *` | `ptr` | points to something of unknown type |
```c
fn double(ptr[int] p) {
p.value = p.value * 2
}
fn main() {
x := 21
double(addr(x))
print(x) // 42
ptr[int] nothing = null
if nothing == null {
print("empty")
}
}
```
Pointers can point to pointers: `ptr[ptr[int]]`, then `pp.value.value`.
Using `.value` on a `null` pointer **stops the program** with
`runtime error: used .value on a null pointer` instead of crashing randomly.
⚠️ A pointer to a variable must not be used after the function that owns the variable
has returned. The variable no longer exists then. Finch does not check this yet.
---
## 11. Using C libraries
Almost every library on Linux has a C interface: graphics, sound, networking, databases.
Finch can use them directly.
### Step 1: import the header
```c
import "stdio.h"
import "math.h"
import "GLFW/glfw3.h" // a path inside the system include folders
import "mylib.h" // a header next to your .fn file
```
Finch reads the header with **libclang** (clang's C parser) and makes these usable:
- **functions**, including ones with a variable number of arguments, like `printf`,
- **`enum` values**,
- **simple `#define` constants** that are a single number, like `M_PI`, `EOF`, `GL_COLOR_BUFFER_BIT`,
- **global variables**, like `stdout` and `stderr`.
### Step 2: link the library
A header only *describes* functions. Their actual code is in a library file (`libNAME.so`).
Tell Finch which library to use, at the top of the file:
```c
link "glfw" // uses libglfw.so
link "GL" // uses libGL.so
```
Write just the name: for `libglfw.so` that is `glfw`. If `pkg-config` knows the name, Finch uses
its settings (paths and extra libraries). Otherwise it passes `-lNAME` to the linker.
The C standard library and the math library (`libm`) are always linked.
On the command line, `-l NAME` does the same as `link "NAME"`.
If you forget the `link` line, Finch tells you exactly what is missing:
```
error: glfwInit, glfwCreateWindow, glfwMakeContextCurrent and 5 more come from "GLFW/glfw3.h", but its library isn't linked
the header only says the functions exist; their code lives in a library.
add this at the top of your file (with the library's real name):
link "glfw"
```
### How C types appear in Finch
| C | Finch |
|---|---|
| `char`, `signed char`, `unsigned char` | `char`, `i8`, `u8` |
| `short`, `int`, `long`, `long long` | `i16`, `i32`, `i64`, `i64` (by actual size) |
| `unsigned …` | `u16`, `u32`, `u64` |
| `float`, `double` | `f32`, `f64` |
| `_Bool` / `bool` | `bool` |
| `enum` | the matching signed integer |
| `char *`, `const char *` | `str` |
| `int *`, `double *`, … | `ptr[i32]`, `ptr[f64]`, … |
| `void *`, `struct X *`, `FILE *`, function pointers | `ptr` |
So C's `int` is Finch's `i32`. Literals adapt automatically (`abs(-5)` works),
but a Finch `int` variable must be converted: `abs(i32(x))`.
### Example
```c
import "stdio.h"
import "math.h"
import "stdlib.h"
fn main() {
printf("%d + %d = %d\n", 2, 3, 5)
print(sqrt(2), M_PI, RAND_MAX)
ptr[i32] n = malloc(4) // ask C for 4 bytes of memory
n.value = 7
print(n.value)
free(n) // and give them back
fprintf(stderr, "this goes to the error output\n")
}
```
A complete graphics example is in `examples/window.fn`: a GLFW + OpenGL window that changes color.
`examples/llvm.fn` shows that Finch can even drive LLVM itself through its C API.
### What does not work yet
- C functions that take or return a **`struct` by value**, such as `div()`. Finch says so
clearly if you try. Functions taking a *pointer* to a struct are fine.
- **Function-like macros** (`#define MAX(a,b) ...`) and macros that are not a single number.
- `long double`, 128-bit integers.
- Reading the **fields** of a C struct.
---
## 12. Errors
### Compile errors
Finch stops at the first problem and shows where it is:
```
game.fn:12:9: error: 'score' must be int, but this is str
12 | score = "high"
| ^
```
Format: `file:line:column: error: explanation`, then the line with a `^` under the spot.
### Runtime errors
Some problems can only be seen while the program runs. Instead of undefined behavior
(as in C), Finch stops with a clear message on the error output and exit code 1:
| Message | Cause |
|---|---|
| `runtime error: division by zero` | `/` or `%` by a variable that was 0 |
| `runtime error: division overflows …` | the smallest signed number divided by −1 |
| `runtime error: used .value on a null pointer` | reading or writing `p.value` while `p` is `null` |
---
## 13. Troubleshooting
| Problem | Solution |
|---|---|
| `can't find the C header 'x.h'` | The library's development files are missing. Install them (on Debian: `libx-dev`; on Nix: add to `shell.nix`). For your own header, put it next to the `.fn` file. |
| `… come from "x.h", but its library isn't linked` | Add `link "name"` at the top of the file. |
| `the library 'x' wasn't found` | The library is not installed, or the name is wrong. On Nix, add it to `shell.nix` and run inside `nix-shell`. |
| `the C function 'f' can't be used from Finch yet` | It uses a struct by value, or another unsupported type. Look for a variant that takes pointers. |
| `no C compiler found to link with` | Install gcc or clang, or set `CC`. |
| The program runs, but a C library is not found at start | It was linked from a path the system does not search. Run it inside the same `nix-shell`, or install the library system-wide. |
| CMake: `libclang not found` | Install the libclang dev package, or run `cmake` inside `nix-shell`. |
| Build fails with LLVM API errors | You have a different LLVM version than 21. |
| A program never ends | A loop condition never becomes false. Press Ctrl+C. |
---
## 14. Project layout and tests
```
Finch/
├── src/ the compiler (C++)
├── examples/ example programs (hello, tour, types, c_import, window, llvm)
├── tests/
│ ├── run/ programs + the exact output they must print (.out)
│ ├── fail/ programs that must fail, with the expected error in line 1
│ └── run.sh the test runner
├── docs/ this documentation (en, pl)
├── shell.nix the Nix development environment
└── CMakeLists.txt
```
Run the tests after building:
```sh
tests/run.sh # → 34 passed, 0 failed
```
---
## 15. Current limits
Finch 1.0 is a solid core, not a finished language. Not there yet:
- `struct`, arrays, reading keyboard input (`input()`), string building (`"a" + "b"`).
For now, use C functions for these (`scanf`, `snprintf`, `malloc`…).
- Automatic memory management (planned: memory freed at the end of the block, plus `defer`).
- Finch modules (one program = one `.fn` file for now).
- Platforms other than Linux x86-64.
See the [roadmap in the README](../../README.md#roadmap).

1136
docs/pl/dla-inzynierow.md Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,670 @@
# Finch dla początkujących
**Ten przewodnik jest dla ciebie, jeśli jeszcze nigdy nie pisałeś programu.**
Nie potrzebujesz żadnego doświadczenia ani matematyki ponad to, czego uczy się w podstawówce.
Czytaj powoli, po jednym rozdziale, i przepisuj każdy przykład samodzielnie. Tak zostaje w głowie najlepiej.
> 🇬🇧 English version: [for-beginners.md](../en/for-beginners.md)
---
## Spis treści
1. [Co to jest program?](#1-co-to-jest-program)
2. [Przygotowanie Fincha](#2-przygotowanie-fincha)
3. [Twój pierwszy program](#3-twój-pierwszy-program)
4. [Wypisywanie na ekran](#4-wypisywanie-na-ekran)
5. [Pudełka z nazwami: zmienne](#5-pudełka-z-nazwami-zmienne)
6. [Rodzaje wartości](#6-rodzaje-wartości)
7. [Liczenie](#7-liczenie)
8. [Podejmowanie decyzji: if](#8-podejmowanie-decyzji-if)
9. [Powtarzanie: pętle](#9-powtarzanie-pętle)
10. [Własne polecenia: funkcje](#10-własne-polecenia-funkcje)
11. [Kiedy coś pójdzie nie tak](#11-kiedy-coś-pójdzie-nie-tak)
12. [Małe projekty do zrobienia](#12-małe-projekty-do-zrobienia)
13. [Ściąga](#13-ściąga)
14. [Słowniczek](#14-słowniczek)
---
## 1. Co to jest program?
Komputer jest bardzo szybki, ale nie myśli. Robi dokładnie to, co mu się każe,
krok po kroku.
**Program** to spisana lista takich kroków. Trochę jak przepis kuchenny:
> 1. Weź dwa jajka.
> 2. Wbij je do miski.
> 3. Wymieszaj.
**Język programowania** to sposób zapisania takiego przepisu, który komputer rozumie.
**Finch** (po polsku: zięba) jest jednym z takich języków. Zrobiono go tak, żeby był
mały i prosty, więc nauczysz się go szybko.
Komputer czyta program od góry do dołu, linijka po linijce.
---
## 2. Przygotowanie Fincha
Finch działa na komputerach z **Linuksem**. Jeśli nauczyciel, rodzic albo znajomy już go
dla ciebie zainstalował, przejdź od razu do następnego rozdziału.
W przeciwnym razie otwórz program **Terminal** (okienko, w którym wpisuje się polecenia)
i wpisz te linijki po kolei, naciskając **Enter** po każdej:
```sh
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell
cmake -S . -B build -G Ninja
ninja -C build
```
Jeśli ostatnia linijka skończy się bez słowa `error`, Finch jest gotowy.
(Jeśli komputer nie zna polecenia `nix-shell`, poproś kogoś o skorzystanie z
[przewodnika dla techników](dla-technikow.md#2-instalacja), gdzie opisano inny sposób.)
Żeby sprawdzić, czy działa, wpisz:
```sh
./build/finch version
```
Powinieneś zobaczyć coś w stylu `finch 1.0.0`.
---
## 3. Twój pierwszy program
1. Otwórz dowolny edytor tekstu (na przykład *Edytor tekstu*, *Kate*, *gedit* albo *VS Code*).
2. Wpisz dokładnie to:
```c
fn main() {
print("Cześć!")
}
```
3. Zapisz plik w folderze `Finch` pod nazwą **`czesc.fn`**. Końcówka `.fn` mówi, że to program w Finchu.
4. W Terminalu wpisz:
```sh
./build/finch run czesc.fn
```
Zobaczysz:
```
Cześć!
```
🎉 **Właśnie napisałeś i uruchomiłeś program.**
### Co właściwie napisaliśmy?
```text
fn main() { ← „tu zaczyna się główna część mojego programu”
print("Cześć!") ← „pokaż na ekranie tekst Cześć!”
} ← „tu główna część się kończy”
```
- `fn main()` to miejsce, od którego **zaczyna się** każdy program w Finchu. Każdy program ma dokładnie jedno `main`.
- Nawiasy klamrowe `{` i `}` obejmują wszystko, co należy do `main`, jak dwie okładki książki.
- `print(...)` pokazuje coś na ekranie.
- Tekst zawsze piszemy w cudzysłowie: `"Cześć!"`.
Spacje przed `print` nie są obowiązkowe, ale dzięki nim od razu widać, co jest w środku
klamer. Zawsze je dodawaj, to dobry nawyk.
---
## 4. Wypisywanie na ekran
`print` umie pokazać tekst i liczby. Między kolejne rzeczy wstaw przecinek, a Finch sam doda spację:
```c
fn main() {
print("Mam", 10, "lat")
print("2 + 2 =", 2 + 2)
print()
print("Linijka wyżej jest pusta")
}
```
Pokaże:
```
Mam 10 lat
2 + 2 = 4
Linijka wyżej jest pusta
```
Każdy `print` zaczyna nową linijkę. `print()` bez niczego w środku robi pustą linijkę.
### Notatki dla siebie: komentarze
Wszystko po `//` komputer pomija. Możesz tam zostawiać sobie notatki:
```c
// Ten program się wita
fn main() {
print("Cześć") // to pokazuje Cześć
}
```
---
## 5. Pudełka z nazwami: zmienne
Wyobraź sobie pudełko z naklejoną etykietą. Możesz coś do niego włożyć, a potem sprawdzić,
co jest w środku, czytając etykietę. W programowaniu takie pudełko nazywa się **zmienną**.
```c
fn main() {
wiek := 10
print(wiek)
}
```
`wiek := 10` znaczy: *„zrób nowe pudełko, nazwij je `wiek` i włóż do niego 10”*.
Później możesz zmienić zawartość pudełka, używając samego `=`:
```c
fn main() {
punkty := 0
print("Punkty:", punkty)
punkty = 5
print("Punkty:", punkty)
punkty = punkty + 1
print("Punkty:", punkty)
}
```
```
Punkty: 0
Punkty: 5
Punkty: 6
```
`punkty = punkty + 1` czytamy tak: *„weź to, co jest w `punkty`, dodaj 1 i włóż wynik z powrotem do `punkty`”*.
To samo można zapisać krócej: `punkty += 1`.
**Zapamiętaj:**
- `:=` robi **nowe** pudełko. Używasz tego tylko raz dla danej nazwy.
- `=` wkłada nową wartość do pudełka, **które już istnieje**.
### Nazywanie pudełek
Nazwy mogą zawierać angielskie litery `a`–`z` i `A`–`Z`, cyfry i znak `_`, ale nie mogą zaczynać się od cyfry:
`wiek`, `suma_punktow`, `gracz2` są w porządku. `2gracz` już nie.
⚠️ **Bez polskich liter w nazwach!** `ą`, `ę`, `ł`, `ż` i inne mogą być tylko w tekście w cudzysłowie.
Pisz `zolw`, a nie `żółw`. Natomiast `print("Żółw")` działa bez problemu.
Wybieraj nazwy, które mówią, co jest w środku: `cena` jest lepsza niż `c`.
---
## 6. Rodzaje wartości
Finch pilnuje, *jakiego rodzaju* rzecz jest w każdym pudełku. Ten rodzaj nazywa się **typem**.
Najczęściej będziesz używać tych:
| Typ | Co przechowuje | Przykłady |
|---------|---------------------------|--------------------------|
| `int` | liczby całkowite | `0`, `42`, `-7` |
| `float` | liczby z przecinkiem | `3.14`, `0.5`, `-2.0` |
| `str` | tekst | `"Cześć"`, `"Ola"` |
| `bool` | tak albo nie | `true` (prawda), `false` (fałsz) |
| `char` | jeden znak | `'A'`, `'z'`, `'?'` |
⚠️ W liczbach zamiast przecinka piszemy **kropkę**: `3.14`, a nie `3,14`. Tak jest w prawie wszystkich językach programowania.
Kiedy używasz `:=`, Finch sam rozpoznaje typ:
```c
imie := "Ola" // str
wiek := 10 // int
wzrost := 1.42 // float
lubi_koty := true // bool
```
Typ możesz też napisać sam, przed nazwą:
```c
int wiek = 10
str imie = "Ola"
```
Oba sposoby robią to samo. Wybierz ten, który ci bardziej pasuje.
**Pudełko nie zmienia typu.** Jeśli w `wiek` są liczby całkowite, nie włożysz tam potem tekstu.
Finch zatrzyma się i powie o tym, co pomaga wcześnie wyłapywać pomyłki.
---
## 7. Liczenie
| Znak | Co robi | Przykład | Wynik |
|------|-----------------------------|----------|-------|
| `+` | dodawanie | `7 + 2` | `9` |
| `-` | odejmowanie | `7 - 2` | `5` |
| `*` | mnożenie | `7 * 2` | `14` |
| `/` | dzielenie | `7 / 2` | `3` |
| `%` | reszta z dzielenia | `7 % 2` | `1` |
**Uwaga na dzielenie liczb całkowitych:** `7 / 2` daje `3`, a nie `3.5`. Obie liczby są
całkowite, więc wynik też jest całkowity (część po kropce jest odrzucana).
Jeśli chcesz dostać `3.5`, użyj liczby z kropką: `7.0 / 2`.
Mnożenie i dzielenie wykonują się przed dodawaniem i odejmowaniem, tak jak w szkole.
Nawiasy zmieniają kolejność:
```c
print(2 + 3 * 4) // 14
print((2 + 3) * 4) // 20
```
`%` przydaje się do sprawdzania, czy liczba jest parzysta. Liczba parzysta dzielona przez 2
nie daje reszty, więc `n % 2` wynosi `0`.
**Nie wolno dzielić przez zero.** Jeśli program spróbuje, zatrzyma się i powie, w której linijce to się stało.
---
## 8. Podejmowanie decyzji: if
Program może wybierać, co zrobić. `if` (czyt. „if”, po polsku „jeżeli”) znaczy *„zrób to tylko wtedy, gdy coś jest prawdą”*.
```c
fn main() {
temperatura := 25
if temperatura > 20 {
print("Jest ciepło, załóż koszulkę")
}
}
```
Dodaj `else` („w przeciwnym razie”):
```c
if temperatura > 20 {
print("Jest ciepło")
} else {
print("Weź kurtkę")
}
```
A `else if` dodaje kolejne możliwości. Finch sprawdza je od góry i wykonuje tylko
**pierwszą** prawdziwą:
```c
if temperatura > 25 {
print("Gorąco!")
} else if temperatura > 15 {
print("Przyjemnie")
} else {
print("Zimno")
}
```
### Porównywanie
| Znak | Znaczy |
|------|------------------------------|
| `==` | jest równe |
| `!=` | nie jest równe |
| `<` | jest mniejsze niż |
| `>` | jest większe niż |
| `<=` | jest mniejsze lub równe |
| `>=` | jest większe lub równe |
⚠️ **Jedno `=` wkłada wartość do pudełka. Dwa `==` pytają „czy to jest równe?”.**
Tekst też można porównywać: `if imie == "Ola" { ... }`.
### Łączenie pytań
- `&&` znaczy **i**: oba warunki muszą być prawdziwe. `if wiek > 6 && wiek < 12 { ... }`
- `||` znaczy **lub**: wystarczy, że jeden jest prawdziwy. `if dzien == "sob" || dzien == "nd" { ... }`
- `!` znaczy **nie**: odwraca prawdę i fałsz. `if !pada { ... }`
---
## 9. Powtarzanie: pętle
Komputer nigdy się nie nudzi. **Pętla** powtarza te same kroki wiele razy.
### Liczenie z `for`
```c
fn main() {
for i in 1..6 {
print("Liczba", i)
}
}
```
```
Liczba 1
Liczba 2
Liczba 3
Liczba 4
Liczba 5
```
`for i in 1..6` znaczy: *„licz za pomocą `i` od 1 do 6, ale **bez** 6”*.
Czyli `0..10` daje dziesięć liczb: 0, 1, 2 … 9.
### Powtarzanie, dopóki coś jest prawdą: `while`
```c
fn main() {
licznik := 3
while licznik > 0 {
print(licznik)
licznik -= 1
}
print("Start!")
}
```
```
3
2
1
Start!
```
⚠️ Upewnij się, że pętla może się skończyć. Gdyby `licznik` nigdy nie malał, pętla kręciłaby się
w nieskończoność. Jeśli tak się stanie, naciśnij w Terminalu **Ctrl + C**, żeby ją zatrzymać.
### Wcześniejsze wyjście i pomijanie
- `break` od razu wychodzi z pętli.
- `continue` pomija resztę bieżącego okrążenia i przechodzi do następnego.
```c
for i in 1..100 {
if i == 5 {
break // stop, gdy dojdziemy do 5
}
print(i) // pokaże 1 2 3 4
}
```
---
## 10. Własne polecenia: funkcje
Kiedy robisz to samo w wielu miejscach, nadaj temu nazwę. Taki nazwany kawałek kodu to **funkcja**.
Jedną już znasz: `main`.
```c
fn przywitaj(str imie) {
print("Cześć,", imie)
}
fn main() {
przywitaj("Ola")
przywitaj("Tomek")
}
```
```
Cześć, Ola
Cześć, Tomek
```
`str imie` w nawiasie znaczy: *„ta funkcja potrzebuje jednego tekstu, a w środku nazywamy go `imie`”*.
To, co wpiszesz w nawias przy wywołaniu, zostanie przekazane do środka.
### Funkcje, które oddają odpowiedź
Napisz `->` i typ odpowiedzi, a odpowiedź oddaj słowem `return`:
```c
fn dodaj(int a, int b) -> int {
return a + b
}
fn main() {
wynik := dodaj(2, 3)
print(wynik) // 5
}
```
Nie ma znaczenia, gdzie w pliku umieścisz swoje funkcje, nad czy pod `main`.
---
## 11. Kiedy coś pójdzie nie tak
Każdy się myli przy programowaniu, nawet eksperci, codziennie.
Finch stara się tłumaczyć, co poszło nie tak, prostymi słowami (na razie po angielsku). Przykład:
```c
fn main() {
wiek := 10
print(wiekk)
}
```
```
czesc.fn:3:11: error: there is no variable named 'wiekk'
3 | print(wiekk)
| ^
```
Jak to czytać:
- `czesc.fn` to plik,
- `3` to numer **linijki**,
- `11` to który znak w linijce (**kolumna**),
- potem wyjaśnienie, a pod nim ta linijka ze strzałką `^` wskazującą problem.
Tutaj po prostu źle napisaliśmy `wiek`. Komunikat znaczy: „nie ma zmiennej o nazwie 'wiekk'”.
### Częste błędy
| Finch mówi | Co to znaczy | Jak naprawić |
|---|---|---|
| `there is no variable named 'x'` | Nie ma zmiennej `x`: literówka albo zapomniałeś ją zrobić | Sprawdź pisownię. Utwórz ją przez `x := ...` |
| `a variable named 'x' already exists here` | Użyłeś `:=` dwa razy dla tej samej nazwy | Za drugim razem użyj `=` |
| `'x' must be int, but this is str` | Zły rodzaj wartości dla tego pudełka | Włóż wartość właściwego rodzaju |
| `put each statement on its own line` | Dwa polecenia w jednej linijce | Wciśnij Enter między nimi |
| `this '{' is never closed` | Brakuje `}` | Dopisz `}` |
| `a condition must be bool` | `if` potrzebuje pytania tak/nie | Porównaj coś: `if x > 0` |
| `unexpected character 'ż'` | Polska litera w nazwie | Zmień na zwykłą literę: `zolw` |
| `runtime error: division by zero` | Program podzielił przez 0 w trakcie działania | Sprawdź liczbę przed dzieleniem |
---
## 12. Małe projekty do zrobienia
Spróbuj najpierw napisać każdy sam. Do rozwiązania zajrzyj dopiero, gdy utkniesz.
### Projekt 1: Tabliczka mnożenia
Pokaż tabliczkę mnożenia przez 7, od 7 × 1 do 7 × 10.
<details><summary>Rozwiązanie</summary>
```c
fn main() {
for i in 1..11 {
print("7 x", i, "=", 7 * i)
}
}
```
</details>
### Projekt 2: Parzysta czy nieparzysta
Dla każdej liczby od 1 do 10 napisz, czy jest parzysta, czy nieparzysta.
<details><summary>Rozwiązanie</summary>
```c
fn main() {
for n in 1..11 {
if n % 2 == 0 {
print(n, "jest parzysta")
} else {
print(n, "jest nieparzysta")
}
}
}
```
</details>
### Projekt 3: Stopnie Celsjusza na Fahrenheita
Pokaż tabelkę od 0 °C do 100 °C co 10 stopni. Wzór: `F = C * 9 / 5 + 32`.
<details><summary>Rozwiązanie</summary>
```c
fn na_fahrenheita(float c) -> float {
return c * 9 / 5 + 32
}
fn main() {
for c in 0..11 {
celsjusz := float(c * 10)
print(celsjusz, "C =", na_fahrenheita(celsjusz), "F")
}
}
```
`float(...)` zamienia liczbę całkowitą na liczbę z przecinkiem.
</details>
### Projekt 4: Fizz Buzz
Policz od 1 do 20. Dla liczb podzielnych przez 3 napisz `Fizz`, przez 5 napisz `Buzz`,
przez obie naraz napisz `FizzBuzz`, a w pozostałych przypadkach samą liczbę.
<details><summary>Rozwiązanie</summary>
```c
fn main() {
for n in 1..21 {
if n % 15 == 0 {
print("FizzBuzz")
} else if n % 3 == 0 {
print("Fizz")
} else if n % 5 == 0 {
print("Buzz")
} else {
print(n)
}
}
}
```
</details>
### Projekt 5: Największa z trzech
Napisz funkcję `najwieksza(int a, int b, int c) -> int`, która oddaje największą z trzech liczb.
<details><summary>Rozwiązanie</summary>
```c
fn najwieksza(int a, int b, int c) -> int {
if a >= b && a >= c {
return a
}
if b >= c {
return b
}
return c
}
fn main() {
print(najwieksza(4, 9, 2)) // 9
}
```
</details>
---
## 13. Ściąga
```c
// komentarz
fn main() { // tu zaczyna się program
print("tekst", 42) // pokaż coś
x := 5 // nowe pudełko (typ zgadnięty)
int y = 10 // nowe pudełko (typ podany)
x = 7 // zmień zawartość
x += 1 // dodaj 1 do x
if x > 5 { // decyzja
print("duże")
} else if x > 0 {
print("małe")
} else {
print("zero albo mniej")
}
for i in 0..10 { // licz od 0 do 9
print(i)
}
while x > 0 { // powtarzaj, dopóki prawda
x -= 1
}
}
fn dodaj(int a, int b) -> int { // własne polecenie
return a + b
}
```
---
## 14. Słowniczek
| Słowo | Znaczenie |
|---|---|
| **program** | Lista kroków dla komputera |
| **kod** | Tekst programu |
| **uruchomić** | Kazać komputerowi wykonać kroki |
| **kompilować** | Przetłumaczyć kod na coś, co komputer umie uruchomić. `finch run` robi to za ciebie |
| **zmienna** | Pudełko z nazwą, w którym jest wartość |
| **typ** | Rodzaj wartości: liczba, tekst, tak/nie… |
| **funkcja** | Nazwana grupa kroków, której można używać wiele razy |
| **pętla** | Kroki, które się powtarzają |
| **warunek** | Pytanie tak/nie, np. `x > 5` |
| **błąd** (error) | Komunikat, że coś jest nie tak, i gdzie |
| **bug** | Pomyłka w programie |
### Słówka po angielsku, które spotkasz w Finchu
| Słowo | Po polsku |
|---|---|
| `print` | wypisz |
| `if` / `else` | jeżeli / w przeciwnym razie |
| `for` … `in` | dla … w |
| `while` | dopóki |
| `break` / `continue` | przerwij / kontynuuj |
| `return` | zwróć (oddaj) |
| `true` / `false` | prawda / fałsz |
| `fn` (od *function*) | funkcja |
| `error` | błąd |
---
**Co dalej?** Kiedy to wszystko wyda ci się łatwe, przejdź do
[przewodnika dla techników](dla-technikow.md). Opisuje każdą część Fincha.

542
docs/pl/dla-technikow.md Normal file
View file

@ -0,0 +1,542 @@
# Finch dla techników
**Dla osób, które dobrze znają komputery, ale programować nie umieją albo umieją niewiele.**
Ten przewodnik opisuje instalację Fincha, obsługę polecenia `finch`, cały język,
korzystanie z bibliotek C i rozwiązywanie typowych problemów. Nie opisuje, jak kompilator
działa w środku. Do tego służy [przewodnik dla inżynierów](dla-inzynierow.md).
> 🇬🇧 English version: [for-technicians.md](../en/for-technicians.md)
---
## Spis treści
1. [Czym jest Finch](#1-czym-jest-finch)
2. [Instalacja](#2-instalacja)
3. [Polecenie finch](#3-polecenie-finch)
4. [Jak wygląda plik Fincha](#4-jak-wygląda-plik-fincha)
5. [Zmienne](#5-zmienne)
6. [Typy](#6-typy)
7. [Operatory](#7-operatory)
8. [Sterowanie przebiegiem](#8-sterowanie-przebiegiem)
9. [Funkcje](#9-funkcje)
10. [Wskaźniki](#10-wskaźniki)
11. [Biblioteki z C](#11-biblioteki-z-c)
12. [Błędy](#12-błędy)
13. [Rozwiązywanie problemów](#13-rozwiązywanie-problemów)
14. [Struktura projektu i testy](#14-struktura-projektu-i-testy)
15. [Obecne ograniczenia](#15-obecne-ograniczenia)
---
## 1. Czym jest Finch
Finch to język **kompilowany**. Narzędzie `finch` tłumaczy plik `.fn` na prawdziwy program
(natywny plik wykonywalny, taki sam jak te z C). Korzysta przy tym z **LLVM**, tego samego
zaplecza kompilatorów, na którym działają clang, Rust i Swift.
Co to daje:
- **Szybkość zbliżoną do C.** Nie ma interpretera, maszyny wirtualnej ani garbage collectora.
- **Małe, samodzielne programy**, które można skopiować i uruchomić.
- **Bezpośredni dostęp do bibliotek C.** Piszesz `import "stdio.h"` i wołasz, co chcesz.
Zasady projektu: jeden sposób na każdą rzecz, składnia podobna do C bez jej pułapek
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.
### Opcja A: Nix (zalecana, nic nie instalujesz ręcznie)
```sh
git clone https://github.com/Nexoniarz/Finch.git
cd Finch
nix-shell # pobiera LLVM, libclang, cmake, ninja, pkg-config
cmake -S . -B build -G Ninja
ninja -C build
./build/finch version # finch 1.0.0 (LLVM 21.x)
```
### Opcja B: pakiety z twojej dystrybucji
Potrzebujesz: kompilatora C/C++, CMake ≥ 3.20, Ninja (albo Make), plików deweloperskich LLVM 21
i libclang 21, a opcjonalnie `pkg-config`.
| Dystrybucja | Pakiety (nazwy mogą się nieco różnić zależnie od wersji) |
|---|---|
| Debian / Ubuntu | `build-essential cmake ninja-build pkg-config llvm-21-dev libclang-21-dev` |
| Fedora | `gcc-c++ cmake ninja-build pkgconf llvm-devel clang-devel` |
| Arch | `base-devel cmake ninja pkgconf llvm clang` |
Jeśli CMake nie znajduje LLVM, wskaż mu katalog:
```sh
cmake -S . -B build -G Ninja -DLLVM_DIR=/usr/lib/llvm-21/lib/cmake/llvm
ninja -C build
```
### Dodanie `finch` do PATH (opcjonalnie)
```sh
sudo cp build/finch /usr/local/bin/
finch version
```
Podczas pracy Finch potrzebuje działającego kompilatora C (`cc`). Używa go jako **linkera**,
który skleja skompilowany kod w gotowy program. Inny kompilator wskażesz zmienną środowiskową `CC`.
---
## 3. Polecenie finch
```
finch run <plik.fn> skompiluj i od razu uruchom
finch build <plik.fn> [-o nazwa] skompiluj do programu (domyślna nazwa: nazwa pliku)
finch ir <plik.fn> pokaż LLVM IR (dla ciekawskich)
finch version pokaż wersję
opcje:
-l <lib> dolinkuj bibliotekę C, to samo co link "lib" w pliku
-O0 bez optymalizacji
```
Przykłady:
```sh
finch run hello.fn # wypisuje wynik
finch build gra.fn -o mojagra # tworzy ./mojagra
./mojagra
finch run okno.fn -l glfw # z biblioteką C
```
`finch run` przekazuje dalej kod wyjścia twojego programu. Jeśli program się wysypie,
powie jak (np. `the program crashed: Segmentation fault`).
---
## 4. Jak wygląda plik Fincha
```c
// komentarz zaczyna się od dwóch ukośników
/* albo zajmuje
kilka linijek */
import "math.h" // nagłówki C (opcjonalne), zawsze na górze
link "m" // biblioteki C do dolinkowania (opcjonalne)
fn main() { // tu zaczyna się program
print("Cześć")
}
```
Zasady, które warto znać:
- **Jedna instrukcja na linijkę.** Średników nie ma. Długie wyrażenie możesz złamać
**po** operatorze (`a +⏎ b`) albo w dowolnym miejscu wewnątrz nawiasów `( )`.
- **Klamry są zawsze obowiązkowe** po `if`, `else`, `for`, `while`, a otwierająca `{` stoi w tej samej linijce.
- **Bez nawiasów wokół warunków:** `if x > 5 {`, a nie `if (x > 5) {`.
- Funkcje mogą być w pliku w dowolnej kolejności.
- `main` to `fn main()` albo `fn main() -> int` (zwraca kod wyjścia).
---
## 5. Zmienne
```c
x := 5 // nowa zmienna, typ zgadnięty (int)
int y = 10 // nowa zmienna, typ podany jawnie
int z // bez wartości: startuje od zera ("" dla str, null dla wskaźników)
x = 7 // przypisanie
x += 1 // także -= *= /= %=
```
- Nazwę można zadeklarować **raz** w funkcji. Finch nie pozwala użyć tej samej nazwy ponownie
w bloku wewnętrznym (nie ma „przesłaniania”), bo to częste źródło pomyłek.
- Zmienna istnieje od deklaracji do końca bloku `{ }`, w którym powstała.
- Nazwy: litery ASCII, cyfry i `_`, bez cyfry na początku. Polskie litery tylko w tekstach w cudzysłowie.
Nazwy typów (`int`, `u8`, …) i słowa kluczowe są zarezerwowane.
**Słowa kluczowe:** `fn return if else while for in break continue true false null import link`
---
## 6. Typy
### Typy na co dzień
| Typ | Przechowuje | Przykład |
|---------|-------------|----------|
| `int` | liczba całkowita, 64-bitowa (to samo co `i64`) | `42`, `-7`, `0xFF`, `1_000_000` |
| `float` | liczba z przecinkiem, 64-bitowa (to samo co `f64`) | `3.14` |
| `bool` | `true` albo `false` | |
| `char` | jeden znak wielkości bajtu | `'A'`, `'\n'` |
| `str` | tekst (napis w stylu C) | `"cześć\tświecie"` |
Znaki specjalne w tekstach: `\n` nowa linia, `\t` tabulator, `\r`, `\0`, `\\`, `\"`, `\'`.
### Typy z rozmiarem (do plików, sprzętu, bibliotek C)
| Ze znakiem | Zakres | Bez znaku | Zakres |
|---|---|---|---|
| `i8` | −128 … 127 | `u8` | 0 … 255 |
| `i16` | −32 768 … 32 767 | `u16` | 0 … 65 535 |
| `i32` | ok. ±2,1 mld | `u32` | 0 … ok. 4,29 mld |
| `i64` | ok. ±9,2 × 10¹⁸ | `u64` | 0 … ok. 1,8 × 10¹⁹ |
`f32` to 32-bitowa liczba z przecinkiem (ok. 7 cyfr znaczących), `f64` to 64-bitowa (ok. 15–16).
### Wskaźniki
`ptr[T]` wskazuje na wartość typu `T`. Samo `ptr` wskazuje na „coś” nieznanego typu,
jak `void*` w C. Szczegóły w rozdziale [Wskaźniki](#10-wskaźniki).
### Zamiana typów
Finch zamienia typy sam **tylko wtedy, gdy nic nie może zginąć**:
| Z | Na | Automatycznie? |
|---|---|---|
| mniejsza liczba całkowita | większa o tej samej „znakowości” (`i8`→`i32`, `u8`→`u64`) | ✅ |
| bez znaku | ściśle większa ze znakiem (`u8`→`i16`, `u32`→`i64`) | ✅ |
| dowolna liczba całkowita | `float` / `f32` | ✅ |
| `f32` | `f64` | ✅ |
| `null` | dowolny wskaźnik | ✅ |
| dowolny wskaźnik, `str` | `ptr` | ✅ |
| `ptr` | dowolny `ptr[T]` | ✅ |
| wszystko inne | | ❌ napisz to jawnie: `typ(wartość)` |
**Liczby wpisane w kod się dopasowują.** Liczba napisana wprost w kodzie pasuje do każdego typu,
który ją pomieści: `u8 b = 200` działa, a `u8 b = 300` to błąd (`the number 300 doesn't fit in u8`).
To samo dotyczy stałych z nagłówków C.
**Jawna zamiana** wygląda jak wywołanie funkcji o nazwie typu:
```c
int(3.99) // 3 (obcina część ułamkową)
int(-3.99) // -3
float(7) / 2 // 3.5
u8(300) // 44 (zostawia najniższe 8 bitów)
i8(200) // -56
int('A') // 65
char(66) // 'B'
bool(0) // false (każda liczba różna od zera to true)
ptr(tekst) // str jako wskaźnik bez typu
str(p) // wskaźnik jako str
```
**Liczby o stałym rozmiarze się „zawijają”**, jak w prawdziwym sprzęcie: `u8` równe 255 plus 1 daje 0.
Działania liczą się w typie użytych wartości, więc `u8(250) + 10` daje `4`, a nie `260`.
Jeśli potrzebujesz więcej miejsca, najpierw zamień typ: `int(x) + 10`.
---
## 7. Operatory
### Według priorytetu (wyższy wiąże mocniej)
| Priorytet | Operatory | Znaczenie |
|---|---|---|
| 5 | `*` `/` `%` `<<` `>>` `&` | mnożenie, dzielenie, reszta, przesunięcie bitów w lewo/prawo, bitowe AND |
| 4 | `+` `-` `\|` `^` | dodawanie, odejmowanie, bitowe OR, bitowe XOR |
| 3 | `==` `!=` `<` `<=` `>` `>=` | porównania |
| 2 | `&&` | logiczne I |
| 1 | `\|\|` | logiczne LUB |
Jednoargumentowe (przed wartością): `-x` zmiana znaku, `!x` logiczne NIE, `~x` odwrócenie wszystkich bitów.
> **Celowo inaczej niż w C:** operatory bitowe wiążą mocniej niż porównania, więc
> `flagi & 4 != 0` znaczy `(flagi & 4) != 0`. W C to samo po cichu znaczy co innego.
Uwagi:
- `/` na liczbach całkowitych zaokrągla w stronę zera: `7 / 2` to `3`, `-7 / 2` to `-3`. `%` ma znak lewej strony.
- Dzielenie przez zero **zatrzymuje program** komunikatem `runtime error: division by zero` z numerem linijki.
Jeśli zero jest wpisane wprost w kod, jest to błąd już przy kompilacji.
- `&&` i `||` liczą prawą stronę tylko wtedy, gdy to potrzebne.
- Tekst (`str`) można porównywać przez `==` i `!=` (porównuje zawartość). `<` i `>` na tekstach nie działają.
- Wskaźniki porównuje się przez `==` i `!=`, także z `null`.
- Operatory bitowe wymagają liczb całkowitych. Dla `bool` używaj `&&` i `||`.
- `>>` na liczbach ze znakiem zachowuje znak (`-16 >> 2` to `-4`). Na liczbach bez znaku wypełnia zerami.
---
## 8. Sterowanie przebiegiem
```c
if x > 10 {
...
} else if x > 0 {
...
} else {
...
}
while licznik > 0 {
licznik -= 1
}
for i in 0..10 { // i = 0, 1, …, 9 (koniec nie jest wliczany)
if i == 3 { continue }
if i == 8 { break }
}
```
- Warunek musi być typu `bool`. `if x {` z liczbą to błąd; napisz `if x != 0 {`.
- W `for i in a..b` oba końce są liczbami całkowitymi obliczanymi **raz**, przed startem pętli.
`i` jest typu `int` i nie można go zmieniać wewnątrz pętli.
- `while true { ... }` kręci się do `break` albo `return`.
- Kod po `return`, `break` lub `continue` w tym samym bloku to błąd, bo nigdy się nie wykona.
---
## 9. Funkcje
```c
fn nazwa(typ1 param1, typ2 param2) -> typ_wyniku {
...
return wartosc
}
fn bez_wyniku(str wiadomosc) { // bez "->": nic nie zwraca
print(wiadomosc)
}
```
- Parametry są kopiami. Zmiana parametru nie zmienia zmiennej u wywołującego.
Do tego służą wskaźniki (niżej).
- Funkcja z `-> typ` musi zwrócić wartość na każdej ścieżce. Finch to sprawdza.
- Funkcji nie można definiować wewnątrz innej funkcji.
- Wbudowane nazwy, których nie możesz użyć: `print`, `addr` i wszystkie nazwy typów.
### Funkcje wbudowane
| Funkcja | Co robi |
|---|---|
| `print(a, b, ...)` | Wypisuje wszystkie wartości oddzielone spacjami i przechodzi do nowej linii. Działa z każdym typem. |
| `addr(x)` | Daje wskaźnik na zmienną `x`. |
| `int(x)`, `u8(x)`, `float(x)`, … | Zamienia typy (zobacz [Zamiana typów](#zamiana-typów)). |
---
## 10. Wskaźniki
Wskaźnik przechowuje **adres** wartości, czyli miejsce w pamięci, gdzie ona leży. Finch zamiast
`*` i `&` z C używa słów:
| C | Finch | Znaczenie |
|---|---|---|
| `int *p` | `ptr[int] p` | p wskazuje na int |
| `&x` | `addr(x)` | adres x |
| `*p` | `p.value` | wartość, na którą wskazuje p |
| `NULL` | `null` | wskazuje donikąd |
| `void *` | `ptr` | wskazuje na coś nieznanego typu |
```c
fn podwoj(ptr[int] p) {
p.value = p.value * 2
}
fn main() {
x := 21
podwoj(addr(x))
print(x) // 42
ptr[int] nic = null
if nic == null {
print("pusty")
}
}
```
Wskaźnik może wskazywać na wskaźnik: `ptr[ptr[int]]`, a potem `pp.value.value`.
Użycie `.value` na wskaźniku `null` **zatrzymuje program** komunikatem
`runtime error: used .value on a null pointer`, zamiast losowo go wysypać.
⚠️ Wskaźnika na zmienną nie wolno używać po zakończeniu funkcji, do której ta zmienna należała,
bo zmienna wtedy już nie istnieje. Finch jeszcze tego nie sprawdza.
---
## 11. Biblioteki z C
Prawie każda biblioteka na Linuksie ma interfejs w C: grafika, dźwięk, sieć, bazy danych.
Finch może z nich korzystać bezpośrednio.
### Krok 1: zaimportuj nagłówek
```c
import "stdio.h"
import "math.h"
import "GLFW/glfw3.h" // ścieżka w systemowych katalogach nagłówków
import "mojalib.h" // nagłówek leżący obok twojego pliku .fn
```
Finch czyta nagłówek przez **libclang** (parser C z clanga) i udostępnia:
- **funkcje**, także te ze zmienną liczbą argumentów, jak `printf`,
- **wartości `enum`**,
- **proste stałe `#define`**, które są pojedynczą liczbą, np. `M_PI`, `EOF`, `GL_COLOR_BUFFER_BIT`,
- **zmienne globalne**, np. `stdout` i `stderr`.
### Krok 2: dolinkuj bibliotekę
Nagłówek tylko *opisuje* funkcje. Ich właściwy kod jest w pliku biblioteki (`libNAZWA.so`).
Powiedz Finchowi, której biblioteki użyć, na górze pliku:
```c
link "glfw" // używa libglfw.so
link "GL" // używa libGL.so
```
Wpisz samą nazwę: dla `libglfw.so` to `glfw`. Jeśli `pkg-config` zna tę nazwę, Finch użyje jego
ustawień (ścieżek i dodatkowych bibliotek). W przeciwnym razie przekaże linkerowi `-lNAZWA`.
Biblioteka standardowa C i matematyczna (`libm`) są dolinkowane zawsze.
Na linii poleceń `-l NAZWA` robi to samo co `link "NAZWA"`.
Jeśli zapomnisz linijki `link`, Finch powie dokładnie, czego brakuje:
```
error: glfwInit, glfwCreateWindow, glfwMakeContextCurrent and 5 more come from "GLFW/glfw3.h", but its library isn't linked
the header only says the functions exist; their code lives in a library.
add this at the top of your file (with the library's real name):
link "glfw"
```
### Jak typy C wyglądają w Finchu
| C | Finch |
|---|---|
| `char`, `signed char`, `unsigned char` | `char`, `i8`, `u8` |
| `short`, `int`, `long`, `long long` | `i16`, `i32`, `i64`, `i64` (według faktycznego rozmiaru) |
| `unsigned …` | `u16`, `u32`, `u64` |
| `float`, `double` | `f32`, `f64` |
| `_Bool` / `bool` | `bool` |
| `enum` | odpowiadająca liczba całkowita ze znakiem |
| `char *`, `const char *` | `str` |
| `int *`, `double *`, … | `ptr[i32]`, `ptr[f64]`, … |
| `void *`, `struct X *`, `FILE *`, wskaźniki na funkcje | `ptr` |
Czyli `int` z C to `i32` w Finchu. Liczby wpisane w kod dopasowują się same (`abs(-5)` działa),
ale zmienną typu `int` z Fincha trzeba zamienić: `abs(i32(x))`.
### Przykład
```c
import "stdio.h"
import "math.h"
import "stdlib.h"
fn main() {
printf("%d + %d = %d\n", 2, 3, 5)
print(sqrt(2), M_PI, RAND_MAX)
ptr[i32] n = malloc(4) // poproś C o 4 bajty pamięci
n.value = 7
print(n.value)
free(n) // i oddaj je
fprintf(stderr, "to idzie na wyjście błędów\n")
}
```
Pełny przykład z grafiką jest w `examples/window.fn`: okno GLFW + OpenGL, które zmienia kolor.
`examples/llvm.fn` pokazuje, że Finch potrafi nawet sterować samym LLVM przez jego API w C.
### Co jeszcze nie działa
- Funkcje C, które przyjmują lub zwracają **`struct` przez wartość**, np. `div()`. Finch mówi o tym
wprost, jeśli spróbujesz. Funkcje przyjmujące *wskaźnik* na strukturę działają.
- **Makra-funkcje** (`#define MAX(a,b) ...`) i makra, które nie są pojedynczą liczbą.
- `long double`, liczby 128-bitowe.
- Odczytywanie **pól** struktury C.
---
## 12. Błędy
### Błędy kompilacji
Finch zatrzymuje się na pierwszym problemie i pokazuje, gdzie jest:
```
gra.fn:12:9: error: 'wynik' must be int, but this is str
12 | wynik = "wysoki"
| ^
```
Format: `plik:linijka:kolumna: error: wyjaśnienie`, a pod spodem linijka ze znakiem `^` pod miejscem błędu.
Komunikaty są po angielsku.
### Błędy w trakcie działania
Niektóre problemy widać dopiero, gdy program działa. Zamiast niezdefiniowanego zachowania
(jak w C) Finch zatrzymuje się z czytelnym komunikatem na wyjściu błędów i kodem wyjścia 1:
| Komunikat | Przyczyna |
|---|---|
| `runtime error: division by zero` | `/` albo `%` przez zmienną równą 0 |
| `runtime error: division overflows …` | najmniejsza liczba ze znakiem podzielona przez −1 |
| `runtime error: used .value on a null pointer` | odczyt lub zapis `p.value`, gdy `p` jest `null` |
---
## 13. Rozwiązywanie problemów
| Problem | Rozwiązanie |
|---|---|
| `can't find the C header 'x.h'` | Brakuje plików deweloperskich biblioteki. Zainstaluj je (Debian: `libx-dev`; Nix: dopisz do `shell.nix`). Własny nagłówek połóż obok pliku `.fn`. |
| `… come from "x.h", but its library isn't linked` | Dopisz `link "nazwa"` na górze pliku. |
| `the library 'x' wasn't found` | Biblioteka nie jest zainstalowana albo nazwa jest zła. Na Niksie dopisz ją do `shell.nix` i pracuj wewnątrz `nix-shell`. |
| `the C function 'f' can't be used from Finch yet` | Używa struktury przez wartość albo innego nieobsługiwanego typu. Poszukaj wariantu, który przyjmuje wskaźniki. |
| `no C compiler found to link with` | Zainstaluj gcc lub clang albo ustaw `CC`. |
| Program się kompiluje, ale przy starcie nie znajduje biblioteki C | Został zlinkowany ze ścieżki, której system nie przeszukuje. Uruchamiaj go w tym samym `nix-shell` albo zainstaluj bibliotekę systemowo. |
| `unexpected character 'ż'` | Polska litera w nazwie. W nazwach używaj tylko a–z. |
| CMake: `libclang not found` | Zainstaluj pakiet deweloperski libclang albo uruchom `cmake` w `nix-shell`. |
| Budowanie kończy się błędami API LLVM | Masz inną wersję LLVM niż 21. |
| Program nigdy się nie kończy | Warunek pętli nigdy nie staje się fałszywy. Naciśnij Ctrl+C. |
---
## 14. Struktura projektu i testy
```
Finch/
├── src/ kompilator (C++)
├── examples/ przykładowe programy (hello, tour, types, c_import, window, llvm)
├── tests/
│ ├── run/ programy + dokładny wynik, który muszą wypisać (.out)
│ ├── fail/ programy, które muszą się nie udać, z oczekiwanym błędem w 1. linijce
│ └── run.sh skrypt uruchamiający testy
├── docs/ ta dokumentacja (en, pl)
├── shell.nix środowisko deweloperskie Nix
└── CMakeLists.txt
```
Testy uruchomisz po zbudowaniu:
```sh
tests/run.sh # → 34 passed, 0 failed
```
---
## 15. Obecne ograniczenia
Finch 1.0 to solidny rdzeń, a nie skończony język. Jeszcze nie ma:
- `struct`, tablic, czytania z klawiatury (`input()`), sklejania tekstów (`"a" + "b"`).
Na razie użyj do tego funkcji z C (`scanf`, `snprintf`, `malloc`…).
- Automatycznego zarządzania pamięcią (w planach: zwalnianie na końcu bloku i `defer`).
- Modułów Fincha (na razie jeden program = jeden plik `.fn`).
- Platform innych niż Linux x86-64.
Plan rozwoju jest w [README](../../README.pl.md#plan-rozwoju).