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:
- ● for base kinds, storing the iname as the identifier for the associated noun, which is quicker to look up;
- ● for constructed kinds, storing it in a cached_kind_declaration, which is slower but occurs considerably less often — there are in practice relatively few cached_kind_declaration objects created.
§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;
- The structure cached_kind_declaration is private to this section.
§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;
- This code is used in §9.
§9.2. Run out inter kind for description9.2 =
arity = 1; operands[0] = Kinds::unary_construction_material(K); icon = DESCRIPTION_ITCONC;
- This code is used in §9.
§9.3. Run out inter kind for column9.3 =
arity = 1; operands[0] = Kinds::unary_construction_material(K); icon = COLUMN_ITCONC;
- This code is used in §9.
§9.4. Run out inter kind for relation9.4 =
arity = 2; Kinds::binary_construction_material(K, &operands[0], &operands[1]); icon = RELATION_ITCONC;
- This code is used in §9.
§9.5. Run out inter kind for activity9.5 =
arity = 1; operands[0] = Kinds::unary_construction_material(K); icon = ACTIVITY_ITCONC;
- This code is used in §9.
§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;
- This code is used in §9.
§9.7. Run out inter kind for rule9.7 =
arity = 2; Kinds::binary_construction_material(K, &operands[0], &operands[1]); icon = RULE_ITCONC;
- This code is used in §9.
§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;
- This code is used in §9.
§9.9. Run out inter kind for generic covariant unary9.9 =
arity = 1; operands[0] = Kinds::unary_construction_material(K); icon = UNARY_COV_ITCONC;
- This code is used in §9.
§9.10. Run out inter kind for generic contravariant unary9.10 =
arity = 1; operands[0] = Kinds::unary_construction_material(K); icon = UNARY_CON_ITCONC;
- This code is used in §9.
§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;
- This code is used in §9.
§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;
- This code is used in §9.
§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;
- This code is used in §9.
§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;
- This code is used in §9.