An invocation defined with Inform 7 source text is made with an Inter function call.

§1. Compiling an invocation into a call to an Inter function is simple enough:

void CallingFunctions::csi_by_call(value_holster *VH, parse_node *inv,
    source_location *where_from, tokens_packet *tokens) {

    id_body *idb = Node::get_phrase_invoked(inv);

    inter_name *IS = PhraseRequests::complex_request(idb, tokens->fn_kind,
        Node::get_kind_variable_declarations(inv), Node::get_text(inv));
    LOGIF(MATCHING, "Calling function %n with kind %u from $e\n", IS,
        tokens->fn_kind, inv);

    int options_supplied = Invocations::get_phrase_options_bitmap(inv);
    if (Node::get_phrase_options_invoked(inv) == NULL) options_supplied = -1;

    if (VH->vhmode_wanted == INTER_VAL_VHMODE) VH->vhmode_provided = INTER_VAL_VHMODE;
    else VH->vhmode_provided = INTER_VOID_VHMODE;
    CallingFunctions::direct_function_call(tokens, IS, options_supplied);
}

§2. The following can be used to call any phrase compiled to an I6 routine, and it's used not only by the code above, but also when calling a phrase value stored dynamically at run-time.

void CallingFunctions::direct_function_call(tokens_packet *tokens, inter_name *identifier,
    int phrase_options) {
    kind *return_kind = NULL;
    Compute the return kind of the phrase2.1;

    EmitCode::call(identifier);
    EmitCode::down();
        Emit the comma-separated list of arguments2.2;
    EmitCode::up();
}

§2.1. Compute the return kind of the phrase2.1 =

    kind *K = tokens->fn_kind;
    if (Kinds::get_construct(K) != CON_phrase) internal_error("no function kind");
    Kinds::binary_construction_material(K, NULL, &return_kind);

§2.2. If the return kind stores values on the heap, we must call the function with a pointer to a new value of that kind as the first argument. Arguments corresponding to the tokens then follow, and finally the optional bitmap of phrase options.

Emit the comma-separated list of arguments2.2 =

    if (Kinds::Behaviour::uses_block_values(return_kind))
        Frames::emit_new_local_value(return_kind);
    for (int k=0; k<tokens->tokens_count; k++)
        CompileValues::to_fresh_code_val_of_kind(tokens->token_vals[k], tokens->token_kinds[k]);
    if (phrase_options != -1)
        EmitCode::val_number((inter_ti) phrase_options);

§3. The indirect version of the function is used when a function whose address is not known at compile time must be called; this is needed in a few inline invocations.

void CallingFunctions::indirect_function_call(tokens_packet *tokens,
    parse_node *indirect_spec, int lookup_flag) {
    kind *return_kind = NULL;
    Compute the return kind of the phrase2.1;

    int arity = tokens->tokens_count;
    if (Kinds::Behaviour::uses_block_values(return_kind)) arity++;
    inter_ti BIP = Primitives::BIP_for_indirect_call_returning_value(arity);
    EmitCode::inv(BIP);
    EmitCode::down();
    if (lookup_flag) {
        EmitCode::inv(LOOKUP_BIP);
        EmitCode::down();
            CompileValues::to_code_val(indirect_spec);
            EmitCode::val_number(1);
        EmitCode::up();
    } else {
        CompileValues::to_code_val(indirect_spec);
    }
    int phrase_options = -1;
    Emit the comma-separated list of arguments2.2;
    EmitCode::up();
}