Skip to content

Commit 388bdf8

Browse files
Automatically collect parameter & return types of builtins
fixes #2325
1 parent 69b6c8f commit 388bdf8

File tree

7 files changed

+135
-219
lines changed

7 files changed

+135
-219
lines changed

src/analysis.zig

Lines changed: 15 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ pub const DocumentScope = @import("DocumentScope.zig");
2323
pub const Declaration = DocumentScope.Declaration;
2424
pub const Scope = DocumentScope.Scope;
2525

26+
const version_data = @import("version_data");
27+
2628
const Analyser = @This();
2729

2830
gpa: std.mem.Allocator,
@@ -2101,10 +2103,6 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) error
21012103
return resolved_type.typeOf(analyser);
21022104
}
21032105

2104-
if (std.mem.eql(u8, call_name, "@typeInfo")) {
2105-
return analyser.instanceStdBuiltinType("Type");
2106-
}
2107-
21082106
const type_map: std.StaticStringMap(InternPool.Index) = .initComptime(.{
21092107
.{ "type", .type_type },
21102108
.{ "void", .void_type },
@@ -2183,20 +2181,10 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) error
21832181
return try analyser.resolveFieldAccess(lhs, field_name);
21842182
}
21852183

2186-
if (std.mem.eql(u8, call_name, "@src")) {
2187-
return analyser.instanceStdBuiltinType("SourceLocation");
2188-
}
2189-
21902184
if (std.mem.eql(u8, call_name, "@compileError")) {
21912185
return .{ .data = .{ .compile_error = node_handle }, .is_type_val = false };
21922186
}
21932187

2194-
if (std.mem.eql(u8, call_name, "@panic") or
2195-
std.mem.eql(u8, call_name, "@trap"))
2196-
{
2197-
return Type.fromIP(analyser, .noreturn_type, null);
2198-
}
2199-
22002188
if (std.mem.eql(u8, call_name, "@Vector")) {
22012189
if (params.len != 2) return null;
22022190

@@ -2220,6 +2208,13 @@ fn resolveTypeOfNodeUncached(analyser: *Analyser, options: ResolveOptions) error
22202208

22212209
return Type.fromIP(analyser, .type_type, vector_ty_ip_index);
22222210
}
2211+
2212+
if (version_data.builtins.get(call_name)) |data| {
2213+
const type_str = data.return_type;
2214+
if (try analyser.resolvePrimitive(type_str)) |primitive|
2215+
return Type.fromIP(analyser, primitive, null);
2216+
return analyser.instanceStdBuiltinType(type_str);
2217+
}
22232218
},
22242219
.fn_proto,
22252220
.fn_proto_multi,
@@ -5828,88 +5823,12 @@ pub fn resolveExpressionTypeFromAncestors(
58285823
return try ty.instanceTypeVal(analyser);
58295824
}
58305825

