Each different kind used anywhere in the tree must be declared with an Inter kind declaration.


§1. Inames for declarations. A few kinds can never be used in Inter code, and are therefore exempt:

int RTKindDeclarations::base_represented_in_Inter(kind *K) {
    if ((Kinds::Behaviour::is_kind_of_kind(K) == FALSE) &&
        (Kinds::is_proper_constructor(K) == FALSE) &&
        (K != K_void) &&
        (K != K_unknown) &&
        (K != K_nil)) return TRUE;
    return FALSE;
}

§2. But all other kinds — number, person, list of texts, whatever may be — need to be declared, and define an Inter symbol as an identifier for that kind. For example:

kind K_action_name int32
kind K_list_of_texts list of K_text

...make two kinds available in Inter, defining K_action_name and K_list_of_texts to refer to them.

We need to remember what we have already declared, so that we don't declare the same kind over and over. We use two different mechanisms for this:

§3. So, firstly, each base kind registers a new noun for itself here:

define REGISTER_NOUN_KINDS_CALLBACK RTKindDeclarations::register
int no_kinds_of_object = 1;
noun *RTKindDeclarations::register(kind *K, kind *super, wording W, general_pointer data) {
    noun *nt = Nouns::new_common_noun(W, NEUTER_GENDER,
        ADD_TO_LEXICON_NTOPT + WITH_PLURAL_FORMS_NTOPT,
        KIND_SLOW_MC, data, Task::language_of_syntax());
    NameResolution::initialise(nt);
    if (Kinds::Behaviour::is_object(super))
        Kinds::Behaviour::set_range_number(K, no_kinds_of_object++);
    return nt;
}

§4. And secondly, here's where we cache inames for constructed kinds:

typedef struct cached_kind_declaration {
    struct kind *noted_kind;
    struct inter_name *noted_iname;
    CLASS_DEFINITION
} cached_kind_declaration;

§5. Calling RTKindDeclarations::iname produces the inter_name referring to the kind in Inter, ensuring that it has been declared exactly once.

inter_name *RTKindDeclarations::iname(kind *K) {
    if (RTKindDeclarations::base_represented_in_Inter(K)) {
        noun *nt = Kinds::Behaviour::get_noun(K);
        if ((nt) && (NounIdentifiers::iname_set(nt) == FALSE))
            NounIdentifiers::set_iname(nt, RTKindDeclarations::create_iname(K));
        return NounIdentifiers::iname(nt);
    }
    if (Kinds::is_proper_constructor(K) == FALSE) internal_error("bad kind");

    cached_kind_declaration *dec;
    LOOP_OVER(dec, cached_kind_declaration)
        if (Kinds::eq(K, dec->noted_kind))
            return dec->noted_iname;

    dec = CREATE(cached_kind_declaration);
    dec->noted_kind = K;
    dec->noted_iname = RTKindDeclarations::create_iname(K);
    RTKindDeclarations::declare_constructed_kind(dec);
    return dec->noted_iname;
}

§6. Whichever cache is used, the following generates a name like K_list_of_numbers for use in the kind declaration. It is called once only for any given K.

Note that in order to play nicely with code in WorldModelKit and elsewhere, we want the names of kinds of objects to come out the same as they traditionally have in Inform 6 and 7 code for many years: so, for example, K3_direction, not K_direction. We do that by throwing in the "range number". See the function RTKindDeclarations::register above for how these numbers originate; they are in registration order, which does not necessarily correspond to the sequence in which declarations are made here.

inter_name *RTKindDeclarations::create_iname(kind *K) {
    package_request *R = RTKindConstructors::package(K->construct);
    TEMPORARY_TEXT(KT)
    Kinds::Textual::write(KT, K);
    wording W = Feeds::feed_text(KT);
    DISCARD_TEXT(KT)
    int v = -2;
    if (Kinds::Behaviour::is_subkind_of_object(K)) {
        int tcn = RTKindConstructors::traditional_class_number(K);
        if (tcn >= 0) v = tcn;
    }
    inter_name *iname = Hierarchy::make_iname_with_memo_and_value(KIND_CLASS_HL, R, W, v);
    if (Kinds::is_proper_constructor(K) == FALSE) Hierarchy::make_available(iname);
    return iname;
}

