package ast import "../source" import "../symbol" 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 :: enum u8 { Invalid, Int, I8, I16, I32, I64, Void, } Expr_Kind :: enum u8 { Invalid, Integer, Name, 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, expr: Expr_Id, diagnostic: source.Diagnostic_Id, } Function :: struct { span: source.Span, name: symbol.Id, pkg: Package_Id, file: File_Id, c_abi: bool, has_body: bool, params: []Param, result: Type_Syntax, body: []Stmt_Id, 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, } Module :: struct { exprs: [dynamic]Expr, statements: [dynamic]Stmt, functions: [dynamic]Function, globals: [dynamic]Global, imports: [dynamic]Import, files: [dynamic]File, packages: [dynamic]Package, allocator: mem.Allocator, } init_module :: proc(allocator := context.allocator) -> Module { module: Module module.allocator = 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 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) } for import_item in module.imports { delete(import_item.path, module.allocator) } for pkg in module.packages { delete(pkg.path, module.allocator) } delete(module.exprs) delete(module.statements) delete(module.functions) delete(module.globals) delete(module.imports) delete(module.files) delete(module.packages) }