From f61bb824e5888d31eac56d950aa32ca038e3b5ee Mon Sep 17 00:00:00 2001 From: fubark Date: Mon, 2 Sep 2024 11:23:24 -0400 Subject: [PATCH] `_` initializes void value. --- src/ast.zig | 5 ++++- src/bc_gen.zig | 13 +++++++++++++ src/ir.zig | 1 + src/parser.zig | 4 ++++ src/sema.zig | 8 ++++++++ src/std/test.zig | 3 +++ src/types.zig | 1 + src/vm.zig | 6 ++++++ test/behavior_test.zig | 1 + test/types/void.cy | 8 ++++++++ 10 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 test/types/void.cy diff --git a/src/ast.zig b/src/ast.zig index 88457e6cb..34424e33a 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -109,6 +109,7 @@ pub const NodeType = enum(u7) { unwrap_choice, unwrap_or, use_alias, + void_lit, whileCondStmt, whileInfStmt, whileOptStmt, @@ -700,6 +701,7 @@ fn NodeData(comptime node_t: NodeType) type { .unwrap_choice => UnwrapChoice, .unwrap_or => UnwrapOr, .use_alias => UseAlias, + .void_lit => Token, .whileCondStmt => WhileCondStmt, .whileInfStmt => WhileInfStmt, .whileOptStmt => WhileOptStmt, @@ -838,6 +840,7 @@ pub const Node = struct { .unwrap_choice => self.cast(.unwrap_choice).left.pos(), .unwrap_or => self.cast(.unwrap_or).opt.pos(), .use_alias => self.cast(.use_alias).pos, + .void_lit => self.cast(.void_lit).pos, .whileInfStmt => self.cast(.whileInfStmt).pos, .whileCondStmt => self.cast(.whileCondStmt).pos, .whileOptStmt => self.cast(.whileOptStmt).pos, @@ -913,7 +916,7 @@ pub const UnaryOp = enum(u8) { }; test "ast internals." { - try t.eq(std.enums.values(NodeType).len, 100); + try t.eq(std.enums.values(NodeType).len, 101); try t.eq(@sizeOf(NodeHeader), 1); } diff --git a/src/bc_gen.zig b/src/bc_gen.zig index 65a402225..ad4eb1b7e 100644 --- a/src/bc_gen.zig +++ b/src/bc_gen.zig @@ -499,6 +499,7 @@ fn genExpr(c: *Chunk, idx: usize, cstr: Cstr) anyerror!GenValue { .unwrapChoice => genUnwrapChoice(c, idx, cstr, node), .unwrap_or => genUnwrapOr(c, idx, cstr, node), .varSym => genVarSym(c, idx, cstr, node), + .voidv => genVoid(c, cstr, node), .blockExpr => genBlockExpr(c, idx, cstr, node), else => { rt.errZFmt(c.vm, "{}\n", .{code}); @@ -1237,6 +1238,18 @@ fn genUnwrapChoice(c: *Chunk, loc: usize, cstr: Cstr, node: *ast.Node) !GenValue return finishDstInst(c, inst, retain); } +fn genVoid(c: *Chunk, cstr: Cstr, node: *ast.Node) !GenValue { + const inst = try bc.selectForNoErrNoDepInst(c, cstr, bt.Void, false, node); + if (inst.requiresPreRelease) { + try pushRelease(c, inst.dst, node); + } + // Does not generate inst. + if (inst.own_dst) { + try initSlot(c, inst.dst, false, node); + } + return finishNoErrNoDepInst(c, inst, false); +} + fn genTrue(c: *Chunk, cstr: Cstr, node: *ast.Node) !GenValue { const inst = try bc.selectForNoErrNoDepInst(c, cstr, bt.Boolean, false, node); if (inst.requiresPreRelease) { diff --git a/src/ir.zig b/src/ir.zig index d5760920a..373eec2de 100644 --- a/src/ir.zig +++ b/src/ir.zig @@ -88,6 +88,7 @@ pub const ExprCode = enum(u8) { list, map, + voidv, truev, falsev, errorv, diff --git a/src/parser.zig b/src/parser.zig index 9a1248292..29dfe9d3a 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -2926,6 +2926,10 @@ pub const Parser = struct { return @ptrCast(try self.newSpanNode(.ident, start)); } }, + .underscore => { + self.advance(); + return try self.ast.newNodeErase(.void_lit, .{ .pos = self.tokenSrcPos(start) }); + }, .true_k => { self.advance(); return try self.ast.newNodeErase(.trueLit, .{ .pos = self.tokenSrcPos(start) }); diff --git a/src/sema.zig b/src/sema.zig index beb53a552..62ad179a3 100644 --- a/src/sema.zig +++ b/src/sema.zig @@ -5482,6 +5482,9 @@ pub const ChunkExt = struct { } return c.reportErrorFmt("Can not infer dot literal.", &.{}, node); }, + .void_lit => { + return c.semaVoid(node); + }, .trueLit => { return c.semaTrue(node); }, @@ -6321,6 +6324,11 @@ pub const ChunkExt = struct { return ExprResult.initStatic(irIdx, bt.Byte); } + pub fn semaVoid(c: *cy.Chunk, node: *ast.Node) !ExprResult { + const loc = try c.ir.pushExpr(.voidv, c.alloc, bt.Void, node, {}); + return ExprResult.initStatic(loc, bt.Void); + } + pub fn semaTrue(c: *cy.Chunk, node: *ast.Node) !ExprResult { const loc = try c.ir.pushExpr(.truev, c.alloc, bt.Boolean, node, {}); return ExprResult.initStatic(loc, bt.Boolean); diff --git a/src/std/test.zig b/src/std/test.zig index e01025bd2..70d9042f4 100644 --- a/src/std/test.zig +++ b/src/std/test.zig @@ -126,6 +126,9 @@ fn eq2(c: cy.Context, type_id: cy.TypeId, act: rt.Any, exp: rt.Any) bool { } } else { switch (type_id) { + bt.Void => { + return true; + }, bt.Byte => { if (act.asByte() == exp.asByte()) { return true; diff --git a/src/types.zig b/src/types.zig index ac2b53a9a..adea59d2e 100644 --- a/src/types.zig +++ b/src/types.zig @@ -214,6 +214,7 @@ pub const SemaExt = struct { pub fn isUnboxedType(s: *cy.Sema, id: cy.TypeId) bool { switch (id) { + bt.Void, bt.Byte, bt.Integer => return true, bt.Symbol, diff --git a/src/vm.zig b/src/vm.zig index f6c75b33b..b0db4783b 100644 --- a/src/vm.zig +++ b/src/vm.zig @@ -2058,6 +2058,9 @@ fn box(vm: *VM, val: Value, type_id: cy.TypeId) !cy.Value { @panic("Unsupported."); } } + if (type_id == bt.Void) { + return cy.Value.Void; + } return vm.allocBoxValue(type_id, val.val); } @@ -2067,6 +2070,9 @@ pub fn unbox(vm: *VM, val: Value, type_id: cy.TypeId) cy.Value { @panic("Unsupported."); } } + if (type_id == bt.Void) { + return cy.Value.initRaw(0); + } return val.asHeapObject().object.firstValue; } diff --git a/test/behavior_test.zig b/test/behavior_test.zig index 6b9e5100f..426d7133f 100644 --- a/test/behavior_test.zig +++ b/test/behavior_test.zig @@ -228,6 +228,7 @@ if (!aot) { run.case("types/type_alias.cy"); run.case("types/type_spec.cy"); run.case("types/unnamed_object.cy"); + run.case("types/void.cy"); if (!cy.isWasm) { run.case2(Config.initFileModules("./test/modules/type_spec.cy"), "modules/type_spec.cy"); diff --git a/test/types/void.cy b/test/types/void.cy new file mode 100644 index 000000000..0e2e9b077 --- /dev/null +++ b/test/types/void.cy @@ -0,0 +1,8 @@ +use test + +-- Initialize void. +var a = _ +test.eq(typeOf(a), void) +test.eq(a, _) + +--cytest: pass \ No newline at end of file