file-local / package-local decls

This commit is contained in:
2026-08-09 17:01:05 +02:00
parent a7a32894f3
commit 8785912b73
15 changed files with 369 additions and 152 deletions
+40 -19
View File
@@ -1249,14 +1249,29 @@ load_package :: proc(
return pkg_id
}
declaration_scopes_overlap :: proc(
left_visibility: types.Visibility,
left_file: ast.File_Id,
right_visibility: types.Visibility,
right_file: ast.File_Id,
) -> bool {
return left_visibility != .File || right_visibility != .File || left_file == right_file
}
declaration_visible_in_file :: proc(visibility: types.Visibility, declaration_file, file: ast.File_Id) -> bool {
return visibility != .File || declaration_file == file
}
declaration_conflicts :: proc(module: ^ast.Module, pkg: ast.Package_Id, file: ast.File_Id, name: symbol.Id) -> bool {
for function in module.functions {
if function.pkg == pkg && function.name == name {
if function.pkg == pkg && function.name == name &&
declaration_visible_in_file(function.visibility, function.file, file) {
return true
}
}
for global in module.globals {
if global.pkg == pkg && global.name == name {
if global.pkg == pkg && global.name == name &&
declaration_visible_in_file(global.visibility, global.file, file) {
return true
}
}
@@ -1327,7 +1342,9 @@ find_visible_enum_global :: proc(
public_only := false,
) -> ast.Global_Id {
for global, index in module.globals {
if global.pkg == pkg && global.name == name && (!global.package_hidden || !public_only) {
if global.pkg == pkg && global.name == name &&
((public_only && global.visibility == .Public) ||
(!public_only && declaration_visible_in_file(global.visibility, global.file, file))) {
return ast.global_id(index)
}
}
@@ -1451,17 +1468,20 @@ resolve_enum_values :: proc(state: ^State) {
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 {
if function.pkg == alias.pkg && function.name == alias.name &&
declaration_scopes_overlap(function.visibility, function.file, alias.visibility, alias.file) {
return true
}
}
for global in module.globals {
if global.pkg == alias.pkg && global.name == alias.name {
if global.pkg == alias.pkg && global.name == alias.name &&
declaration_scopes_overlap(global.visibility, global.file, alias.visibility, alias.file) {
return true
}
}
for item in module.type_store.nodes {
if item.declared && item.pkg == u32(alias.pkg) && item.name == u32(alias.name) {
if item.declared && item.pkg == u32(alias.pkg) && item.name == u32(alias.name) &&
declaration_scopes_overlap(item.visibility, ast.File_Id(item.file), alias.visibility, alias.file) {
return true
}
}
@@ -1473,7 +1493,7 @@ direct_alias_target :: proc(module: ^ast.Module, pkg: ast.Package_Id, name: symb
target: u32
kinds := 0
for function, index in module.functions {
if function.pkg == pkg && function.name == name && !function.generated && !function.package_hidden {
if function.pkg == pkg && function.name == name && !function.generated && function.visibility == .Public {
kind = .Function
target = u32(ast.function_id(index))
kinds += 1
@@ -1481,7 +1501,7 @@ direct_alias_target :: proc(module: ^ast.Module, pkg: ast.Package_Id, name: symb
}
}
for global, index in module.globals {
if global.pkg == pkg && global.name == name && !global.package_hidden {
if global.pkg == pkg && global.name == name && global.visibility == .Public {
kind = .Global
target = u32(ast.global_id(index))
kinds += 1
@@ -1498,24 +1518,24 @@ direct_alias_target :: proc(module: ^ast.Module, pkg: ast.Package_Id, name: symb
return kind, target, kinds
}
hidden_alias_target_exists :: proc(module: ^ast.Module, pkg: ast.Package_Id, name: symbol.Id) -> bool {
non_public_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.package_hidden {
if function.pkg == pkg && function.name == name && function.visibility != .Public {
return true
}
}
for global in module.globals {
if global.pkg == pkg && global.name == name && global.package_hidden {
if global.pkg == pkg && global.name == name && global.visibility != .Public {
return true
}
}
for item in module.type_store.nodes {
if item.declared && item.pkg == u32(pkg) && item.name == u32(name) && item.package_hidden {
if item.declared && item.pkg == u32(pkg) && item.name == u32(name) && item.visibility != .Public {
return true
}
}
for alias in module.aliases {
if alias.valid && alias.pkg == pkg && alias.name == name && alias.package_hidden {
if alias.valid && alias.pkg == pkg && alias.name == name && alias.visibility != .Public {
return true
}
}
@@ -1524,7 +1544,7 @@ hidden_alias_target_exists :: proc(module: ^ast.Module, pkg: ast.Package_Id, nam
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.package_hidden {
if alias.valid && alias.pkg == pkg && alias.name == name && alias.visibility == .Public {
return index
}
}
@@ -1581,11 +1601,11 @@ resolve_declaration_alias :: proc(state: ^State, index: int, states: []u8) -> bo
return false
}
if hidden_alias_target_exists(state.module, alias.target_pkg, alias.member) {
if non_public_alias_target_exists(state.module, alias.target_pkg, alias.member) {
alias.diagnostic = source.addf(
state.diagnostics,
alias.span,
"package member '%s.%s' is package-hidden",
"package member '%s.%s' is not public",
symbol.resolve(state.symbols, alias.qualifier),
symbol.resolve(state.symbols, alias.member),
)
@@ -1611,7 +1631,8 @@ validate_declaration_aliases :: proc(state: ^State) {
continue
}
for previous in state.module.aliases[:index] {
if previous.pkg == alias.pkg && previous.name == alias.name {
if previous.pkg == alias.pkg && previous.name == alias.name &&
declaration_scopes_overlap(previous.visibility, previous.file, alias.visibility, alias.file) {
alias.diagnostic = source.addf(state.diagnostics, alias.span, "duplicate declaration alias '%s'", name)
alias.valid = false
break
@@ -1661,9 +1682,9 @@ validate_declaration_aliases :: proc(state: ^State) {
u32(alias.pkg),
u32(alias.name),
file=u32(alias.file),
package_hidden=alias.package_hidden,
visibility=alias.visibility,
)
if !types.define_alias(&state.module.type_store, id, types.Type(alias.target), alias.package_hidden) {
if !types.define_alias(&state.module.type_store, id, types.Type(alias.target), alias.visibility) {
alias.diagnostic = source.addf(state.diagnostics, alias.span, "duplicate type declaration '%s'", symbol.resolve(state.symbols, alias.name))
alias.valid = false
}