diff options
Diffstat (limited to 'proc.c')
| -rw-r--r-- | proc.c | 113 |
1 files changed, 113 insertions, 0 deletions
@@ -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); + } +} |
