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

23
examples/c_import.fn Normal file
View file

@ -0,0 +1,23 @@
// Use any C library: import its header and call it.
import "stdio.h"
import "math.h"
import "stdlib.h"
import "string.h"
fn main() {
printf("printf works: %d + %d = %d\n", 2, 3, 2 + 3)
puts("so does puts")
print("sqrt(2) =", sqrt(2))
print("pi from math.h:", M_PI)
print("strlen(\"finch\") =", strlen("finch"))
print("RAND_MAX =", RAND_MAX, "EOF =", EOF)
// memory from C: malloc gives a ptr, free gives it back
ptr[i32] n = malloc(4)
n.value = 7
print("from the heap:", n.value)
free(n)
fprintf(stderr, "this goes to stderr\n")
}

3
examples/hello.fn Normal file
View file

@ -0,0 +1,3 @@
fn main() {
print("Hello, Finch!")
}

18
examples/llvm.fn Normal file
View file

@ -0,0 +1,18 @@
// Finch driving LLVM itself through the LLVM-C API: the first step toward
// a compiler written in Finch. Builds a module with `answer() -> 42` and prints its IR.
import "llvm-c/Core.h"
link "LLVM"
fn main() {
mod := LLVMModuleCreateWithName("from_finch")
i64t := LLVMInt64Type()
fnType := LLVMFunctionType(i64t, null, 0, 0)
f := LLVMAddFunction(mod, "answer", fnType)
entry := LLVMAppendBasicBlock(f, "entry")
b := LLVMCreateBuilder()
LLVMPositionBuilderAtEnd(b, entry)
LLVMBuildRet(b, LLVMConstInt(i64t, 42, 0))
LLVMDumpModule(mod)
LLVMDisposeBuilder(b)
LLVMDisposeModule(mod)
}

62
examples/tour.fn Normal file
View file

@ -0,0 +1,62 @@
// A quick tour of Finch.
fn add(int a, int b) -> int {
return a + b
}
fn fib(int n) -> int {
if n < 2 {
return n
}
return fib(n - 1) + fib(n - 2)
}
fn isEven(int n) -> bool {
return n % 2 == 0
}
fn greet(str name) {
if name == "Finch" {
print("Hi, it's me!")
} else {
print("Hi,", name)
}
}
fn main() {
// two ways to make a variable
int age = 10
name := "Ola" // type is guessed: str
pi := 3.14 // float
letter := 'F' // char
print(name, "is", age, "years old")
print("2 + 3 =", add(2, 3))
print("pi * 2 =", pi * 2)
print("first letter:", letter)
print("10 is even?", isEven(10))
greet("Finch")
greet(name)
// loops
for i in 0..10 {
if i == 3 {
continue
}
if i == 7 {
break
}
print("i =", i)
}
count := 3
while count > 0 {
print("countdown", count)
count -= 1
}
print("fib(30) =", fib(30))
print("7 / 2 =", 7 / 2, "and as float:", float(7) / 2)
print("int(9.99) =", int(9.99))
}

31
examples/types.fn Normal file
View file

@ -0,0 +1,31 @@
// Sized numbers and pointers.
fn double(ptr[int] p) {
p.value = p.value * 2
}
fn main() {
// everyday: int and float. For bytes and hardware: exact sizes.
u8 small = 255
i32 points = -1000
big := u64(0xFFFF_FFFF)
f32 half = 0.5
small += 1 // u8 wraps around, like real hardware
print("u8 255 + 1 =", small)
print("points:", points, "big:", big, "half:", half)
i64 wide = points // a smaller type fits into a bigger one by itself
print("wide:", wide)
// pointers: addr(x) gives you where x lives, p.value is what is there
int x = 21
p := addr(x)
double(p)
print("x is now", x)
ptr[int] nothing = null
if nothing == null {
print("nothing points nowhere")
}
}

34
examples/window.fn Normal file
View file

@ -0,0 +1,34 @@
// A window that slowly changes color. Needs GLFW and OpenGL
// (on Nix they are in shell.nix: run this inside nix-shell).
import "GLFW/glfw3.h"
import "GL/gl.h"
import "math.h"
link "glfw"
link "GL"
fn main() {
if glfwInit() == 0 {
print("could not start GLFW")
return
}
window := glfwCreateWindow(800, 600, "Finch", null, null)
if window == null {
print("could not open a window")
glfwTerminate()
return
}
glfwMakeContextCurrent(window)
while glfwWindowShouldClose(window) == 0 {
t := glfwGetTime()
glClearColor(f32(sin(t) * 0.5 + 0.5), 0.3, 0.6, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glfwSwapBuffers(window)
glfwPollEvents()
}
glfwDestroyWindow(window)
glfwTerminate()
}