mirror of
https://github.com/Nexoniarz/Finch.git
synced 2026-11-03 00:44:27 +00:00
The compiler is written in Finch, and nothing else: src/*.fch, built from a seed
boot/ is src/ now. The C++ compiler and CMake are gone from this branch (they are on before-bootstrap). bootstrap/build.sh builds the compiler from bootstrap/<system>.ll -- the compiler's own LLVM IR -- then builds it with itself and checks the two come out identical. bootstrap/build.sh seed writes the seed anew. The driver is complete: the runtime is compiled once and kept in ~/.cache/finch; a program's own C files, .o and .a files and frameworks link along; a linker failure is read and answered with link "lib" or the library that is missing. The old tests/fail diagnostics are all in again (a missing import, a str compared with null, 'write just the library's name', a map key that is a float, non-ASCII names, ...). tests/run.sh is the one test runner: programs, refusals, -g builds and the shared library. 106 passed.
This commit is contained in:
parent
750eca3e85
commit
b9378050ab
39 changed files with 80403 additions and 7251 deletions
123
src/ast.fch
Normal file
123
src/ast.fch
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// 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
|
||||
}
|
||||
|
||||
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.count != b.count {
|
||||
return false
|
||||
}
|
||||
if a.kind == "array" || a.kind == "ptr" || a.kind == "map" || a.kind == "fixed" {
|
||||
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 == "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
|
||||
}
|
||||
|
||||
struct Program {
|
||||
str module
|
||||
str path
|
||||
[]str imports // Finch modules
|
||||
[]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
|
||||
}
|
||||
Loading…
Reference in a new issue