From 6a053ffcc85ce3f2b598be08e5d0587c930b4358 Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 20 Aug 2020 18:50:13 +0300 Subject: [PATCH] stage2: comptime decl --- src-self-hosted/Module.zig | 51 ++++++++++++++++++++++++++++++++-- test/stage2/compare_output.zig | 5 ---- test/stage2/compile_errors.zig | 36 ++++++++---------------- 3 files changed, 60 insertions(+), 32 deletions(-) diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index 4893aaba7a..ba39aa8f38 100644 --- a/src-self-hosted/Module.zig +++ b/src-self-hosted/Module.zig @@ -1485,6 +1485,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { const type_node = var_decl.getTrailer("type_node") orelse break :blk null; + // Temporary arena for the zir instructions. var type_scope_arena = std.heap.ArenaAllocator.init(self.gpa); defer type_scope_arena.deinit(); var type_scope: Scope.GenZIR = .{ @@ -1539,7 +1540,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { try self.coerce(&inner_block.base, some, ret.operand) else ret.operand; - const val = try self.resolveConstValue(&inner_block.base, coerced); + const val = coerced.value() orelse + return self.fail(&block_scope.base, inst.src, "unable to resolve comptime value", .{}); var_type = explicit_type orelse try ret.operand.ty.copy(block_scope.arena); break :blk try val.copy(block_scope.arena); @@ -1603,7 +1605,41 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { } return type_changed; }, - .Comptime => @panic("TODO comptime decl"), + .Comptime => { + const comptime_decl = @fieldParentPtr(ast.Node.Comptime, "base", ast_node); + + decl.analysis = .in_progress; + + // A comptime decl does not store any value so we can just deinit this arena after analysis is done. + var analysis_arena = std.heap.ArenaAllocator.init(self.gpa); + defer analysis_arena.deinit(); + var gen_scope: Scope.GenZIR = .{ + .decl = decl, + .arena = &analysis_arena.allocator, + .parent = decl.scope, + }; + defer gen_scope.instructions.deinit(self.gpa); + + // TODO comptime scope here + _ = try astgen.expr(self, &gen_scope.base, .none, comptime_decl.expr); + + var block_scope: Scope.Block = .{ + .parent = null, + .func = null, + .decl = decl, + .instructions = .{}, + .arena = &analysis_arena.allocator, + }; + defer block_scope.instructions.deinit(self.gpa); + + _ = try zir_sema.analyzeBody(self, &block_scope.base, .{ + .instructions = gen_scope.instructions.items, + }); + + decl.analysis = .complete; + decl.generation = self.generation; + return true; + }, .Use => @panic("TODO usingnamespace decl"), else => unreachable, } @@ -1794,7 +1830,16 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void { } } } else if (src_decl.castTag(.Comptime)) |comptime_node| { - log.err("TODO: analyze comptime decl", .{}); + const name_index = self.getNextAnonNameIndex(); + const name = try std.fmt.allocPrint(self.gpa, "__comptime_{}", .{name_index}); + defer self.gpa.free(name); + + const name_hash = root_scope.fullyQualifiedNameHash(name); + const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl)); + + const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash); + root_scope.decls.appendAssumeCapacity(new_decl); + self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); } else if (src_decl.castTag(.ContainerField)) |container_field| { log.err("TODO: analyze container field", .{}); } else if (src_decl.castTag(.TestDecl)) |test_decl| { diff --git a/test/stage2/compare_output.zig b/test/stage2/compare_output.zig index 6fbc760f26..6c4b9c47e0 100644 --- a/test/stage2/compare_output.zig +++ b/test/stage2/compare_output.zig @@ -23,11 +23,6 @@ pub fn addCases(ctx: *TestContext) !void { case.addError("", &[_][]const u8{":1:1: error: no entry point found"}); - case.addError( - \\export fn _start() noreturn { - \\} - , &[_][]const u8{":2:1: error: expected noreturn, found void"}); - // Regular old hello world case.addCompareOutput( \\export fn _start() noreturn { diff --git a/test/stage2/compile_errors.zig b/test/stage2/compile_errors.zig index 45e60c0741..d90c0c7fae 100644 --- a/test/stage2/compile_errors.zig +++ b/test/stage2/compile_errors.zig @@ -67,6 +67,18 @@ pub fn addCases(ctx: *TestContext) !void { \\fn entry() void {} , &[_][]const u8{":2:4: error: redefinition of 'entry'"}); + ctx.compileError("incorrect return type", linux_x64, + \\export fn _start() noreturn { + \\} + , &[_][]const u8{":2:1: error: expected noreturn, found void"}); + + ctx.compileError("extern variable has no type", linux_x64, + \\comptime { + \\ _ = foo; + \\} + \\extern var foo; + , &[_][]const u8{":4:1: error: unable to infer variable type"}); + //ctx.incrementalFailure("function redefinition", linux_x64, // \\fn entry() void {} // \\fn entry() void {} @@ -108,28 +120,4 @@ pub fn addCases(ctx: *TestContext) !void { // \\ return 36893488147419103232; // \\} //, "1.zig", 2, 12, "integer value '36893488147419103232' cannot be stored in type 'c_int'"); - - //ctx.testCompileError( - // \\comptime { - // \\ var a: *align(4) align(4) i32 = 0; - // \\} - //, "1.zig", 2, 22, "Extra align qualifier"); - - //ctx.testCompileError( - // \\comptime { - // \\ var b: *const const i32 = 0; - // \\} - //, "1.zig", 2, 19, "Extra align qualifier"); - - //ctx.testCompileError( - // \\comptime { - // \\ var c: *volatile volatile i32 = 0; - // \\} - //, "1.zig", 2, 22, "Extra align qualifier"); - - //ctx.testCompileError( - // \\comptime { - // \\ var d: *allowzero allowzero i32 = 0; - // \\} - //, "1.zig", 2, 23, "Extra align qualifier"); }