DoxigAlpha

tupleDecl

Function parameters

Parameters

#
gz:*GenZir
scope:*Scope
node:Ast.Node.Index
container_decl:Ast.full.ContainerDecl
layout:std.builtin.Type.ContainerLayout
backing_int_node:Ast.Node.OptionalIndex

Functions in this namespace

Functions

#

Source

Implementation

#
fn tupleDecl(
    gz: *GenZir,
    scope: *Scope,
    node: Ast.Node.Index,
    container_decl: Ast.full.ContainerDecl,
    layout: std.builtin.Type.ContainerLayout,
    backing_int_node: Ast.Node.OptionalIndex,
) InnerError!Zir.Inst.Ref {
    const astgen = gz.astgen;
    const gpa = astgen.gpa;
    const tree = astgen.tree;

    switch (layout) {
        .auto => {},
        .@"extern", .@"packed" => return astgen.failNode(node, "{s} tuples are not supported", .{@tagName(layout)}),
    }

    if (backing_int_node.unwrap()) |arg| {
        return astgen.failNode(arg, "tuple does not support backing integer type", .{});
    }

    // We will use the scratch buffer, starting here, for the field data:
    // 1. fields: { // for every `fields_len` (stored in `extended.small`)
    //        type: Inst.Ref,
    //        init: Inst.Ref, // `.none` for non-`comptime` fields
    //    }
    const fields_start = astgen.scratch.items.len;
    defer astgen.scratch.items.len = fields_start;

    try astgen.scratch.ensureUnusedCapacity(gpa, container_decl.ast.members.len * 2);

    for (container_decl.ast.members) |member_node| {
        const field = tree.fullContainerField(member_node) orelse {
            const tuple_member = for (container_decl.ast.members) |maybe_tuple| switch (tree.nodeTag(maybe_tuple)) {
                .container_field_init,
                .container_field_align,
                .container_field,
                => break maybe_tuple,
                else => {},
            } else unreachable;
            return astgen.failNodeNotes(
                member_node,
                "tuple declarations cannot contain declarations",
                .{},
                &.{try astgen.errNoteNode(tuple_member, "tuple field here", .{})},
            );
        };

        if (!field.ast.tuple_like) {
            return astgen.failTok(field.ast.main_token, "tuple field has a name", .{});
        }

        if (field.ast.align_expr != .none) {
            return astgen.failTok(field.ast.main_token, "tuple field has alignment", .{});
        }

        if (field.ast.value_expr != .none and field.comptime_token == null) {
            return astgen.failTok(field.ast.main_token, "non-comptime tuple field has default initialization value", .{});
        }

        if (field.ast.value_expr == .none and field.comptime_token != null) {
            return astgen.failTok(field.comptime_token.?, "comptime field without default initialization value", .{});
        }

        const field_type_ref = try typeExpr(gz, scope, field.ast.type_expr.unwrap().?);
        astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));

        if (field.ast.value_expr.unwrap()) |value_expr| {
            const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, value_expr, .tuple_field_default_value);
            astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));
        } else {
            astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));
        }
    }

    const fields_len = std.math.cast(u16, container_decl.ast.members.len) orelse {
        return astgen.failNode(node, "this compiler implementation only supports 65535 tuple fields", .{});
    };

    const extra_trail = astgen.scratch.items[fields_start..];
    assert(extra_trail.len == fields_len * 2);
    try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.TupleDecl).@"struct".fields.len + extra_trail.len);
    const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.TupleDecl{
        .src_node = gz.nodeIndexToRelative(node),
    });
    astgen.extra.appendSliceAssumeCapacity(extra_trail);

    return gz.add(.{
        .tag = .extended,
        .data = .{ .extended = .{
            .opcode = .tuple_decl,
            .small = fields_len,
            .operand = payload_index,
        } },
    });
}