1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-09 10:34:22 +03:00
inform7/inter/pipeline-module/Chapter 6/Eliminate Redundant Matter Stage.w

130 lines
5.5 KiB
OpenEdge ABL
Raw Normal View History

2022-01-02 23:29:43 +02:00
[EliminateRedundantMatterStage::] Eliminate Redundant Matter Stage.
2019-02-05 02:44:07 +02:00
2022-01-02 23:29:43 +02:00
To remove definitions which are never used: for example, functions which are
never called or referred to.
2019-02-05 02:44:07 +02:00
2022-01-02 23:29:43 +02:00
@ Experience shows that around 20 per cent of the code generated by //inform7//
and, especially, //inter// consists of functions which are never in fact needed.
(A kit, of its nature, is a library of code: some will be useful, some not, in
any given circumstance. Many Inform 7 works will never need to sort a table,
for example.)
This stage removes everything that isn't used.
NB: At present (January 2022) it doesn't work on some test cases, so it's not
included in the standard pipeline.
=
2022-01-02 23:29:43 +02:00
void EliminateRedundantMatterStage::create_pipeline_stage(void) {
ParsingPipelines::new_stage(I"eliminate-redundant-matter",
EliminateRedundantMatterStage::run, NO_STAGE_ARG, FALSE);
}
2022-01-02 23:29:43 +02:00
int EliminateRedundantMatterStage::run(pipeline_step *step) {
2022-01-08 12:00:07 +02:00
inter_tree *I = step->ephemera.tree;
2022-01-02 23:29:43 +02:00
InterTree::traverse(I, EliminateRedundantMatterStage::preserver, step, NULL, PACKAGE_IST);
InterTree::traverse(I, EliminateRedundantMatterStage::destroyer, step, NULL, PACKAGE_IST);
return TRUE;
}
2022-01-02 23:29:43 +02:00
@ We operate on a presumption of guilt: any package which we cannot prove is
2019-07-16 14:53:24 +03:00
needed will be deleted. |Main_fn| is clearly needed, since it is where
execution will begin. A handful of other functions, not called yet but
2019-07-17 02:39:04 +03:00
needed in the final compilation stage (and which replace stubs which would
otherwise be provided by the veneer), must also be included. Command
2019-07-16 14:53:24 +03:00
packages contain grammar for command verbs typed at run-time: these affect
an essential data structure (i.e., the parser grammar) implicitly, and so
we can't detect the dependency here. So we require all command packages to
be included.
2019-02-05 02:44:07 +02:00
=
2022-01-02 23:29:43 +02:00
void EliminateRedundantMatterStage::preserver(inter_tree *I, inter_tree_node *P, void *state) {
2021-11-15 01:40:33 +02:00
pipeline_step *step = (pipeline_step *) state;
2022-01-31 01:49:12 +02:00
inter_package *pack = InterPackage::at_this_head(P);
inter_symbol *ptype = InterPackage::type(pack);
2021-11-15 01:40:33 +02:00
if (ptype == RunningPipelines::get_symbol(step, command_ptype_RPSYM))
2022-01-02 23:29:43 +02:00
EliminateRedundantMatterStage::preserve(pack, step, NULL, I"it's a _command package");
2021-11-15 01:40:33 +02:00
else if (ptype == RunningPipelines::get_symbol(step, property_ptype_RPSYM)) {
2022-01-31 01:49:12 +02:00
text_stream *N = InterPackage::name(pack);
2020-01-12 02:35:36 +02:00
if (Str::eq(N, I"workflag_prop"))
2022-01-02 23:29:43 +02:00
EliminateRedundantMatterStage::preserve(pack, step, NULL, I"it's workflag");
if (Str::eq(N, I"pluralname_prop"))
2022-01-02 23:29:43 +02:00
EliminateRedundantMatterStage::preserve(pack, step, NULL, I"it's pluralname");
if (Str::eq(N, I"ambigpluralname_prop"))
2022-01-02 23:29:43 +02:00
EliminateRedundantMatterStage::preserve(pack, step, NULL, I"it's ambigpluralname");
if (Str::eq(N, I"proper_prop"))
2022-01-02 23:29:43 +02:00
EliminateRedundantMatterStage::preserve(pack, step, NULL, I"it's proper");
2020-01-12 02:35:36 +02:00
}
2021-11-15 01:40:33 +02:00
else if (ptype == RunningPipelines::get_symbol(step, function_ptype_RPSYM)) {
2022-01-31 01:49:12 +02:00
text_stream *N = InterPackage::name(pack);
2019-07-26 12:14:17 +03:00
if (Str::eq(N, I"Main_fn"))
2022-01-02 23:29:43 +02:00
EliminateRedundantMatterStage::preserve(pack, step, NULL, I"it's Main");
if (Str::eq(N, I"MistakeActionSub_fn"))
EliminateRedundantMatterStage::preserve(pack, step, NULL, I"it's MistakeActionSub");
2022-01-02 23:29:43 +02:00
if (Str::eq(N, I"TestScriptSub_fn"))
EliminateRedundantMatterStage::preserve(pack, step, NULL, I"it's TestScriptSub");
2019-07-16 14:53:24 +03:00
}
2019-07-16 02:03:09 +03:00
}
2019-07-16 14:53:24 +03:00
@ Once you need a package, what else do you need?
=
2022-01-02 23:29:43 +02:00
void EliminateRedundantMatterStage::preserve(inter_package *pack, pipeline_step *step,
2021-11-15 01:40:33 +02:00
inter_package *witness, text_stream *reason) {
2019-06-10 10:30:20 +03:00
if ((pack->package_flags) & USED_PACKAGE_FLAG) return;
pack->package_flags |= USED_PACKAGE_FLAG;
2019-07-16 14:53:24 +03:00
if (witness) {
LOGIF(ELIMINATION, "Need $6 because of $6 (because %S)\n", pack, witness, reason);
} else {
LOGIF(ELIMINATION, "Need $6 (because %S)\n", pack, reason);
}
@<If you need a package, you need its parent@>;
@<If you need a package, you need its external dependencies@>;
@<If you need a function or action, you need its internal resources@>;
}
@<If you need a package, you need its parent@> =
2022-01-31 01:49:12 +02:00
inter_package *parent = InterPackage::parent(pack);
if (parent) EliminateRedundantMatterStage::preserve(parent, step, pack,
I"it's the parent");
2019-07-16 14:53:24 +03:00
@<If you need a package, you need its external dependencies@> =
2022-01-31 01:49:12 +02:00
inter_symbols_table *tab = InterPackage::scope(pack);
2022-02-03 17:51:44 +02:00
LOOP_OVER_SYMBOLS_TABLE(symb, tab) {
2022-01-04 01:40:23 +02:00
if (Wiring::is_wired(symb)) {
inter_symbol *E = Wiring::cable_end(symb);
2022-02-03 17:51:44 +02:00
inter_package *needed = Inter::Symbols::package(E);
EliminateRedundantMatterStage::preserve(needed, step, pack,
I"it's an external symbol");
2019-02-05 02:44:07 +02:00
}
2019-06-10 10:30:20 +03:00
}
2019-07-16 14:53:24 +03:00
@<If you need a function or action, you need its internal resources@> =
text_stream *rationale = NULL;
2022-01-31 01:49:12 +02:00
inter_symbol *ptype = InterPackage::type(pack);
if (ptype == RunningPipelines::get_symbol(step, function_ptype_RPSYM))
rationale = I"it's a _function block";
if (ptype == RunningPipelines::get_symbol(step, action_ptype_RPSYM))
rationale = I"it's an _action subpackage";
2019-07-16 14:53:24 +03:00
if (rationale) {
2022-01-31 01:49:12 +02:00
inter_tree_node *D = InterPackage::head(pack);
2019-07-13 16:17:48 +03:00
LOOP_THROUGH_INTER_CHILDREN(C, D) {
2022-01-30 15:32:38 +02:00
if (C->W.instruction[ID_IFLD] == PACKAGE_IST) {
2022-01-31 01:49:12 +02:00
inter_package *P = InterPackage::at_this_head(C);
2022-01-02 23:29:43 +02:00
EliminateRedundantMatterStage::preserve(P, step, pack, rationale);
2019-07-13 16:17:48 +03:00
}
2019-02-05 02:44:07 +02:00
}
}
2022-01-02 23:29:43 +02:00
@ Whatever has not been preserved, is now destroyed.
2019-07-16 14:53:24 +03:00
=
2022-01-02 23:29:43 +02:00
void EliminateRedundantMatterStage::destroyer(inter_tree *I, inter_tree_node *P, void *state) {
2022-01-31 01:49:12 +02:00
inter_package *pack = InterPackage::at_this_head(P);
if ((pack) && ((pack->package_flags & USED_PACKAGE_FLAG) == 0)) {
2019-07-26 21:20:27 +03:00
LOGIF(ELIMINATION, "Striking unused package $6 (type %S)\n",
2022-01-31 01:49:12 +02:00
pack, InterPackage::type(pack)->symbol_name);
2022-01-27 01:59:02 +02:00
NodePlacement::remove(P);
}
2019-06-10 10:30:20 +03:00
}