aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-01-01 19:24:02 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-01-02 19:10:11 -0700
commitfea8659b82ea1a785f933c58ba9d65ceb05a4094 (patch)
tree91d33abe8ae357bc5aecc06e9fd2423bd83a10a8 /src/Module.zig
parentfb37c1b0912c65d72b82f32df8bc7e780ab1ad80 (diff)
downloadzig-fea8659b82ea1a785f933c58ba9d65ceb05a4094.tar.gz
zig-fea8659b82ea1a785f933c58ba9d65ceb05a4094.zip
stage2: comptime function calls
* Function calls that happen in a comptime scope get called at compile-time. We do this by putting the parameters in place as constant values and then running regular function analysis on the body. * Added `Scope.Block.dump()` for debugging purposes. * Fixed some code to call `identifierTokenString` rather than `tokenSlice`, making it work for `@""` syntax. * Implemented `Value.copy` for big integers. Follow-up issues to tackle: * Adding compile errors to the callsite instead of the callee Decl. * Proper error notes for "called from here". - Related: #7555 * Branch quotas. * ZIR support?
Diffstat (limited to 'src/Module.zig')
-rw-r--r--src/Module.zig42
1 files changed, 35 insertions, 7 deletions
diff --git a/src/Module.zig b/src/Module.zig
index d1719059c4..29c19c09a0 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -268,6 +268,11 @@ pub const Decl = struct {
}
}
+ /// Asserts that the `Decl` is part of AST and not ZIRModule.
+ pub fn getFileScope(self: *Decl) *Scope.File {
+ return self.scope.cast(Scope.Container).?.file_scope;
+ }
+
fn removeDependant(self: *Decl, other: *Decl) void {
self.dependants.removeAssertDiscard(other);
}
@@ -776,6 +781,11 @@ pub const Scope = struct {
results: ArrayListUnmanaged(*Inst),
block_inst: *Inst.Block,
};
+
+ /// For debugging purposes.
+ pub fn dump(self: *Block, mod: Module) void {
+ zir.dumpBlock(mod, self);
+ }
};
/// This is a temporary structure, references to it are valid only
@@ -992,11 +1002,11 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
defer tracy.end();
const container_scope = decl.scope.cast(Scope.Container).?;
- const tree = try self.getAstTree(container_scope);
+ const tree = try self.getAstTree(container_scope.file_scope);
const ast_node = tree.root_node.decls()[decl.src_index];
switch (ast_node.tag) {
.FnProto => {
- const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", ast_node);
+ const fn_proto = ast_node.castTag(.FnProto).?;
decl.analysis = .in_progress;
@@ -1131,7 +1141,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
for (fn_proto.params()) |param, i| {
const name_token = param.name_token.?;
const src = tree.token_locs[name_token].start;
- const param_name = tree.tokenSlice(name_token); // TODO: call identifierTokenString
+ const param_name = try self.identifierTokenString(&gen_scope.base, name_token);
const arg = try gen_scope_arena.allocator.create(zir.Inst.Arg);
arg.* = .{
.base = .{
@@ -1496,12 +1506,10 @@ fn getSrcModule(self: *Module, root_scope: *Scope.ZIRModule) !*zir.Module {
}
}
-fn getAstTree(self: *Module, container_scope: *Scope.Container) !*ast.Tree {
+pub fn getAstTree(self: *Module, root_scope: *Scope.File) !*ast.Tree {
const tracy = trace(@src());
defer tracy.end();
- const root_scope = container_scope.file_scope;
-
switch (root_scope.status) {
.never_loaded, .unloaded_success => {
try self.failed_files.ensureCapacity(self.gpa, self.failed_files.items().len + 1);
@@ -1549,7 +1557,7 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void
// We may be analyzing it for the first time, or this may be
// an incremental update. This code handles both cases.
- const tree = try self.getAstTree(container_scope);
+ const tree = try self.getAstTree(container_scope.file_scope);
const decls = tree.root_node.decls();
try self.comp.work_queue.ensureUnusedCapacity(decls.len);
@@ -3427,3 +3435,23 @@ pub fn validateVarType(mod: *Module, scope: *Scope, src: usize, ty: Type) !void
return mod.fail(scope, src, "variable of type '{}' must be const or comptime", .{ty});
}
}
+
+/// Identifier token -> String (allocated in scope.arena())
+pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex) InnerError![]const u8 {
+ const tree = scope.tree();
+
+ const ident_name = tree.tokenSlice(token);
+ if (mem.startsWith(u8, ident_name, "@")) {
+ const raw_string = ident_name[1..];
+ var bad_index: usize = undefined;
+ return std.zig.parseStringLiteral(scope.arena(), raw_string, &bad_index) catch |err| switch (err) {
+ error.InvalidCharacter => {
+ const bad_byte = raw_string[bad_index];
+ const src = tree.token_locs[token].start;
+ return mod.fail(scope, src + 1 + bad_index, "invalid string literal character: '{c}'\n", .{bad_byte});
+ },
+ else => |e| return e,
+ };
+ }
+ return ident_name;
+}