To make sure certain symbol names translate into globally unique target symbols.
§1. 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
MAKE_NAME_UNIQUE_ISYMF bit. So for example
NAME MAKE_NAME_UNIQUE_ISYMF TRANSLATION
call TRUE --
call TRUE --
example FALSE --
call TRUE --
will become
NAME MAKE_NAME_UNIQUE_ISYMF TRANSLATION
call FALSE call_U1
call FALSE call_U2
example FALSE --
call FALSE call_U3
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.
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.
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) { inter_tree *I = step->ephemera.tree; dictionary *D = Dictionaries::new(16, FALSE); InterTree::traverse(I, MakeIdentifiersUniqueStage::visitor, D, NULL, 0); return TRUE; }
§2. 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.
classdef uniqueness_count { int count; }
- The structure uniqueness_count is private to this section.
§3. 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; if (Inode::is(P, PACKAGE_IST)) { inter_package *Q = PackageInstruction::at_this_head(P); inter_symbols_table *ST = InterPackage::scope(Q); LOOP_OVER_SYMBOLS_TABLE(S, ST) { if (Wiring::is_wired(S) == FALSE) { 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); } } if (InterSymbol::get_flag(S, MAKE_NAME_UNIQUE_ISYMF)) { Give this symbol a unique translation3.1; InterSymbol::clear_flag(S, MAKE_NAME_UNIQUE_ISYMF); } else if (SymbolAnnotation::get_b(S, PRIVATE_IANN)) { Give this symbol a unique translation3.1; } } } } }
§3.1. Give this symbol a unique translation3.1 =
text_stream *N = InterSymbol::trans(S); uniqueness_count *U = NULL; dict_entry *de = Dictionaries::find(D, N); if (de) { U = (uniqueness_count *) Dictionaries::value_for_entry(de); } 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); InterSymbol::set_translate(S, T); DISCARD_TEXT(T)
- This code is used in §3 (twice).