Translate a string literal that is initializing an array. In general narrow string
literals become "<string>".* or "<string>"[0..<size>].* if they need truncation.
Wide string literals become an array of integers. zero-fillers pad out the array to
the appropriate length, if necessary.
fn transStringLiteralInitializer(
t: *Translator,
expr: Node.Index,
literal: Node.CharLiteral,
array_type: ZigNode,
) TransError!ZigNode
fn transStringLiteralInitializer(
t: *Translator,
expr: Node.Index,
literal: Node.CharLiteral,
array_type: ZigNode,
) TransError!ZigNode {
assert(array_type.tag() == .array_type or array_type.tag() == .null_sentinel_array_type);
const is_narrow = literal.kind == .ascii or literal.kind == .utf8;
// The length of the string literal excluding the sentinel.
const str_length = literal.qt.arrayLen(t.comp).? - 1;
const payload = (array_type.castTag(.array_type) orelse array_type.castTag(.null_sentinel_array_type).?).data;
const array_size = payload.len;
const elem_type = payload.elem_type;
if (array_size == 0) return ZigTag.empty_array.create(t.arena, array_type);
const num_inits = @min(str_length, array_size);
if (num_inits == 0) {
return ZigTag.array_filler.create(t.arena, .{
.type = elem_type,
.filler = ZigTag.zero_literal.init(),
.count = array_size,
});
}
const init_node = if (is_narrow) blk: {
// "string literal".* or string literal"[0..num_inits].*
var str = try t.transNarrowStringLiteral(expr, literal);
if (str_length != array_size) str = try ZigTag.string_slice.create(t.arena, .{ .string = str, .end = num_inits });
break :blk try ZigTag.deref.create(t.arena, str);
} else blk: {
const size = literal.qt.childType(t.comp).sizeof(t.comp);
const val = t.tree.value_map.get(expr).?;
const bytes = t.comp.interner.get(val.ref()).bytes;
const init_list = try t.arena.alloc(ZigNode, @intCast(num_inits));
for (init_list, 0..) |*item, i| {
const codepoint = switch (size) {
2 => @as(*const u16, @ptrCast(@alignCast(bytes.ptr + i * 2))).*,
4 => @as(*const u32, @ptrCast(@alignCast(bytes.ptr + i * 4))).*,
else => unreachable,
};
item.* = try t.createCharLiteralNode(false, codepoint);
}
const init_args: ast.Payload.Array.ArrayTypeInfo = .{ .len = num_inits, .elem_type = elem_type };
const init_array_type = if (array_type.tag() == .array_type)
try ZigTag.array_type.create(t.arena, init_args)
else
try ZigTag.null_sentinel_array_type.create(t.arena, init_args);
break :blk try ZigTag.array_init.create(t.arena, .{
.cond = init_array_type,
.cases = init_list,
});
};
if (num_inits == array_size) return init_node;
assert(array_size > str_length); // If array_size <= str_length, `num_inits == array_size` and we've already returned.
const filler_node = try ZigTag.array_filler.create(t.arena, .{
.type = elem_type,
.filler = ZigTag.zero_literal.init(),
.count = array_size - str_length,
});
return ZigTag.array_cat.create(t.arena, .{ .lhs = init_node, .rhs = filler_node });
}