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/Inter in Memory.w

309 lines
9.4 KiB
OpenEdge ABL
Raw Normal View History

2019-02-05 02:44:07 +02:00
[Inter::] Inter in Memory.
To store bytecode-like intermediate code in memory.
@h Bytecode definition.
@d inter_t unsigned int
@d signed_inter_t int
@h Chunks.
@d IST_SIZE 100
@d SYMBOL_BASE_VAL 0x40000000
@d PREFRAME_SKIP_AMOUNT 0
@d PREFRAME_VERIFICATION_COUNT 1
@d PREFRAME_ORIGIN 2
@d PREFRAME_COMMENT 3
@d PREFRAME_PACKAGE 4
@d PREFRAME_PARENT 5
@d PREFRAME_FIRST_CHILD 6
@d PREFRAME_LAST_CHILD 7
@d PREFRAME_PREVIOUS 8
@d PREFRAME_NEXT 9
@d PREFRAME_GLOBALS 10
@d PREFRAME_SIZE 11
2019-02-05 02:44:07 +02:00
=
typedef struct inter_tree {
struct inter_warehouse *warehouse;
struct inter_frame root_definition_frame;
struct inter_package *root_package;
2019-02-05 02:44:07 +02:00
struct inter_package *main_package;
MEMORY_MANAGEMENT
} inter_tree;
2019-02-05 02:44:07 +02:00
@ =
inter_tree *Inter::create(void) {
inter_tree *I = CREATE(inter_tree);
2019-02-05 02:44:07 +02:00
I->main_package = NULL;
I->warehouse = Inter::Warehouse::new(I);
inter_t N = Inter::create_symbols_table(I);
I->root_package = Inter::get_package(I, Inter::create_package(I));
I->root_definition_frame = Inter::Frame::root_frame(I);
Inter::Packages::make_rootlike(I->root_package);
Inter::Packages::set_scope(I->root_package, Inter::get_symbols_table(I, N));
return I;
2019-02-05 02:44:07 +02:00
}
inter_warehouse *Inter::warehouse(inter_tree *I) {
return I->warehouse;
2019-02-05 02:44:07 +02:00
}
inter_t Inter::create_symbols_table(inter_tree *I) {
inter_warehouse *warehouse = Inter::warehouse(I);
inter_t n = Inter::Warehouse::create_resource(warehouse);
if (warehouse->stored_resources[n].stored_symbols_table == NULL) {
warehouse->stored_resources[n].stored_symbols_table = Inter::SymbolsTables::new();
warehouse->stored_resources[n].stored_symbols_table->n_index = (int) n;
2019-02-05 02:44:07 +02:00
}
return n;
2019-02-05 02:44:07 +02:00
}
inter_symbols_table *Inter::get_global_symbols(inter_tree *I) {
return Inter::Packages::scope(I->root_package);
2019-02-05 02:44:07 +02:00
}
inter_symbols_table *Inter::get_symbols_table(inter_tree *I, inter_t n) {
inter_warehouse *warehouse = Inter::warehouse(I);
if (n >= (inter_t) warehouse->size) return NULL;
if (n == 0) return NULL;
return warehouse->stored_resources[n].stored_symbols_table;
2019-02-05 02:44:07 +02:00
}
inter_t Inter::create_package(inter_tree *I) {
inter_warehouse *warehouse = Inter::warehouse(I);
inter_t n = Inter::Warehouse::create_resource(warehouse);
if (warehouse->stored_resources[n].stored_package == NULL) {
warehouse->stored_resources[n].stored_package = Inter::Packages::new(I, n);
2019-02-05 02:44:07 +02:00
}
return n;
}
inter_package *Inter::get_package(inter_tree *I, inter_t n) {
inter_warehouse *warehouse = Inter::warehouse(I);
if (n >= (inter_t) warehouse->size) return NULL;
2019-02-05 02:44:07 +02:00
if (n == 0) return NULL;
return warehouse->stored_resources[n].stored_package;
2019-02-05 02:44:07 +02:00
}
inter_t Inter::create_text(inter_tree *I) {
inter_warehouse *warehouse = Inter::warehouse(I);
inter_t n = Inter::Warehouse::create_resource(warehouse);
if (warehouse->stored_resources[n].stored_text_stream == NULL) {
warehouse->stored_resources[n].stored_text_stream = Str::new();
2019-02-05 02:44:07 +02:00
}
return n;
}
text_stream *Inter::get_text(inter_tree *I, inter_t n) {
inter_warehouse *warehouse = Inter::warehouse(I);
if (n >= (inter_t) warehouse->size) return NULL;
return warehouse->stored_resources[n].stored_text_stream;
2019-02-05 02:44:07 +02:00
}
inter_t Inter::create_ref(inter_tree *I) {
inter_warehouse *warehouse = Inter::warehouse(I);
inter_t n = Inter::Warehouse::create_resource(warehouse);
warehouse->stored_resources[n].stored_ref = NULL;
2019-02-05 02:44:07 +02:00
return n;
}
void *Inter::get_ref(inter_tree *I, inter_t n) {
inter_warehouse *warehouse = Inter::warehouse(I);
if (n >= (inter_t) warehouse->size) return NULL;
return warehouse->stored_resources[n].stored_ref;
2019-02-05 02:44:07 +02:00
}
void Inter::set_ref(inter_tree *I, inter_t n, void *ref) {
inter_warehouse *warehouse = Inter::warehouse(I);
if (n >= (inter_t) warehouse->size) return;
warehouse->stored_resources[n].stored_ref = ref;
2019-02-05 02:44:07 +02:00
}
inter_frame_list *Inter::new_frame_list(void) {
inter_frame_list *ifl = CREATE(inter_frame_list);
ifl->spare_storage = NULL;
ifl->storage_used = 0;
ifl->storage_capacity = 0;
ifl->first_in_ifl = NULL;
ifl->last_in_ifl = NULL;
return ifl;
2019-02-05 02:44:07 +02:00
}
inter_t Inter::create_frame_list(inter_tree *I) {
inter_warehouse *warehouse = Inter::warehouse(I);
inter_t n = Inter::Warehouse::create_resource(warehouse);
warehouse->stored_resources[n].stored_frame_list = CREATE(inter_frame_list);
warehouse->stored_resources[n].stored_frame_list->spare_storage = NULL;
warehouse->stored_resources[n].stored_frame_list->storage_used = 0;
warehouse->stored_resources[n].stored_frame_list->storage_capacity = 0;
warehouse->stored_resources[n].stored_frame_list->first_in_ifl = NULL;
warehouse->stored_resources[n].stored_frame_list->last_in_ifl = NULL;
return n;
2019-02-05 02:44:07 +02:00
}
typedef struct inter_frame_list {
int storage_used;
int storage_capacity;
struct inter_frame_list_entry *spare_storage;
struct inter_frame_list_entry *first_in_ifl;
struct inter_frame_list_entry *last_in_ifl;
MEMORY_MANAGEMENT
} inter_frame_list;
typedef struct inter_frame_list_entry {
struct inter_frame listed_frame;
struct inter_frame_list_entry *next_in_ifl;
struct inter_frame_list_entry *prev_in_ifl;
MEMORY_MANAGEMENT
} inter_frame_list_entry;
2019-02-05 02:44:07 +02:00
@
@d LOOP_THROUGH_INTER_FRAME_LIST(F, ifl)
for (inter_frame_list_entry *F##_entry = (ifl)?(ifl->first_in_ifl):NULL; F##_entry; F##_entry = F##_entry->next_in_ifl)
2019-07-11 22:38:01 +03:00
if (Inter::Frame::valid(((F = F##_entry->listed_frame), &F)))
2019-02-05 02:44:07 +02:00
=
inter_frame_list *Inter::find_frame_list(inter_tree *I, inter_t N) {
2019-02-05 02:44:07 +02:00
if (I == NULL) return NULL;
inter_warehouse *warehouse = Inter::warehouse(I);
2019-02-05 02:44:07 +02:00
int n = (int) N;
if (n >= warehouse->size) return NULL;
return warehouse->stored_resources[n].stored_frame_list;
2019-02-05 02:44:07 +02:00
}
inter_frame Inter::first_child(inter_frame P) {
LOOP_THROUGH_INTER_CHILDREN(F, P)
return F;
return Inter::Frame::around(NULL, -1);
2019-02-05 02:44:07 +02:00
}
inter_frame Inter::second_child(inter_frame P) {
int c = 0;
LOOP_THROUGH_INTER_CHILDREN(F, P)
if (++c == 2)
return F;
return Inter::Frame::around(NULL, -1);
2019-02-05 02:44:07 +02:00
}
inter_frame Inter::third_child(inter_frame P) {
int c = 0;
LOOP_THROUGH_INTER_CHILDREN(F, P)
if (++c == 3)
return F;
return Inter::Frame::around(NULL, -1);
2019-02-05 02:44:07 +02:00
}
inter_frame Inter::fourth_child(inter_frame P) {
int c = 0;
LOOP_THROUGH_INTER_CHILDREN(F, P)
if (++c == 4)
return F;
return Inter::Frame::around(NULL, -1);
2019-02-05 02:44:07 +02:00
}
inter_frame Inter::fifth_child(inter_frame P) {
int c = 0;
LOOP_THROUGH_INTER_CHILDREN(F, P)
if (++c == 5)
return F;
return Inter::Frame::around(NULL, -1);
2019-02-05 02:44:07 +02:00
}
inter_frame Inter::sixth_child(inter_frame P) {
int c = 0;
LOOP_THROUGH_INTER_CHILDREN(F, P)
if (++c == 6)
return F;
return Inter::Frame::around(NULL, -1);
2019-02-05 02:44:07 +02:00
}
void Inter::add_to_frame_list(inter_frame_list *FL, inter_frame F) {
2019-02-05 02:44:07 +02:00
if (Inter::Frame::valid(&F) == FALSE) internal_error("linked imvalid frame");
if (FL == NULL) internal_error("bad frame list");
if (FL->storage_used >= FL->storage_capacity) {
int new_size = 128;
while (new_size < 2*FL->storage_capacity) new_size = 2*new_size;
inter_frame_list_entry *storage = (inter_frame_list_entry *) Memory::I7_calloc(new_size, sizeof(inter_frame_list_entry), INTER_LINKS_MREASON);
FL->spare_storage = storage;
FL->storage_used = 0;
FL->storage_capacity = new_size;
}
inter_frame_list_entry *entry = &(FL->spare_storage[FL->storage_used ++]);
entry->listed_frame = F;
entry->next_in_ifl = NULL;
entry->prev_in_ifl = FL->last_in_ifl;
if (FL->last_in_ifl) FL->last_in_ifl->next_in_ifl = entry;
FL->last_in_ifl = entry;
if (FL->first_in_ifl == NULL) FL->first_in_ifl = entry;
2019-02-05 02:44:07 +02:00
}
typedef struct inter_error_stash {
struct inter_error_location stashed_eloc;
struct text_file_position stashed_tfp;
MEMORY_MANAGEMENT
} inter_error_stash;
void Inter::traverse_global_list(inter_tree *from, void (*visitor)(inter_tree *, inter_frame, void *), void *state, int filter) {
PROTECTED_LOOP_THROUGH_INTER_CHILDREN(P, (from->root_definition_frame)) {
2019-07-13 19:15:26 +03:00
if ((filter == 0) ||
((filter > 0) && (P.data[ID_IFLD] == (inter_t) filter)) ||
((filter < 0) && (P.data[ID_IFLD] != (inter_t) -filter)))
(*visitor)(from, P, state);
}
}
void Inter::set_mask(inter_tree *I, inter_package *mp) {
if (mp) {
while (mp) {
inter_package *par = Inter::Packages::parent(mp);
if (par) par->mask_down = mp;
mp = par;
}
} else {
mp = Inter::Packages::main(I);
while (mp->mask_down) {
inter_package *ch = mp->mask_down;
mp->mask_down = NULL;
mp = ch;
}
}
}
void Inter::traverse_tree(inter_tree *from, void (*visitor)(inter_tree *, inter_frame, void *), void *state, inter_package *mp, int filter) {
2019-07-13 19:15:26 +03:00
if (mp == NULL) mp = Inter::Packages::main(from);
if (mp) {
while (mp->mask_down) {
inter_frame D = Inter::Symbols::defining_frame(mp->package_name);
mp = mp->mask_down;
if ((filter == 0) ||
((filter > 0) && (D.data[ID_IFLD] == (inter_t) filter)) ||
((filter < 0) && (D.data[ID_IFLD] != (inter_t) -filter)))
(*visitor)(from, D, state);
Inter::traverse_tree_r(from, D, visitor, state, filter);
}
2019-07-13 19:15:26 +03:00
inter_frame D = Inter::Symbols::defining_frame(mp->package_name);
if ((filter == 0) ||
((filter > 0) && (D.data[ID_IFLD] == (inter_t) filter)) ||
((filter < 0) && (D.data[ID_IFLD] != (inter_t) -filter)))
(*visitor)(from, D, state);
Inter::traverse_tree_r(from, D, visitor, state, filter);
}
}
void Inter::traverse_tree_r(inter_tree *from, inter_frame P, void (*visitor)(inter_tree *, inter_frame, void *), void *state, int filter) {
2019-07-13 19:15:26 +03:00
PROTECTED_LOOP_THROUGH_INTER_CHILDREN(C, P) {
if ((filter == 0) ||
((filter > 0) && (C.data[ID_IFLD] == (inter_t) filter)) ||
((filter < 0) && (C.data[ID_IFLD] != (inter_t) -filter)))
(*visitor)(from, C, state);
Inter::traverse_tree_r(from, C, visitor, state, filter);
}
}