1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-06-01 07:48:35 +03:00
inform7/inform7/core-module/Chapter 27/Hierarchy Locations.w
2019-04-16 08:15:15 +01:00

349 lines
13 KiB
OpenEdge ABL

[HierarchyLocations::] Hierarchy Locations.
@
=
typedef struct location_requirement {
struct submodule_identity *this_local_submodule;
struct package_request *this_mundane_package;
int this_exotic_package;
struct inter_symbol *any_package_of_this_type;
} location_requirement;
location_requirement HierarchyLocations::blank(void) {
location_requirement req;
req.this_local_submodule = NULL;
req.this_mundane_package = NULL;
req.this_exotic_package = -1;
req.any_package_of_this_type = NULL;
return req;
}
location_requirement HierarchyLocations::local_submodule(submodule_identity *sid) {
location_requirement req = HierarchyLocations::blank();
req.this_local_submodule = sid;
return req;
}
location_requirement HierarchyLocations::generic_submodule(submodule_identity *sid) {
location_requirement req = HierarchyLocations::blank();
req.this_mundane_package = Packaging::generic_resource(sid);
return req;
}
location_requirement HierarchyLocations::synoptic_submodule(submodule_identity *sid) {
location_requirement req = HierarchyLocations::blank();
req.this_mundane_package = Packaging::synoptic_resource(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 = HierarchyLocations::ptype(ptype_name);
return req;
}
location_requirement HierarchyLocations::this_package(package_request *P) {
location_requirement req = HierarchyLocations::blank();
req.this_mundane_package = P;
return req;
}
location_requirement HierarchyLocations::this_exotic_package(int N) {
location_requirement req = HierarchyLocations::blank();
req.this_exotic_package = N;
return req;
}
typedef struct named_resource_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 inter_symbol *package_type;
struct name_translation trans;
MEMORY_MANAGEMENT
} named_resource_location;
named_resource_location *HierarchyLocations::new(void) {
named_resource_location *nrl = CREATE(named_resource_location);
nrl->access_number = -1;
nrl->access_name = NULL;
nrl->function_package_name = NULL;
nrl->datum_package_name = NULL;
nrl->equates_to_iname = NULL;
nrl->package_type = NULL;
nrl->trans = Translation::same();
nrl->requirements = HierarchyLocations::blank();
return nrl;
}
named_resource_location *HierarchyLocations::con(int id, text_stream *name, name_translation nt, location_requirement req) {
named_resource_location *nrl = HierarchyLocations::new();
nrl->access_number = id;
nrl->access_name = Str::duplicate(name);
nrl->requirements = req;
nrl->trans = nt;
HierarchyLocations::index(nrl);
return nrl;
}
named_resource_location *HierarchyLocations::package(int id, text_stream *name, text_stream *ptype_name, location_requirement req) {
named_resource_location *nrl = HierarchyLocations::new();
nrl->access_number = id;
nrl->access_name = Str::duplicate(name);
nrl->requirements = req;
nrl->package_type = HierarchyLocations::ptype(ptype_name);
HierarchyLocations::index(nrl);
return nrl;
}
named_resource_location *HierarchyLocations::make_as(int id, text_stream *name, inter_name *iname) {
named_resource_location *nrl = HierarchyLocations::new();
nrl->access_number = id;
nrl->access_name = Str::duplicate(name);
nrl->requirements = HierarchyLocations::this_package(iname->eventual_owner);
nrl->equates_to_iname = iname;
HierarchyLocations::index(nrl);
return nrl;
}
named_resource_location *HierarchyLocations::func(int id, text_stream *name, name_translation nt, location_requirement req) {
named_resource_location *nrl = CREATE(named_resource_location);
nrl->access_number = id;
nrl->access_name = Str::duplicate(nt.translate_to);
nrl->function_package_name = Str::duplicate(name);
nrl->requirements = req;
nrl->trans = nt;
HierarchyLocations::index(nrl);
return nrl;
}
named_resource_location *HierarchyLocations::datum(int id, text_stream *name, name_translation nt, location_requirement req) {
named_resource_location *nrl = CREATE(named_resource_location);
nrl->access_number = id;
nrl->access_name = Str::duplicate(nt.translate_to);
nrl->datum_package_name = Str::duplicate(name);
nrl->requirements = req;
nrl->trans = nt;
HierarchyLocations::index(nrl);
return nrl;
}
named_resource_location *nrls_indexed_by_id[MAX_HL];
dictionary *nrls_indexed_by_name = NULL;
int nrls_created = FALSE;
void HierarchyLocations::create_nrls(void) {
nrls_created = TRUE;
for (int i=0; i<MAX_HL; i++) nrls_indexed_by_id[i] = NULL;
nrls_indexed_by_name = Dictionaries::new(512, FALSE);
Hierarchy::establish();
}
void HierarchyLocations::index(named_resource_location *nrl) {
if (nrls_created == FALSE) HierarchyLocations::create_nrls();
if (nrl->access_number >= 0) nrls_indexed_by_id[nrl->access_number] = nrl;
if (nrl->requirements.any_package_of_this_type == NULL) {
Dictionaries::create(nrls_indexed_by_name, nrl->access_name);
Dictionaries::write_value(nrls_indexed_by_name, nrl->access_name, (void *) nrl);
}
}
inter_name *HierarchyLocations::find(int id) {
if (nrls_created == FALSE) HierarchyLocations::create_nrls();
if ((id < 0) || (id >= MAX_HL) || (nrls_indexed_by_id[id] == NULL))
internal_error("bad nrl ID");
return HierarchyLocations::nrl_to_iname(nrls_indexed_by_id[id]);
}
inter_name *HierarchyLocations::find_by_name(text_stream *name) {
if (Str::len(name) == 0) internal_error("bad nrl name");
if (nrls_created == FALSE) HierarchyLocations::create_nrls();
if (Dictionaries::find(nrls_indexed_by_name, name))
return HierarchyLocations::nrl_to_iname(
(named_resource_location *)
Dictionaries::read_value(nrls_indexed_by_name, name));
return NULL;
}
inter_name *HierarchyLocations::function(package_request *R, text_stream *name, text_stream *trans) {
inter_name *iname = Packaging::function(InterNames::one_off(name, R), R, NULL);
if (trans) Inter::Symbols::set_translate(InterNames::to_symbol(iname), trans);
return iname;
}
inter_name *HierarchyLocations::nrl_to_iname(named_resource_location *nrl) {
if (nrl->requirements.any_package_of_this_type) internal_error("NRL accessed inappropriately");
if (nrl->equates_to_iname == NULL) {
if (nrl->requirements.this_mundane_package == NULL) {
if (nrl->requirements.this_exotic_package >= 0)
nrl->requirements.this_mundane_package = Hierarchy::exotic_package(nrl->requirements.this_exotic_package);
else internal_error("package can't be found'");
}
if (nrl->requirements.this_mundane_package == Hierarchy::template()) {
packaging_state save = Packaging::enter(nrl->requirements.this_mundane_package);
nrl->equates_to_iname = InterNames::one_off(nrl->access_name, Hierarchy::template());
nrl->equates_to_iname->symbol = Emit::extern(nrl->access_name, K_value);
Packaging::exit(save);
} else if (Str::len(nrl->function_package_name) > 0) {
nrl->equates_to_iname = Packaging::function_text(
InterNames::one_off(nrl->function_package_name, nrl->requirements.this_mundane_package),
nrl->requirements.this_mundane_package,
nrl->access_name);
} else if (Str::len(nrl->datum_package_name) > 0) {
nrl->equates_to_iname = Packaging::datum_text(
InterNames::one_off(nrl->datum_package_name, nrl->requirements.this_mundane_package),
nrl->requirements.this_mundane_package,
nrl->access_name);
} else if ((nrl->requirements.this_mundane_package) && (nrl->equates_to_iname == NULL)) {
nrl->equates_to_iname = InterNames::one_off(nrl->access_name, nrl->requirements.this_mundane_package);
}
nrl->equates_to_iname = Hierarchy::post_process(nrl->access_number, nrl->equates_to_iname);
nrl->requirements.this_mundane_package = Packaging::home_of(nrl->equates_to_iname);
}
return nrl->equates_to_iname;
}
inter_name *HierarchyLocations::find_in_package(int id, package_request *P, wording W, compilation_module *C) {
if (nrls_created == FALSE) HierarchyLocations::create_nrls();
if ((id < 0) || (id >= MAX_HL) || (nrls_indexed_by_id[id] == NULL))
internal_error("bad nrl ID");
named_resource_location *nrl = nrls_indexed_by_id[id];
if (nrl->requirements.any_package_of_this_type == NULL) internal_error("NRL accessed inappropriately");
if ((P == NULL) || (P->eventual_type != nrl->requirements.any_package_of_this_type)) {
LOG("AN: %S, FPN: %S\n", nrl->access_name, nrl->function_package_name);
LOG("Have type: $3, required: $3\n", P->eventual_type, nrl->requirements.any_package_of_this_type);
internal_error("constant in wrong superpackage");
}
inter_name *iname = NULL;
if (nrl->trans.translate_to) {
text_stream *T = nrl->trans.translate_to;
@<Make the actual iname@>;
} else if (nrl->trans.generate_from >= 0) {
TEMPORARY_TEXT(T);
inter_name *temp_iname = NULL;
if (nrl->trans.localise)
temp_iname = InterNames::new_in(nrl->trans.generate_from, C);
else
temp_iname = InterNames::new(nrl->trans.generate_from);
WRITE_TO(T, "%n", temp_iname);
@<Make the actual iname@>;
DISCARD_TEXT(T);
} else {
text_stream *T = NULL;
@<Make the actual iname@>;
}
if (nrl->trans.then_make_unique)
Inter::Symbols::set_flag(InterNames::to_symbol(iname), MAKE_NAME_UNIQUE);
return iname;
}
@<Make the actual iname@> =
if (Str::len(nrl->function_package_name) > 0) {
iname = Packaging::function_text(
InterNames::one_off(nrl->function_package_name, P),
P,
NULL);
} else {
if (Str::len(nrl->access_name) == 0) {
LOG("********** %S\n", T);
iname = InterNames::one_off(T, P);
} else
iname = InterNames::one_off(nrl->access_name, P);
}
if (!Wordings::empty(W)) InterNames::attach_memo(iname, W);
if ((Str::len(T) > 0) && (nrl->access_name)) InterNames::translate(iname, T);
@ =
package_request *HierarchyLocations::package_in_package(int id, package_request *P) {
if (nrls_created == FALSE) HierarchyLocations::create_nrls();
if ((id < 0) || (id >= MAX_HL) || (nrls_indexed_by_id[id] == NULL))
internal_error("bad nrl ID");
named_resource_location *nrl = nrls_indexed_by_id[id];
if (nrl->requirements.any_package_of_this_type == NULL) internal_error("NRL accessed inappropriately");
if ((P == NULL) || (P->eventual_type != nrl->requirements.any_package_of_this_type)) internal_error("subpackage in wrong superpackage");
if (nrl->package_type == NULL) internal_error("package_in_package used wrongly");
return Packaging::request(InterNames::one_off(nrl->access_name, P), P, nrl->package_type);
}
@
@e BOGUS_HAP from 0
=
typedef struct hierarchy_attachment_point {
int hap_id;
int counter;
struct inter_symbol *type;
struct location_requirement requirements;
MEMORY_MANAGEMENT
} hierarchy_attachment_point;
hierarchy_attachment_point *haps_indexed_by_id[MAX_HAP];
int haps_created = FALSE;
void HierarchyLocations::create_haps(void) {
haps_created = TRUE;
for (int i=0; i<MAX_HAP; i++) haps_indexed_by_id[i] = NULL;
}
void HierarchyLocations::index_ap(hierarchy_attachment_point *hap) {
if (haps_created == FALSE) HierarchyLocations::create_haps();
if (hap->hap_id >= 0) haps_indexed_by_id[hap->hap_id] = hap;
}
hierarchy_attachment_point *HierarchyLocations::ap(int ap_id, location_requirement req, text_stream *iterated_text, text_stream *ptype_name) {
hierarchy_attachment_point *hap = CREATE(hierarchy_attachment_point);
hap->hap_id = ap_id;
hap->requirements = req;
hap->counter = Packaging::register_counter(iterated_text);
hap->type = HierarchyLocations::ptype(ptype_name);
HierarchyLocations::index_ap(hap);
return hap;
}
package_request *HierarchyLocations::attach_new_package(compilation_module *C, package_request *R, int hap_id) {
if ((hap_id < 0) || (hap_id >= MAX_HAP) || (haps_created == FALSE) || (haps_indexed_by_id[hap_id] == NULL))
internal_error("invalid HAP request");
hierarchy_attachment_point *hap = haps_indexed_by_id[hap_id];
if (hap->requirements.this_local_submodule)
R = Packaging::request_resource(C, hap->requirements.this_local_submodule);
else if (hap->requirements.this_mundane_package)
R = hap->requirements.this_mundane_package;
else if (hap->requirements.this_exotic_package >= 0)
R = Hierarchy::exotic_package(hap->requirements.this_exotic_package);
else if (hap->requirements.any_package_of_this_type) {
if ((R == NULL) || (R->eventual_type != hap->requirements.any_package_of_this_type))
internal_error("subpackage in wrong superpackage");
}
return Packaging::request(Packaging::supply_iname(R, hap->counter), R, hap->type);
}
@
=
dictionary *ptypes_indexed_by_name = NULL;
int ptypes_created = FALSE;
inter_symbol *HierarchyLocations::ptype(text_stream *name) {
if (ptypes_created == FALSE) {
ptypes_created = TRUE;
ptypes_indexed_by_name = Dictionaries::new(512, FALSE);
}
if (Dictionaries::find(ptypes_indexed_by_name, name))
return (inter_symbol *) Dictionaries::read_value(ptypes_indexed_by_name, name);
inter_symbol *new_ptype = Packaging::register_ptype(name, TRUE);
Dictionaries::create(ptypes_indexed_by_name, name);
Dictionaries::write_value(ptypes_indexed_by_name, name, (void *) new_ptype);
return new_ptype;
}