add ArrayList alias to std
This commit is contained in:
@@ -251,6 +251,28 @@ Import :: struct {
|
||||
diagnostic: source.Diagnostic_Id,
|
||||
}
|
||||
|
||||
Declaration_Alias_Kind :: enum u8 {
|
||||
Invalid,
|
||||
Function,
|
||||
Global,
|
||||
Type,
|
||||
}
|
||||
|
||||
Declaration_Alias :: struct {
|
||||
span: source.Span,
|
||||
name: symbol.Id,
|
||||
qualifier: symbol.Id,
|
||||
member: symbol.Id,
|
||||
pkg: Package_Id,
|
||||
file: File_Id,
|
||||
target_pkg: Package_Id,
|
||||
target: u32,
|
||||
kind: Declaration_Alias_Kind,
|
||||
file_hidden: bool,
|
||||
valid: bool,
|
||||
diagnostic: source.Diagnostic_Id,
|
||||
}
|
||||
|
||||
File :: struct {
|
||||
source: source.Source_Id,
|
||||
pkg: Package_Id,
|
||||
@@ -290,6 +312,7 @@ Module :: struct {
|
||||
functions: [dynamic]Function,
|
||||
globals: [dynamic]Global,
|
||||
imports: [dynamic]Import,
|
||||
aliases: [dynamic]Declaration_Alias,
|
||||
files: [dynamic]File,
|
||||
packages: [dynamic]Package,
|
||||
unsupported: [dynamic]Unsupported,
|
||||
@@ -309,6 +332,7 @@ init_module :: proc(allocator := context.allocator) -> Module {
|
||||
module.functions.allocator = allocator
|
||||
module.globals.allocator = allocator
|
||||
module.imports.allocator = allocator
|
||||
module.aliases.allocator = allocator
|
||||
module.files.allocator = allocator
|
||||
module.packages.allocator = allocator
|
||||
module.unsupported.allocator = allocator
|
||||
@@ -360,6 +384,7 @@ destroy_module :: proc(module: ^Module) {
|
||||
delete(module.functions)
|
||||
delete(module.globals)
|
||||
delete(module.imports)
|
||||
delete(module.aliases)
|
||||
delete(module.files)
|
||||
delete(module.packages)
|
||||
delete(module.unsupported)
|
||||
|
||||
@@ -868,6 +868,11 @@ build_symbol_indexes :: proc(checker: ^Checker) {
|
||||
function_count += 1
|
||||
}
|
||||
}
|
||||
for alias in checker.ast_module.aliases {
|
||||
if alias.valid && alias.kind == .Function {
|
||||
function_count += 1
|
||||
}
|
||||
}
|
||||
checker.function_index = make([]Function_Index_Entry, function_count, checker.allocator)
|
||||
function_index := 0
|
||||
for function, id in checker.ast_module.functions {
|
||||
@@ -877,12 +882,31 @@ build_symbol_indexes :: proc(checker: ^Checker) {
|
||||
checker.function_index[function_index] = Function_Index_Entry{scope=function.pkg, file=function.file, hidden=function.file_hidden, name=function.name, id=ast.function_id(id)}
|
||||
function_index += 1
|
||||
}
|
||||
for alias in checker.ast_module.aliases {
|
||||
if alias.valid && alias.kind == .Function {
|
||||
checker.function_index[function_index] = Function_Index_Entry{scope=alias.pkg, file=alias.file, hidden=alias.file_hidden, name=alias.name, id=ast.Function_Id(alias.target)}
|
||||
function_index += 1
|
||||
}
|
||||
}
|
||||
slice.sort_by(checker.function_index, function_index_less)
|
||||
|
||||
checker.global_index = make([]Global_Index_Entry, len(checker.ast_module.globals), checker.allocator)
|
||||
global_count := len(checker.ast_module.globals)
|
||||
for alias in checker.ast_module.aliases {
|
||||
if alias.valid && alias.kind == .Global {
|
||||
global_count += 1
|
||||
}
|
||||
}
|
||||
checker.global_index = make([]Global_Index_Entry, global_count, checker.allocator)
|
||||
for global, id in checker.ast_module.globals {
|
||||
checker.global_index[id] = Global_Index_Entry{scope=global.pkg, file=global.file, hidden=global.file_hidden, name=global.name, id=ast.global_id(id)}
|
||||
}
|
||||
global_index := len(checker.ast_module.globals)
|
||||
for alias in checker.ast_module.aliases {
|
||||
if alias.valid && alias.kind == .Global {
|
||||
checker.global_index[global_index] = Global_Index_Entry{scope=alias.pkg, file=alias.file, hidden=alias.file_hidden, name=alias.name, id=ast.Global_Id(alias.target)}
|
||||
global_index += 1
|
||||
}
|
||||
}
|
||||
slice.sort_by(checker.global_index, global_index_less)
|
||||
|
||||
checker.import_index = make([]Import_Index_Entry, len(checker.ast_module.imports), checker.allocator)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -2425,6 +2425,31 @@ parse_distinct :: proc(parser: ^Parser, name: token.Token) {
|
||||
|
||||
parse_alias :: proc(parser: ^Parser, name: token.Token) {
|
||||
start := advance(parser)
|
||||
saved := parser.cursor
|
||||
if current(parser).kind == .Identifier && peek(parser).kind == .Dot {
|
||||
qualifier := advance(parser)
|
||||
advance(parser)
|
||||
if current(parser).kind == .Identifier {
|
||||
member := advance(parser)
|
||||
if current(parser).kind == .Newline || current(parser).kind == .Eof {
|
||||
append(&parser.module.aliases, ast.Declaration_Alias{
|
||||
span=span_from(name.span, member.span),
|
||||
name=name.symbol,
|
||||
qualifier=qualifier.symbol,
|
||||
member=member.symbol,
|
||||
pkg=parser.pkg,
|
||||
file=parser.file,
|
||||
target_pkg=ast.INVALID_PACKAGE,
|
||||
file_hidden=file_hidden_name(parser, name),
|
||||
valid=true,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
_ = finish_statement(parser)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
parser.cursor = saved
|
||||
child := parse_type(parser)
|
||||
id := types.named(&parser.module.type_store, u32(parser.pkg), u32(name.symbol), file=u32(parser.file), file_hidden=file_hidden_name(parser, name))
|
||||
if !types.define_alias(&parser.module.type_store, id, child) {
|
||||
|
||||
Reference in New Issue
Block a user