§1. Suppose we have an identifier name, say BlkValueCreate, which we think refers to some symbol in an Inter tree. How do we find it, coming up with the right inter_symbol?
The answer must depend on context, so the question really has to be "with the conventions given by this identifier_finder, what inter_symbol does this name correspond to?".
define MAX_IDENTIFIER_PRIORITIES 3
typedef struct identifier_finder { int no_priorities; struct inter_symbols_table *priorities[MAX_IDENTIFIER_PRIORITIES]; } identifier_finder;
- The structure identifier_finder is private to this section.
§2. The most basic set of conventions only allows us to see names visible everywhere:
identifier_finder IdentifierFinders::common_names_only(void) { identifier_finder finder; finder.no_priorities = 0; return finder; }
§3. But we can add to that by providing up to three symbols tables to search in preference order (first match wins):
void IdentifierFinders::next_priority(identifier_finder *finder, inter_symbols_table *where) { if (finder->no_priorities >= MAX_IDENTIFIER_PRIORITIES) internal_error("too many identifier finder priorities"); finder->priorities[finder->no_priorities++] = where; }
inter_symbol *IdentifierFinders::find(inter_tree *I, text_stream *name, identifier_finder finder) { if (Str::get_at(name, 0) == 0x00A7) Interpret this as an absolute URL4.1 else Interpret this as an identifier4.2; LOG("Defeated on %S\n", name); internal_error("unable to find identifier"); return NULL; }
§4.1. If the name begins with this magic character, we interpret it as an absolute URL within the tree — the conventions are then unimportant: either the symbol exists where we said it is, or nothing is found. And in that case we will halt with an internal error: so this must be done speculatively.
Interpret this as an absolute URL4.1 =
TEMPORARY_TEXT(SR) Str::copy(SR, name); Str::delete_first_character(SR); Str::delete_last_character(SR); inter_symbol *S = InterSymbolsTable::URL_to_symbol(I, SR); DISCARD_TEXT(SR) if (S) return S;
- This code is used in §4.
§4.2. Here, though, if all attempts to find the identifier fail, we in effect force it to exist by creating a plug with this name, and then returning that. So the above internal error cannot occur.
Interpret this as an identifier4.2 =
for (int i = 0; i < finder.no_priorities; i++) { inter_symbol *S = InterSymbolsTable::symbol_from_name(finder.priorities[i], name); if (S) return S; } inter_symbol *S = LargeScale::find_architectural_symbol(I, name); if (S) return S; S = InterSymbolsTable::symbol_from_name(LargeScale::connectors_scope(I), name); if (S) return S; S = InterSymbolsTable::symbol_from_name(LargeScale::main_scope(I), name); if (S) return S; S = InterNames::to_symbol(HierarchyLocations::find_by_name(I, name)); if (S) return S;
- This code is used in §4.
§5. A small variation. Note that a token can be marked explicitly with an iname to which it corresponds; if it has been, then this overrides the finding process, because the symbol which that iname incarnates as must be the right one.
inter_symbol *IdentifierFinders::find_token(inter_tree *I, inter_schema_token *t, identifier_finder finder) { if (t->as_quoted) return InterNames::to_symbol(t->as_quoted); #ifdef CORE_MODULE local_variable *lvar = LocalVariables::by_identifier(t->material); if (lvar) return LocalVariables::declare(lvar); #endif return IdentifierFinders::find(I, t->material, finder); }