shithub: mc

ref: 136c7085039d88051aa71ad041bd749e69dadbfd
dir: /parse/stab.c/

View raw version
#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);
}