§7. Actual declarations. First, base kinds:

void RTKindDeclarations::declare_base_kinds(void) {
    kind *K; inter_ti c = 0;
    LOOP_OVER_BASE_KINDS(K)
        if (RTKindDeclarations::base_represented_in_Inter(K)) {
            RTKindDeclarations::declare_base_kind(K);
            inter_name *iname = RTKindDeclarations::iname(K);
            package_request *req = InterNames::location(iname);
            Hierarchy::apply_metadata_from_number(req, KIND_SOURCE_ORDER_MD_HL, c++);
        }
}

§8. Note the little dance here to ensure that if K is a subkind of L, then L is always declared before K, even if K appears before L in the original source text.

void RTKindDeclarations::declare_base_kind(kind *K) {
    if (K == NULL) internal_error("tried to emit null kind");
    if (InterNames::is_defined(RTKindDeclarations::iname(K))) return;
    inter_ti dt = INT32_ITCONC;
    if (K == K_object) dt = ENUM_ITCONC;
    if (Kinds::Behaviour::is_an_enumeration(K)) dt = ENUM_ITCONC;
    if (K == K_truth_state) dt = INT2_ITCONC;
    if (K == K_text) dt = TEXT_ITCONC;
    if (K == K_table) dt = TABLE_ITCONC;
    kind *S = Latticework::super(K);
    if ((S) && (Kinds::conforms_to(S, K_object) == FALSE)) S = NULL;
    if (S) {
        RTKindDeclarations::declare_base_kind(S);
        dt = ENUM_ITCONC;
    }
    Emit::kind(RTKindDeclarations::iname(K), S?RTKindDeclarations::iname(S):NULL,
        dt, 0, NULL);
    if (K == K_object) {
        InterNames::set_translation(RTKindDeclarations::iname(K), I"K0_kind");
        Hierarchy::make_available(RTKindDeclarations::iname(K));
    }
}

§9. And now constructed kinds.

void RTKindDeclarations::declare_constructed_kind(cached_kind_declaration *dec) {
    kind *K = dec->noted_kind;
    int arity = 0;
    kind *operands[MAX_KIND_ARITY];
    inter_ti icon = 0;
    kind_constructor *kc = Kinds::get_construct(K);
    if (kc == CON_description)       Run out inter kind for description9.2
    else if (kc == CON_list_of)      Run out inter kind for list9.1
    else if (kc == CON_phrase)       Run out inter kind for phrase9.6
    else if (kc == CON_rule)         Run out inter kind for rule9.7
    else if (kc == CON_rulebook)     Run out inter kind for rulebook9.8
    else if (kc == CON_table_column) Run out inter kind for column9.3
    else if (kc == CON_relation)     Run out inter kind for relation9.4
    else if (kc == CON_activity)     Run out inter kind for activity9.5
    else if ((KindConstructors::arity(kc) == 1)
             && (KindConstructors::variance(kc, 0) == COVARIANT))
                                     Run out inter kind for generic covariant unary9.9
    else if ((KindConstructors::arity(kc) == 1)
             && (KindConstructors::variance(kc, 0) == CONTRAVARIANT))
                                     Run out inter kind for generic contravariant unary9.10
    else if ((KindConstructors::arity(kc) == 2)
             && (KindConstructors::variance(kc, 0) == COVARIANT)
             && (KindConstructors::variance(kc, 1) == COVARIANT))
                                     Run out inter kind for generic cov-cov binary9.11
    else if ((KindConstructors::arity(kc) == 2)
             && (KindConstructors::variance(kc, 0) == COVARIANT)
             && (KindConstructors::variance(kc, 1) == CONTRAVARIANT))
                                     Run out inter kind for generic cov-con binary9.12
    else if ((KindConstructors::arity(kc) == 2)
             && (KindConstructors::variance(kc, 0) == CONTRAVARIANT)
             && (KindConstructors::variance(kc, 1) == COVARIANT))
                                     Run out inter kind for generic con-cov binary9.13
    else if ((KindConstructors::arity(kc) == 2)
             && (KindConstructors::variance(kc, 0) == CONTRAVARIANT)
             && (KindConstructors::variance(kc, 1) == CONTRAVARIANT))
                                     Run out inter kind for generic con-con binary9.14
    else {
        LOG("Unfortunate kind is: %u\n", K);
        internal_error("unable to represent kind in inter");
    }
    if (icon == 0) internal_error("icon unset");
    Emit::kind(dec->noted_iname, NULL, icon, arity, operands);
}

