This commit is contained in:
agra
2026-02-24 13:37:27 +02:00
parent 170e236764
commit b98711a1d3
13 changed files with 157 additions and 632 deletions

View File

@@ -172,6 +172,10 @@ pub const CodeGen = struct {
diagnostics: ?*errors.DiagnosticList = null,
// Current source span (set at genExpr/genStmt/genExprAsType entry)
current_span: Span = .{ .start = 0, .end = 0 },
// Current source file path (for error reporting in imported files)
current_source_file: ?[]const u8 = null,
// Import source map (path → source text, for error reporting)
import_sources: ?*const std.StringHashMap([:0]const u8) = null,
// Loop context: break/continue target basic blocks (null when not in a loop)
loop_break_bb: c.LLVMBasicBlockRef = null,
loop_continue_bb: c.LLVMBasicBlockRef = null,
@@ -238,6 +242,7 @@ pub const CodeGen = struct {
fd: ast.FnDecl,
name: []const u8, // qualified name (may differ from fd.name for namespaced functions)
namespace: ?[]const u8 = null,
source_file: ?[]const u8 = null,
};
const TypeCategory = enum {
@@ -526,12 +531,18 @@ pub const CodeGen = struct {
}
fn emitError(self: *CodeGen, msg: []const u8) error{CodeGenError} {
if (self.diagnostics) |diags| diags.add(.err, msg, self.current_span);
if (self.diagnostics) |diags| {
diags.current_source_file = self.current_source_file;
diags.add(.err, msg, self.current_span);
}
return error.CodeGenError;
}
fn emitErrorFmt(self: *CodeGen, comptime fmt: []const u8, args: anytype) error{CodeGenError} {
if (self.diagnostics) |diags| diags.addFmt(.err, self.current_span, fmt, args);
if (self.diagnostics) |diags| {
diags.current_source_file = self.current_source_file;
diags.addFmt(.err, self.current_span, fmt, args);
}
return error.CodeGenError;
}
@@ -1235,6 +1246,7 @@ pub const CodeGen = struct {
// Pre-scan: collect named library constants (handles forward references)
for (root.data.root.decls) |decl| {
self.current_source_file = decl.source_file;
switch (decl.data) {
.library_decl => |ld| {
try self.library_constants.put(ld.name, ld.lib_name);
@@ -1256,6 +1268,7 @@ pub const CodeGen = struct {
// Pass 1: Register all declarations (signatures only, no bodies)
for (root.data.root.decls) |decl| {
self.current_source_file = decl.source_file;
switch (decl.data) {
.fn_decl => |fd| {
if (fd.body.data == .builtin_expr) {
@@ -1392,13 +1405,14 @@ pub const CodeGen = struct {
// Functions with Any parameters (like any_to_string) are deferred to Pass 3
// so that all types are registered before their type-match expressions are compiled.
for (root.data.root.decls) |decl| {
self.current_source_file = decl.source_file;
switch (decl.data) {
.fn_decl => |fd| {
if (fd.body.data == .builtin_expr or fd.body.data == .foreign_expr) {
// skip — no body to generate
} else if (fd.type_params.len == 0) {
if (shouldDeferFnBody(fd)) {
try self.deferred_fn_bodies.append(self.allocator, .{ .fd = fd, .name = fd.name });
try self.deferred_fn_bodies.append(self.allocator, .{ .fd = fd, .name = fd.name, .source_file = self.current_source_file });
} else {
try self.genFnBody(fd, fd.name);
}
@@ -1431,8 +1445,11 @@ pub const CodeGen = struct {
// Pass 3: Compile deferred function bodies (after all types are registered)
for (self.deferred_fn_bodies.items) |deferred| {
const saved_ns = self.current_namespace;
const saved_sf = self.current_source_file;
self.current_namespace = deferred.namespace;
self.current_source_file = deferred.source_file;
defer self.current_namespace = saved_ns;
defer self.current_source_file = saved_sf;
try self.genFnBody(deferred.fd, deferred.name);
}
@@ -2448,7 +2465,7 @@ pub const CodeGen = struct {
} else if (fd.type_params.len == 0) {
const qualified = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ns.name, fd.name });
if (shouldDeferFnBody(fd)) {
try self.deferred_fn_bodies.append(self.allocator, .{ .fd = fd, .name = qualified, .namespace = ns.name });
try self.deferred_fn_bodies.append(self.allocator, .{ .fd = fd, .name = qualified, .namespace = ns.name, .source_file = self.current_source_file });
} else {
try self.genFnBody(fd, qualified);
}
@@ -2483,7 +2500,7 @@ pub const CodeGen = struct {
if (fd.type_params.len > 0) continue; // generic methods instantiated on demand
const qualified = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ sd.name, fd.name });
if (shouldDeferFnBody(fd)) {
try self.deferred_fn_bodies.append(self.allocator, .{ .fd = fd, .name = qualified, .namespace = sd.name });
try self.deferred_fn_bodies.append(self.allocator, .{ .fd = fd, .name = qualified, .namespace = sd.name, .source_file = self.current_source_file });
} else {
try self.genFnBody(fd, qualified);
}
@@ -5249,7 +5266,7 @@ pub const CodeGen = struct {
if (fd.type_params.len > 0) continue; // generic methods instantiated on demand
const qualified = try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ ib.target_type, fd.name });
if (shouldDeferFnBody(fd)) {
try self.deferred_fn_bodies.append(self.allocator, .{ .fd = fd, .name = qualified, .namespace = ib.target_type });
try self.deferred_fn_bodies.append(self.allocator, .{ .fd = fd, .name = qualified, .namespace = ib.target_type, .source_file = self.current_source_file });
} else {
try self.genFnBody(fd, qualified);
}