more forward declarations
This commit is contained in:
44
src/sema.zig
44
src/sema.zig
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user