Commit 86922b8d08

pfg <pfg@pfg.pw>
2020-07-16 23:08:36
stage2: support @"identifier" syntax
1 parent 83a0073
Changed files (1)
src-self-hosted
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", .{});