file-local / package-local decls
This commit is contained in:
@@ -139,17 +139,19 @@ Build_Ctx :: struct {
|
||||
}
|
||||
|
||||
Function_Index_Entry :: struct {
|
||||
scope: ast.Package_Id,
|
||||
hidden: bool,
|
||||
name: symbol.Id,
|
||||
id: ast.Function_Id,
|
||||
scope: ast.Package_Id,
|
||||
file: ast.File_Id,
|
||||
visibility: types.Visibility,
|
||||
name: symbol.Id,
|
||||
id: ast.Function_Id,
|
||||
}
|
||||
|
||||
Global_Index_Entry :: struct {
|
||||
scope: ast.Package_Id,
|
||||
hidden: bool,
|
||||
name: symbol.Id,
|
||||
id: ast.Global_Id,
|
||||
scope: ast.Package_Id,
|
||||
file: ast.File_Id,
|
||||
visibility: types.Visibility,
|
||||
name: symbol.Id,
|
||||
id: ast.Global_Id,
|
||||
}
|
||||
|
||||
Import_Index_Entry :: struct {
|
||||
@@ -1537,12 +1539,17 @@ find_function_symbol :: proc(index: []Function_Index_Entry, scope: ast.Package_I
|
||||
visible := ast.INVALID_FUNCTION
|
||||
for low < len(index) && index[low].scope == scope && index[low].name == name {
|
||||
entry := index[low]
|
||||
if entry.hidden {
|
||||
switch entry.visibility {
|
||||
case .Public:
|
||||
visible = entry.id
|
||||
case .Package:
|
||||
if file != ast.INVALID_FILE {
|
||||
visible = entry.id
|
||||
}
|
||||
case .File:
|
||||
if entry.file == file {
|
||||
return entry.id
|
||||
}
|
||||
} else {
|
||||
visible = entry.id
|
||||
}
|
||||
low += 1
|
||||
}
|
||||
@@ -1564,12 +1571,17 @@ find_global_symbol :: proc(index: []Global_Index_Entry, scope: ast.Package_Id, n
|
||||
visible := ast.INVALID_GLOBAL
|
||||
for low < len(index) && index[low].scope == scope && index[low].name == name {
|
||||
entry := index[low]
|
||||
if entry.hidden {
|
||||
switch entry.visibility {
|
||||
case .Public:
|
||||
visible = entry.id
|
||||
case .Package:
|
||||
if file != ast.INVALID_FILE {
|
||||
visible = entry.id
|
||||
}
|
||||
case .File:
|
||||
if entry.file == file {
|
||||
return entry.id
|
||||
}
|
||||
} else {
|
||||
visible = entry.id
|
||||
}
|
||||
low += 1
|
||||
}
|
||||
@@ -1612,12 +1624,12 @@ build_symbol_indexes :: proc(checker: ^Checker) {
|
||||
if function.generated {
|
||||
continue
|
||||
}
|
||||
checker.function_index[function_index] = Function_Index_Entry{scope=function.pkg, hidden=function.package_hidden, name=function.name, id=ast.function_id(id)}
|
||||
checker.function_index[function_index] = Function_Index_Entry{scope=function.pkg, file=function.file, visibility=function.visibility, 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, hidden=alias.package_hidden, name=alias.name, id=ast.Function_Id(alias.target)}
|
||||
checker.function_index[function_index] = Function_Index_Entry{scope=alias.pkg, file=alias.file, visibility=alias.visibility, name=alias.name, id=ast.Function_Id(alias.target)}
|
||||
function_index += 1
|
||||
}
|
||||
}
|
||||
@@ -1631,12 +1643,12 @@ build_symbol_indexes :: proc(checker: ^Checker) {
|
||||
}
|
||||
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, hidden=global.package_hidden, name=global.name, id=ast.global_id(id)}
|
||||
checker.global_index[id] = Global_Index_Entry{scope=global.pkg, file=global.file, visibility=global.visibility, 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, hidden=alias.package_hidden, name=alias.name, id=ast.Global_Id(alias.target)}
|
||||
checker.global_index[global_index] = Global_Index_Entry{scope=alias.pkg, file=alias.file, visibility=alias.visibility, name=alias.name, id=ast.Global_Id(alias.target)}
|
||||
global_index += 1
|
||||
}
|
||||
}
|
||||
@@ -1737,7 +1749,7 @@ configure_entry_point :: proc(checker: ^Checker) {
|
||||
type_from_syntax(checker, function.result, function.pkg, function.file),
|
||||
&checker.module.types,
|
||||
)
|
||||
if function.package_hidden && function.has_body && !function.c_abi && !function.infer_error &&
|
||||
if function.visibility == .Package && function.has_body && !function.c_abi && !function.infer_error &&
|
||||
len(function.params) == 0 && !types.is_valid(function.error) && types.equal(result, io_type) {
|
||||
provider = ast.function_id(function_id)
|
||||
}
|
||||
@@ -1774,9 +1786,25 @@ declared_type_named :: proc(checker: ^Checker, pkg: ast.Package_Id, name: symbol
|
||||
}
|
||||
|
||||
|
||||
type_declaration_conflicts :: proc(checker: ^Checker, pkg: ast.Package_Id, name: symbol.Id) -> bool {
|
||||
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
|
||||
}
|
||||
|
||||
type_declaration_conflicts :: proc(
|
||||
checker: ^Checker,
|
||||
pkg: ast.Package_Id,
|
||||
name: symbol.Id,
|
||||
visibility: types.Visibility,
|
||||
file: ast.File_Id,
|
||||
) -> bool {
|
||||
for item in checker.module.types.nodes {
|
||||
if item.declared && item.pkg == u32(pkg) && item.name == u32(name) {
|
||||
if item.declared && item.pkg == u32(pkg) && item.name == u32(name) &&
|
||||
declaration_scopes_overlap(visibility, file, item.visibility, ast.File_Id(item.file)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -3996,11 +4024,11 @@ validate_declarations :: proc(checker: ^Checker) {
|
||||
function.span,
|
||||
"inferred error channels are not allowed on 'c_func'",
|
||||
)
|
||||
} else if !function.package_hidden && !root_main {
|
||||
} else if function.visibility == .Public && !root_main {
|
||||
checker.template_diagnostics[function_id] = source.add(
|
||||
checker.diagnostics,
|
||||
function.span,
|
||||
"inferred error channels are only allowed on hidden functions and root main",
|
||||
"inferred error channels are only allowed on local functions and root main",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -13971,8 +13999,13 @@ build_function :: proc(checker: ^Checker, id: Spec_Id) {
|
||||
symbol_text(checker, function.name),
|
||||
)
|
||||
}
|
||||
checker.specs[id].result = types.I64
|
||||
spec.result = types.I64
|
||||
recovery_result := types.fallible_success(spec.result, &checker.module.types) if function.infer_error else types.INVALID
|
||||
if !types.is_void(recovery_result) && !types.is_noreturn(recovery_result) &&
|
||||
!is_runtime_type(checker, recovery_result) {
|
||||
recovery_result = types.I64
|
||||
}
|
||||
checker.specs[id].result = recovery_result
|
||||
spec.result = recovery_result
|
||||
}
|
||||
for arg in spec.args {
|
||||
if !is_runtime_type(checker, arg) {
|
||||
@@ -14810,26 +14843,29 @@ check :: proc(
|
||||
continue
|
||||
}
|
||||
for previous in ast_module.functions[:index] {
|
||||
if !previous.generated && previous.pkg == function.pkg && previous.name == function.name {
|
||||
if !previous.generated && previous.pkg == function.pkg && previous.name == function.name &&
|
||||
declaration_scopes_overlap(previous.visibility, previous.file, function.visibility, function.file) {
|
||||
source.addf(diagnostics, function.span, "duplicate function '%s'", symbol_text(&checker, function.name))
|
||||
}
|
||||
}
|
||||
for global in ast_module.globals {
|
||||
if global.pkg == function.pkg && global.name == function.name {
|
||||
if global.pkg == function.pkg && global.name == function.name &&
|
||||
declaration_scopes_overlap(global.visibility, global.file, function.visibility, function.file) {
|
||||
source.addf(diagnostics, function.span, "package declaration '%s' conflicts with a global", symbol_text(&checker, function.name))
|
||||
}
|
||||
}
|
||||
if type_declaration_conflicts(&checker, function.pkg, function.name) {
|
||||
if type_declaration_conflicts(&checker, function.pkg, function.name, function.visibility, function.file) {
|
||||
source.addf(diagnostics, function.span, "function '%s' shadows visible type", symbol_text(&checker, function.name))
|
||||
}
|
||||
}
|
||||
for global, index in ast_module.globals {
|
||||
for previous in ast_module.globals[:index] {
|
||||
if previous.pkg == global.pkg && previous.name == global.name {
|
||||
if previous.pkg == global.pkg && previous.name == global.name &&
|
||||
declaration_scopes_overlap(previous.visibility, previous.file, global.visibility, global.file) {
|
||||
source.addf(diagnostics, global.span, "duplicate global '%s'", symbol_text(&checker, global.name))
|
||||
}
|
||||
}
|
||||
if type_declaration_conflicts(&checker, global.pkg, global.name) {
|
||||
if type_declaration_conflicts(&checker, global.pkg, global.name, global.visibility, global.file) {
|
||||
source.addf(diagnostics, global.span, "global '%s' shadows visible type", symbol_text(&checker, global.name))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user