ref: 4546bb9cf7773e4647e83358ed71beaeb9a4c08c
dir: /parse/stab.c/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "parse.h"
typedef struct Tydefn Tydefn;
struct Tydefn {
int line;
Node *name;
Type *type;
};
#define Maxstabdepth 128
static Stab *stabstk[Maxstabdepth];
static int stabstkoff;
Stab *curstab()
{
return stabstk[stabstkoff - 1];
}
void pushstab(Stab *st)
{
stabstk[stabstkoff++] = st;
}
void popstab(void)
{
stabstkoff--;
}
static char *name(Node *n)
{
return n->name.parts[n->name.nparts - 1];
}
static ulong namehash(void *n)
{
return strhash(name(n));
}
static int nameeq(void *a, void *b)
{
return a == b || !strcmp(name(a), name(b));
}
Sym *mksym(int line, Node *name, Type *ty)
{
static int nextid;
Sym *sym;
sym = zalloc(sizeof(Sym));
sym->id = nextid++;
sym->name = name;
sym->type = ty;
sym->line = line;
return sym;
}
Stab *mkstab()
{
Stab *st;
st = zalloc(sizeof(Stab));
st->ns = mkht(namehash, nameeq);
st->dcl = mkht(namehash, nameeq);
st->ty = mkht(namehash, nameeq);
return st;
}
/* FIXME: do namespaces */
Sym *getdcl(Stab *st, Node *n)
{
Sym *s;
Stab *orig;
orig = st;
do {
if ((s = htget(st->dcl, n))) {
/* record that this is in the closure of this scope */
if (!st->closure)
st->closure = mkht(namehash, nameeq);
if (st != orig)
htput(st->closure, s->name, s);
return s;
}
st = st->super;
} while (st);
return NULL;
}
Type *gettype(Stab *st, Node *n)
{
Tydefn *t;
do {
if ((t = htget(st->ty, n)))
return t->type;
st = st->super;
} while (st);
return NULL;
}
Stab *getns(Stab *st, Node *n)
{
Stab *s;
do {
if ((s = htget(st->ns, n)))
return s;
st = st->super;
} while (st);
return NULL;
}
void putdcl(Stab *st, Sym *s)
{
Sym *d;
d = getdcl(st, s->name);
if (d)
fatal(s->line, "%s already declared (line %d", name(s->name), d->line);
htput(st->dcl, s->name, s);
}
void updatetype(Stab *st, Node *n, Type *t)
{
Tydefn *td;
td = htget(st->ty, n);
if (!td)
die("No type %s to update", name(n));
td->type = t;
}
void puttype(Stab *st, Node *n, Type *t)
{
Type *ty;
Tydefn *td;
assert(t != NULL);
ty = gettype(st, n);
if (ty)
fatal(n->line, "Type %s already defined", name(n));
td = xalloc(sizeof(Tydefn));
td->line = n->line;
td->name = n;
td->type = t;
htput(st->ty, td->name, td);
}
void putns(Stab *st, Stab *scope)
{
Stab *s;
s = getns(st, scope->name);
if (s)
fatal(scope->name->line, "Ns %s already defined", name(s->name));
htput(st->ns, scope->name, scope);
}