From 0d454383163e469192f08a30f63fa68d05cdb80c Mon Sep 17 00:00:00 2001 From: Ali Chraghi Date: Sat, 8 Apr 2023 22:03:33 +0330 Subject: [PATCH] dusk: AstGen expressions --- libs/dusk/src/Ast.zig | 8 ++- libs/dusk/src/AstGen.zig | 60 +++++++++++++++++++++ libs/dusk/src/IR.zig | 8 ++- libs/dusk/src/Parser.zig | 8 ++- libs/dusk/src/print_ir.zig | 107 +++++++++++++++++++++++++++++-------- 5 files changed, 164 insertions(+), 27 deletions(-) diff --git a/libs/dusk/src/Ast.zig b/libs/dusk/src/Ast.zig index d71f8ec6..0a9ab9f9 100644 --- a/libs/dusk/src/Ast.zig +++ b/libs/dusk/src/Ast.zig @@ -537,10 +537,14 @@ pub const Node = struct { // ####### Literals ####### - /// TOK : k_true, k_false + /// TOK : k_true /// LHS : -- /// RHS : -- - bool_literal, + bool_true, + /// TOK : k_false + /// LHS : -- + /// RHS : -- + bool_false, /// TOK : number /// LHS : -- /// RHS : -- diff --git a/libs/dusk/src/AstGen.zig b/libs/dusk/src/AstGen.zig index 5211768b..8db1419b 100644 --- a/libs/dusk/src/AstGen.zig +++ b/libs/dusk/src/AstGen.zig @@ -135,6 +135,7 @@ pub fn genGlobalVariable(self: *AstGen, scope: *Scope, node: Ast.Index) !IR.Inst std.debug.assert(self.tree.nodeTag(node) == .global_variable); const inst = try self.reserveInst(); + const rhs = self.tree.nodeRHS(node); const gv = self.tree.extraData(Ast.Node.GlobalVarDecl, self.tree.nodeLHS(node)); // for (self.tree.spanToList(gv.attrs), 0..) |attr_node, i| { // const attr = switch (self.tree.nodeTag(attr_node)) { @@ -170,6 +171,11 @@ pub fn genGlobalVariable(self: *AstGen, scope: *Scope, node: Ast.Index) !IR.Inst }; } + var expr = IR.Inst.Ref.none; + if (rhs != Ast.null_index) { + expr = try self.genExpr(scope, rhs); + } + const name_index = try self.addString(self.declNameLoc(node).?.slice(self.tree.source)); self.instructions.items[inst] = .{ .tag = .global_variable_decl, @@ -180,6 +186,7 @@ pub fn genGlobalVariable(self: *AstGen, scope: *Scope, node: Ast.Index) !IR.Inst .addr_space = addr_space, .access_mode = access_mode, .attrs = 0, // TODO + .expr = expr, }, }, }; @@ -278,6 +285,59 @@ pub fn genStruct(self: *AstGen, scope: *Scope, node: Ast.Index) !IR.Inst.Ref { return IR.Inst.toRef(inst); } +pub fn genExpr(self: *AstGen, scope: *Scope, node: Ast.Index) !IR.Inst.Ref { + const tag = self.tree.nodeTag(node); + const lhs = self.tree.nodeLHS(node); + const rhs = self.tree.nodeRHS(node); + + switch (tag) { + .bool_true => return .true_literal, + .bool_false => return .true_literal, + else => {}, + } + + const inst_index = try self.reserveInst(); + const inst: IR.Inst = switch (tag) { + .number_literal => .{ .tag = .integer_literal, .data = .{ .integer_literal = 1 } }, + .not => .{ .tag = .not, .data = .{ .ref = try self.genExpr(scope, lhs) } }, + .negate => .{ .tag = .negate, .data = .{ .ref = try self.genExpr(scope, lhs) } }, + .deref => .{ .tag = .deref, .data = .{ .ref = try self.genExpr(scope, lhs) } }, + .addr_of => .{ .tag = .addr_of, .data = .{ .ref = try self.genExpr(scope, lhs) } }, + .mul => .{ .tag = .mul, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .div => .{ .tag = .div, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .mod => .{ .tag = .mod, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .add => .{ .tag = .add, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .sub => .{ .tag = .sub, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .shift_left => .{ .tag = .shift_left, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .shift_right => .{ .tag = .shift_right, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .binary_and => .{ .tag = .binary_and, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .binary_or => .{ .tag = .binary_or, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .binary_xor => .{ .tag = .binary_xor, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .circuit_and => .{ .tag = .circuit_and, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .circuit_or => .{ .tag = .circuit_or, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .equal => .{ .tag = .equal, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .not_equal => .{ .tag = .not_equal, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .less => .{ .tag = .less, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .less_equal => .{ .tag = .less_equal, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .greater => .{ .tag = .greater, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .greater_equal => .{ .tag = .greater_equal, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .index_access => .{ .tag = .index, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .component_access => .{ .tag = .member_access, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genExpr(scope, rhs) } } }, + .bitcast => .{ .tag = .bitcast, .data = .{ .binary = .{ .lhs = try self.genExpr(scope, lhs), .rhs = try self.genType(scope, rhs) } } }, + .ident_expr => .{ + .tag = .ident, + .data = .{ .name = try self.addString(self.tree.tokenLoc(self.tree.nodeToken(node)).slice(self.tree.source)) }, + }, + else => { + std.debug.print("WTF REALLY\n", .{}); + unreachable; + }, + }; + + self.instructions.items[inst_index] = inst; + return IR.Inst.toRef(inst_index); +} + pub fn addString(self: *AstGen, str: []const u8) error{OutOfMemory}!u32 { const len = str.len + 1; try self.strings.ensureUnusedCapacity(self.allocator, len); diff --git a/libs/dusk/src/IR.zig b/libs/dusk/src/IR.zig index bf254168..40848d97 100644 --- a/libs/dusk/src/IR.zig +++ b/libs/dusk/src/IR.zig @@ -187,6 +187,9 @@ pub const Inst = struct { /// data is binary (lhs is expr, rhs is type) bitcast, + /// data is name + ident, + pub fn isDecl(self: Tag) bool { return switch (self) { .global_variable_decl, .struct_decl => true, @@ -197,6 +200,8 @@ pub const Inst = struct { pub const Data = union { ref: Ref, + /// index to null-terminated string in `strings` + name: u32, global_variable_decl: GlobalVariableDecl, struct_decl: StructDecl, struct_member: StructMember, @@ -234,6 +239,7 @@ pub const Inst = struct { access_mode: AccessMode, /// length of attributes attrs: u4 = 0, + expr: Ref = .none, pub const AddressSpace = enum { none, @@ -442,6 +448,6 @@ pub const Inst = struct { }; comptime { - std.debug.assert(@sizeOf(Inst) <= 24); + std.debug.assert(@sizeOf(Inst) <= 32); } }; diff --git a/libs/dusk/src/Parser.zig b/libs/dusk/src/Parser.zig index 64befc36..89d75365 100644 --- a/libs/dusk/src/Parser.zig +++ b/libs/dusk/src/Parser.zig @@ -1452,9 +1452,13 @@ pub fn primaryExpr(p: *Parser) !?Ast.Index { const main_token = p.tok_i; if (try p.callExpr()) |call| return call; switch (p.getToken(.tag, main_token)) { - .k_true, .k_false => { + .k_true => { _ = p.advanceToken(); - return try p.addNode(.{ .tag = .bool_literal, .main_token = main_token }); + return try p.addNode(.{ .tag = .bool_true, .main_token = main_token }); + }, + .k_false => { + _ = p.advanceToken(); + return try p.addNode(.{ .tag = .bool_false, .main_token = main_token }); }, .number => { _ = p.advanceToken(); diff --git a/libs/dusk/src/print_ir.zig b/libs/dusk/src/print_ir.zig index a0d99ee2..a1921427 100644 --- a/libs/dusk/src/print_ir.zig +++ b/libs/dusk/src/print_ir.zig @@ -37,7 +37,7 @@ fn Printer(comptime Writer: type) type { const inst = self.ir.instructions[index]; if (decl_scope and inst.tag.isDecl()) { - try self.writer.print("%{d}", .{index}); + try self.writer.print("&[{d}]", .{index}); return; } @@ -45,8 +45,41 @@ fn Printer(comptime Writer: type) type { .global_variable_decl => try self.printGlobalVariable(indent, index), .struct_decl => try self.printStructDecl(indent, index), .struct_member => try self.printStructMember(indent, index), + .integer_literal => { + try self.writer.print("int({d})", .{inst.data.integer_literal}); + }, + .float_literal => { + try self.writer.print("float({d})", .{inst.data.float_literal}); + }, + .mul, + .div, + .mod, + .add, + .sub, + .shift_left, + .shift_right, + .binary_and, + .binary_or, + .binary_xor, + .circuit_and, + .circuit_or, + .equal, + .not_equal, + .less, + .less_equal, + .greater, + .greater_equal, + => { + try self.instStart(index); + defer self.instEnd() catch unreachable; + try self.printInst(indent, inst.data.binary.lhs, true); + try self.writer.writeAll(", "); + try self.printInst(indent, inst.data.binary.rhs, true); + }, else => { - try self.writer.print("%{d} = {s}{{TODO}},\n", .{ index, @tagName(inst.tag) }); + try self.instStart(index); + defer self.instEnd() catch unreachable; + try self.writer.writeAll("TODO"); }, } }, @@ -56,60 +89,90 @@ fn Printer(comptime Writer: type) type { fn printGlobalVariable(self: @This(), indent: u16, index: IR.Inst.Index) anyerror!void { const inst = self.ir.instructions[index]; - try self.instStart(index); - defer self.instEnd(indent) catch unreachable; + try self.instBlockStart(index); + defer self.instBlockEnd(indent) catch unreachable; - try self.printIndent(indent + 1); - try self.writer.writeAll(".type = "); + try self.printField(indent + 1, "type"); try self.printInst(indent + 2, inst.data.global_variable_decl.type, true); try self.writer.writeAll(",\n"); + + try self.printField(indent + 1, "value"); + try self.printInst(indent + 2, inst.data.global_variable_decl.expr, true); + try self.writer.writeAll(",\n"); } fn printStructDecl(self: @This(), indent: u16, index: IR.Inst.Index) anyerror!void { const inst = self.ir.instructions[index]; - try self.instStart(index); - defer self.instEnd(indent) catch unreachable; + try self.instBlockStart(index); + defer self.instBlockEnd(indent) catch unreachable; - try self.printIndent(indent + 1); - try self.writer.print(".name = \"{s}\",\n", .{self.ir.getStr(inst.data.struct_decl.name)}); + try self.printField(indent + 1, "name"); + try self.printStr(inst.data.struct_decl.name); + try self.writer.writeAll(",\n"); + try self.printField(indent + 1, "members"); + try self.listStart(); const members = std.mem.sliceTo(self.ir.refs[inst.data.struct_decl.members..], .none); - try self.printIndent(indent + 1); - try self.writer.writeAll(".members = [\n"); for (members) |member| { try self.printIndent(indent + 2); try self.printStructMember(indent + 2, member.toIndex().?); } - try self.printIndent(indent + 1); - try self.writer.writeAll("],\n"); + try self.listEnd(indent + 1); } fn printStructMember(self: @This(), indent: u16, index: IR.Inst.Index) anyerror!void { const inst = self.ir.instructions[index]; - try self.instStart(index); - defer self.instEnd(indent) catch unreachable; + try self.instBlockStart(index); + defer self.instBlockEnd(indent) catch unreachable; - try self.printIndent(indent + 1); - try self.writer.print(".name = \"{s}\",\n", .{self.ir.getStr(inst.data.struct_member.name)}); + try self.printField(indent + 1, "name"); + try self.printStr(inst.data.struct_member.name); + try self.writer.writeAll(",\n"); - try self.printIndent(indent + 1); - try self.writer.writeAll(".type = "); + try self.printField(indent + 1, "type"); try self.printInst(indent + 2, inst.data.struct_member.type, true); try self.writer.writeAll(",\n"); } fn instStart(self: @This(), index: IR.Inst.Index) !void { const inst = self.ir.instructions[index]; - try self.writer.print("%{d} = {s}{{\n", .{ index, @tagName(inst.tag) }); + try self.writer.print("[{d}] = {s}(", .{ index, @tagName(inst.tag) }); } - fn instEnd(self: @This(), indent: u16) !void { + fn instEnd(self: @This()) !void { + try self.writer.writeAll(")"); + } + + fn instBlockStart(self: @This(), index: IR.Inst.Index) !void { + const inst = self.ir.instructions[index]; + try self.writer.print("[{d}] = {s}{{\n", .{ index, @tagName(inst.tag) }); + } + + fn instBlockEnd(self: @This(), indent: u16) !void { try self.printIndent(indent); try self.writer.writeAll("},\n"); } + fn listStart(self: @This()) !void { + try self.writer.writeAll("{\n"); + } + + fn listEnd(self: @This(), indent: u16) !void { + try self.printIndent(indent); + try self.writer.writeAll("},\n"); + } + + fn printField(self: @This(), indent: u16, name: []const u8) !void { + try self.printIndent(indent); + try self.writer.print("{s} -> ", .{name}); + } + + fn printStr(self: @This(), name_index: u32) !void { + try self.writer.print("\"{s}\"", .{self.ir.getStr(name_index)}); + } + fn printIndent(self: @This(), indent: u16) !void { try self.writer.writeByteNTimes(' ', indent * indention_size); }