mirror of
https://github.com/Nexoniarz/Finch.git
synced 2026-11-03 08:54:25 +00:00
Methods are functions whose first parameter is the receiver's address; a method that changes self can't be called on a temporary or a read-only value, and calling one on a variable keeps a parameter from being borrowed. An argument that lives inside the receiver is copied (c.merge(c)). str(x) and print of arrays and structs go through one formatter, as in the C++ compiler. boot.sh: 12 passed, 0 failed, 10 skipped.
95 lines
2.4 KiB
Text
95 lines
2.4 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
|
|
}
|
|
|
|
fn simple(str kind) -> Type {
|
|
return Type(kind: kind)
|
|
}
|
|
|
|
fn arrayOf(Type t) -> Type {
|
|
out := Type(kind: "array")
|
|
out.elem.push(t)
|
|
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" {
|
|
return a.name == b.name && a.module == b.module
|
|
}
|
|
if a.kind == "array" || a.kind == "ptr" {
|
|
if a.elem.len != b.elem.len {
|
|
return false
|
|
}
|
|
if a.elem.len == 0 {
|
|
return true
|
|
}
|
|
return same(a.elem[0], b.elem[0])
|
|
}
|
|
return true
|
|
}
|
|
|
|
fn show(Type t) -> str {
|
|
if t.kind == "array" {
|
|
return "[]" + show(t.elem[0])
|
|
}
|
|
if t.kind == "ptr" {
|
|
if t.elem.len == 0 {
|
|
return "ptr"
|
|
}
|
|
return "ptr[" + show(t.elem[0]) + "]"
|
|
}
|
|
if t.kind == "struct" || t.kind == "named" {
|
|
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
|
|
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 text // literal text
|
|
Type ty // declared type (decl, param, field, fn result)
|
|
bool flag // decl: has a type; fn: has a body
|
|
[]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
|
|
[]Node structs
|
|
[]Node fns
|
|
}
|