DoxigAlpha

calleeExpr

calleeExpr generates the function part of a call expression (f in f(x)), but not the callee argument to the @call() builtin. Its purpose is to distinguish between standard calls and method call syntax a.b(). Thus, if the lhs is a field access, we return using the field union field; otherwise, we use the direct union field.

Function parameters

Parameters

#
gz:*GenZir
scope:*Scope
call_rl:ResultInfo.Loc
override_decl_literal_type:Zir.Inst.Ref
If this is not `.none` and this call is a decl literal form (`.foo(...)`), then this
node:Ast.Node.Index

Functions in this namespace

Functions

#

Source

Implementation

#
fn calleeExpr(
    gz: *GenZir,
    scope: *Scope,
    call_rl: ResultInfo.Loc,
    /// If this is not `.none` and this call is a decl literal form (`.foo(...)`), then this
    /// type is used as the decl literal result type instead of the result type from `call_rl`.
    override_decl_literal_type: Zir.Inst.Ref,
    node: Ast.Node.Index,
) InnerError!Callee {
    const astgen = gz.astgen;
    const tree = astgen.tree;

    const tag = tree.nodeTag(node);
    switch (tag) {
        .field_access => {
            const object_node, const field_ident = tree.nodeData(node).node_and_token;
            const str_index = try astgen.identAsString(field_ident);
            // Capture the object by reference so we can promote it to an
            // address in Sema if needed.
            const lhs = try expr(gz, scope, .{ .rl = .ref }, object_node);

            const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
            try emitDbgStmt(gz, cursor);

            return .{ .field = .{
                .obj_ptr = lhs,
                .field_name_start = str_index,
            } };
        },
        .enum_literal => {
            const res_ty = res_ty: {
                if (override_decl_literal_type != .none) break :res_ty override_decl_literal_type;
                break :res_ty try call_rl.resultType(gz, node) orelse {
                    // No result type; lower to a literal call of an enum literal.
                    return .{ .direct = try expr(gz, scope, .{ .rl = .none }, node) };
                };
            };
            // Decl literal call syntax, e.g.
            // `const foo: T = .init();`
            // Look up `init` in `T`, but don't try and coerce it.
            const str_index = try astgen.identAsString(tree.nodeMainToken(node));
            const callee = try gz.addPlNode(.decl_literal_no_coerce, node, Zir.Inst.Field{
                .lhs = res_ty,
                .field_name_start = str_index,
            });
            return .{ .direct = callee };
        },
        else => return .{ .direct = try expr(gz, scope, .{ .rl = .none }, node) },
    }
}