5831-
if (std.mem.eql(u8, call_name, "@branchHint")) {
5832-
if (params.len == 0) return null;
5833-
if (params[0] != node) return null;
5834-
return analyser.instanceStdBuiltinType("BranchHint");
5835-
}
5836-
5837-
if (std.mem.eql(u8, call_name, "@atomicLoad")) {
5838-
if (params.len <= 2) return null;
5839-
if (params[2] != node) return null;
5840-
return analyser.instanceStdBuiltinType("AtomicOrder");
5841-
}
5842-
5843-
if (std.mem.eql(u8, call_name, "@atomicRmw")) {
5844-
if (params.len > 2 and params[2] == node)
5845-
return analyser.instanceStdBuiltinType("AtomicRmwOp");
5846-
if (params.len > 4 and params[4] == node)
5847-
return analyser.instanceStdBuiltinType("AtomicOrder");
5848-
return null;
5849-
}
5850-
5851-
if (std.mem.eql(u8, call_name, "@atomicStore")) {
5852-
if (params.len <= 3) return null;
5853-
if (params[3] != node) return null;
5854-
return analyser.instanceStdBuiltinType("AtomicOrder");
5855-
}
5856-
5857-
if (std.mem.eql(u8, call_name, "@cmpxchgStrong")) {
5858-
if (params.len > 4 and params[4] == node)
5859-
return analyser.instanceStdBuiltinType("AtomicOrder");
5860-
if (params.len > 5 and params[5] == node)
5861-
return analyser.instanceStdBuiltinType("AtomicOrder");
5862-
return null;
5863-
}
5864-
5865-
if (std.mem.eql(u8, call_name, "@cmpxchgWeak")) {
5866-
if (params.len > 4 and params[4] == node)
5867-
return analyser.instanceStdBuiltinType("AtomicOrder");
5868-
if (params.len > 5 and params[5] == node)
5869-
return analyser.instanceStdBuiltinType("AtomicOrder");
5870-
return null;
5871-
}
5872-
5873-
if (std.mem.eql(u8, call_name, "@call")) {
5874-
if (params.len == 0) return null;
5875-
if (params[0] != node) return null;
5876-
return analyser.instanceStdBuiltinType("CallModifier");
5877-
}
5878-
5879-
if (std.mem.eql(u8, call_name, "@export")) {
5880-
if (params.len <= 1) return null;
5881-
if (params[1] != node) return null;
5882-
return analyser.instanceStdBuiltinType("ExportOptions");
5883-
}
5884-
5885-
if (std.mem.eql(u8, call_name, "@extern")) {
5886-
if (params.len <= 1) return null;
5887-
if (params[1] != node) return null;
5888-
return analyser.instanceStdBuiltinType("ExternOptions");
5889-
}
5890-
5891-
if (std.mem.eql(u8, call_name, "@prefetch")) {
5892-
if (params.len <= 1) return null;
5893-
if (params[1] != node) return null;
5894-
return analyser.instanceStdBuiltinType("PrefetchOptions");
5895-
}
5896-
5897-
if (std.mem.eql(u8, call_name, "@reduce")) {
5898-
if (params.len == 0) return null;
5899-
if (params[0] != node) return null;
5900-
return analyser.instanceStdBuiltinType("ReduceOp");
5901-
}
5902-
5903-
if (std.mem.eql(u8, call_name, "@setFloatMode")) {
5904-
if (params.len == 0) return null;
5905-
if (params[0] != node) return null;
5906-
return analyser.instanceStdBuiltinType("FloatMode");
5907-
}
5908-
5909-
if (std.mem.eql(u8, call_name, "@Type")) {
5910-
if (params.len == 0) return null;
5911-
if (params[0] != node) return null;
5912-
return analyser.instanceStdBuiltinType("Type");
5826+
if (version_data.builtins.get(call_name)) |data| {
5827+
const index = std.mem.indexOfScalar(Ast.Node.Index, params, node) orelse return null;
5828+
if (index >= data.parameters.len) return null;
5829+
const parameter = data.parameters[index];
5830+
const type_str = parameter.type orelse return null;
5831+
return analyser.instanceStdBuiltinType(type_str);
59135832
}
59145833
},
59155834

src/features/completions.zig

Lines changed: 5 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ fn completeBuiltin(builder: *Builder) error{OutOfMemory}!void {
529529
.only_name => .{ name, .PlainText },
530530
.snippet => blk: {
531531
std.debug.assert(use_snippets);
532-
if (builtin.arguments.len == 0) break :blk .{ try std.fmt.allocPrint(builder.arena, "{s}()", .{name}), .PlainText };
532+
if (builtin.parameters.len == 0) break :blk .{ try std.fmt.allocPrint(builder.arena, "{s}()", .{name}), .PlainText };
533533
if (use_placeholders) break :blk .{ builtin.snippet, .Snippet };
534534
break :blk .{ try std.fmt.allocPrint(builder.arena, "{s}(${{1:}})", .{name}), .Snippet };
535535
},
@@ -1484,95 +1484,10 @@ fn resolveBuiltinFnArg(
14841484
/// Includes leading `@`
14851485
name: []const u8,
14861486
) std.mem.Allocator.Error!?Analyser.Type {
1487-
const builtin_name: []const u8 = name: {
1488-
if (std.mem.eql(u8, name, "@Type")) {
1489-
switch (arg_index) {
1490-
0 => break :name "Type",
1491-
else => return null,
1492-
}
1493-
}
1494-
1495-
if (std.mem.eql(u8, name, "@setFloatMode")) {
1496-
switch (arg_index) {
1497-
0 => break :name "FloatMode",
1498-
else => return null,
1499-
}
1500-
}
1501-
1502-
if (std.mem.eql(u8, name, "@prefetch")) {
1503-
switch (arg_index) {
1504-
1 => break :name "PrefetchOptions",
1505-
else => return null,
1506-
}
1507-
}
1508-
1509-
if (std.mem.eql(u8, name, "@reduce")) {
1510-
switch (arg_index) {
1511-
0 => break :name "ReduceOp",
1512-
else => return null,
1513-
}
1514-
}
1515-
1516-
if (std.mem.eql(u8, name, "@export")) {
1517-
switch (arg_index) {
1518-
1 => break :name "ExportOptions",
1519-
else => return null,
1520-
}
1521-
}
1522-
1523-
if (std.mem.eql(u8, name, "@extern")) {
1524-
switch (arg_index) {
1525-
1 => break :name "ExternOptions",
1526-
else => return null,
1527-
}
1528-
}
1529-
1530-
if (std.mem.eql(u8, name, "@cmpxchgWeak") or std.mem.eql(u8, name, "@cmpxchgStrong")) {
1531-
switch (arg_index) {
1532-
4, 5 => break :name "AtomicOrder",
1533-
else => return null,
1534-
}
1535-
}
1536-
1537-
if (std.mem.eql(u8, name, "@atomicLoad")) {
1538-
switch (arg_index) {
1539-
2 => break :name "AtomicOrder",
1540-
else => return null,
1541-
}
1542-
}
1543-
1544-
if (std.mem.eql(u8, name, "@atomicStore")) {
1545-
switch (arg_index) {
1546-
3 => break :name "AtomicOrder",
1547-
else => return null,
1548-
}
1549-
}
1550-
1551-
if (std.mem.eql(u8, name, "@atomicRmw")) {
1552-
switch (arg_index) {
1553-
2 => break :name "AtomicRmwOp",
1554-
4 => break :name "AtomicOrder",
1555-
else => return null,
1556-
}
1557-
}
1558-
1559-
if (std.mem.eql(u8, name, "@call")) {
1560-
switch (arg_index) {
1561-
0 => break :name "CallModifier",
1562-
else => return null,
1563-
}
1564-
}
1565-
1566-
if (std.mem.eql(u8, name, "@branchHint")) {
1567-
switch (arg_index) {
1568-
0 => break :name "BranchHint",
1569-
else => return null,
1570-
}
1571-
}
1572-
1573-
return null;
1574-
};
1575-
1487+
const builtin = version_data.builtins.get(name) orelse return null;
1488+
if (arg_index >= builtin.parameters.len) return null;
1489+
const param = builtin.parameters[arg_index];
1490+
const builtin_name = param.type orelse return null;
15761491
return analyser.instanceStdBuiltinType(builtin_name);
15771492
}
15781493

src/features/inlay_hints.zig

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -282,26 +282,28 @@ fn writeCallHint(
282282
}
283283
}
284284

