From 83a0073b68f905786caccf5ce7907b7e562096fd Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 16 Jul 2020 04:22:05 -0700 Subject: [PATCH 1/2] stage2: period and suffixop --- src-self-hosted/astgen.zig | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index be70a724c2..d6093b3c85 100644 --- a/src-self-hosted/astgen.zig +++ b/src-self-hosted/astgen.zig @@ -33,6 +33,8 @@ pub fn expr(mod: *Module, scope: *Scope, node: *ast.Node) InnerError!*zir.Inst { .GreaterOrEqual => return cmp(mod, scope, node.castTag(.GreaterOrEqual).?, .gte), .LessThan => return cmp(mod, scope, node.castTag(.LessThan).?, .lt), .LessOrEqual => return cmp(mod, scope, node.castTag(.LessOrEqual).?, .lte), + .Period => return field(mod, scope, node.castTag(.Period).?), + .SuffixOp => return suffixOp(mod, scope, node.castTag(.SuffixOp).?), .BoolNot => return boolNot(mod, scope, node.castTag(.BoolNot).?), else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}), } @@ -121,6 +123,43 @@ fn assign(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) Inne } } +/// Identifier nodes -> ZIR string instruction +pub fn identifierString(mod: *Module, scope: *Scope, node: *ast.Node.Identifier) InnerError!*zir.Inst { + const tree = scope.tree(); + const src = tree.token_locs[node.token].start; + + var ident_name = tree.tokenSlice(node.token); + if (std.mem.startsWith(u8, ident_name, "@")) + ident_name = ident_name[2 .. ident_name.len - 1]; + + return mod.addZIRInst(scope, src, zir.Inst.Str, .{ .bytes = ident_name }, .{}); +} + +fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { + const tree = scope.tree(); + const src = tree.token_locs[node.op_token].start; + + const lhs = try expr(mod, scope, node.lhs); + const field_name = try identifierString(mod, scope, node.rhs.castTag(.Identifier).?); + + const pointer = try mod.addZIRInst(scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{}); + return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = pointer }, .{}); +} + +fn suffixOp(mod: *Module, scope: *Scope, node: *ast.Node.SuffixOp) InnerError!*zir.Inst { + switch (node.op) { + .Deref => { + const tree = scope.tree(); + const src = tree.token_locs[node.rtoken].start; + + const lhs = try expr(mod, scope, node.lhs); + + return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = lhs }, .{}); + }, + else => return mod.failNode(scope, &node.base, "TODO implement astGenExpr for suffixOp {}", .{node.op}), + } +} + fn add(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst { const lhs = try expr(mod, scope, infix_node.lhs); const rhs = try expr(mod, scope, infix_node.rhs); From 86922b8d0812977df667c0872c54c7f9c44493d7 Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 16 Jul 2020 14:08:36 -0700 Subject: [PATCH 2/2] stage2: support @"identifier" syntax --- src-self-hosted/astgen.zig | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index d6093b3c85..39e1583ae7 100644 --- a/src-self-hosted/astgen.zig +++ b/src-self-hosted/astgen.zig @@ -92,7 +92,7 @@ fn varDecl(mod: *Module, scope: *Scope, node: *ast.Node.VarDecl) InnerError!Scop return mod.failNode(scope, init_node, "TODO implement result locations", .{}); } const init_inst = try expr(mod, scope, init_node); - const ident_name = tree.tokenSlice(node.name_token); // TODO support @"aoeu" identifiers + const ident_name = try identifierTokenString(mod, scope, node.name_token); return Scope.LocalVar{ .parent = scope, .gen_zir = scope.getGenZIR(), @@ -112,7 +112,7 @@ fn assign(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) Inne if (infix_node.lhs.tag == .Identifier) { const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs); const tree = scope.tree(); - const ident_name = tree.tokenSlice(ident.token); + const ident_name = try identifierTokenString(mod, scope, ident.token); if (std.mem.eql(u8, ident_name, "_")) { return expr(mod, scope, infix_node.rhs); } else { @@ -123,14 +123,31 @@ fn assign(mod: *Module, scope: *Scope, infix_node: *ast.Node.SimpleInfixOp) Inne } } -/// Identifier nodes -> ZIR string instruction -pub fn identifierString(mod: *Module, scope: *Scope, node: *ast.Node.Identifier) InnerError!*zir.Inst { +/// 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 (std.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; +} + +pub fn identifierStringInst(mod: *Module, scope: *Scope, node: *ast.Node.Identifier) InnerError!*zir.Inst { const tree = scope.tree(); const src = tree.token_locs[node.token].start; - var ident_name = tree.tokenSlice(node.token); - if (std.mem.startsWith(u8, ident_name, "@")) - ident_name = ident_name[2 .. ident_name.len - 1]; + const ident_name = try identifierTokenString(mod, scope, node.token); return mod.addZIRInst(scope, src, zir.Inst.Str, .{ .bytes = ident_name }, .{}); } @@ -140,7 +157,7 @@ fn field(mod: *Module, scope: *Scope, node: *ast.Node.SimpleInfixOp) InnerError! const src = tree.token_locs[node.op_token].start; const lhs = try expr(mod, scope, node.lhs); - const field_name = try identifierString(mod, scope, node.rhs.castTag(.Identifier).?); + const field_name = try identifierStringInst(mod, scope, node.rhs.castTag(.Identifier).?); const pointer = try mod.addZIRInst(scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{}); return mod.addZIRInst(scope, src, zir.Inst.Deref, .{ .ptr = pointer }, .{}); @@ -296,8 +313,7 @@ fn identifier(mod: *Module, scope: *Scope, ident: *ast.Node.Identifier) InnerErr defer tracy.end(); const tree = scope.tree(); - // TODO implement @"aoeu" identifiers - const ident_name = tree.tokenSlice(ident.token); + const ident_name = try identifierTokenString(mod, scope, ident.token); const src = tree.token_locs[ident.token].start; if (mem.eql(u8, ident_name, "_")) { return mod.failNode(scope, &ident.base, "TODO implement '_' identifier", .{});