build system (first pass)
This commit is contained in:
@@ -152,6 +152,10 @@ Checker :: struct {
|
||||
infer_stack: [dynamic]Infer_Frame,
|
||||
build_stack: [dynamic]Build_Expr_Frame,
|
||||
cycle_stack: [dynamic]Cycle_Frame,
|
||||
// Anonymous globals synthesized for `&<array literal>` (Zig's `&.{...}`). Staged
|
||||
// here during global/function building and flushed into module.globals AFTER
|
||||
// build_globals, so the 1:1 module.globals <-> ast.globals index identity holds.
|
||||
anon_globals: [dynamic]hir.Global,
|
||||
main_symbol: symbol.Id,
|
||||
sink_symbol: symbol.Id,
|
||||
type_symbol: symbol.Id,
|
||||
@@ -3792,6 +3796,46 @@ build_compound_expr :: proc(
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
case .Address:
|
||||
// `&<array literal>` (Zig's `&.{...}`): the operand is an rvalue with no
|
||||
// address, so promote it to an anonymous global constant and take *its*
|
||||
// address. Reuses the existing non-scalar-global storage path; only the
|
||||
// stable global address enters the expression, so it never dangles. The
|
||||
// resulting `*[N]T` then decays to a slice via the usual coercion.
|
||||
if expr.left != ast.INVALID_EXPR && checker.ast_module.exprs[expr.left].kind == .Array {
|
||||
operand := checker.ast_module.exprs[expr.left]
|
||||
// Propagate an element-expected type through `&` so literal elements
|
||||
// coerce to the target slice's element type (e.g. string -> []u8).
|
||||
// Without this, `&["x"]` infers `*[1]*[N:0]u8`, which won't decay to
|
||||
// `[][]u8` because can_decay_array_pointer requires child equality.
|
||||
element := types.INVALID
|
||||
if node, ok := types.node(store, expected); ok && (node.kind == .Slice || node.kind == .Array) {
|
||||
element = node.child
|
||||
}
|
||||
synth_expected := types.INVALID
|
||||
if types.is_valid(element) {
|
||||
synth_expected = types.array(store, element, u64(len(operand.args)), false)
|
||||
}
|
||||
value := build_nested_expr(checker, expr.left, locals, global_reads, calls, synth_expected, pkg, file)
|
||||
array_type := checker.module.exprs[value].type
|
||||
hidden_id := hir.Global_Id(len(checker.ast_module.globals) + len(checker.anon_globals))
|
||||
append(&checker.anon_globals, hir.Global{
|
||||
name = symbol.intern(checker.symbols, "__anon.array"),
|
||||
type = array_type,
|
||||
expr = value,
|
||||
writable = false,
|
||||
external = false,
|
||||
diagnostic = source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
add_unique_global(global_reads, hidden_id)
|
||||
global_ref := add_hir_expr(checker, hir.Expr{
|
||||
kind=.Global, span=expr.span, type=array_type, target=hir.global_ref(hidden_id),
|
||||
left=hir.INVALID_EXPR, right=hir.INVALID_EXPR, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
return add_hir_expr(checker, hir.Expr{
|
||||
kind=.Address, span=expr.span, type=types.pointer(store, array_type, false, false),
|
||||
left=global_ref, target=hir.INVALID_REF, right=hir.INVALID_EXPR, diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
value := build_nested_expr(checker, expr.left, locals, global_reads, calls, types.INVALID, pkg, file)
|
||||
if !hir_is_location(checker, value) {
|
||||
id := source.add(checker.diagnostics, expr.span, "'&' requires an addressable location")
|
||||
@@ -8087,6 +8131,7 @@ check :: proc(
|
||||
checker.infer_stack.allocator = allocator
|
||||
checker.build_stack.allocator = allocator
|
||||
checker.cycle_stack.allocator = allocator
|
||||
checker.anon_globals.allocator = allocator
|
||||
build_symbol_indexes(&checker)
|
||||
checker.global_types = make([]types.Type, len(ast_module.globals), allocator)
|
||||
checker.global_demands = make([]types.Type, len(ast_module.globals), allocator)
|
||||
@@ -8167,6 +8212,12 @@ check :: proc(
|
||||
for index := 0; index < len(checker.specs); index += 1 {
|
||||
build_function(&checker, spec_id(index))
|
||||
}
|
||||
// Flush anonymous globals synthesized for `&<array literal>`. Appended only now
|
||||
// (after every ast global was built at its identity-mapped index) so their ids,
|
||||
// pre-assigned as len(ast.globals)+stage_index, land exactly.
|
||||
for anon in checker.anon_globals {
|
||||
append(&checker.module.globals, anon)
|
||||
}
|
||||
propagate_global_reads(&checker)
|
||||
|
||||
main_template := find_template(&checker, checker.main_symbol, 0)
|
||||
|
||||
Reference in New Issue
Block a user