more forward declarations

This commit is contained in:
agra
2026-02-24 17:37:52 +02:00
parent 97475d6cfe
commit 566121c45a
13 changed files with 867 additions and 88 deletions

View File

@@ -129,7 +129,8 @@ pub const Analyzer = struct {
fn registerTopLevelDeclPrefixed(self: *Analyzer, node: *Node, ns_prefix: ?[]const u8) !void {
switch (node.data) {
.fn_decl => |fd| {
const ret_ty = resolveReturnType(fd);
const ret_ty = resolveReturnType(fd) orelse
if (fd.is_arrow) self.inferFnReturnType(fd.params, fd.body) else null;
try self.addSymbol(fd.name, .function, ret_ty, node.span);
// Populate fn_signatures registry
var param_types = std.ArrayList(Type).empty;
@@ -171,7 +172,10 @@ pub const Analyzer = struct {
const pt = Type.fromTypeExpr(param.type_expr) orelse Type.s(64);
try param_types.append(self.allocator, pt);
}
const ret = if (lam.return_type) |rt| Type.fromTypeExpr(rt) orelse .void_type else .void_type;
const ret = if (lam.return_type) |rt|
Type.fromTypeExpr(rt) orelse .void_type
else
self.inferFnReturnType(lam.params, lam.body) orelse .void_type;
const key = if (ns_prefix) |pfx|
try std.fmt.allocPrint(self.allocator, "{s}.{s}", .{ pfx, cd.name })
else
@@ -666,7 +670,21 @@ pub const Analyzer = struct {
fn analyzeNode(self: *Analyzer, node: *Node) !void {
switch (node.data) {
.fn_decl => |fd| {
try self.addSymbol(fd.name, .function, resolveReturnType(fd), node.span);
const local_ret_ty = resolveReturnType(fd) orelse
if (fd.is_arrow) self.inferFnReturnType(fd.params, fd.body) else null;
try self.addSymbol(fd.name, .function, local_ret_ty, node.span);
// Register fn_signatures for local functions (for return type hints + hover)
{
var param_types = std.ArrayList(Type).empty;
for (fd.params) |param| {
const pt = Type.fromTypeExpr(param.type_expr) orelse Type.s(64);
try param_types.append(self.allocator, pt);
}
try self.fn_signatures.put(fd.name, .{
.param_types = try param_types.toOwnedSlice(self.allocator),
.return_type = local_ret_ty orelse .void_type,
});
}
try self.pushScope();
try self.analyzeParams(fd.params);
try self.analyzeNode(fd.body);
@@ -967,6 +985,26 @@ pub const Analyzer = struct {
return null;
}
/// Infer return type from a function/lambda body by temporarily registering params.
fn inferFnReturnType(self: *Analyzer, params: []const ast.Param, body: *const Node) ?Type {
self.pushScope() catch return null;
for (params) |param| {
const pt = Type.fromTypeExpr(param.type_expr) orelse Type.s(64);
self.addSymbol(param.name, .param, pt, param.name_span) catch {};
}
// Arrow fn_decl wraps body in block{[expr]} — unwrap to inner expression
const expr_node = if (body.data == .block) blk: {
const stmts = body.data.block.stmts;
if (stmts.len > 0) break :blk stmts[stmts.len - 1];
break :blk body;
} else body;
const inferred = self.inferExprType(expr_node);
self.popScope();
if (inferred != .void_type) return inferred;
return null;
}
fn resolveTypeAnnotation(self: *Analyzer, type_node: ?*Node) ?Type {
if (type_node) |tn| {
if (Type.fromTypeExpr(tn)) |t| return t;