1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-08 18:14:21 +03:00
inform7/inter/bytecode-module/Chapter 2/Inter Trees.w

294 lines
8.5 KiB
OpenEdge ABL
Raw Normal View History

2019-07-24 22:29:29 +03:00
[Inter::Tree::] Inter Trees.
2019-02-05 02:44:07 +02:00
2019-07-24 22:29:29 +03:00
To manage tree structures of inter code, and manage the movement of nodes
within these trees.
2019-02-05 02:44:07 +02:00
@
2019-02-05 02:44:07 +02:00
=
typedef struct inter_tree {
2019-07-24 22:29:29 +03:00
struct inter_warehouse *housed;
2019-07-24 20:15:07 +03:00
struct inter_tree_node *root_node;
struct inter_package *root_package;
struct building_site site;
2020-05-09 15:07:39 +03:00
CLASS_DEFINITION
} inter_tree;
2019-02-05 02:44:07 +02:00
@ =
2019-07-24 22:29:29 +03:00
inter_tree *Inter::Tree::new(void) {
inter_tree *I = CREATE(inter_tree);
2019-07-24 22:29:29 +03:00
I->housed = Inter::Warehouse::new();
inter_t N = Inter::Warehouse::create_symbols_table(I->housed);
inter_symbols_table *globals = Inter::Warehouse::get_symbols_table(I->housed, N);
inter_t root_package_ID = Inter::Warehouse::create_package(I->housed, I);
I->root_package = Inter::Warehouse::get_package(I->housed, root_package_ID);
2020-05-11 17:21:29 +03:00
I->root_node = Inode::root_frame(I->housed, I);
2019-07-26 12:14:17 +03:00
I->root_package->package_head = I->root_node;
Inter::Packages::make_rootlike(I->root_package);
Inter::Packages::set_scope(I->root_package, globals);
2019-07-24 22:29:29 +03:00
I->root_node->package = I->root_package;
Inter::Warehouse::attribute_resource(I->housed, N, I->root_package);
Site::clear(I);
return I;
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
inter_package *Inter::Tree::root_package(inter_tree *I) {
if (I) return I->root_package;
return NULL;
}
inter_warehouse *Inter::Tree::warehouse(inter_tree *I) {
return I->housed;
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
inter_symbols_table *Inter::Tree::global_scope(inter_tree *I) {
return Inter::Packages::scope(I->root_package);
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::previous(inter_tree_node *F) {
2019-07-24 20:15:07 +03:00
if (F == NULL) return NULL;
return F->previous_itn;
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::next(inter_tree_node *F) {
2019-07-24 20:15:07 +03:00
if (F == NULL) return NULL;
return F->next_itn;
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::first_child(inter_tree_node *F) {
if (F == NULL) return NULL;
2019-07-24 20:15:07 +03:00
return F->first_child_itn;
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::second_child(inter_tree_node *P) {
2019-07-24 20:15:07 +03:00
if (P == NULL) return NULL;
P = P->first_child_itn;
if (P == NULL) return NULL;
return P->next_itn;
}
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::third_child(inter_tree_node *P) {
2019-07-24 20:15:07 +03:00
if (P == NULL) return NULL;
P = P->first_child_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
return P->next_itn;
}
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::fourth_child(inter_tree_node *P) {
2019-07-24 20:15:07 +03:00
if (P == NULL) return NULL;
P = P->first_child_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
return P->next_itn;
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::fifth_child(inter_tree_node *P) {
2019-07-24 20:15:07 +03:00
if (P == NULL) return NULL;
P = P->first_child_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
return P->next_itn;
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::sixth_child(inter_tree_node *P) {
2019-07-24 20:15:07 +03:00
if (P == NULL) return NULL;
P = P->first_child_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
P = P->next_itn;
if (P == NULL) return NULL;
return P->next_itn;
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::last_child(inter_tree_node *F) {
if (F == NULL) return NULL;
return F->last_child_itn;
}
2019-07-24 20:15:07 +03:00
2019-07-24 22:29:29 +03:00
inter_tree_node *Inter::Tree::parent(inter_tree_node *F) {
if (F == NULL) return NULL;
return F->parent_itn;
}
@
2019-02-05 02:44:07 +02:00
2019-07-24 20:15:07 +03:00
=
2019-07-24 22:29:29 +03:00
void Inter::Tree::remove_node(inter_tree_node *P) {
Inter::Tree::place(P, NOWHERE_ICPLACEMENT, NULL);
2019-02-05 02:44:07 +02:00
}
2019-07-24 22:29:29 +03:00
void Inter::Tree::place(inter_tree_node *C, int how, inter_tree_node *R) {
2019-07-24 20:15:07 +03:00
@<Extricate C from its current tree position@>;
switch (how) {
case NOWHERE_ICPLACEMENT:
return;
case AS_FIRST_CHILD_OF_ICPLACEMENT:
@<Make C the first child of R@>;
break;
case AS_LAST_CHILD_OF_ICPLACEMENT:
@<Make C the last child of R@>;
break;
case AFTER_ICPLACEMENT:
case IMMEDIATELY_AFTER_ICPLACEMENT:
@<Insert C after R@>;
break;
case BEFORE_ICPLACEMENT:
@<Insert C before R@>;
break;
default:
internal_error("unimplemented");
}
2019-02-05 02:44:07 +02:00
}
2019-07-24 20:15:07 +03:00
@<Extricate C from its current tree position@> =
2019-07-24 22:29:29 +03:00
inter_tree_node *OP = Inter::Tree::parent(C);
2019-07-24 20:15:07 +03:00
if (OP) {
2019-07-24 22:29:29 +03:00
if (Inter::Tree::first_child(OP) == C)
Inter::Tree::set_first_child_UNSAFE(OP, Inter::Tree::next(C));
2019-07-24 22:29:29 +03:00
if (Inter::Tree::last_child(OP) == C)
Inter::Tree::set_last_child_UNSAFE(OP, Inter::Tree::previous(C));
2019-07-24 20:15:07 +03:00
}
2019-07-24 22:29:29 +03:00
inter_tree_node *OB = Inter::Tree::previous(C);
inter_tree_node *OD = Inter::Tree::next(C);
2019-07-24 20:15:07 +03:00
if (OB) {
Inter::Tree::set_next_UNSAFE(OB, OD);
2019-07-24 20:15:07 +03:00
}
if (OD) {
Inter::Tree::set_previous_UNSAFE(OD, OB);
2019-07-24 20:15:07 +03:00
}
Inter::Tree::set_parent_UNSAFE(C, NULL);
Inter::Tree::set_previous_UNSAFE(C, NULL);
Inter::Tree::set_next_UNSAFE(C, NULL);
2019-07-24 20:15:07 +03:00
@<Make C the first child of R@> =
Inter::Tree::set_parent_UNSAFE(C, R);
2019-07-24 22:29:29 +03:00
inter_tree_node *D = Inter::Tree::first_child(R);
2019-07-24 20:15:07 +03:00
if (D == NULL) {
Inter::Tree::set_last_child_UNSAFE(R, C);
Inter::Tree::set_next_UNSAFE(C, NULL);
2019-07-24 20:15:07 +03:00
} else {
Inter::Tree::set_previous_UNSAFE(D, C);
Inter::Tree::set_next_UNSAFE(C, D);
2019-07-24 20:15:07 +03:00
}
Inter::Tree::set_first_child_UNSAFE(R, C);
2019-07-24 20:15:07 +03:00
@<Make C the last child of R@> =
Inter::Tree::set_parent_UNSAFE(C, R);
2019-07-24 22:29:29 +03:00
inter_tree_node *B = Inter::Tree::last_child(R);
2019-07-24 20:15:07 +03:00
if (B == NULL) {
Inter::Tree::set_first_child_UNSAFE(R, C);
Inter::Tree::set_previous_UNSAFE(C, NULL);
2019-07-24 20:15:07 +03:00
} else {
Inter::Tree::set_next_UNSAFE(B, C);
Inter::Tree::set_previous_UNSAFE(C, B);
2019-07-24 20:15:07 +03:00
}
Inter::Tree::set_last_child_UNSAFE(R, C);
2019-07-24 20:15:07 +03:00
@<Insert C after R@> =
2019-07-24 22:29:29 +03:00
inter_tree_node *P = Inter::Tree::parent(R);
if (P == NULL) internal_error("can't move C before R when R is nowhere");
Inter::Tree::set_parent_UNSAFE(C, P);
2019-07-24 22:29:29 +03:00
if (Inter::Tree::last_child(P) == R)
Inter::Tree::set_last_child_UNSAFE(P, C);
2019-07-24 20:15:07 +03:00
else {
2019-07-24 22:29:29 +03:00
inter_tree_node *D = Inter::Tree::next(R);
2019-07-24 20:15:07 +03:00
if (D == NULL) internal_error("inter tree broken");
Inter::Tree::set_next_UNSAFE(C, D);
Inter::Tree::set_previous_UNSAFE(D, C);
2019-07-24 20:15:07 +03:00
}
Inter::Tree::set_next_UNSAFE(R, C);
Inter::Tree::set_previous_UNSAFE(C, R);
2019-07-24 20:15:07 +03:00
@<Insert C before R@> =
2019-07-24 22:29:29 +03:00
inter_tree_node *P = Inter::Tree::parent(R);
2019-07-24 20:15:07 +03:00
if (P == NULL) internal_error("can't move C before R when R is nowhere");
Inter::Tree::set_parent_UNSAFE(C, P);
2019-07-24 22:29:29 +03:00
if (Inter::Tree::first_child(P) == R)
Inter::Tree::set_first_child_UNSAFE(P, C);
2019-07-24 20:15:07 +03:00
else {
2019-07-24 22:29:29 +03:00
inter_tree_node *B = Inter::Tree::previous(R);
2019-07-24 20:15:07 +03:00
if (B == NULL) internal_error("inter tree broken");
Inter::Tree::set_previous_UNSAFE(C, B);
Inter::Tree::set_next_UNSAFE(B, C);
2019-07-24 20:15:07 +03:00
}
Inter::Tree::set_next_UNSAFE(C, R);
Inter::Tree::set_previous_UNSAFE(R, C);
@
=
void Inter::Tree::set_previous_UNSAFE(inter_tree_node *F, inter_tree_node *V) {
if (F) F->previous_itn = V;
}
void Inter::Tree::set_next_UNSAFE(inter_tree_node *F, inter_tree_node *V) {
if (F) F->next_itn = V;
}
void Inter::Tree::set_first_child_UNSAFE(inter_tree_node *F, inter_tree_node *V) {
if (F) F->first_child_itn = V;
}
void Inter::Tree::set_last_child_UNSAFE(inter_tree_node *F, inter_tree_node *V) {
if (F) F->last_child_itn = V;
}
void Inter::Tree::set_parent_UNSAFE(inter_tree_node *F, inter_tree_node *V) {
if (F) F->parent_itn = V;
}
2019-07-24 20:15:07 +03:00
@
@d LOOP_THROUGH_INTER_CHILDREN(F, P)
2019-07-24 22:29:29 +03:00
for (inter_tree_node *F = Inter::Tree::first_child(P); F; F = Inter::Tree::next(F))
2019-07-24 20:15:07 +03:00
@d PROTECTED_LOOP_THROUGH_INTER_CHILDREN(F, P)
2019-07-24 22:29:29 +03:00
for (inter_tree_node *F = Inter::Tree::first_child(P), *FN = F?(Inter::Tree::next(F)):NULL;
F; F = FN, FN = FN?(Inter::Tree::next(FN)):NULL)
2019-07-24 20:15:07 +03:00
=
2019-07-24 22:29:29 +03:00
void Inter::Tree::traverse_root_only(inter_tree *from, void (*visitor)(inter_tree *, inter_tree_node *, void *), void *state, int filter) {
2019-07-24 20:15:07 +03:00
PROTECTED_LOOP_THROUGH_INTER_CHILDREN(P, from->root_node) {
2019-07-13 19:15:26 +03:00
if ((filter == 0) ||
2019-07-24 20:15:07 +03:00
((filter > 0) && (P->W.data[ID_IFLD] == (inter_t) filter)) ||
((filter < 0) && (P->W.data[ID_IFLD] != (inter_t) -filter)))
2019-07-13 19:15:26 +03:00
(*visitor)(from, P, state);
}
}
2019-07-24 22:29:29 +03:00
void Inter::Tree::traverse(inter_tree *from, void (*visitor)(inter_tree *, inter_tree_node *, void *), void *state, inter_package *mp, int filter) {
if (mp == NULL) mp = Site::main_package_if_it_exists(from);
2019-07-13 19:15:26 +03:00
if (mp) {
2019-07-26 21:20:27 +03:00
inter_tree_node *D = Inter::Packages::definition(mp);
2019-07-13 19:15:26 +03:00
if ((filter == 0) ||
2019-07-24 20:15:07 +03:00
((filter > 0) && (D->W.data[ID_IFLD] == (inter_t) filter)) ||
((filter < 0) && (D->W.data[ID_IFLD] != (inter_t) -filter)))
2019-07-13 19:15:26 +03:00
(*visitor)(from, D, state);
2019-07-24 22:29:29 +03:00
Inter::Tree::traverse_r(from, D, visitor, state, filter);
2019-07-13 19:15:26 +03:00
}
}
2019-07-24 22:29:29 +03:00
void Inter::Tree::traverse_r(inter_tree *from, inter_tree_node *P, void (*visitor)(inter_tree *, inter_tree_node *, void *), void *state, int filter) {
2019-07-13 19:15:26 +03:00
PROTECTED_LOOP_THROUGH_INTER_CHILDREN(C, P) {
if ((filter == 0) ||
2019-07-24 20:15:07 +03:00
((filter > 0) && (C->W.data[ID_IFLD] == (inter_t) filter)) ||
((filter < 0) && (C->W.data[ID_IFLD] != (inter_t) -filter)))
2019-07-13 19:15:26 +03:00
(*visitor)(from, C, state);
2019-07-24 22:29:29 +03:00
Inter::Tree::traverse_r(from, C, visitor, state, filter);
2019-07-13 19:15:26 +03:00
}
}