summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/proc.c b/proc.c
new file mode 100644
index 0000000..ff1197f
--- /dev/null
+++ b/proc.c
@@ -0,0 +1,113 @@
+#include <string.h>
+#include "proc.h"
+
+/* procedures */
+
+void proc_init(Proc *proc, Str name) {
+ memset(proc, 0, sizeof(Proc));
+ Graph *g = &proc->graph;
+ proc->pool.arena = &proc->perm;
+ proc->scope.arena = &proc->perm;
+ g->pool = &proc->pool;
+ g->start = node_new(g, N_START, NULL);
+ g->start->type = (Type) {
+ .lvl = T_BOT,
+ .t = T_TUPLE,
+ .next = NULL
+ };
+ g->stop = node_new_empty(g, N_STOP);
+ g->ctrl = g->start;
+ g->keepalive = node_new(g, N_KEEPALIVE, NULL);
+ proc->name = name;
+}
+
+void proc_free(Proc *proc) {
+ arena_free(&proc->perm);
+ arena_free(&proc->scratch);
+}
+
+/* scope */
+
+NameBinding *scope_find(Scope *scope, Str name) {
+ for (ScopeFrame *f = scope->tail; f; f = f->prev) {
+ for (NameBinding *b = f->latest; b; b = b->prev) {
+ if (str_eql(b->name, name)) {
+ return b;
+ }
+ }
+ }
+ return NULL;
+}
+
+ScopeFrame *scope_push(Scope *scope) {
+ ScopeFrame *f;
+ if (scope->free_scope) {
+ f = scope->free_scope;
+ *f = (ScopeFrame) { 0 };
+ scope->free_scope = f->prev;
+ } else {
+ f = new(scope->arena, ScopeFrame);
+ }
+ f->prev = scope->tail;
+ scope->tail = f;
+ return f;
+}
+
+ScopeFrame *scope_pop(Scope *scope, Graph *g) {
+ ScopeFrame *f = scope->tail;
+ scope->tail = f->prev;
+ f->prev = scope->free_scope;
+ scope->free_scope = f;
+ for (NameBinding *b = f->latest; b; ) {
+ NameBinding *p = b->prev;
+ b->prev = scope->free_bind;
+ scope->free_bind = b;
+ node_remove(g, b->node, g->keepalive);
+ b = p;
+ }
+ return scope->tail;
+}
+
+/* returns previous value */
+NameBinding *scope_bind(Scope *scope, Str name, Node *value, LexSpan pos, Graph *g) {
+ NameBinding *prev = scope_find(scope, name);
+ NameBinding *b;
+ if (scope->free_bind) {
+ b = scope->free_bind;
+ *b = (NameBinding) { 0 };
+ scope->free_bind = b->prev;
+ } else {
+ b = new(scope->arena, NameBinding);
+ }
+ b->name = name;
+ b->prev = scope->tail->latest;
+ scope->tail->latest = b;
+ b->node = value;
+ b->src_pos = pos;
+ node_add(g, value, g->keepalive);
+ return prev;
+}
+
+NameBinding *scope_update(NameBinding *b, Node *to, Graph *g) {
+ Node *n = b->node;
+ 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_uncollect(Scope *scope, Graph *g, ScopeNameList *nl) {
+ for (int i = 0; i < nl->len; i++) {
+ node_remove(g, nl->data[i].node, g->keepalive);
+ }
+}