mirror of
https://github.com/Nexoniarz/Finch.git
synced 2026-11-03 00:44:27 +00:00
- fNxM / iNxM / uNxM up to 512 bits, as LLVM vectors (<8 x float>): LLVM picks SSE, AVX2, AVX-512 or NEON for them - f32x8(x) in every lane, f32x8(a, ..., h), f32x8(list, i) loads, f32x8(i32x8 v) converts - + - * / and the bit operators lane by lane, with a plain number on either side counting for every lane; v[i], v[i] = x, v.len, == / != (every lane), print and str - methods: sum min max dot abs sqrt floor ceil round fma store; min/max/abs/clamp lane by lane - wide vectors (and structs holding them) are loaded and stored with align 16, what malloc and the stack give - --cpu <name> (and cpu = "..." in finch.toml): native, x86-64-v3, apple-m1, ... - debug info shows vectors; the language server completes their methods; Kate and VS Code highlight them - f32 x = -1.5 works: a minus in front of a float written in the code keeps it such a number Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Psc42moPLwP43Cmb9oZqSR
171 lines
5.1 KiB
Text
171 lines
5.1 KiB
Text
// The syntax tree of the self-hosted compiler.
|
|
|
|
// A type as written or resolved.
|
|
// kind: "void" "int" "bool" "char" "float" "str" "null" "ptr" "array" "named" "struct"
|
|
// elem: the element of an array or the target of a ptr (zero or one entry)
|
|
// name, module: structs ("" module = the main file)
|
|
struct Type {
|
|
str kind
|
|
[]Type elem
|
|
str name
|
|
str module
|
|
int count // "fixed": [N]T, only inside C structs
|
|
}
|
|
|
|
fn simple(str kind) -> Type {
|
|
return Type(kind: kind)
|
|
}
|
|
|
|
fn arrayOf(Type t) -> Type {
|
|
out := Type(kind: "array")
|
|
out.elem.push(t)
|
|
return out
|
|
}
|
|
|
|
// map[K]V: elem holds the key, then the value
|
|
fn mapOf(Type k, Type v) -> Type {
|
|
out := Type(kind: "map")
|
|
out.elem.push(k)
|
|
out.elem.push(v)
|
|
return out
|
|
}
|
|
|
|
fn ptrTo(Type t) -> Type {
|
|
out := Type(kind: "ptr")
|
|
out.elem.push(t)
|
|
return out
|
|
}
|
|
|
|
// f32x8, i8x32, u16x16, f64x4: N numbers of one type side by side, worked on all at once (SIMD).
|
|
// Its kind is "vec", elem[0] the type of one lane, count the number of lanes. kind "" if `name` is no such type.
|
|
fn vecType(str name) -> Type {
|
|
x := name.find("x")
|
|
if x < 2 || x + 1 >= name.len {
|
|
return Type()
|
|
}
|
|
lane := name.sub(0, x)
|
|
if !["i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64", "f32", "f64"].contains(lane) {
|
|
return Type()
|
|
}
|
|
n := 0
|
|
for c in name.sub(x + 1, name.len) {
|
|
if c < '0' || c > '9' {
|
|
return Type()
|
|
}
|
|
n = n * 10 + (int(c) - int('0'))
|
|
}
|
|
if n != 2 && n != 4 && n != 8 && n != 16 && n != 32 && n != 64 {
|
|
return Type()
|
|
}
|
|
bits := int(lane.sub(1, lane.len)) or 0
|
|
if n * bits > 512 {
|
|
return Type() // the widest registers (AVX-512) hold 512 bits
|
|
}
|
|
if lane == "i64" {
|
|
lane = "int"
|
|
} else if lane == "f64" {
|
|
lane = "float"
|
|
}
|
|
out := Type(kind: "vec", count: n)
|
|
out.elem.push(simple(lane))
|
|
return out
|
|
}
|
|
|
|
fn same(Type a, Type b) -> bool {
|
|
if a.kind != b.kind {
|
|
return false
|
|
}
|
|
if a.kind == "struct" || a.kind == "named" || a.kind == "enum" {
|
|
return a.name == b.name && a.module == b.module
|
|
}
|
|
if (a.kind == "fixed" || a.kind == "vec") && a.count != b.count {
|
|
return false
|
|
}
|
|
if a.kind == "array" || a.kind == "ptr" || a.kind == "map" || a.kind == "fixed" || a.kind == "vec" {
|
|
if a.elem.len != b.elem.len {
|
|
return false
|
|
}
|
|
for i in 0..a.elem.len {
|
|
if !same(a.elem[i], b.elem[i]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
return true
|
|
}
|
|
|
|
fn show(Type t) -> str {
|
|
if t.kind == "array" {
|
|
return "[]" + show(t.elem[0])
|
|
}
|
|
if t.kind == "fixed" {
|
|
return "[" + str(t.count) + "]" + show(t.elem[0])
|
|
}
|
|
if t.kind == "vec" {
|
|
lane := t.elem[0].kind
|
|
if lane == "int" {
|
|
lane = "i64"
|
|
} else if lane == "float" {
|
|
lane = "f64"
|
|
}
|
|
return lane + "x" + str(t.count)
|
|
}
|
|
if t.kind == "map" {
|
|
return "map[" + show(t.elem[0]) + "]" + show(t.elem[1])
|
|
}
|
|
if t.kind == "ptr" {
|
|
if t.elem.len == 0 {
|
|
return "ptr"
|
|
}
|
|
return "ptr[" + show(t.elem[0]) + "]"
|
|
}
|
|
if t.kind == "struct" || t.kind == "named" || t.kind == "enum" {
|
|
if t.module.len > 0 {
|
|
return t.module + "." + t.name
|
|
}
|
|
return t.name
|
|
}
|
|
if t.kind == "void" {
|
|
return "nothing"
|
|
}
|
|
return t.kind
|
|
}
|
|
|
|
// One node of the tree, for expressions, statements, functions and structs alike.
|
|
// expressions: int float str char bool null var unary binary call member index array method
|
|
// statements: decl assign expr if while for each return break continue block
|
|
// top level: fn param struct field enum variant
|
|
// match: match (kids: subject, arms...), arm (kids: patterns node, body; flag: the else arm), patterns
|
|
struct Node {
|
|
str kind
|
|
str name // identifier, operator, callee, field or method name
|
|
str recv // fn Point.move(...): "Point"; empty for a plain function
|
|
[]str tparams // fn max[T](...), struct Stack[T], fn Stack[T].push: the type parameters
|
|
str text // literal text
|
|
Type ty // declared type (decl, param, field, fn result)
|
|
bool flag // decl: has a type; or: the right side is a { block }
|
|
bool fallible // fn: -> T! or -> !
|
|
bool exported // export fn: a C function of a library (finch build --shared)
|
|
[]Node kids
|
|
[]str names // named arguments: Point(x: 1)
|
|
int line
|
|
int col
|
|
int file
|
|
int endLine // block, fn: the line of the closing }
|
|
}
|
|
|
|
struct Program {
|
|
str module
|
|
str path
|
|
[]str imports // Finch modules, by the name this file uses: import ui/button -> "button"
|
|
[]str modules // which module each is: "ui/button" (import path as p: "path")
|
|
[]str cimports // C headers: import "stdio.h"
|
|
[]str cwhere // where each was written, for error messages
|
|
[]str links // link "glfw", link "mine.c"
|
|
[]Node structs
|
|
[]Node enums
|
|
[]Node fns
|
|
[]Node consts // const NAME = value
|
|
[]str tests // the functions made from test "..." { } blocks, in order
|
|
}
|