intern identifiers

This commit is contained in:
2026-06-10 21:27:00 +02:00
parent d6e03b6f08
commit cdbe4fbc99
16 changed files with 497 additions and 182 deletions
+14 -9
View File
@@ -4,6 +4,7 @@ import "../ast"
import "../lexer"
import "../parser"
import "../source"
import "../symbol"
import "core:mem"
import "core:os"
import "core:path/filepath"
@@ -14,6 +15,7 @@ State :: struct {
module: ^ast.Module,
sources: ^source.Store,
diagnostics: ^source.Diagnostics,
symbols: ^symbol.Table,
token_allocator: mem.Allocator,
allocator: mem.Allocator,
root_failed: bool,
@@ -53,7 +55,7 @@ add_placeholder :: proc(state: ^State, path: string) -> int {
id := len(state.module.packages)
append(&state.module.packages, ast.Package{
path=strings.clone(path, state.allocator),
name=strings.clone(filepath.base(path), state.allocator),
name=symbol.intern(state.symbols, filepath.base(path)),
available=false,
})
return id
@@ -130,7 +132,7 @@ load_package :: proc(state: ^State, path: string, import_span: source.Span, is_r
pkg_id := len(state.module.packages)
append(&state.module.packages, ast.Package{
path=canonical,
name=strings.clone(filepath.base(canonical), state.allocator),
name=symbol.intern(state.symbols, filepath.base(canonical)),
available=true,
})
files, files_ok := read_package_files(state, canonical)
@@ -159,8 +161,8 @@ load_package :: proc(state: ^State, path: string, import_span: source.Span, is_r
delete(bytes)
file_id := len(state.module.files)
append(&state.module.files, ast.File{source=source_id, pkg=pkg_id})
stream := lexer.lex(&state.sources.items[source_id], state.diagnostics, state.token_allocator)
parser.parse_into(&stream, state.diagnostics, state.module, pkg_id, file_id)
stream := lexer.lex(&state.sources.items[source_id], state.diagnostics, state.symbols, state.token_allocator)
parser.parse_into(&stream, &state.sources.items[source_id], state.diagnostics, state.module, pkg_id, file_id)
delete(stream.items)
}
os.file_info_slice_delete(files, state.allocator)
@@ -188,7 +190,7 @@ load_package :: proc(state: ^State, path: string, import_span: source.Span, is_r
return pkg_id
}
declaration_conflicts :: proc(module: ^ast.Module, pkg: int, name: string) -> bool {
declaration_conflicts :: proc(module: ^ast.Module, pkg: int, name: symbol.Id) -> bool {
for function in module.functions {
if function.pkg == pkg && function.name == name {
return true
@@ -204,11 +206,12 @@ declaration_conflicts :: proc(module: ^ast.Module, pkg: int, name: string) -> bo
validate_imports :: proc(state: ^State) {
for import_item, import_id in state.module.imports {
if import_item.alias == "" && import_item.target >= 0 {
if !symbol.is_valid(import_item.alias) && import_item.target >= 0 {
state.module.imports[import_id].alias = state.module.packages[import_item.target].name
}
alias := state.module.imports[import_id].alias
if !is_identifier(alias) {
alias_text := symbol.resolve(state.symbols, alias)
if !is_identifier(alias_text) {
state.module.imports[import_id].diagnostic = source.add(
state.diagnostics,
import_item.span,
@@ -221,7 +224,7 @@ validate_imports :: proc(state: ^State) {
state.diagnostics,
import_item.span,
"import alias '%s' conflicts with a package declaration",
alias,
alias_text,
)
state.module.imports[import_id].valid = false
}
@@ -231,7 +234,7 @@ validate_imports :: proc(state: ^State) {
state.diagnostics,
import_item.span,
"duplicate import alias '%s' in the same file",
alias,
alias_text,
)
state.module.imports[import_id].valid = false
break
@@ -244,6 +247,7 @@ load :: proc(
root_path: string,
sources: ^source.Store,
diagnostics: ^source.Diagnostics,
symbols: ^symbol.Table,
token_allocator := context.allocator,
allocator := context.allocator,
) -> (ast.Module, bool) {
@@ -252,6 +256,7 @@ load :: proc(
module=&module,
sources=sources,
diagnostics=diagnostics,
symbols=symbols,
token_allocator=token_allocator,
allocator=allocator,
}