aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-06-15 14:08:57 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-06-15 14:08:57 -0700
commit515d6430c0298daf304e48b46e6b43802bbfdab4 (patch)
tree0b67deffdca555ce4deaa0b5fb01e3f1edcfbc9b /src
parent0f4173c5d834dca2710005ffc1e040a4b307df00 (diff)
downloadzig-515d6430c0298daf304e48b46e6b43802bbfdab4.tar.gz
zig-515d6430c0298daf304e48b46e6b43802bbfdab4.zip
AstGen: support `@export` with field access
The Zig language specification will support identifiers and field access in order to refer to which declaration to export with `@export`. This commit implements the change in AstGen and updates the language reference.
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig29
-rw-r--r--src/Sema.zig3
-rw-r--r--src/Zir.zig11
3 files changed, 33 insertions, 10 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index d7720e7678..54500675df 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -6706,18 +6706,33 @@ fn builtinCall(
.@"export" => {
const node_tags = tree.nodes.items(.tag);
+ const node_datas = tree.nodes.items(.data);
// This function causes a Decl to be exported. The first parameter is not an expression,
// but an identifier of the Decl to be exported.
- if (node_tags[params[0]] != .identifier) {
- return astgen.failNode(params[0], "the first @export parameter must be an identifier", .{});
+ var namespace: Zir.Inst.Ref = .none;
+ var decl_name: u32 = 0;
+ switch (node_tags[params[0]]) {
+ .identifier => {
+ const ident_token = main_tokens[params[0]];
+ decl_name = try astgen.identAsString(ident_token);
+ // TODO look for local variables in scope matching `decl_name` and emit a compile
+ // error. Only top-level declarations can be exported. Until this is done, the
+ // compile error will end up being "use of undeclared identifier" in Sema.
+ },
+ .field_access => {
+ const namespace_node = node_datas[params[0]].lhs;
+ namespace = try typeExpr(gz, scope, namespace_node);
+ const dot_token = main_tokens[params[0]];
+ const field_ident = dot_token + 1;
+ decl_name = try astgen.identAsString(field_ident);
+ },
+ else => return astgen.failNode(
+ params[0], "the first @export parameter must be an identifier", .{},
+ ),
}
- const ident_token = main_tokens[params[0]];
- const decl_name = try astgen.identAsString(ident_token);
- // TODO look for local variables in scope matching `decl_name` and emit a compile
- // error. Only top-level declarations can be exported. Until this is done, the
- // compile error will end up being "use of undeclared identifier" in Sema.
const options = try comptimeExpr(gz, scope, .{ .ty = .export_options_type }, params[1]);
_ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
+ .namespace = namespace,
.decl_name = decl_name,
.options = options,
});
diff --git a/src/Sema.zig b/src/Sema.zig
index c9a150202e..07c8c3fc26 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1985,6 +1985,9 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!
const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
const decl_name = sema.code.nullTerminatedString(extra.decl_name);
+ if (extra.namespace != .none) {
+ return sema.mod.fail(&block.base, src, "TODO: implement exporting with field access", .{});
+ }
const decl = try sema.lookupIdentifier(block, lhs_src, decl_name);
const options = try sema.resolveInstConst(block, rhs_src, extra.options);
const struct_obj = options.ty.castTag(.@"struct").?.data;
diff --git a/src/Zir.zig b/src/Zir.zig
index 8f40d95940..0c8855bbc9 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -347,8 +347,9 @@ pub const Inst = struct {
error_union_type,
/// `error.Foo` syntax. Uses the `str_tok` field of the Data union.
error_value,
- /// Implements the `@export` builtin function.
- /// Uses the `pl_node` union field. Payload is `Bin`.
+ /// Implements the `@export` builtin function, based on either an identifier to a Decl,
+ /// or field access of a Decl.
+ /// Uses the `pl_node` union field. Payload is `Export`.
@"export",
/// Given a pointer to a struct or object that contains virtual fields, returns a pointer
/// to the named field. The field name is stored in string_bytes. Used by a.b syntax.
@@ -2738,6 +2739,9 @@ pub const Inst = struct {
};
pub const Export = struct {
+ /// If present, this is referring to a Decl via field access, e.g. `a.b`.
+ /// If omitted, this is referring to a Decl via identifier, e.g. `a`.
+ namespace: Ref,
/// Null-terminated string index.
decl_name: u32,
options: Ref,
@@ -3284,7 +3288,8 @@ const Writer = struct {
const extra = self.code.extraData(Inst.Export, inst_data.payload_index).data;
const decl_name = self.code.nullTerminatedString(extra.decl_name);
- try stream.print("{}, ", .{std.zig.fmtId(decl_name)});
+ try self.writeInstRef(stream, extra.namespace);
+ try stream.print(", {}, ", .{std.zig.fmtId(decl_name)});
try self.writeInstRef(stream, extra.options);
try stream.writeAll(") ");
try self.writeSrc(stream, inst_data.src());