2022-01-02 23:29:43 +02:00
|
|
|
[MakeIdentifiersUniqueStage::] Make Identifiers Unique Stage.
|
|
|
|
|
|
|
|
To make sure certain symbol names translate into globally unique target symbols.
|
|
|
|
|
|
|
|
@ Inter frequently contains multiple symbols with different meanings but the
|
|
|
|
same name: for example, the active part of a function package is referred to
|
|
|
|
with the symbol |call|, so Inter trees tend to be full of symbols called that.
|
|
|
|
|
|
|
|
This overlap of names is not convenient when we eventually generate code from
|
|
|
|
the Inter tree: we want different meanings to produce different "translated"
|
|
|
|
names. (Recall that a symbol has a "translated" name as well as its real name;
|
|
|
|
the "translated" name is the identifier used for it in the code we generated.)
|
|
|
|
|
|
|
|
So the following gives unique translated names to symbols marked with the
|
2022-02-04 02:55:12 +02:00
|
|
|
|MAKE_NAME_UNIQUE_ISYMF| bit. So for example
|
2022-01-02 23:29:43 +02:00
|
|
|
= (text)
|
2022-02-04 02:55:12 +02:00
|
|
|
NAME MAKE_NAME_UNIQUE_ISYMF TRANSLATION
|
2022-04-19 02:29:00 +03:00
|
|
|
call TRUE --
|
|
|
|
call TRUE --
|
|
|
|
example FALSE --
|
|
|
|
call TRUE --
|
2022-01-02 23:29:43 +02:00
|
|
|
=
|
|
|
|
will become
|
|
|
|
= (text)
|
2022-02-04 02:55:12 +02:00
|
|
|
NAME MAKE_NAME_UNIQUE_ISYMF TRANSLATION
|
2022-04-19 02:29:00 +03:00
|
|
|
call FALSE call_U1
|
|
|
|
call FALSE call_U2
|
|
|
|
example FALSE --
|
|
|
|
call FALSE call_U3
|
2022-01-02 23:29:43 +02:00
|
|
|
=
|
|
|
|
Only the translation changes, not the name itself, which remains |call|.
|
|
|
|
|
|
|
|
Note that this operation is done at the end of linking because these |call|
|
|
|
|
symbols (or whatever) may occur in multiple compilation units; it would be no
|
|
|
|
good to uniquely number them within each kit, for example, because then each
|
|
|
|
kit would have its own |call_U1|, causing a collision.
|
|
|
|
|
2022-10-11 01:38:11 +03:00
|
|
|
The same operation is performed on identifiers marked as |+private|, because
|
|
|
|
we might have a situation where two kits each contain a function called (say)
|
|
|
|
|Start|, each of them private. When compiled, both functions must exist, and
|
|
|
|
must have different names.
|
|
|
|
|
2022-01-02 23:29:43 +02:00
|
|
|
=
|
|
|
|
void MakeIdentifiersUniqueStage::create_pipeline_stage(void) {
|
|
|
|
ParsingPipelines::new_stage(I"make-identifiers-unique",
|
|
|
|
MakeIdentifiersUniqueStage::run_pipeline_stage, NO_STAGE_ARG, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
int MakeIdentifiersUniqueStage::run_pipeline_stage(pipeline_step *step) {
|
2022-01-08 12:00:07 +02:00
|
|
|
inter_tree *I = step->ephemera.tree;
|
2022-02-03 17:51:44 +02:00
|
|
|
dictionary *D = Dictionaries::new(16, FALSE);
|
2022-01-02 23:29:43 +02:00
|
|
|
InterTree::traverse(I, MakeIdentifiersUniqueStage::visitor, D, NULL, 0);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
@ The dictionary efficiently connects names such as |call| to an integer count
|
|
|
|
for each one, but //foundation// does not provide dictionaries from texts to
|
|
|
|
integers, only to structures allocated by the memory manager: so we must use
|
|
|
|
the following.
|
|
|
|
|
|
|
|
=
|
|
|
|
typedef struct uniqueness_count {
|
|
|
|
int count;
|
|
|
|
CLASS_DEFINITION
|
|
|
|
} uniqueness_count;
|
|
|
|
|
|
|
|
@ Note that if |S| is equated to some other symbol, then its translated
|
|
|
|
name will never matter, because identifiers in the eventual code will come
|
|
|
|
from the symbol |S| is equated to. So we needn't bother to have a unique
|
|
|
|
translation in that case.
|
|
|
|
|
|
|
|
=
|
|
|
|
void MakeIdentifiersUniqueStage::visitor(inter_tree *I, inter_tree_node *P, void *state) {
|
|
|
|
dictionary *D = (dictionary *) state;
|
2022-03-14 00:08:41 +02:00
|
|
|
if (Inode::is(P, PACKAGE_IST)) {
|
2022-03-01 02:41:22 +02:00
|
|
|
inter_package *Q = PackageInstruction::at_this_head(P);
|
2022-01-31 01:49:12 +02:00
|
|
|
inter_symbols_table *ST = InterPackage::scope(Q);
|
2022-02-03 17:51:44 +02:00
|
|
|
LOOP_OVER_SYMBOLS_TABLE(S, ST) {
|
2022-10-11 01:38:11 +03:00
|
|
|
if (Wiring::is_wired(S) == FALSE) {
|
2022-10-13 01:53:21 +03:00
|
|
|
if (Str::len(InterSymbol::get_translate(S)) == 0) {
|
|
|
|
text_stream *N = InterSymbol::identifier(S);
|
|
|
|
int last_tick = -1;
|
|
|
|
for (int i=0; i<Str::len(N); i++)
|
|
|
|
if (Str::get_at(N, i) == '`')
|
|
|
|
last_tick = i;
|
|
|
|
if (last_tick >= 0) {
|
|
|
|
TEMPORARY_TEXT(T)
|
|
|
|
WRITE_TO(T, "NS_");
|
|
|
|
for (int i=last_tick+1; i<Str::len(N); i++)
|
|
|
|
PUT_TO(T, Str::get_at(N, i));
|
|
|
|
InterSymbol::set_translate(S, T);
|
|
|
|
DISCARD_TEXT(T)
|
|
|
|
InterSymbol::set_flag(S, MAKE_NAME_UNIQUE_ISYMF);
|
|
|
|
}
|
|
|
|
}
|
2022-10-11 01:38:11 +03:00
|
|
|
if (InterSymbol::get_flag(S, MAKE_NAME_UNIQUE_ISYMF)) {
|
|
|
|
@<Give this symbol a unique translation@>;
|
|
|
|
InterSymbol::clear_flag(S, MAKE_NAME_UNIQUE_ISYMF);
|
|
|
|
} else if (SymbolAnnotation::get_b(S, PRIVATE_IANN)) {
|
|
|
|
@<Give this symbol a unique translation@>;
|
|
|
|
}
|
2022-01-02 23:29:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@<Give this symbol a unique translation@> =
|
2022-10-13 01:53:21 +03:00
|
|
|
text_stream *N = InterSymbol::trans(S);
|
2022-01-02 23:29:43 +02:00
|
|
|
uniqueness_count *U = NULL;
|
2022-03-24 12:53:32 +02:00
|
|
|
dict_entry *de = Dictionaries::find(D, N);
|
|
|
|
if (de) {
|
|
|
|
U = (uniqueness_count *) Dictionaries::value_for_entry(de);
|
2022-01-02 23:29:43 +02:00
|
|
|
} else {
|
|
|
|
U = CREATE(uniqueness_count);
|
|
|
|
U->count = 0;
|
|
|
|
Dictionaries::create(D, N);
|
|
|
|
Dictionaries::write_value(D, N, (void *) U);
|
|
|
|
}
|
|
|
|
U->count++;
|
|
|
|
TEMPORARY_TEXT(T)
|
|
|
|
WRITE_TO(T, "%S_U%d", N, U->count);
|
2022-02-03 21:44:57 +02:00
|
|
|
InterSymbol::set_translate(S, T);
|
2022-01-02 23:29:43 +02:00
|
|
|
DISCARD_TEXT(T)
|