add ArrayList alias to std

This commit is contained in:
2026-07-13 13:46:45 +02:00
parent 288df082e2
commit 6455df52b4
14 changed files with 600 additions and 13 deletions
+230
View File
@@ -1293,6 +1293,235 @@ find_type_import :: proc(module: ^ast.Module, file: ast.File_Id, alias: symbol.I
return ast.INVALID_IMPORT
}
alias_declarations_conflict :: proc(left_file: ast.File_Id, left_hidden: bool, right_file: ast.File_Id, right_hidden: bool) -> bool {
return left_file == right_file if left_hidden && right_hidden else true
}
alias_conflicts_with_declaration :: proc(module: ^ast.Module, alias: ast.Declaration_Alias) -> bool {
for function in module.functions {
if function.pkg == alias.pkg && function.name == alias.name &&
alias_declarations_conflict(alias.file, alias.file_hidden, function.file, function.file_hidden) {
return true
}
}
for global in module.globals {
if global.pkg == alias.pkg && global.name == alias.name &&
alias_declarations_conflict(alias.file, alias.file_hidden, global.file, global.file_hidden) {
return true
}
}
for item in module.type_store.nodes {
if item.declared && item.pkg == u32(alias.pkg) && item.name == u32(alias.name) &&
alias_declarations_conflict(alias.file, alias.file_hidden, ast.File_Id(item.file), item.file_hidden) {
return true
}
}
return false
}
direct_alias_target :: proc(module: ^ast.Module, pkg: ast.Package_Id, name: symbol.Id) -> (ast.Declaration_Alias_Kind, u32, int) {
kind := ast.Declaration_Alias_Kind.Invalid
target: u32
kinds := 0
for function, index in module.functions {
if function.pkg == pkg && function.name == name && !function.generated && !function.file_hidden {
kind = .Function
target = u32(ast.function_id(index))
kinds += 1
break
}
}
for global, index in module.globals {
if global.pkg == pkg && global.name == name && !global.file_hidden {
kind = .Global
target = u32(ast.global_id(index))
kinds += 1
break
}
}
if value := types.find_named(&module.type_store, u32(pkg), u32(name)); types.is_valid(value) {
if item, ok := types.node(&module.type_store, value); ok && item.declared {
kind = .Type
target = u32(value)
kinds += 1
}
}
return kind, target, kinds
}
hidden_alias_target_exists :: proc(module: ^ast.Module, pkg: ast.Package_Id, name: symbol.Id) -> bool {
for function in module.functions {
if function.pkg == pkg && function.name == name && function.file_hidden {
return true
}
}
for global in module.globals {
if global.pkg == pkg && global.name == name && global.file_hidden {
return true
}
}
for item in module.type_store.nodes {
if item.declared && item.pkg == u32(pkg) && item.name == u32(name) && item.file_hidden {
return true
}
}
for alias in module.aliases {
if alias.valid && alias.pkg == pkg && alias.name == name && alias.file_hidden {
return true
}
}
return false
}
find_public_alias :: proc(module: ^ast.Module, pkg: ast.Package_Id, name: symbol.Id) -> int {
for alias, index in module.aliases {
if alias.valid && alias.pkg == pkg && alias.name == name && !alias.file_hidden {
return index
}
}
return -1
}
resolve_declaration_alias :: proc(state: ^State, index: int, states: []u8) -> bool {
alias := &state.module.aliases[index]
if !alias.valid {
return false
}
if states[index] == 2 {
return alias.kind != .Invalid
}
if states[index] == 1 {
alias.diagnostic = source.addf(
state.diagnostics,
alias.span,
"declaration alias cycle involving '%s'",
symbol.resolve(state.symbols, alias.name),
)
alias.valid = false
return false
}
states[index] = 1
defer states[index] = 2
kind, target, kinds := direct_alias_target(state.module, alias.target_pkg, alias.member)
if kinds > 1 {
alias.diagnostic = source.addf(
state.diagnostics,
alias.span,
"package member '%s.%s' is ambiguous",
symbol.resolve(state.symbols, alias.qualifier),
symbol.resolve(state.symbols, alias.member),
)
alias.valid = false
return false
}
if kinds == 1 {
alias.kind = kind
alias.target = target
return true
}
if target_alias := find_public_alias(state.module, alias.target_pkg, alias.member); target_alias >= 0 {
if resolve_declaration_alias(state, target_alias, states) {
resolved := state.module.aliases[target_alias]
alias.kind = resolved.kind
alias.target = resolved.target
return true
}
alias.valid = false
return false
}
if hidden_alias_target_exists(state.module, alias.target_pkg, alias.member) {
alias.diagnostic = source.addf(
state.diagnostics,
alias.span,
"package member '%s.%s' is file-hidden",
symbol.resolve(state.symbols, alias.qualifier),
symbol.resolve(state.symbols, alias.member),
)
} else {
alias.diagnostic = source.addf(
state.diagnostics,
alias.span,
"package '%s' has no member '%s'",
symbol.resolve(state.symbols, alias.qualifier),
symbol.resolve(state.symbols, alias.member),
)
}
alias.valid = false
return false
}
validate_declaration_aliases :: proc(state: ^State) {
for &alias, index in state.module.aliases {
name := symbol.resolve(state.symbols, alias.name)
if alias_conflicts_with_declaration(state.module, alias) {
alias.diagnostic = source.addf(state.diagnostics, alias.span, "declaration alias '%s' conflicts with a package declaration", name)
alias.valid = false
continue
}
for previous in state.module.aliases[:index] {
if previous.pkg == alias.pkg && previous.name == alias.name &&
alias_declarations_conflict(alias.file, alias.file_hidden, previous.file, previous.file_hidden) {
alias.diagnostic = source.addf(state.diagnostics, alias.span, "duplicate declaration alias '%s'", name)
alias.valid = false
break
}
}
if !alias.valid {
continue
}
for import_item in state.module.imports {
if import_item.file == alias.file && import_item.alias == alias.name {
alias.diagnostic = source.addf(state.diagnostics, alias.span, "declaration alias '%s' conflicts with an import", name)
alias.valid = false
break
}
}
if !alias.valid {
continue
}
import_id := find_type_import(state.module, alias.file, alias.qualifier)
if import_id == ast.INVALID_IMPORT {
alias.diagnostic = source.addf(state.diagnostics, alias.span, "unknown package alias '%s'", symbol.resolve(state.symbols, alias.qualifier))
alias.valid = false
continue
}
state.module.imports[import_id].used = true
import_item := state.module.imports[import_id]
alias.target_pkg = import_item.target
if !import_item.valid || import_item.target == ast.INVALID_PACKAGE ||
int(import_item.target) >= len(state.module.packages) || !state.module.packages[import_item.target].available {
alias.diagnostic = source.addf(state.diagnostics, alias.span, "unavailable imported package '%s'", symbol.resolve(state.symbols, alias.qualifier))
alias.valid = false
}
}
states := make([]u8, len(state.module.aliases), state.allocator)
defer delete(states, state.allocator)
for _, index in state.module.aliases {
_ = resolve_declaration_alias(state, index, states)
}
for &alias in state.module.aliases {
if !alias.valid || alias.kind != .Type {
continue
}
id := types.named(
&state.module.type_store,
u32(alias.pkg),
u32(alias.name),
file=u32(alias.file),
file_hidden=alias.file_hidden,
)
if !types.define_alias(&state.module.type_store, id, types.Type(alias.target)) {
alias.diagnostic = source.addf(state.diagnostics, alias.span, "duplicate type declaration '%s'", symbol.resolve(state.symbols, alias.name))
alias.valid = false
}
}
}
canonical_type :: proc(
module: ^ast.Module,
value: types.Type,
@@ -1456,6 +1685,7 @@ load :: proc(
state.root_failed = true
}
validate_imports(&state)
validate_declaration_aliases(&state)
canonicalize_types(&module, allocator)
return module, !state.root_failed
}