From 30d6f24581b0e7fd450f4de0b83c5040a32d670d Mon Sep 17 00:00:00 2001 From: Mason Remaley Date: Wed, 6 Nov 2024 15:28:59 -0800 Subject: [PATCH] Parses strings to known result type --- src/zon.zig | 83 ++++++++++++++++++++++++++++++++++++++++++- test/behavior/zon.zig | 6 ++-- 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/src/zon.zig b/src/zon.zig index 7f2e32df84..ecfd564c32 100644 --- a/src/zon.zig +++ b/src/zon.zig @@ -260,7 +260,7 @@ fn parseExpr(self: LowerZon, node: Ast.Node.Index, res_ty: Type) CompileError!In .array => return self.parseArray(node, res_ty), .@"struct" => return self.parseStructOrTuple(node, res_ty), .@"union" => {}, - .pointer => {}, + .pointer => return self.parsePointer(node, res_ty), .type, .noreturn, @@ -930,6 +930,87 @@ fn parseTuple(self: LowerZon, node: Ast.Node.Index, res_ty: Type) !InternPool.In } }); } +fn parsePointer(self: LowerZon, node: Ast.Node.Index, res_ty: Type) !InternPool.Index { + const tags = self.file.tree.nodes.items(.tag); + + const ptr_info = res_ty.ptrInfo(self.sema.pt.zcu); + + if (ptr_info.flags.size != .Slice) { + return self.fail(.{ .node_abs = node }, "ZON import cannot be coerced to non slice pointer", .{}); + } + + const string_alignment = ptr_info.flags.alignment == .none or ptr_info.flags.alignment == .@"1"; + const string_sentinel = ptr_info.sentinel == .none or ptr_info.sentinel == .zero_u8; + if (string_alignment and ptr_info.child == .u8_type and string_sentinel) { + if (tags[node] == .string_literal or tags[node] == .multiline_string_literal) { + return self.parseStringLiteral(node, res_ty); + } + } + + var buf: [2]Ast.Node.Index = undefined; + const elem_nodes = try self.elements(res_ty, &buf, node); + _ = elem_nodes; + @panic("unimplemented"); +} + +fn parseStringLiteral(self: LowerZon, node: Ast.Node.Index, res_ty: Type) !InternPool.Index { + const gpa = self.sema.gpa; + const ip = &self.sema.pt.zcu.intern_pool; + const main_tokens = self.file.tree.nodes.items(.main_token); + const tags = self.file.tree.nodes.items(.tag); + const data = self.file.tree.nodes.items(.data); + + const token = main_tokens[node]; + const raw_string = self.file.tree.tokenSlice(token); + + var bytes = std.ArrayListUnmanaged(u8){}; + defer bytes.deinit(gpa); + switch (tags[node]) { + .string_literal => switch (try std.zig.string_literal.parseWrite(bytes.writer(gpa), raw_string)) { + .success => {}, + .failure => |err| { + const offset = self.file.tree.tokens.items(.start)[token]; + return self.fail( + .{ .byte_abs = offset + @as(u32, @intCast(err.offset())) }, + "{}", + .{err.fmtWithSource(raw_string)}, + ); + }, + }, + .multiline_string_literal => { + var parser = std.zig.string_literal.multilineParser(bytes.writer(gpa)); + var tok_i = data[node].lhs; + while (tok_i <= data[node].rhs) : (tok_i += 1) { + try parser.line(self.file.tree.tokenSlice(tok_i)); + } + }, + else => unreachable, + } + + const string = try ip.getOrPutString(gpa, self.sema.pt.tid, bytes.items, .maybe_embedded_nulls); + const array_ty = try self.sema.pt.intern(.{ .array_type = .{ + .len = bytes.items.len, + .sentinel = .zero_u8, + .child = .u8_type, + } }); + const array_val = try self.sema.pt.intern(.{ .aggregate = .{ + .ty = array_ty, + .storage = .{ .bytes = string }, + } }); + return self.sema.pt.intern(.{ .slice = .{ + .ty = res_ty.toIntern(), + .ptr = try self.sema.pt.intern(.{ .ptr = .{ + .ty = .manyptr_const_u8_sentinel_0_type, + .base_addr = .{ .uav = .{ + .orig_ty = .slice_const_u8_sentinel_0_type, + .val = array_val, + } }, + .byte_offset = 0, + } }), + .len = (try self.sema.pt.intValue(Type.usize, bytes.items.len)).toIntern(), + } }); +} + fn elements( self: LowerZon, container: Type, diff --git a/test/behavior/zon.zig b/test/behavior/zon.zig index df8504d064..0b662da1db 100644 --- a/test/behavior/zon.zig +++ b/test/behavior/zon.zig @@ -68,9 +68,8 @@ test "struct enum field" { } test "tuple" { - return error.SkipZigTest; // Failing because we haven't updated string parsing yet - // const Tuple = struct { f32, bool, []const u8, u16 }; - // try expectEqualDeep(Tuple{ 1.2, true, "hello", 3 }, @as(Tuple, @import("zon/tuple.zon"))); + const Tuple = struct { f32, bool, []const u8, u16 }; + try expectEqualDeep(Tuple{ 1.2, true, "hello", 3 }, @as(Tuple, @import("zon/tuple.zon"))); } test "char" { @@ -141,6 +140,7 @@ test "string literals" { try expectEqualSlices(u8, "ab\\c", @import("zon/abc-escaped.zon")); const zero_terminated: [:0]const u8 = @import("zon/abc.zon"); try expectEqualDeep(zero_terminated, "abc"); + try expectEqual(0, zero_terminated[zero_terminated.len]); try expectEqualStrings( \\Hello, world! \\This is a multiline string!