vtables, protocol
This commit is contained in:
49
src/sema.zig
49
src/sema.zig
@@ -16,6 +16,7 @@ pub const SymbolKind = enum {
|
||||
function,
|
||||
enum_type,
|
||||
struct_type,
|
||||
protocol_type,
|
||||
type_alias,
|
||||
param,
|
||||
namespace,
|
||||
@@ -650,9 +651,10 @@ pub const Analyzer = struct {
|
||||
}
|
||||
|
||||
// Built-in names that aren't declared in source
|
||||
if (std.mem.eql(u8, name, "io")) return;
|
||||
if (std.mem.eql(u8, name, "true") or std.mem.eql(u8, name, "false")) return;
|
||||
if (std.mem.eql(u8, name, "cast")) return;
|
||||
const builtins = [_][]const u8{ "io", "true", "false", "cast", "closure", "out", "size_of", "malloc", "free", "memcpy", "memset" };
|
||||
for (builtins) |b| {
|
||||
if (std.mem.eql(u8, name, b)) return;
|
||||
}
|
||||
|
||||
try self.diagnostics.append(self.allocator, .{
|
||||
.level = .warn,
|
||||
@@ -844,6 +846,7 @@ pub const Analyzer = struct {
|
||||
.param,
|
||||
.match_arm,
|
||||
.undef_literal,
|
||||
.inferred_type,
|
||||
.builtin_expr,
|
||||
.foreign_expr,
|
||||
.library_decl,
|
||||
@@ -863,6 +866,30 @@ pub const Analyzer = struct {
|
||||
.slice_expr,
|
||||
.tuple_type_expr,
|
||||
=> {},
|
||||
.protocol_decl => |pd| {
|
||||
try self.addSymbol(pd.name, .protocol_type, null, node.span);
|
||||
// Recurse into default method bodies
|
||||
for (pd.methods) |method| {
|
||||
if (method.default_body) |body| {
|
||||
try self.pushScope();
|
||||
// `self` is implicit in protocol default methods
|
||||
try self.addSymbol("self", .param, null, node.span);
|
||||
for (method.param_names) |pname| {
|
||||
try self.addSymbol(pname, .param, null, node.span);
|
||||
}
|
||||
try self.analyzeNode(body);
|
||||
self.popScope();
|
||||
}
|
||||
}
|
||||
},
|
||||
.impl_block => |ib| {
|
||||
// Each impl block gets its own scope so methods don't conflict across impls
|
||||
try self.pushScope();
|
||||
for (ib.methods) |method_node| {
|
||||
try self.analyzeNode(method_node);
|
||||
}
|
||||
self.popScope();
|
||||
},
|
||||
.ufcs_alias => |ua| {
|
||||
// Register the alias name as a function and resolve the target
|
||||
try self.addSymbol(ua.name, .function, null, node.span);
|
||||
@@ -1205,6 +1232,7 @@ pub fn findNodeAtOffset(node: *Node, offset: u32) ?*Node {
|
||||
.param,
|
||||
.match_arm,
|
||||
.undef_literal,
|
||||
.inferred_type,
|
||||
.builtin_expr,
|
||||
.foreign_expr,
|
||||
.library_decl,
|
||||
@@ -1228,6 +1256,21 @@ pub fn findNodeAtOffset(node: *Node, offset: u32) ?*Node {
|
||||
.ufcs_alias,
|
||||
.closure_type_expr,
|
||||
=> {},
|
||||
.protocol_decl => |pd| {
|
||||
for (pd.methods) |method| {
|
||||
if (method.default_body) |body| {
|
||||
if (findNodeAtOffset(body, offset)) |found| return found;
|
||||
}
|
||||
for (method.params) |param| {
|
||||
if (findNodeAtOffset(param, offset)) |found| return found;
|
||||
}
|
||||
}
|
||||
},
|
||||
.impl_block => |ib| {
|
||||
for (ib.methods) |method_node| {
|
||||
if (findNodeAtOffset(method_node, offset)) |found| return found;
|
||||
}
|
||||
},
|
||||
.tuple_literal => |tl| {
|
||||
for (tl.elements) |elem| {
|
||||
if (findNodeAtOffset(elem.value, offset)) |found| return found;
|
||||
|
||||
Reference in New Issue
Block a user