summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c92
1 files changed, 82 insertions, 10 deletions
diff --git a/proc.c b/proc.c
index 0877a91..7e983ca 100644
--- a/proc.c
+++ b/proc.c
@@ -102,26 +102,98 @@ NameBinding *scope_bind(Scope *scope, Str name, Node *value, LexSpan pos, Graph
return prev;
}
-NameBinding *scope_update(NameBinding *b, Node *to, Graph *g) {
+NameBinding *scope_update(Scope *scope, NameBinding *b, Node *to, Graph *g) {
Node *n = b->node;
+ unsigned nestlvl = scope->nestlvl;
+ for (ScopeChangeList *l = scope->changes; l; l = l->prev) {
+ if (b->nestlvl < nestlvl) {
+ scope_changelist_update(l, b, n, to, g);
+ }
+ nestlvl--;
+ }
node_add(g, to, g->keepalive);
b->node = to;
node_remove(g, n, g->keepalive);
return b;
}
-/* adds to keepalive so these aren't invalidated */
-void scope_collect(Scope *scope, Graph *g, ScopeNameList *nl, Arena *arena) {
- for (ScopeFrame *f = scope->tail; f; f = f->prev) {
- for (NameBinding *b = f->latest; b; b = b->prev) {
- node_add(g, b->node, g->keepalive);
- ZDA_PUSH(arena, nl, (ScopeName) { b->name, b->node });
+void scope_changelist_update(ScopeChangeList *l, NameBinding *b, Node *from, Node *to, Graph *g) {
+ for (unsigned i = 0; i < l->n; i++) {
+ ScopeChange *chg = XAR_GET(l, i);
+ if (chg->bind == b) {
+ node_add(g, to, g->keepalive);
+ node_remove(g, chg->to, g->keepalive);
+ chg->to = to;
+ return;
+ }
+ }
+ ScopeChange *chg = XAR_PUT(l, l->n++, l->arena);
+ node_add(g, from, g->keepalive);
+ node_add(g, to, g->keepalive);
+ chg->bind = b;
+ chg->from = from;
+ chg->to = to;
+}
+
+void scope_changelist_push(Scope *scope, ScopeChangeList *l, Arena *a) {
+ l->arena = a;
+ l->prev = scope->changes;
+ scope->changes = l;
+ scope->nestlvl++;
+}
+
+void scope_changelist_pop(Scope *scope, Graph *g) {
+ ScopeChangeList *l = scope->changes;
+ scope->changes = l->prev;
+ scope->nestlvl--;
+ for (unsigned i = 0; i < l->n; i++) {
+ ScopeChange *chg = XAR_GET(l, i);
+ scope_update(scope, chg->bind, chg->from, g);
+ }
+}
+
+#include <stdio.h>
+/* TODO: implement merge, probably will need scratch arena to build up
+ * a Xar of something like struct { NameBinding *b; Node *y, *n; }. if
+ * no match for the given bind is found in the opposite change list,
+ * it gets the "from" value found in the other.
+ **/
+typedef struct {
+ NameBinding *b;
+ Node *y, *n;
+} MergeChange;
+void scope_changelist_merge(Scope *scope, ScopeChangeList *y, ScopeChangeList *n, Node *region, Graph *graph, Arena *scratch) {
+ MergeChange *m = new_arr(scratch, MergeChange, y->n + n->n);
+ unsigned c = 0;
+ for (unsigned i = 0; i < y->n; i++) {
+ ScopeChange *chg = XAR_GET(y, i);
+ m[c].b = chg->bind;
+ m[c].y = chg->to;
+ m[c].n = chg->from;
+ c++;
+ }
+ unsigned yc = c;
+ for (unsigned i = 0; i < n->n; i++) {
+ ScopeChange *chg = XAR_GET(n, i);
+ for (unsigned j = 0; j < yc; j++) {
+ if (m[j].b == chg->bind) {
+ m[j].n = chg->to;
+ goto next;
+ }
}
+ m[c].b = chg->bind;
+ m[c].y = chg->from;
+ m[c].n = chg->to;
+ c++;
+next:
}
+ fprintf(stderr, "%u\n", c);
}
-void scope_uncollect(Scope *scope, Graph *g, ScopeNameList *nl) {
- for (int i = 0; i < nl->len; i++) {
- node_remove(g, nl->data[i].node, g->keepalive);
+void scope_changelist_discard(ScopeChangeList *l, Graph *g) {
+ for (unsigned i = 0; i < l->n; i++) {
+ ScopeChange *chg = XAR_GET(l, i);
+ node_remove(g, chg->from, g->keepalive);
+ node_remove(g, chg->to, g->keepalive);
}
}