|
|
|
@@ -110,12 +110,16 @@ Build_Ctx :: struct {
|
|
|
|
|
|
|
|
|
|
Function_Index_Entry :: struct {
|
|
|
|
|
scope: ast.Package_Id,
|
|
|
|
|
file: ast.File_Id,
|
|
|
|
|
hidden: bool,
|
|
|
|
|
name: symbol.Id,
|
|
|
|
|
id: ast.Function_Id,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Global_Index_Entry :: struct {
|
|
|
|
|
scope: ast.Package_Id,
|
|
|
|
|
file: ast.File_Id,
|
|
|
|
|
hidden: bool,
|
|
|
|
|
name: symbol.Id,
|
|
|
|
|
id: ast.Global_Id,
|
|
|
|
|
}
|
|
|
|
@@ -617,7 +621,7 @@ import_index_less :: proc(left, right: Import_Index_Entry) -> bool {
|
|
|
|
|
return left.id < right.id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
find_function_symbol :: proc(index: []Function_Index_Entry, scope: ast.Package_Id, name: symbol.Id) -> ast.Function_Id {
|
|
|
|
|
find_function_symbol :: proc(index: []Function_Index_Entry, scope: ast.Package_Id, name: symbol.Id, file := ast.INVALID_FILE) -> ast.Function_Id {
|
|
|
|
|
low := 0
|
|
|
|
|
high := len(index)
|
|
|
|
|
for low < high {
|
|
|
|
@@ -629,13 +633,22 @@ find_function_symbol :: proc(index: []Function_Index_Entry, scope: ast.Package_I
|
|
|
|
|
high = middle
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if low < len(index) && index[low].scope == scope && index[low].name == name {
|
|
|
|
|
return index[low].id
|
|
|
|
|
visible := ast.INVALID_FUNCTION
|
|
|
|
|
for low < len(index) && index[low].scope == scope && index[low].name == name {
|
|
|
|
|
entry := index[low]
|
|
|
|
|
if entry.hidden {
|
|
|
|
|
if entry.file == file {
|
|
|
|
|
return entry.id
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
visible = entry.id
|
|
|
|
|
}
|
|
|
|
|
low += 1
|
|
|
|
|
}
|
|
|
|
|
return ast.INVALID_FUNCTION
|
|
|
|
|
return visible
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
find_global_symbol :: proc(index: []Global_Index_Entry, scope: ast.Package_Id, name: symbol.Id) -> ast.Global_Id {
|
|
|
|
|
find_global_symbol :: proc(index: []Global_Index_Entry, scope: ast.Package_Id, name: symbol.Id, file := ast.INVALID_FILE) -> ast.Global_Id {
|
|
|
|
|
low := 0
|
|
|
|
|
high := len(index)
|
|
|
|
|
for low < high {
|
|
|
|
@@ -647,10 +660,19 @@ find_global_symbol :: proc(index: []Global_Index_Entry, scope: ast.Package_Id, n
|
|
|
|
|
high = middle
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if low < len(index) && index[low].scope == scope && index[low].name == name {
|
|
|
|
|
return index[low].id
|
|
|
|
|
visible := ast.INVALID_GLOBAL
|
|
|
|
|
for low < len(index) && index[low].scope == scope && index[low].name == name {
|
|
|
|
|
entry := index[low]
|
|
|
|
|
if entry.hidden {
|
|
|
|
|
if entry.file == file {
|
|
|
|
|
return entry.id
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
visible = entry.id
|
|
|
|
|
}
|
|
|
|
|
low += 1
|
|
|
|
|
}
|
|
|
|
|
return ast.INVALID_GLOBAL
|
|
|
|
|
return visible
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
find_import_symbol :: proc(index: []Import_Index_Entry, scope: ast.File_Id, name: symbol.Id) -> ast.Import_Id {
|
|
|
|
@@ -684,14 +706,14 @@ build_symbol_indexes :: proc(checker: ^Checker) {
|
|
|
|
|
if function.generated {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
checker.function_index[function_index] = Function_Index_Entry{scope=function.pkg, name=function.name, id=ast.function_id(id)}
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
slice.sort_by(checker.function_index, function_index_less)
|
|
|
|
|
|
|
|
|
|
checker.global_index = make([]Global_Index_Entry, len(checker.ast_module.globals), checker.allocator)
|
|
|
|
|
for global, id in checker.ast_module.globals {
|
|
|
|
|
checker.global_index[id] = Global_Index_Entry{scope=global.pkg, name=global.name, id=ast.global_id(id)}
|
|
|
|
|
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)}
|
|
|
|
|
}
|
|
|
|
|
slice.sort_by(checker.global_index, global_index_less)
|
|
|
|
|
|
|
|
|
@@ -702,12 +724,12 @@ build_symbol_indexes :: proc(checker: ^Checker) {
|
|
|
|
|
slice.sort_by(checker.import_index, import_index_less)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
find_template :: proc(checker: ^Checker, name: symbol.Id, pkg := ast.Package_Id(0)) -> ast.Function_Id {
|
|
|
|
|
return find_function_symbol(checker.function_index, pkg, name)
|
|
|
|
|
find_template :: proc(checker: ^Checker, name: symbol.Id, pkg := ast.Package_Id(0), file := ast.INVALID_FILE) -> ast.Function_Id {
|
|
|
|
|
return find_function_symbol(checker.function_index, pkg, name, file)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
find_global :: proc(checker: ^Checker, name: symbol.Id, pkg := ast.Package_Id(0)) -> ast.Global_Id {
|
|
|
|
|
return find_global_symbol(checker.global_index, pkg, name)
|
|
|
|
|
find_global :: proc(checker: ^Checker, name: symbol.Id, pkg := ast.Package_Id(0), file := ast.INVALID_FILE) -> ast.Global_Id {
|
|
|
|
|
return find_global_symbol(checker.global_index, pkg, name, file)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
find_import :: proc(checker: ^Checker, file: ast.File_Id, alias: symbol.Id, mark_used := false) -> ast.Import_Id {
|
|
|
|
@@ -718,12 +740,26 @@ find_import :: proc(checker: ^Checker, file: ast.File_Id, alias: symbol.Id, mark
|
|
|
|
|
return id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
declared_type_named :: proc(checker: ^Checker, pkg: ast.Package_Id, name: symbol.Id) -> bool {
|
|
|
|
|
id := types.find_named(&checker.module.types, u32(pkg), u32(name))
|
|
|
|
|
declared_type_named :: proc(checker: ^Checker, pkg: ast.Package_Id, name: symbol.Id, file := ast.INVALID_FILE) -> bool {
|
|
|
|
|
id := types.find_named(&checker.module.types, u32(pkg), u32(name), file=u32(file))
|
|
|
|
|
item, ok := types.node(&checker.module.types, id)
|
|
|
|
|
return ok && item.declared
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type_declaration_conflicts :: proc(checker: ^Checker, pkg: ast.Package_Id, name: symbol.Id, file: ast.File_Id, hidden: bool) -> bool {
|
|
|
|
|
for item in checker.module.types.nodes {
|
|
|
|
|
if item.declared && item.pkg == u32(pkg) && item.name == u32(name) &&
|
|
|
|
|
declarations_conflict(file, hidden, ast.File_Id(item.file), item.file_hidden) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
visible_name_kind :: proc(
|
|
|
|
|
checker: ^Checker,
|
|
|
|
|
name: symbol.Id,
|
|
|
|
@@ -755,13 +791,13 @@ visible_name_kind :: proc(
|
|
|
|
|
if find_import(checker, file, name) != ast.INVALID_IMPORT {
|
|
|
|
|
return "import"
|
|
|
|
|
}
|
|
|
|
|
if find_global(checker, name, pkg) != ast.INVALID_GLOBAL {
|
|
|
|
|
if find_global(checker, name, pkg, file) != ast.INVALID_GLOBAL {
|
|
|
|
|
return "global"
|
|
|
|
|
}
|
|
|
|
|
if find_template(checker, name, pkg) != ast.INVALID_FUNCTION {
|
|
|
|
|
if find_template(checker, name, pkg, file) != ast.INVALID_FUNCTION {
|
|
|
|
|
return "function"
|
|
|
|
|
}
|
|
|
|
|
if declared_type_named(checker, pkg, name) {
|
|
|
|
|
if declared_type_named(checker, pkg, name, file) {
|
|
|
|
|
return "type"
|
|
|
|
|
}
|
|
|
|
|
return ""
|
|
|
|
@@ -831,6 +867,10 @@ expr_package :: proc(checker: ^Checker, expr: ast.Expr, pkg: ast.Package_Id, fil
|
|
|
|
|
return import_item.target, true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expr_lookup_file :: proc(expr: ast.Expr, file: ast.File_Id) -> ast.File_Id {
|
|
|
|
|
return ast.INVALID_FILE if symbol.is_valid(expr.qualifier) else file
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_package_resolution_diagnostic :: proc(checker: ^Checker, expr: ast.Expr, file: ast.File_Id) -> source.Diagnostic_Id {
|
|
|
|
|
if find_import(checker, file, expr.qualifier) == ast.INVALID_IMPORT {
|
|
|
|
|
return source.addf(checker.diagnostics, expr.span, "unknown package alias '%s'", symbol_text(checker, expr.qualifier))
|
|
|
|
@@ -838,8 +878,8 @@ add_package_resolution_diagnostic :: proc(checker: ^Checker, expr: ast.Expr, fil
|
|
|
|
|
return source.addf(checker.diagnostics, expr.span, "unavailable imported package '%s'", symbol_text(checker, expr.qualifier))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_name_resolution_diagnostic :: proc(checker: ^Checker, expr: ast.Expr, target_pkg: ast.Package_Id) -> source.Diagnostic_Id {
|
|
|
|
|
if find_template(checker, expr.name, target_pkg) != ast.INVALID_FUNCTION {
|
|
|
|
|
add_name_resolution_diagnostic :: proc(checker: ^Checker, expr: ast.Expr, target_pkg: ast.Package_Id, file: ast.File_Id) -> source.Diagnostic_Id {
|
|
|
|
|
if find_template(checker, expr.name, target_pkg, expr_lookup_file(expr, file)) != ast.INVALID_FUNCTION {
|
|
|
|
|
return source.addf(checker.diagnostics, expr.span, "'%s' is a function, not a global value", symbol_text(checker, expr.name))
|
|
|
|
|
}
|
|
|
|
|
if symbol.is_valid(expr.qualifier) {
|
|
|
|
@@ -854,8 +894,8 @@ add_name_resolution_diagnostic :: proc(checker: ^Checker, expr: ast.Expr, target
|
|
|
|
|
return source.addf(checker.diagnostics, expr.span, "unresolved global '%s'", symbol_text(checker, expr.name))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
add_call_resolution_diagnostic :: proc(checker: ^Checker, expr: ast.Expr, target_pkg: ast.Package_Id) -> source.Diagnostic_Id {
|
|
|
|
|
if find_global(checker, expr.name, target_pkg) != ast.INVALID_GLOBAL {
|
|
|
|
|
add_call_resolution_diagnostic :: proc(checker: ^Checker, expr: ast.Expr, target_pkg: ast.Package_Id, file: ast.File_Id) -> source.Diagnostic_Id {
|
|
|
|
|
if find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file)) != ast.INVALID_GLOBAL {
|
|
|
|
|
return source.addf(checker.diagnostics, expr.span, "'%s' is a global, not a function", symbol_text(checker, expr.name))
|
|
|
|
|
}
|
|
|
|
|
if symbol.is_valid(expr.qualifier) {
|
|
|
|
@@ -976,7 +1016,7 @@ resolve_type_argument :: proc(
|
|
|
|
|
if !available {
|
|
|
|
|
return types.INVALID, false
|
|
|
|
|
}
|
|
|
|
|
value := types.find_named(&checker.module.types, u32(target_pkg), u32(expr.name))
|
|
|
|
|
value := types.find_named(&checker.module.types, u32(target_pkg), u32(expr.name), file=u32(expr_lookup_file(expr, file)))
|
|
|
|
|
value = types.resolve_alias(value, &checker.module.types)
|
|
|
|
|
return value, types.is_valid(value)
|
|
|
|
|
}
|
|
|
|
@@ -1963,7 +2003,7 @@ infer_compound_expr :: proc(
|
|
|
|
|
return types.INVALID
|
|
|
|
|
}
|
|
|
|
|
target_pkg, available := expr_package(checker, expr, pkg, file)
|
|
|
|
|
value := types.find_named(store, u32(target_pkg), u32(expr.name)) if available else types.INVALID
|
|
|
|
|
value := types.find_named(store, u32(target_pkg), u32(expr.name), file=u32(expr_lookup_file(expr, file))) if available else types.INVALID
|
|
|
|
|
return types.resolve_alias(value, store)
|
|
|
|
|
case .Keyed:
|
|
|
|
|
return infer_nested_expr(checker, expr.left, locals, pkg, file, demanded, local_types)
|
|
|
|
@@ -2069,7 +2109,7 @@ infer_expr :: proc(
|
|
|
|
|
}
|
|
|
|
|
if !types.is_valid(last) && symbol.is_valid(expr.qualifier) &&
|
|
|
|
|
find_import(checker, file, expr.qualifier) == ast.INVALID_IMPORT {
|
|
|
|
|
if global := find_global(checker, expr.qualifier, pkg); global != ast.INVALID_GLOBAL {
|
|
|
|
|
if global := find_global(checker, expr.qualifier, pkg, file); global != ast.INVALID_GLOBAL {
|
|
|
|
|
base_type := checker.global_types[global]
|
|
|
|
|
item, has_item := types.container(base_type, &checker.module.types)
|
|
|
|
|
field_name := symbol_text(checker, expr.name)
|
|
|
|
@@ -2112,7 +2152,7 @@ infer_expr :: proc(
|
|
|
|
|
if !types.is_valid(last) {
|
|
|
|
|
target_pkg, available := expr_package(checker, expr, pkg, file)
|
|
|
|
|
if available {
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg)
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
|
|
|
|
|
if global != ast.INVALID_GLOBAL {
|
|
|
|
|
last = checker.global_types[global]
|
|
|
|
|
}
|
|
|
|
@@ -2121,7 +2161,7 @@ infer_expr :: proc(
|
|
|
|
|
if !types.is_valid(last) {
|
|
|
|
|
target_pkg, available := expr_package(checker, expr, pkg, file)
|
|
|
|
|
if available {
|
|
|
|
|
template := find_template(checker, expr.name, target_pkg)
|
|
|
|
|
template := find_template(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
|
|
|
|
|
if template != ast.INVALID_FUNCTION &&
|
|
|
|
|
len(checker.ast_module.functions[template].unsupported_reason) == 0 &&
|
|
|
|
|
checker.template_diagnostics[template] == source.INVALID_DIAGNOSTIC {
|
|
|
|
@@ -2205,7 +2245,7 @@ infer_expr :: proc(
|
|
|
|
|
target_pkg, available := expr_package(checker, expr, pkg, file)
|
|
|
|
|
template := ast.INVALID_FUNCTION
|
|
|
|
|
if available {
|
|
|
|
|
template = find_template(checker, expr.name, target_pkg)
|
|
|
|
|
template = find_template(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
|
|
|
|
|
}
|
|
|
|
|
if template == ast.INVALID_FUNCTION {
|
|
|
|
|
callee_type := types.INVALID
|
|
|
|
@@ -2213,14 +2253,14 @@ infer_expr :: proc(
|
|
|
|
|
callee_type = find_infer_local(locals, expr.name)
|
|
|
|
|
}
|
|
|
|
|
if !types.is_valid(callee_type) && available {
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg)
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
|
|
|
|
|
if global != ast.INVALID_GLOBAL {
|
|
|
|
|
callee_type = checker.global_types[global]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_, function_item, function_type, ok := types.function_pointer(callee_type, &checker.module.types)
|
|
|
|
|
if !ok {
|
|
|
|
|
distinct_type := types.find_named(&checker.module.types, u32(target_pkg), u32(expr.name))
|
|
|
|
|
distinct_type := types.find_named(&checker.module.types, u32(target_pkg), u32(expr.name), file=u32(expr_lookup_file(expr, file)))
|
|
|
|
|
distinct_item, distinct_ok := types.node(&checker.module.types, distinct_type)
|
|
|
|
|
if available && distinct_ok && distinct_item.kind == .Distinct && len(expr.args) == 1 {
|
|
|
|
|
stack[frame_index].left = distinct_type
|
|
|
|
@@ -2585,7 +2625,7 @@ infer_statements :: proc(
|
|
|
|
|
if !rhs_is_arith {
|
|
|
|
|
_ = record_demand(checker, statement.expr, locals^[local_index].type, locals^[:], local_types, pkg, file)
|
|
|
|
|
}
|
|
|
|
|
} else if global := find_global(checker, statement.name, pkg); global != ast.INVALID_GLOBAL {
|
|
|
|
|
} else if global := find_global(checker, statement.name, pkg, file); global != ast.INVALID_GLOBAL {
|
|
|
|
|
_ = merge_global_demand(checker, global, value_type)
|
|
|
|
|
if !rhs_is_arith {
|
|
|
|
|
_ = record_demand(checker, statement.expr, checker.global_types[global], locals^[:], local_types, pkg, file)
|
|
|
|
@@ -2945,7 +2985,7 @@ open_const_default_type :: proc(
|
|
|
|
|
if !available {
|
|
|
|
|
return types.INVALID
|
|
|
|
|
}
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg)
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
|
|
|
|
|
index := int(global)
|
|
|
|
|
if global == ast.INVALID_GLOBAL || index < 0 || index >= len(checker.global_open_const) {
|
|
|
|
|
return types.INVALID
|
|
|
|
@@ -3022,7 +3062,7 @@ expr_accepts_numeric_demand :: proc(
|
|
|
|
|
if !available {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg)
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
|
|
|
|
|
index := int(global)
|
|
|
|
|
if global == ast.INVALID_GLOBAL || index < 0 || index >= len(checker.global_open_const) {
|
|
|
|
|
return false
|
|
|
|
@@ -3112,7 +3152,7 @@ record_demand :: proc(
|
|
|
|
|
if !available {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg)
|
|
|
|
|
global := find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
|
|
|
|
|
if global != ast.INVALID_GLOBAL {
|
|
|
|
|
return merge_global_demand(checker, global, demand)
|
|
|
|
|
}
|
|
|
|
@@ -3791,7 +3831,7 @@ infer_qualified_value_field_type :: proc(
|
|
|
|
|
}
|
|
|
|
|
base_type := find_infer_local(locals, expr.qualifier)
|
|
|
|
|
if !types.is_valid(base_type) {
|
|
|
|
|
if global := find_global(checker, expr.qualifier, pkg); global != ast.INVALID_GLOBAL {
|
|
|
|
|
if global := find_global(checker, expr.qualifier, pkg, file); global != ast.INVALID_GLOBAL {
|
|
|
|
|
base_type = checker.global_types[global]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -3866,7 +3906,7 @@ build_qualified_value_field :: proc(
|
|
|
|
|
value, ok := build_field_from_value(checker, expr, base, local.type)
|
|
|
|
|
return value, true, ok
|
|
|
|
|
}
|
|
|
|
|
if global := find_global(checker, expr.qualifier, pkg); global != ast.INVALID_GLOBAL {
|
|
|
|
|
if global := find_global(checker, expr.qualifier, pkg, file); global != ast.INVALID_GLOBAL {
|
|
|
|
|
base := build_global_reference(checker, global, expr.span, global_reads)
|
|
|
|
|
value, ok := build_field_from_value(checker, expr, base, checker.global_types[global])
|
|
|
|
|
return value, true, ok
|
|
|
|
@@ -3893,7 +3933,7 @@ enum_type_from_name_expr :: proc(
|
|
|
|
|
find_import(checker, file, expr.qualifier) != ast.INVALID_IMPORT {
|
|
|
|
|
return types.INVALID, false
|
|
|
|
|
}
|
|
|
|
|
enum_type := types.find_named(&checker.module.types, u32(pkg), u32(expr.qualifier))
|
|
|
|
|
enum_type := types.find_named(&checker.module.types, u32(pkg), u32(expr.qualifier), file=u32(file))
|
|
|
|
|
return enum_type, types.is_enum(enum_type, &checker.module.types)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -3915,7 +3955,7 @@ enum_type_from_field_expr :: proc(
|
|
|
|
|
if !available {
|
|
|
|
|
return types.INVALID, false
|
|
|
|
|
}
|
|
|
|
|
enum_type := types.find_named(&checker.module.types, u32(target_pkg), u32(base.name))
|
|
|
|
|
enum_type := types.find_named(&checker.module.types, u32(target_pkg), u32(base.name), file=u32(expr_lookup_file(base, file)))
|
|
|
|
|
return enum_type, types.is_enum(enum_type, &checker.module.types)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -4615,7 +4655,7 @@ build_compound_expr :: proc(
|
|
|
|
|
struct_type := types.INVALID
|
|
|
|
|
if symbol.is_valid(expr.name) {
|
|
|
|
|
target_pkg, available := expr_package(checker, expr, pkg, file, true)
|
|
|
|
|
struct_type = types.find_named(store, u32(target_pkg), u32(expr.name)) if available else types.INVALID
|
|
|
|
|
struct_type = types.find_named(store, u32(target_pkg), u32(expr.name), file=u32(expr_lookup_file(expr, file))) if available else types.INVALID
|
|
|
|
|
struct_type = types.resolve_alias(struct_type, store)
|
|
|
|
|
if !types.is_record(struct_type, store) || types.is_opaque_struct(struct_type, store) {
|
|
|
|
|
id := source.addf(checker.diagnostics, expr.span, "unknown or opaque record type '%s'", symbol_text(checker, expr.name))
|
|
|
|
@@ -4853,7 +4893,7 @@ build_expr :: proc(
|
|
|
|
|
}
|
|
|
|
|
if last == hir.INVALID_EXPR && symbol.is_valid(expr.qualifier) &&
|
|
|
|
|
find_import(checker, file, expr.qualifier) == ast.INVALID_IMPORT {
|
|
|
|
|
if global := find_global(checker, expr.qualifier, pkg); global != ast.INVALID_GLOBAL {
|
|
|
|
|
if global := find_global(checker, expr.qualifier, pkg, file); global != ast.INVALID_GLOBAL {
|
|
|
|
|
base := build_global_reference(checker, global, expr.span, global_reads)
|
|
|
|
|
base_type := checker.global_types[global]
|
|
|
|
|
item, has_item := types.container(base_type, &checker.module.types)
|
|
|
|
@@ -4924,16 +4964,16 @@ build_expr :: proc(
|
|
|
|
|
if !available {
|
|
|
|
|
id := add_package_resolution_diagnostic(checker, expr, file)
|
|
|
|
|
last = invalid_hir_expr(checker, expr.span, id)
|
|
|
|
|
} else if global := find_global(checker, expr.name, target_pkg); global != ast.INVALID_GLOBAL {
|
|
|
|
|
} else if global := find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file)); global != ast.INVALID_GLOBAL {
|
|
|
|
|
last = build_global_reference(checker, global, expr.span, global_reads)
|
|
|
|
|
} else {
|
|
|
|
|
template := find_template(checker, expr.name, target_pkg)
|
|
|
|
|
template := find_template(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
|
|
|
|
|
if template != ast.INVALID_FUNCTION {
|
|
|
|
|
last = build_function_value(checker, template, expr.span, frame.expected)
|
|
|
|
|
} else {
|
|
|
|
|
id := add_unsupported_diagnostic(checker, expr.span, target_pkg, expr.name)
|
|
|
|
|
if id == source.INVALID_DIAGNOSTIC {
|
|
|
|
|
id = add_name_resolution_diagnostic(checker, expr, target_pkg)
|
|
|
|
|
id = add_name_resolution_diagnostic(checker, expr, target_pkg, file)
|
|
|
|
|
}
|
|
|
|
|
last = invalid_hir_expr(checker, expr.span, id)
|
|
|
|
|
}
|
|
|
|
@@ -5005,7 +5045,7 @@ build_expr :: proc(
|
|
|
|
|
_ = pop(&stack)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
template := find_template(checker, expr.name, target_pkg)
|
|
|
|
|
template := find_template(checker, expr.name, target_pkg, expr_lookup_file(expr, file))
|
|
|
|
|
if template == ast.INVALID_FUNCTION {
|
|
|
|
|
callee := hir.INVALID_EXPR
|
|
|
|
|
non_callable := false
|
|
|
|
@@ -5020,7 +5060,7 @@ build_expr :: proc(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if callee == hir.INVALID_EXPR && !non_callable {
|
|
|
|
|
if global := find_global(checker, expr.name, target_pkg); global != ast.INVALID_GLOBAL {
|
|
|
|
|
if global := find_global(checker, expr.name, target_pkg, expr_lookup_file(expr, file)); global != ast.INVALID_GLOBAL {
|
|
|
|
|
if _, _, _, callable := types.function_pointer(checker.global_types[global], &checker.module.types); callable {
|
|
|
|
|
callee = build_global_reference(checker, global, expr.span, global_reads)
|
|
|
|
|
} else {
|
|
|
|
@@ -5030,7 +5070,7 @@ build_expr :: proc(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if callee == hir.INVALID_EXPR {
|
|
|
|
|
distinct_type := types.find_named(&checker.module.types, u32(target_pkg), u32(expr.name))
|
|
|
|
|
distinct_type := types.find_named(&checker.module.types, u32(target_pkg), u32(expr.name), file=u32(expr_lookup_file(expr, file)))
|
|
|
|
|
distinct_item, distinct_ok := types.node(&checker.module.types, distinct_type)
|
|
|
|
|
if distinct_ok && distinct_item.kind == .Distinct {
|
|
|
|
|
if !is_runtime_type(checker, distinct_type) {
|
|
|
|
@@ -5067,12 +5107,12 @@ build_expr :: proc(
|
|
|
|
|
}
|
|
|
|
|
id := source.INVALID_DIAGNOSTIC
|
|
|
|
|
if non_callable {
|
|
|
|
|
id = add_call_resolution_diagnostic(checker, expr, target_pkg) if non_callable_global else
|
|
|
|
|
id = add_call_resolution_diagnostic(checker, expr, target_pkg, file) if non_callable_global else
|
|
|
|
|
source.add(checker.diagnostics, expr.span, "call target is not a function pointer")
|
|
|
|
|
} else {
|
|
|
|
|
id = add_unsupported_diagnostic(checker, expr.span, target_pkg, expr.name)
|
|
|
|
|
if id == source.INVALID_DIAGNOSTIC {
|
|
|
|
|
id = add_call_resolution_diagnostic(checker, expr, target_pkg)
|
|
|
|
|
id = add_call_resolution_diagnostic(checker, expr, target_pkg, file)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
last = invalid_hir_expr(checker, expr.span, id)
|
|
|
|
@@ -5475,6 +5515,9 @@ make_link_name :: proc(checker: ^Checker, id: Spec_Id) -> string {
|
|
|
|
|
defer strings.builder_destroy(&builder)
|
|
|
|
|
strings.write_string(&builder, "bro_c__" if function.c_abi else "bro__")
|
|
|
|
|
fmt.sbprintf(&builder, "p%d__", function.pkg)
|
|
|
|
|
if function.file_hidden {
|
|
|
|
|
fmt.sbprintf(&builder, "f%d__", function.file)
|
|
|
|
|
}
|
|
|
|
|
strings.write_string(&builder, symbol_text(checker, function.name))
|
|
|
|
|
for arg in spec.args {
|
|
|
|
|
strings.write_string(&builder, "__")
|
|
|
|
@@ -5823,7 +5866,7 @@ build_block :: proc(
|
|
|
|
|
}
|
|
|
|
|
local, found := find_build_local(ctx.locals^[:], statement.name)
|
|
|
|
|
if !found {
|
|
|
|
|
global := find_global(checker, statement.name, ctx.pkg)
|
|
|
|
|
global := find_global(checker, statement.name, ctx.pkg, ctx.file)
|
|
|
|
|
if global == ast.INVALID_GLOBAL {
|
|
|
|
|
id := source.addf(checker.diagnostics, statement.span, "cannot assign unresolved local '%s'", symbol_text(checker, statement.name))
|
|
|
|
|
append(&body, hir.stmt_id(len(checker.module.statements)))
|
|
|
|
@@ -5967,7 +6010,7 @@ build_block :: proc(
|
|
|
|
|
}
|
|
|
|
|
} else if expr_ast.kind == .Struct_Literal {
|
|
|
|
|
target_pkg, available := expr_package(checker, expr_ast, ctx.pkg, ctx.file, true)
|
|
|
|
|
named := types.find_named(store, u32(target_pkg), u32(expr_ast.name)) if available else types.INVALID
|
|
|
|
|
named := types.find_named(store, u32(target_pkg), u32(expr_ast.name), file=u32(expr_lookup_file(expr_ast, ctx.file))) if available else types.INVALID
|
|
|
|
|
named = types.resolve_alias(named, store)
|
|
|
|
|
error_path = can_implicitly_convert_type(checker, named, error_type)
|
|
|
|
|
} else {
|
|
|
|
@@ -8688,26 +8731,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 &&
|
|
|
|
|
declarations_conflict(function.file, function.file_hidden, previous.file, previous.file_hidden) {
|
|
|
|
|
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 &&
|
|
|
|
|
declarations_conflict(function.file, function.file_hidden, global.file, global.file_hidden) {
|
|
|
|
|
source.addf(diagnostics, function.span, "package declaration '%s' conflicts with a global", symbol_text(&checker, function.name))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if declared_type_named(&checker, function.pkg, function.name) {
|
|
|
|
|
if type_declaration_conflicts(&checker, function.pkg, function.name, function.file, function.file_hidden) {
|
|
|
|
|
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 &&
|
|
|
|
|
declarations_conflict(global.file, global.file_hidden, previous.file, previous.file_hidden) {
|
|
|
|
|
source.addf(diagnostics, global.span, "duplicate global '%s'", symbol_text(&checker, global.name))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if declared_type_named(&checker, global.pkg, global.name) {
|
|
|
|
|
if type_declaration_conflicts(&checker, global.pkg, global.name, global.file, global.file_hidden) {
|
|
|
|
|
source.addf(diagnostics, global.span, "global '%s' shadows visible type", symbol_text(&checker, global.name))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|