285-
/// takes parameter nodes from the ast and function parameter names from `Builtin.arguments` and writes parameter hints into `builder.hints`
286-
fn writeBuiltinHint(builder: *Builder, parameters: []const Ast.Node.Index, arguments: []const []const u8) !void {
285+
/// takes parameter nodes from the ast and function parameter names from `Builtin.parameters` and writes parameter hints into `builder.hints`
286+
fn writeBuiltinHint(builder: *Builder, parameters: []const Ast.Node.Index, params: []const data.Builtin.Parameter) !void {
287287
const tracy_zone = tracy.trace(@src());
288288
defer tracy_zone.end();
289289

290290
const handle = builder.handle;
291291
const tree = handle.tree;
292292

293-
const len = @min(arguments.len, parameters.len);
294-
for (arguments[0..len], parameters[0..len]) |arg, parameter| {
295-
if (arg.len == 0) continue;
293+
const len = @min(params.len, parameters.len);
294+
for (params[0..len], parameters[0..len]) |param, parameter| {
295+
const signature = param.signature;
296+
if (signature.len == 0) continue;
296297

297-
const colonIndex = std.mem.indexOfScalar(u8, arg, ':');
298-
const type_expr: []const u8 = if (colonIndex) |index| arg[index + 1 ..] else &.{};
298+
const colonIndex = std.mem.indexOfScalar(u8, signature, ':');
299+
const type_expr = param.type orelse "";
299300

301+
// TODO: parse noalias/comptime/label in config_gen.zig
300302
var maybe_label: ?[]const u8 = null;
301303
var no_alias = false;
302304
var comp_time = false;
303305

304-
var it = std.mem.splitScalar(u8, arg[0 .. colonIndex orelse arg.len], ' ');
306+
var it = std.mem.splitScalar(u8, signature[0 .. colonIndex orelse signature.len], ' ');
305307
while (it.next()) |item| {
306308
if (item.len == 0) continue;
307309
maybe_label = item;
@@ -518,7 +520,7 @@ fn writeNodeInlayHint(
518520
if (params.len == 0) return;
519521

520522
if (data.builtins.get(name)) |builtin| {
521-
try writeBuiltinHint(builder, params, builtin.arguments);
523+
try writeBuiltinHint(builder, params, builtin.parameters);
522524
}
523525
},
524526
.struct_init_one,

src/features/signature_help.zig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,11 @@ pub fn getSignatureInfo(
193193
const builtin = data.builtins.get(tree.tokenSlice(expr_last_token)) orelse return null;
194194
const param_infos = try arena.alloc(
195195
types.ParameterInformation,
196-
builtin.arguments.len,
196+
builtin.parameters.len,
197197
);
198-
for (param_infos, builtin.arguments) |*info, argument| {
198+
for (param_infos, builtin.parameters) |*info, parameter| {
199199
info.* = .{
200-
.label = .{ .string = argument },
200+
.label = .{ .string = parameter.signature },
201201
.documentation = null,
202202
};
203203
}

0 commit comments

Comments
 (0)