Parses strings to known result type

This commit is contained in:
Mason Remaley 2024-11-06 15:28:59 -08:00
parent d3f1bb9ab1
commit 30d6f24581
2 changed files with 85 additions and 4 deletions

View File

@ -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,

View File

@ -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!