§9.1. Run out inter kind for list9.1 =

    arity = 1;
    operands[0] = Kinds::unary_construction_material(K);
    icon = LIST_ITCONC;

§9.2. Run out inter kind for description9.2 =

    arity = 1;
    operands[0] = Kinds::unary_construction_material(K);
    icon = DESCRIPTION_ITCONC;

§9.3. Run out inter kind for column9.3 =

    arity = 1;
    operands[0] = Kinds::unary_construction_material(K);
    icon = COLUMN_ITCONC;

§9.4. Run out inter kind for relation9.4 =

    arity = 2;
    Kinds::binary_construction_material(K, &operands[0], &operands[1]);
    icon = RELATION_ITCONC;

§9.5. Run out inter kind for activity9.5 =

    arity = 1;
    operands[0] = Kinds::unary_construction_material(K);
    icon = ACTIVITY_ITCONC;

§9.6. Run out inter kind for phrase9.6 =

    icon = FUNCTION_ITCONC;
    kind *X = NULL, *result = NULL;
    Kinds::binary_construction_material(K, &X, &result);
    while (Kinds::get_construct(X) == CON_TUPLE_ENTRY) {
        kind *A = NULL;
        Kinds::binary_construction_material(X, &A, &X);
        operands[arity++] = A;
    }
    if (arity == 0) {
        operands[arity++] = NULL;  void arguments
    }
    operands[arity++] = result;

§9.7. Run out inter kind for rule9.7 =

    arity = 2;
    Kinds::binary_construction_material(K, &operands[0], &operands[1]);
    icon = RULE_ITCONC;

§9.8. Run out inter kind for rulebook9.8 =

    arity = 1;
    kind *X = NULL, *Y = NULL;
    Kinds::binary_construction_material(K, &X, &Y);
    operands[0] = Kinds::binary_con(CON_phrase, X, Y);
    icon = RULEBOOK_ITCONC;

§9.9. Run out inter kind for generic covariant unary9.9 =

    arity = 1;
    operands[0] = Kinds::unary_construction_material(K);
    icon = UNARY_COV_ITCONC;

§9.10. Run out inter kind for generic contravariant unary9.10 =

    arity = 1;
    operands[0] = Kinds::unary_construction_material(K);
    icon = UNARY_CON_ITCONC;

§9.11. Run out inter kind for generic cov-cov binary9.11 =

    arity = 2;
    Kinds::binary_construction_material(K, &operands[0], &operands[1]);
    icon = BINARY_COV_COV_ITCONC;

§9.12. Run out inter kind for generic cov-con binary9.12 =

    arity = 2;
    Kinds::binary_construction_material(K, &operands[0], &operands[1]);
    icon = BINARY_COV_CON_ITCONC;

§9.13. Run out inter kind for generic con-cov binary9.13 =

    arity = 2;
    Kinds::binary_construction_material(K, &operands[0], &operands[1]);
    icon = BINARY_CON_COV_ITCONC;

§9.14. Run out inter kind for generic con-con binary9.14 =

    arity = 2;
    Kinds::binary_construction_material(K, &operands[0], &operands[1]);
    icon = BINARY_CON_CON_ITCONC;