1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-05 16:44:21 +03:00
inform7/inter/inter-module/Chapter 2/Symbols.w
2019-02-05 00:44:07 +00:00

318 lines
9.8 KiB
OpenEdge ABL

[Inter::Symbols::] Symbols.
To manage named symbols in inter code.
@h Symbols themselves.
@e LABEL_ISYMT from 1
@e MISC_ISYMT
@e PACKAGE_ISYMT
@e PTYPE_ISYMT
@e DEFINED_ISYMD from 1
@e UNDEFINED_ISYMD
@e LINKED_ISYMD
@e PRIVATE_ISYMS from 1
@e PUBLIC_ISYMS
@e EXTERNAL_ISYMS
=
typedef struct inter_symbol {
inter_t symbol_ID;
struct inter_symbols_table *owning_table;
struct text_stream *symbol_name;
int symbol_type;
int symbol_scope;
int definition_status;
struct inter_frame definition;
struct inter_frame importation_frame;
struct inter_reading_state following_symbol;
struct inter_symbol *equated_to;
struct text_stream *equated_name;
int transient_flags;
int no_symbol_annotations;
struct inter_annotation symbol_annotations[MAX_INTER_ANNOTATIONS_PER_SYMBOL];
struct text_stream *splat_text;
struct text_stream *translate_text;
struct text_stream *export_name;
struct text_stream *append_text;
struct inter_symbol *bridge_symbol;
MEMORY_MANAGEMENT
} inter_symbol;
@ =
inter_symbol *Inter::Symbols::new(text_stream *name, inter_symbols_table *T, inter_t ID) {
if (Str::len(name) == 0) internal_error("symbol cannot have empty text as identifier");
inter_symbol *symb = CREATE(inter_symbol);
symb->owning_table = T;
symb->symbol_ID = ID;
symb->symbol_type = MISC_ISYMT;
symb->symbol_scope = PUBLIC_ISYMS;
symb->symbol_name = Str::duplicate(name);
Inter::Symbols::undefine(symb);
symb->importation_frame = Inter::Frame::around(NULL, -1);
symb->no_symbol_annotations = 0;
for (int i=0; i<MAX_INTER_ANNOTATIONS_PER_SYMBOL; i++)
symb->symbol_annotations[i] = Inter::Defn::invalid_annotation();
symb->equated_to = NULL;
symb->equated_name = NULL;
symb->transient_flags = 0;
symb->splat_text = NULL;
symb->translate_text = NULL;
symb->export_name = NULL;
symb->append_text = NULL;
symb->bridge_symbol = NULL;
LOGIF(INTER_SYMBOLS, "Created symbol $3 in $4\n", symb, T);
return symb;
}
void Inter::Symbols::log(OUTPUT_STREAM, void *vs) {
inter_symbol *S = (inter_symbol *) vs;
if (S == NULL) WRITE("<no-symbol>");
else WRITE("%S/%d", S->symbol_name, S->symbol_ID - SYMBOL_BASE_VAL);
}
@ =
int Inter::Symbols::is_stored_in_data(inter_t val1, inter_t val2) {
if (val1 == ALIAS_IVAL) return TRUE;
return FALSE;
}
void Inter::Symbols::to_data(inter_repository *I, inter_package *pack, inter_symbol *S, inter_t *val1, inter_t *val2) {
if (S == NULL) internal_error("no symbol");
*val1 = ALIAS_IVAL; *val2 = Inter::SymbolsTables::id_from_symbol(I, pack, S);
}
@ =
void Inter::Symbols::write_declaration(OUTPUT_STREAM, inter_symbol *mark, int N) {
for (int L=0; L<N; L++) WRITE("\t");
WRITE("symbol ");
switch (mark->symbol_scope) {
case PRIVATE_ISYMS: WRITE("private"); break;
case PUBLIC_ISYMS: WRITE("public"); break;
case EXTERNAL_ISYMS: WRITE("external"); break;
default: internal_error("unknown symbol type"); break;
}
WRITE(" ");
switch (mark->symbol_type) {
case LABEL_ISYMT: WRITE("label"); break;
case MISC_ISYMT: WRITE("misc"); break;
case PACKAGE_ISYMT: WRITE("package"); break;
case PTYPE_ISYMT: WRITE("packagetype"); break;
default: internal_error("unknown symbol type"); break;
}
WRITE(" %S", mark->symbol_name);
if (Inter::Symbols::get_flag(mark, MAKE_NAME_UNIQUE)) WRITE("*");
text_stream *trans_name = Inter::Symbols::get_translate(mark);
if (Str::len(trans_name) > 0)
WRITE(" -> %S", trans_name);
inter_symbol *eq = mark->equated_to;
if (eq) {
WRITE(" == ");
Inter::SymbolsTables::symbol_to_url_name(OUT, eq);
}
}
void Inter::Symbols::define(inter_symbol *S, inter_frame P) {
if (S == NULL) internal_error("tried to define null symbol");
S->definition = P;
S->definition_status = DEFINED_ISYMD;
}
inter_frame Inter::Symbols::defining_frame(inter_symbol *S) {
if (S == NULL) internal_error("tried to find definition of null symbol");
return S->definition;
}
int Inter::Symbols::is_defined(inter_symbol *S) {
if (S == NULL) return FALSE;
inter_frame D = Inter::Symbols::defining_frame(S);
if (Inter::Frame::valid(&D)) return TRUE;
return FALSE;
}
void Inter::Symbols::strike_definition(inter_symbol *S) {
if (S) {
inter_frame D = Inter::Symbols::defining_frame(S);
if (Inter::Frame::valid(&D)) {
inter_repository *I = D.repo_segment->owning_repo;
Inter::Nop::nop_out(I, D);
}
Inter::Symbols::undefine(S);
}
}
void Inter::Symbols::undefine(inter_symbol *S) {
if (S == NULL) internal_error("tried to undefine null symbol");
S->definition = Inter::Frame::around(NULL, -1);
S->definition_status = UNDEFINED_ISYMD;
}
void Inter::Symbols::clear_transient_flags(void) {
inter_symbol *symb;
LOOP_OVER(symb, inter_symbol) symb->transient_flags = 0;
}
int Inter::Symbols::get_flag(inter_symbol *symb, int f) {
if (symb == NULL) internal_error("no symbol");
// LOG("Get %08x for %S (%08x)\n", f, symb->symbol_name, symb->transient_flags);
return (symb->transient_flags & f)?TRUE:FALSE;
}
void Inter::Symbols::set_flag(inter_symbol *symb, int f) {
if (symb == NULL) internal_error("no symbol");
// LOG("Set %08x for %S\n", f, symb->symbol_name);
symb->transient_flags = symb->transient_flags | f;
}
void Inter::Symbols::clear_flag(inter_symbol *symb, int f) {
if (symb == NULL) internal_error("no symbol");
if (symb->transient_flags & f) symb->transient_flags = symb->transient_flags - f;
}
void Inter::Symbols::set_splat(inter_symbol *symb, text_stream *S) {
if (symb == NULL) internal_error("no symbol");
symb->splat_text = S;
}
text_stream *Inter::Symbols::get_splat(inter_symbol *symb) {
if (symb == NULL) internal_error("no symbol");
return symb->splat_text;
}
void Inter::Symbols::set_bridge(inter_symbol *symb, inter_symbol *B) {
if (symb == NULL) internal_error("no symbol");
symb->bridge_symbol = B;
}
inter_symbol *Inter::Symbols::get_bridge(inter_symbol *symb) {
if (symb == NULL) internal_error("no symbol");
return symb->bridge_symbol;
}
void Inter::Symbols::set_translate(inter_symbol *symb, text_stream *S) {
if (symb == NULL) internal_error("no symbol");
symb->translate_text = Str::duplicate(S);
}
text_stream *Inter::Symbols::get_translate(inter_symbol *symb) {
if (symb == NULL) internal_error("no symbol");
return symb->translate_text;
}
void Inter::Symbols::set_export_name(inter_symbol *symb, text_stream *S) {
if (symb == NULL) internal_error("no symbol");
symb->export_name = S;
}
text_stream *Inter::Symbols::get_export_name(inter_symbol *symb) {
if (symb == NULL) internal_error("no symbol");
return symb->export_name;
}
void Inter::Symbols::set_append(inter_symbol *symb, text_stream *S) {
if (symb == NULL) internal_error("no symbol");
symb->append_text = S;
}
text_stream *Inter::Symbols::get_append(inter_symbol *symb) {
if (symb == NULL) internal_error("no symbol");
return symb->append_text;
}
void Inter::Symbols::annotate(inter_repository *I, inter_symbol *symb, inter_annotation IA) {
if (symb == NULL) internal_error("annotated null symbol");
if (symb->no_symbol_annotations >= MAX_INTER_ANNOTATIONS_PER_SYMBOL)
internal_error("too many annotations");
LOGIF(INTER_SYMBOLS, "Annot %d of %S is ", symb->no_symbol_annotations, symb->symbol_name);
if (Log::aspect_switched_on(INTER_SYMBOLS_DA)) Inter::Defn::write_annotation(DL, I, IA);
LOGIF(INTER_SYMBOLS, "\n");
symb->symbol_annotations[symb->no_symbol_annotations++] = IA;
}
void Inter::Symbols::annotate_i(inter_repository *I, inter_symbol *symb, inter_t annot_ID, inter_t n) {
inter_annotation IA = Inter::Defn::annotation_from_bytecode(annot_ID, n);
Inter::Symbols::annotate(I, symb, IA);
}
int Inter::Symbols::read_annotation(inter_symbol *symb, inter_t ID) {
for (int i=0; i<symb->no_symbol_annotations; i++)
if (symb->symbol_annotations[i].annot->annotation_ID == ID)
return (int) symb->symbol_annotations[i].annot_value;
return -1;
}
text_stream *Inter::Symbols::read_annotation_t(inter_symbol *symb, inter_repository *I, inter_t ID) {
for (int i=0; i<symb->no_symbol_annotations; i++)
if (symb->symbol_annotations[i].annot->annotation_ID == ID) {
inter_t N = symb->symbol_annotations[i].annot_value;
return Inter::get_text(I, N);
}
return NULL;
}
void Inter::Symbols::annotate_t(inter_repository *I, inter_symbol *symb, inter_t annot_ID, text_stream *S) {
inter_t n = Inter::create_text(I);
Str::copy(Inter::get_text(I, n), S);
inter_annotation IA = Inter::Defn::annotation_from_bytecode(annot_ID, n);
Inter::Symbols::annotate(I, symb, IA);
}
void Inter::Symbols::write_annotations(OUTPUT_STREAM, inter_repository *I, inter_symbol *symb) {
if (symb)
for (int i=0; i<symb->no_symbol_annotations; i++)
Inter::Defn::write_annotation(OUT, I, symb->symbol_annotations[i]);
}
@ =
int Inter::Symbols::is_predeclared(inter_symbol *S) {
if (S == NULL) return FALSE;
if (S->symbol_scope != PUBLIC_ISYMS) return FALSE;
if (S->symbol_scope != MISC_ISYMT) return FALSE;
if (S->definition_status != UNDEFINED_ISYMD) return FALSE;
return TRUE;
}
int Inter::Symbols::is_predeclared_local(inter_symbol *S) {
if (S == NULL) return FALSE;
if (S->symbol_scope != PRIVATE_ISYMS) return FALSE;
if (S->symbol_scope != MISC_ISYMT) return FALSE;
if (S->definition_status != UNDEFINED_ISYMD) return FALSE;
return TRUE;
}
int Inter::Symbols::is_extern(inter_symbol *S) {
if (S == NULL) return FALSE;
if (S->symbol_scope == EXTERNAL_ISYMS) return TRUE;
return FALSE;
}
void Inter::Symbols::extern(inter_symbol *S) {
S->symbol_scope = EXTERNAL_ISYMS;
S->symbol_type = MISC_ISYMT;
S->definition_status = UNDEFINED_ISYMD;
}
int Inter::Symbols::is_label(inter_symbol *S) {
if (S == NULL) return FALSE;
if (S->symbol_scope != PRIVATE_ISYMS) return FALSE;
if (S->symbol_scope != LABEL_ISYMT) return FALSE;
return TRUE;
}
void Inter::Symbols::label(inter_symbol *S) {
S->symbol_scope = PRIVATE_ISYMS;
S->symbol_type = LABEL_ISYMT;
S->definition_status = UNDEFINED_ISYMD;
}
void Inter::Symbols::local(inter_symbol *S) {
S->symbol_scope = PRIVATE_ISYMS;
S->symbol_type = MISC_ISYMT;
S->definition_status = UNDEFINED_ISYMD;
}