Files
brolang/compiler/ast/ast.odin
T

248 lines
5.1 KiB
Odin

package ast
import "../source"
import "../symbol"
import "../types"
import "core:mem"
Expr_Id :: distinct u32
Stmt_Id :: distinct u32
Function_Id :: distinct u32
Global_Id :: distinct u32
Import_Id :: distinct u32
File_Id :: distinct u32
Package_Id :: distinct u32
INVALID_EXPR :: Expr_Id(0xffff_ffff)
INVALID_STMT :: Stmt_Id(0xffff_ffff)
INVALID_FUNCTION :: Function_Id(0xffff_ffff)
INVALID_GLOBAL :: Global_Id(0xffff_ffff)
INVALID_IMPORT :: Import_Id(0xffff_ffff)
INVALID_FILE :: File_Id(0xffff_ffff)
INVALID_PACKAGE :: Package_Id(0xffff_ffff)
expr_id :: proc(index: int) -> Expr_Id {
assert(index >= 0 && u64(index) < u64(INVALID_EXPR))
return Expr_Id(index)
}
stmt_id :: proc(index: int) -> Stmt_Id {
assert(index >= 0 && u64(index) < u64(INVALID_STMT))
return Stmt_Id(index)
}
function_id :: proc(index: int) -> Function_Id {
assert(index >= 0 && u64(index) < u64(INVALID_FUNCTION))
return Function_Id(index)
}
global_id :: proc(index: int) -> Global_Id {
assert(index >= 0 && u64(index) < u64(INVALID_GLOBAL))
return Global_Id(index)
}
import_id :: proc(index: int) -> Import_Id {
assert(index >= 0 && u64(index) < u64(INVALID_IMPORT))
return Import_Id(index)
}
file_id :: proc(index: int) -> File_Id {
assert(index >= 0 && u64(index) < u64(INVALID_FILE))
return File_Id(index)
}
package_id :: proc(index: int) -> Package_Id {
assert(index >= 0 && u64(index) < u64(INVALID_PACKAGE))
return Package_Id(index)
}
index :: proc(id: $T, invalid: T, count: int) -> (int, bool) {
value := int(id)
return value, id != invalid && value < count
}
Type_Syntax :: types.Type
Expr_Kind :: enum u8 {
Invalid,
Integer,
Float,
String,
Array,
None,
Name,
Address,
Deref,
Index,
Slice,
Field,
Unwrap,
Orelse,
Struct_Literal,
Keyed,
Negate,
Add,
Call,
}
Expr :: struct {
span: source.Span,
integer: u64,
args: []Expr_Id,
qualifier: symbol.Id,
name: symbol.Id,
left: Expr_Id,
right: Expr_Id,
diagnostic: source.Diagnostic_Id,
kind: Expr_Kind,
}
Param :: struct {
name: symbol.Id,
span: source.Span,
type: Type_Syntax,
}
Stmt_Kind :: enum u8 {
Invalid,
Declaration,
Assignment,
Return,
Expression,
}
Stmt :: struct {
kind: Stmt_Kind,
span: source.Span,
name: symbol.Id,
type: Type_Syntax,
immutable: bool,
target: Expr_Id,
expr: Expr_Id,
diagnostic: source.Diagnostic_Id,
}
Function :: struct {
span: source.Span,
name: symbol.Id,
pkg: Package_Id,
file: File_Id,
c_abi: bool,
imported: bool,
has_body: bool,
params: []Param,
result: Type_Syntax,
body: []Stmt_Id,
unsupported_reason: string,
diagnostic: source.Diagnostic_Id,
}
Global :: struct {
span: source.Span,
name: symbol.Id,
pkg: Package_Id,
file: File_Id,
type: Type_Syntax,
immutable: bool,
expr: Expr_Id,
diagnostic: source.Diagnostic_Id,
}
Import :: struct {
span: source.Span,
alias: symbol.Id,
path: string,
pkg: Package_Id,
file: File_Id,
target: Package_Id,
valid: bool,
used: bool,
diagnostic: source.Diagnostic_Id,
}
File :: struct {
source: source.Source_Id,
pkg: Package_Id,
}
Package :: struct {
path: string,
name: symbol.Id,
available: bool,
kind: Package_Kind,
}
Package_Kind :: enum u8 {
Native,
C_Header,
}
Unsupported :: struct {
pkg: Package_Id,
name: symbol.Id,
reason: string,
}
Module :: struct {
exprs: [dynamic]Expr,
statements: [dynamic]Stmt,
functions: [dynamic]Function,
globals: [dynamic]Global,
imports: [dynamic]Import,
files: [dynamic]File,
packages: [dynamic]Package,
unsupported: [dynamic]Unsupported,
strings: [dynamic]string,
type_store: types.Store,
allocator: mem.Allocator,
}
init_module :: proc(allocator := context.allocator) -> Module {
module: Module
module.allocator = allocator
module.type_store = types.init_store(allocator)
module.exprs.allocator = allocator
module.statements.allocator = allocator
module.functions.allocator = allocator
module.globals.allocator = allocator
module.imports.allocator = allocator
module.files.allocator = allocator
module.packages.allocator = allocator
module.unsupported.allocator = allocator
module.strings.allocator = allocator
return module
}
destroy_module :: proc(module: ^Module) {
for expr in module.exprs {
delete(expr.args, module.allocator)
}
for function in module.functions {
delete(function.params, module.allocator)
delete(function.body, module.allocator)
delete(function.unsupported_reason, module.allocator)
}
for import_item in module.imports {
delete(import_item.path, module.allocator)
}
for pkg in module.packages {
delete(pkg.path, module.allocator)
}
for item in module.unsupported {
delete(item.reason, module.allocator)
}
for value in module.strings {
delete(value, module.allocator)
}
delete(module.exprs)
delete(module.statements)
delete(module.functions)
delete(module.globals)
delete(module.imports)
delete(module.files)
delete(module.packages)
delete(module.unsupported)
delete(module.strings)
types.destroy_store(&module.type_store)
}