1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/inter/building-module/Chapter 1/Hierarchy Locations.w
2021-06-09 12:02:33 +01:00

371 lines
14 KiB
OpenEdge ABL

[HierarchyLocations::] Hierarchy Locations.
@h Requirements.
Inform's code for compiling resources to different positions in the Inter hierarchy
is quite defensively written, in order to keep everything to a fairly tightly
specified schema.
The following is really a union: a requirement should have exactly one of the
following fields set.
=
typedef struct location_requirement {
struct submodule_identity *any_submodule_package_of_this_identity;
struct package_request *this_exact_package;
int this_exact_package_not_yet_created;
struct text_stream *any_package_of_this_type;
int any_enclosure;
int must_be_plug;
int must_be_main_source_text;
} location_requirement;
location_requirement HierarchyLocations::blank(void) {
location_requirement req;
req.any_submodule_package_of_this_identity = NULL;
req.this_exact_package = NULL;
req.this_exact_package_not_yet_created = -1;
req.any_package_of_this_type = NULL;
req.any_enclosure = FALSE;
req.must_be_plug = FALSE;
req.must_be_main_source_text = FALSE;
return req;
}
@ Here are the functions to create requirements:
=
location_requirement HierarchyLocations::local_submodule(submodule_identity *sid) {
location_requirement req = HierarchyLocations::blank();
req.any_submodule_package_of_this_identity = sid;
return req;
}
location_requirement HierarchyLocations::completion_submodule(inter_tree *I, submodule_identity *sid) {
location_requirement req = HierarchyLocations::blank();
req.this_exact_package = Packaging::completion_submodule(I, sid);
req.must_be_main_source_text = TRUE;
return req;
}
location_requirement HierarchyLocations::generic_submodule(inter_tree *I, submodule_identity *sid) {
location_requirement req = HierarchyLocations::blank();
req.this_exact_package = Packaging::generic_submodule(I, sid);
return req;
}
location_requirement HierarchyLocations::synoptic_submodule(inter_tree *I, submodule_identity *sid) {
location_requirement req = HierarchyLocations::blank();
req.this_exact_package = Packaging::synoptic_submodule(I, sid);
return req;
}
location_requirement HierarchyLocations::any_package_of_type(text_stream *ptype_name) {
location_requirement req = HierarchyLocations::blank();
req.any_package_of_this_type = Str::duplicate(ptype_name);
return req;
}
location_requirement HierarchyLocations::any_enclosure(void) {
location_requirement req = HierarchyLocations::blank();
req.any_enclosure = TRUE;
return req;
}
location_requirement HierarchyLocations::the_veneer(inter_tree *I) {
return HierarchyLocations::this_package(Site::veneer_request(I));
}
location_requirement HierarchyLocations::this_package(package_request *P) {
location_requirement req = HierarchyLocations::blank();
req.this_exact_package = P;
return req;
}
location_requirement HierarchyLocations::this_exotic_package(int N) {
location_requirement req = HierarchyLocations::blank();
req.this_exact_package_not_yet_created = N;
return req;
}
location_requirement HierarchyLocations::plug(void) {
location_requirement req = HierarchyLocations::blank();
req.must_be_plug = TRUE;
return req;
}
@h Hierarchy locations.
=
typedef struct hierarchy_location {
int access_number;
struct text_stream *access_name;
struct text_stream *function_package_name;
struct text_stream *datum_package_name;
struct location_requirement requirements;
struct inter_name *equates_to_iname;
struct text_stream *package_type;
struct name_translation trans;
CLASS_DEFINITION
} hierarchy_location;
hierarchy_location *HierarchyLocations::new(void) {
hierarchy_location *hl = CREATE(hierarchy_location);
hl->access_number = -1;
hl->access_name = NULL;
hl->function_package_name = NULL;
hl->datum_package_name = NULL;
hl->equates_to_iname = NULL;
hl->package_type = NULL;
hl->trans = Translation::same();
hl->requirements = HierarchyLocations::blank();
return hl;
}
hierarchy_location *HierarchyLocations::ctr(inter_tree *I, int id, text_stream *name, name_translation nt, location_requirement req) {
hierarchy_location *hl = HierarchyLocations::new();
hl->access_number = id;
hl->access_name = Str::duplicate(name);
hl->requirements = req;
hl->trans = nt;
HierarchyLocations::index(I, hl);
return hl;
}
hierarchy_location *HierarchyLocations::con(inter_tree *I, int id, text_stream *name, location_requirement req) {
hierarchy_location *hl = HierarchyLocations::new();
hl->access_number = id;
hl->access_name = Str::duplicate(name);
hl->requirements = req;
hl->trans = Translation::same();
HierarchyLocations::index(I, hl);
return hl;
}
hierarchy_location *HierarchyLocations::pkg(inter_tree *I, int id, text_stream *name, text_stream *ptype_name, location_requirement req) {
hierarchy_location *hl = HierarchyLocations::new();
hl->access_number = id;
hl->access_name = Str::duplicate(name);
hl->requirements = req;
hl->package_type = Str::duplicate(ptype_name);
HierarchyLocations::index(I, hl);
return hl;
}
hierarchy_location *HierarchyLocations::make_as(inter_tree *I, int id, text_stream *name, inter_name *iname) {
hierarchy_location *hl = HierarchyLocations::new();
hl->access_number = id;
hl->access_name = Str::duplicate(name);
hl->requirements = HierarchyLocations::this_package(InterNames::location(iname));
hl->equates_to_iname = iname;
HierarchyLocations::index(I, hl);
return hl;
}
hierarchy_location *HierarchyLocations::fun(inter_tree *I, int id, text_stream *name, name_translation nt, location_requirement req) {
hierarchy_location *hl = CREATE(hierarchy_location);
hl->access_number = id;
hl->access_name = Str::duplicate(nt.translate_to);
hl->function_package_name = Str::duplicate(name);
hl->requirements = req;
hl->trans = nt;
HierarchyLocations::index(I, hl);
return hl;
}
hierarchy_location *HierarchyLocations::dat(inter_tree *I, int id, text_stream *name, name_translation nt, location_requirement req) {
hierarchy_location *hl = CREATE(hierarchy_location);
hl->access_number = id;
hl->access_name = Str::duplicate(nt.translate_to);
hl->datum_package_name = Str::duplicate(name);
hl->requirements = req;
hl->trans = nt;
HierarchyLocations::index(I, hl);
return hl;
}
void HierarchyLocations::index(inter_tree *I, hierarchy_location *hl) {
if (hl->access_number >= 0) I->site.hls_indexed_by_id[hl->access_number] = hl;
if (hl->requirements.any_package_of_this_type == NULL) {
Dictionaries::create(I->site.hls_indexed_by_name, hl->access_name);
Dictionaries::write_value(I->site.hls_indexed_by_name, hl->access_name, (void *) hl);
}
}
inter_name *HierarchyLocations::find(inter_tree *I, int id) {
if ((id < 0) || (id >= NO_DEFINED_HL_VALUES) || (I->site.hls_indexed_by_id[id] == NULL))
internal_error("bad hl ID");
return HierarchyLocations::hl_to_iname(I, I->site.hls_indexed_by_id[id]);
}
inter_name *HierarchyLocations::find_by_name(inter_tree *I, text_stream *name) {
if (Str::len(name) == 0) internal_error("bad hl name");
if (Dictionaries::find(I->site.hls_indexed_by_name, name))
return HierarchyLocations::hl_to_iname(I,
(hierarchy_location *)
Dictionaries::read_value(I->site.hls_indexed_by_name, name));
return NULL;
}
inter_name *HierarchyLocations::function(inter_tree *I, package_request *R, text_stream *name, text_stream *trans) {
inter_name *iname = Packaging::function(I, InterNames::explicitly_named(name, R), NULL);
if (trans) Produce::change_translation(iname, trans);
return iname;
}
inter_name *HierarchyLocations::hl_to_iname(inter_tree *I, hierarchy_location *hl) {
if (hl->requirements.any_package_of_this_type) internal_error("NRL accessed inappropriately");
if (hl->equates_to_iname == NULL) {
if (hl->requirements.must_be_plug) {
hl->equates_to_iname = InterNames::explicitly_named_in_template(I, hl->access_name);
} else {
if (hl->requirements.this_exact_package == NULL) {
if (hl->requirements.this_exact_package_not_yet_created >= 0) {
#ifdef CORE_MODULE
hl->requirements.this_exact_package = Hierarchy::exotic_package(hl->requirements.this_exact_package_not_yet_created);
#endif
#ifndef CORE_MODULE
internal_error("feature not available in inter");
#endif
} else internal_error("package can't be found");
}
if (Str::len(hl->function_package_name) > 0) {
hl->equates_to_iname = Packaging::function_text(I,
InterNames::explicitly_named(hl->function_package_name, hl->requirements.this_exact_package),
hl->access_name);
} else if (Str::len(hl->datum_package_name) > 0) {
hl->equates_to_iname = Packaging::datum_text(I,
InterNames::explicitly_named(hl->datum_package_name, hl->requirements.this_exact_package),
hl->access_name);
} else if ((hl->requirements.this_exact_package) && (hl->equates_to_iname == NULL)) {
hl->equates_to_iname = InterNames::explicitly_named(hl->access_name, hl->requirements.this_exact_package);
}
}
hl->requirements.this_exact_package = InterNames::location(hl->equates_to_iname);
if (hl->trans.translate_to) Produce::change_translation(hl->equates_to_iname, hl->trans.translate_to);
}
return hl->equates_to_iname;
}
inter_name *HierarchyLocations::find_in_package(inter_tree *I, int id, package_request *P, wording W, inter_name *derive_from, int fix, text_stream *imposed_name) {
if ((id < 0) || (id >= NO_DEFINED_HL_VALUES) || (I->site.hls_indexed_by_id[id] == NULL))
internal_error("bad hl ID");
hierarchy_location *hl = I->site.hls_indexed_by_id[id];
if ((hl->requirements.any_package_of_this_type == NULL) &&
(hl->requirements.any_enclosure == FALSE)) internal_error("NRL accessed inappropriately");
if (hl->requirements.any_enclosure) {
if (Inter::Symbols::read_annotation(P->eventual_type, ENCLOSING_IANN) != 1)
internal_error("subpackage not in enclosing superpackage");
} else if (P == NULL) {
internal_error("constant in null package");
} else if (P->eventual_type != PackageTypes::get(I, hl->requirements.any_package_of_this_type)) {
LOG("AN: %S, FPN: %S\n", hl->access_name, hl->function_package_name);
LOG("Have type: $3, required: %S\n", P->eventual_type, hl->requirements.any_package_of_this_type);
internal_error("constant in wrong superpackage");
}
inter_name *iname = NULL;
if (hl->trans.translate_to) {
text_stream *T = hl->trans.translate_to;
@<Make the actual iname@>;
} else if (hl->trans.by_imposition) {
text_stream *T = NULL;
@<Make the actual iname@>;
} else if (hl->trans.name_generator) {
TEMPORARY_TEXT(T)
inter_name *temp_iname = NULL;
if (derive_from) {
temp_iname = InterNames::derived(hl->trans.name_generator, derive_from, W);
} else {
temp_iname = InterNames::generated(hl->trans.name_generator, fix, W);
}
W = EMPTY_WORDING;
WRITE_TO(T, "%n", temp_iname);
@<Make the actual iname@>;
DISCARD_TEXT(T)
} else {
text_stream *T = NULL;
@<Make the actual iname@>;
}
if (hl->trans.then_make_unique) Produce::set_flag(iname, MAKE_NAME_UNIQUE);
return iname;
}
@<Make the actual iname@> =
if (Str::len(hl->function_package_name) > 0) {
iname = Packaging::function(I,
InterNames::explicitly_named(hl->function_package_name, P), NULL);
} else {
if (hl->trans.by_imposition) iname = InterNames::explicitly_named_with_memo(imposed_name, P, W);
else if (Str::len(hl->access_name) == 0) iname = InterNames::explicitly_named_with_memo(T, P, W);
else iname = InterNames::explicitly_named_with_memo(hl->access_name, P, W);
}
if ((Str::len(T) > 0) && (hl->access_name)) Produce::change_translation(iname, T);
@ =
package_request *HierarchyLocations::package_in_package(inter_tree *I, int id, package_request *P) {
if ((id < 0) || (id >= NO_DEFINED_HL_VALUES) || (I->site.hls_indexed_by_id[id] == NULL))
internal_error("bad hl ID");
hierarchy_location *hl = I->site.hls_indexed_by_id[id];
if (P == NULL) internal_error("no superpackage");
if (hl->package_type == NULL) internal_error("package_in_package used wrongly");
if (hl->requirements.any_package_of_this_type) {
if (P->eventual_type != PackageTypes::get(I, hl->requirements.any_package_of_this_type))
internal_error("subpackage in wrong superpackage");
} else if (hl->requirements.any_enclosure) {
if (Inter::Symbols::read_annotation(P->eventual_type, ENCLOSING_IANN) != 1)
internal_error("subpackage not in enclosing superpackage");
} else internal_error("NRL accessed inappropriately");
return Packaging::request(I, InterNames::explicitly_named(hl->access_name, P), PackageTypes::get(I, hl->package_type));
}
@h Hierarchy locations.
=
typedef struct hierarchy_attachment_point {
int hap_id;
struct text_stream *name_stem;
struct text_stream *type;
struct location_requirement requirements;
CLASS_DEFINITION
} hierarchy_attachment_point;
void HierarchyLocations::index_ap(inter_tree *I, hierarchy_attachment_point *hap) {
if (hap->hap_id >= 0) I->site.haps_indexed_by_id[hap->hap_id] = hap;
}
hierarchy_attachment_point *HierarchyLocations::att(inter_tree *I, int hap_id, text_stream *iterated_text, text_stream *ptype_name, location_requirement req) {
hierarchy_attachment_point *hap = CREATE(hierarchy_attachment_point);
hap->hap_id = hap_id;
hap->requirements = req;
hap->name_stem = Str::duplicate(iterated_text);
hap->type = Str::duplicate(ptype_name);
HierarchyLocations::index_ap(I, hap);
return hap;
}
#ifdef CORE_MODULE
package_request *HierarchyLocations::attach_new_package(inter_tree *I, compilation_unit *C, package_request *R, int hap_id) {
if ((hap_id < 0) || (hap_id >= NO_DEFINED_HAP_VALUES) || (I->site.haps_indexed_by_id[hap_id] == NULL))
internal_error("invalid HAP request");
hierarchy_attachment_point *hap = I->site.haps_indexed_by_id[hap_id];
if (hap->requirements.must_be_main_source_text) {
R = hap->requirements.this_exact_package;
} else if (hap->requirements.any_submodule_package_of_this_identity) {
R = Packaging::request_submodule(I, C, hap->requirements.any_submodule_package_of_this_identity);
} else if (hap->requirements.this_exact_package) {
R = hap->requirements.this_exact_package;
} else if (hap->requirements.this_exact_package_not_yet_created >= 0) {
R = Hierarchy::exotic_package(hap->requirements.this_exact_package_not_yet_created);
} else if (hap->requirements.any_package_of_this_type) {
if ((R == NULL) || (R->eventual_type != PackageTypes::get(I, hap->requirements.any_package_of_this_type)))
internal_error("subpackage in wrong superpackage");
}
return Packaging::request(I, Packaging::make_iname_within(R, hap->name_stem), PackageTypes::get(I, hap->type));
}
#endif