1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/inter/bytecode-module/Chapter 2/Symbols.w
2021-05-03 14:39:21 +01:00

348 lines
11 KiB
OpenEdge ABL

[Inter::Symbols::] Symbols.
To manage named symbols in inter code.
@h Symbols themselves.
=
typedef struct inter_symbol {
inter_ti symbol_ID;
struct inter_symbols_table *owning_table;
struct text_stream *symbol_name;
struct inter_tree_node *definition;
struct inter_symbol *equated_to;
struct text_stream *equated_name;
int symbol_status;
struct inter_annotation_set ann_set;
struct text_stream *translate_text;
int link_time;
struct inter_symbol *linked_to;
int metadata_key;
} inter_symbol;
@ =
inter_symbol *Inter::Symbols::new(text_stream *name, inter_symbols_table *T, inter_ti 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_status = 0;
Inter::Symbols::set_type(symb, MISC_ISYMT);
Inter::Symbols::set_scope(symb, PUBLIC_ISYMS);
symb->symbol_name = Str::duplicate(name);
Inter::Symbols::undefine(symb);
symb->ann_set = Inter::Annotations::new_set();
symb->equated_to = NULL;
symb->equated_name = NULL;
symb->translate_text = NULL;
symb->link_time = 0;
symb->linked_to = NULL;
symb->metadata_key = FALSE;
if (Metadata::valid_key(name)) {
symb->metadata_key = TRUE;
Inter::Symbols::set_scope(symb, PRIVATE_ISYMS);
}
LOGIF(INTER_SYMBOLS, "Created symbol $3 in $4\n", symb, T);
return symb;
}
int Inter::Symbols::get_type(inter_symbol *S) {
return S->symbol_status & SYMBOL_TYPE_MASK_ISYMT;
}
int Inter::Symbols::get_scope(inter_symbol *S) {
return S->symbol_status & SYMBOL_SCOPE_MASK_ISYMT;
}
void Inter::Symbols::set_type(inter_symbol *S, int V) {
S->symbol_status = S->symbol_status - (S->symbol_status & SYMBOL_TYPE_MASK_ISYMT) + V;
}
void Inter::Symbols::set_scope(inter_symbol *S, int V) {
S->symbol_status = S->symbol_status - (S->symbol_status & SYMBOL_SCOPE_MASK_ISYMT) + V;
}
void Inter::Symbols::log(OUTPUT_STREAM, void *vs) {
inter_symbol *S = (inter_symbol *) vs;
if (S == NULL) WRITE("<no-symbol>");
else {
InterSymbolsTables::symbol_to_url_name(DL, S);
WRITE("{%d}", S->symbol_ID - SYMBOL_BASE_VAL);
if (Str::len(S->translate_text) > 0) WRITE("'%S'", S->translate_text);
}
}
int Inter::Symbols::sort_number(const inter_symbol *S) {
if (S == NULL) return 0;
return 100000 * (S->owning_table->allocation_id) + (int) (S->symbol_ID);
}
@ =
int Inter::Symbols::is_stored_in_data(inter_ti val1, inter_ti val2) {
if (val1 == ALIAS_IVAL) return TRUE;
return FALSE;
}
void Inter::Symbols::to_data(inter_tree *I, inter_package *pack, inter_symbol *S, inter_ti *val1, inter_ti *val2) {
if (S == NULL) internal_error("no symbol");
*val1 = ALIAS_IVAL; *val2 = InterSymbolsTables::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 (Inter::Symbols::get_scope(mark)) {
case PRIVATE_ISYMS: WRITE("private"); break;
case PUBLIC_ISYMS: WRITE("public"); break;
case EXTERNAL_ISYMS: WRITE("external"); break;
case PLUG_ISYMS: WRITE("plug"); break;
case SOCKET_ISYMS: WRITE("socket"); break;
default: internal_error("unknown symbol type"); break;
}
WRITE(" ");
switch (Inter::Symbols::get_type(mark)) {
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("*");
if (Str::len(mark->equated_name) > 0) {
WRITE(" --? %S", mark->equated_name);
}
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(" --> ");
InterSymbolsTables::symbol_to_url_name(OUT, eq);
}
}
void Inter::Symbols::define(inter_symbol *S, inter_tree_node *P) {
if (S == NULL) internal_error("tried to define null symbol");
S->definition = P;
}
inter_tree_node *Inter::Symbols::definition(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;
if (Inter::Symbols::definition(S)) return TRUE;
return FALSE;
}
int Inter::Symbols::evaluate_to_int(inter_symbol *S) {
inter_tree_node *P = Inter::Symbols::definition(S);
if ((P) &&
(P->W.data[ID_IFLD] == CONSTANT_IST) &&
(P->W.data[FORMAT_CONST_IFLD] == CONSTANT_DIRECT) &&
(P->W.data[DATA_CONST_IFLD] == LITERAL_IVAL)) {
return (int) P->W.data[DATA_CONST_IFLD + 1];
}
if ((P) &&
(P->W.data[ID_IFLD] == CONSTANT_IST) &&
(P->W.data[FORMAT_CONST_IFLD] == CONSTANT_DIRECT) &&
(P->W.data[DATA_CONST_IFLD] == ALIAS_IVAL)) {
inter_symbols_table *scope = S->owning_table;
inter_symbol *alias_to = InterSymbolsTables::symbol_from_id(scope, P->W.data[DATA_CONST_IFLD + 1]);
return Inter::Symbols::evaluate_to_int(alias_to);
}
return -1;
}
void Inter::Symbols::set_int(inter_symbol *S, int N) {
inter_tree_node *P = Inter::Symbols::definition(S);
if ((P) &&
(P->W.data[ID_IFLD] == CONSTANT_IST) &&
(P->W.data[FORMAT_CONST_IFLD] == CONSTANT_DIRECT) &&
(P->W.data[DATA_CONST_IFLD] == LITERAL_IVAL)) {
P->W.data[DATA_CONST_IFLD + 1] = (inter_ti) N;
return;
}
if ((P) &&
(P->W.data[ID_IFLD] == CONSTANT_IST) &&
(P->W.data[FORMAT_CONST_IFLD] == CONSTANT_DIRECT) &&
(P->W.data[DATA_CONST_IFLD] == ALIAS_IVAL)) {
inter_symbols_table *scope = S->owning_table;
inter_symbol *alias_to = InterSymbolsTables::symbol_from_id(scope, P->W.data[DATA_CONST_IFLD + 1]);
Inter::Symbols::set_int(alias_to, N);
return;
}
if (P == NULL) LOG("Synbol $3 is undefined\n", S);
LOG("Synbol $3 cannot be set to %d\n", S, N);
internal_error("unable to set symbol");
}
void Inter::Symbols::strike_definition(inter_symbol *S) {
if (S) {
inter_tree_node *D = Inter::Symbols::definition(S);
if (D) InterTree::remove_node(D);
Inter::Symbols::undefine(S);
}
}
void Inter::Symbols::remove_from_table(inter_symbol *S) {
int index = (int) S->symbol_ID - (int) SYMBOL_BASE_VAL;
S->owning_table->symbol_array[index] = NULL;
}
void Inter::Symbols::undefine(inter_symbol *S) {
if (S == NULL) internal_error("tried to undefine null symbol");
S->definition = NULL;
}
void Inter::Symbols::clear_transient_flags(inter_symbol *symb) {
symb->symbol_status = (symb->symbol_status) & NONTRANSIENT_SYMBOL_BITS;
}
int Inter::Symbols::get_flag(inter_symbol *symb, int f) {
if (symb == NULL) internal_error("no symbol");
return (symb->symbol_status & f)?TRUE:FALSE;
}
void Inter::Symbols::set_flag(inter_symbol *symb, int f) {
if (symb == NULL) internal_error("no symbol");
symb->symbol_status = symb->symbol_status | f;
}
void Inter::Symbols::clear_flag(inter_symbol *symb, int f) {
if (symb == NULL) internal_error("no symbol");
if (symb->symbol_status & f) symb->symbol_status = symb->symbol_status - f;
}
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::annotate(inter_symbol *symb, inter_annotation IA) {
if (symb == NULL) internal_error("annotated null symbol");
Inter::Annotations::add_to_set(&(symb->ann_set), IA);
}
void Inter::Symbols::unannotate(inter_symbol *symb, inter_ti annot_ID) {
if (symb == NULL) internal_error("annotated null symbol");
Inter::Annotations::remove_from_set(&(symb->ann_set), annot_ID);
}
void Inter::Symbols::annotate_i(inter_symbol *symb, inter_ti annot_ID, inter_ti n) {
inter_annotation IA = Inter::Annotations::from_bytecode(annot_ID, n);
Inter::Symbols::annotate(symb, IA);
}
int Inter::Symbols::read_annotation(const inter_symbol *symb, inter_ti ID) {
inter_annotation *IA = Inter::Annotations::find(&(symb->ann_set), ID);
if (IA) return (int) IA->annot_value;
return -1;
}
text_stream *Inter::Symbols::read_annotation_t(inter_symbol *symb, inter_tree *I, inter_ti ID) {
inter_annotation *IA = Inter::Annotations::find(&(symb->ann_set), ID);
if (IA) return Inter::Warehouse::get_text(InterTree::warehouse(I), IA->annot_value);
return NULL;
}
void Inter::Symbols::annotate_t(inter_tree *I, inter_package *owner, inter_symbol *symb, inter_ti annot_ID, text_stream *S) {
inter_ti n = Inter::Warehouse::create_text(InterTree::warehouse(I), owner);
Str::copy(Inter::Warehouse::get_text(InterTree::warehouse(I), n), S);
inter_annotation IA = Inter::Annotations::from_bytecode(annot_ID, n);
Inter::Symbols::annotate(symb, IA);
}
void Inter::Symbols::write_annotations(OUTPUT_STREAM, inter_tree_node *F, inter_symbol *symb) {
if (symb) Inter::Annotations::write_set(OUT, &(symb->ann_set), F);
}
void Inter::Symbols::transpose_annotations(inter_symbol *symb, inter_ti *grid, inter_ti grid_extent, inter_error_message **E) {
if (symb) Inter::Annotations::transpose_set(&(symb->ann_set), grid, grid_extent, E);
}
@ =
int Inter::Symbols::is_predeclared(inter_symbol *S) {
if (S == NULL) return FALSE;
if (Inter::Symbols::get_scope(S) != PUBLIC_ISYMS) return FALSE;
if (Inter::Symbols::get_type(S) != MISC_ISYMT) return FALSE;
if (Inter::Symbols::is_defined(S)) return FALSE;
return TRUE;
}
int Inter::Symbols::is_predeclared_local(inter_symbol *S) {
if (S == NULL) return FALSE;
if (Inter::Symbols::get_scope(S) != PRIVATE_ISYMS) return FALSE;
if (Inter::Symbols::get_type(S) != MISC_ISYMT) return FALSE;
if (Inter::Symbols::is_defined(S)) return FALSE;
return TRUE;
}
int Inter::Symbols::is_undefined_private(inter_symbol *S) {
if (S == NULL) return FALSE;
if (Inter::Symbols::get_scope(S) != PRIVATE_ISYMS) return FALSE;
if (Inter::Symbols::is_defined(S)) return FALSE;
return TRUE;
}
int Inter::Symbols::is_extern(inter_symbol *S) {
if (S == NULL) return FALSE;
if (Inter::Symbols::get_scope(S) == EXTERNAL_ISYMS) return TRUE;
if (Inter::Symbols::get_scope(S) == PLUG_ISYMS) return TRUE;
return FALSE;
}
void Inter::Symbols::extern(inter_symbol *S) {
Inter::Symbols::set_scope(S, EXTERNAL_ISYMS);
Inter::Symbols::set_type(S, MISC_ISYMT);
S->definition = NULL;
}
int Inter::Symbols::is_label(inter_symbol *S) {
if (S == NULL) return FALSE;
if (Inter::Symbols::get_scope(S) != PRIVATE_ISYMS) return FALSE;
if (Inter::Symbols::get_type(S) != LABEL_ISYMT) return FALSE;
return TRUE;
}
void Inter::Symbols::label(inter_symbol *S) {
if (Str::get_first_char(S->symbol_name) != '.') {
LOG("Name is %S\n", S->symbol_name);
internal_error("not a label name");
}
Inter::Symbols::set_scope(S, PRIVATE_ISYMS);
Inter::Symbols::set_type(S, LABEL_ISYMT);
S->definition = NULL;
}
void Inter::Symbols::local(inter_symbol *S) {
Inter::Symbols::set_scope(S, PRIVATE_ISYMS);
Inter::Symbols::set_type(S, MISC_ISYMT);
S->definition = NULL;
}
int Inter::Symbols::is_local(inter_symbol *S) {
if (S == NULL) return FALSE;
if (Inter::Symbols::get_scope(S) != PRIVATE_ISYMS) return FALSE;
if (Inter::Symbols::get_type(S) != MISC_ISYMT) return FALSE;
return TRUE;
}
int Inter::Symbols::is_connector(inter_symbol *S) {
if ((S) && ((Inter::Symbols::get_scope(S) == PLUG_ISYMS) ||
(Inter::Symbols::get_scope(S) == SOCKET_ISYMS)))
return TRUE;
return FALSE;
}