shithub: mc

ref: b7be6fd5a31f8563949c2a7ac6db10f8b9ad0126
dir: /parse/node.c/

View raw version
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.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"

Node **nodes;
size_t nnodes;
Node **decls;
size_t ndecls;

char *fname(Srcloc l)
{
    return file->file.files[l.file];
}

int lnum(Srcloc l)
{
    return l.line;
}

/*
 * Bah, this is going to need to know how to fold things.
 * FIXME: teach it.
 */
uint64_t arraysz(Node *sz)
{
    Node *n;

    n = sz;
    if (exprop(n) != Olit)
        fatal(sz, "too many layers of indirection when finding intializer. (initialization loop?)");

    n = n->expr.args[0];
    if (n->lit.littype != Lint)
        fatal(sz, "initializer is not an integer");
    return n->lit.intval;
}

Node *mknode(Srcloc loc, Ntype nt)
{
    Node *n;

    n = zalloc(sizeof(Node));
    n->nid = nnodes;
    n->type = nt;
    n->loc = loc;
    lappend(&nodes, &nnodes, n);
    return n;
}

Node *mkfile(char *name)
{
    Node *n;

    n = mknode(Zloc, Nfile);
    n->file.ns = mkht(strhash, streq);
    lappend(&n->file.files, &n->file.nfiles, strdup(name));
    return n;
}

Node *mkuse(Srcloc loc, char *use, int islocal)
{
    Node *n;

    n = mknode(loc, Nuse);
    n->use.name = strdup(use);
    n->use.islocal = islocal;

    return n;
}

Node *mksliceexpr(Srcloc loc, Node *sl, Node *base, Node *off)
{
    if (!base)
        base = mkintlit(loc, 0);
    if (!off)
        off = mkexpr(loc, Omemb, sl, mkname(loc, "len"), NULL);
    return mkexpr(loc, Oslice, sl, base, off, NULL);
}

Node *mkexprl(Srcloc loc, Op op, Node **args, size_t nargs)
{
    Node *n;

    n = mknode(loc, Nexpr);
    n->expr.op = op;
    n->expr.args = args;
    n->expr.nargs = nargs;
    return n;
}

Node *mkexpr(Srcloc loc, Op op, ...)
{
    Node *n;
    va_list ap;
    Node *arg;

    n = mknode(loc, Nexpr);
    n->expr.op = op;
    va_start(ap, op);
    while ((arg = va_arg(ap, Node*)) != NULL)
        lappend(&n->expr.args, &n->expr.nargs, arg);
    va_end(ap);

    return n;
}

Node *mkcall(Srcloc loc, Node *fn, Node **args, size_t nargs) 
{
    Node *n;
    size_t i;

    n = mkexpr(loc, Ocall, fn, NULL);
    for (i = 0; i < nargs; i++)
        lappend(&n->expr.args, &n->expr.nargs, args[i]);
    return n;
}

Node *mkifstmt(Srcloc loc, Node *cond, Node *iftrue, Node *iffalse)
{
    Node *n;

    n = mknode(loc, Nifstmt);
    n->ifstmt.cond = cond;
    n->ifstmt.iftrue = iftrue;
    n->ifstmt.iffalse = iffalse;

    return n;
}

Node *mkloopstmt(Srcloc loc, Node *init, Node *cond, Node *incr, Node *body)
{
    Node *n;

    n = mknode(loc, Nloopstmt);
    n->loopstmt.init = init;
    n->loopstmt.cond = cond;
    n->loopstmt.step = incr;
    n->loopstmt.body = body;
    n->loopstmt.scope = mkstab();

    return n;
}

Node *mkiterstmt(Srcloc loc, Node *elt, Node *seq, Node *body)
{
    Node *n;

    n = mknode(loc, Niterstmt);
    n->iterstmt.elt = elt;
    n->iterstmt.seq = seq;
    n->iterstmt.body = body;

    return n;
}

Node *mkmatchstmt(Srcloc loc, Node *val, Node **matches, size_t nmatches)
{
    Node *n;

    n = mknode(loc, Nmatchstmt);
    n->matchstmt.val = val;
    n->matchstmt.matches = matches;
    n->matchstmt.nmatches = nmatches;
    return n;
}

Node *mkmatch(Srcloc loc, Node *pat, Node *body)
{
    Node *n;

    n = mknode(loc, Nmatch);
    n->match.pat = pat;
    n->match.block = body;
    return n;
}

Node *mkfunc(Srcloc loc, Node **args, size_t nargs, Type *ret, Node *body)
{
    Node *n;
    Node *f;
    size_t i;

    f = mknode(loc, Nfunc);
    f->func.args = args;
    f->func.nargs = nargs;
    f->func.body = body;
    f->func.scope = mkstab();
    f->func.type = mktyfunc(loc, args, nargs, ret);

    for (i = 0; i < nargs; i++)
        putdcl(f->func.scope, args[i]);

    n = mknode(loc, Nlit);
    n->lit.littype = Lfunc;
    n->lit.fnval = f;
    return n;
}

Node *mkblock(Srcloc loc, Stab *scope)
{
    Node *n;

    n = mknode(loc, Nblock);
    n->block.scope = scope;
    return n;
}


Node *mkimplstmt(Srcloc loc, Node *name, Type *t, Node **decls, size_t ndecls)
{
    Node *n;

    n = mknode(loc, Nimpl);
    n->impl.traitname = name;
    n->impl.type = t;
    n->impl.decls = decls;
    n->impl.ndecls = ndecls;
    return n;
}


Node *mkintlit(Srcloc loc, uvlong val)
{
    return mkexpr(loc, Olit, mkint(loc, val), NULL);
}

Node *mklbl(Srcloc loc, char *lbl)
{
    Node *n;

    assert(lbl != NULL);
    n = mknode(loc, Nlit);
    n->lit.littype = Llbl;
    n->lit.lblval = strdup(lbl);
    return mkexpr(loc, Olit, n, NULL);
}

Node *mkstr(Srcloc loc, Str val)
{
    Node *n;

    n = mknode(loc, Nlit);
    n->lit.littype = Lstr;
    n->lit.strval.len = val.len;
    n->lit.strval.buf = malloc(val.len);
    memcpy(n->lit.strval.buf, val.buf, val.len);

    return n;
}

Node *mkint(Srcloc loc, uint64_t val)
{
    Node *n;

    n = mknode(loc, Nlit);
    n->lit.littype = Lint;
    n->lit.intval = val;

    return n;
}

Node *mkchar(Srcloc loc, uint32_t val)
{
    Node *n;

    n = mknode(loc, Nlit);
    n->lit.littype = Lchr;
    n->lit.chrval = val;

    return n;
}

Node *mkfloat(Srcloc loc, double val)
{
    Node *n;

    n = mknode(loc, Nlit);
    n->lit.littype = Lflt;
    n->lit.fltval = val;

    return n;
}

Node *mkidxinit(Srcloc loc, Node *idx, Node *init)
{
    init->expr.idx = idx;
    return init;
}

Node *mkname(Srcloc loc, char *name)
{
    Node *n;

    n = mknode(loc, Nname);
    n->name.name = strdup(name);

    return n;
}

Node *mknsname(Srcloc loc, char *ns, char *name)
{
    Node *n;

    n = mknode(loc, Nname);
    n->name.ns = strdup(ns);
    n->name.name = strdup(name);

    return n;
}

Node *mkdecl(Srcloc loc, Node *name, Type *ty)
{
    Node *n;

    n = mknode(loc, Ndecl);
    n->decl.did = ndecls;
    n->decl.name = name;
    n->decl.type = ty;
    lappend(&decls, &ndecls, n);
    return n;
}

Ucon *mkucon(Srcloc loc, Node *name, Type *ut, Type *et)
{
    Ucon *uc;

    uc = zalloc(sizeof(Ucon));
    uc->loc = loc;
    uc->name = name;
    uc->utype = ut;
    uc->etype = et;
    return uc;
}

Node *mkbool(Srcloc loc, int val)
{
    Node *n;

    n = mknode(loc, Nlit);
    n->lit.littype = Lbool;
    n->lit.boolval = val;

    return n;
}

char *declname(Node *n)
{
    Node *name;
    assert(n->type == Ndecl);
    name = n->decl.name;
    return name->name.name;
}

Type *decltype(Node *n)
{
    assert(n->type == Ndecl);
    return nodetype(n);
}

Type *exprtype(Node *n)
{
    assert(n->type == Nexpr);
    return nodetype(n);
}

Type *nodetype(Node *n)
{
    switch (n->type) {
        case Ndecl:     return n->decl.type;            break;
        case Nexpr:     return n->expr.type;            break;
        case Nlit:      return n->lit.type;             break;
        default:        die("Node %s has no type", nodestr[n->type]); break;
    }
    return NULL;
}

int liteq(Node *a, Node *b)
{
    assert(a->type == Nlit && b->type == Nlit);
    if (a->lit.littype != b->lit.littype)
        return 0;
    if (!tyeq(a->lit.type, b->lit.type))
        return 0;
    switch (a->lit.littype) {
        case Lchr:
            return a->lit.chrval == b->lit.chrval;
        case Lbool:
            return a->lit.boolval == b->lit.boolval;
        case Lint:
            return a->lit.intval == b->lit.intval;
        case Lflt:
            return a->lit.fltval == b->lit.fltval;
        case Lstr:
            return a->lit.strval.len == b->lit.strval.len &&
                !memcmp(a->lit.strval.buf, b->lit.strval.buf, a->lit.strval.len);
        case Lfunc:
            return a->lit.fnval == b->lit.fnval;
        case Llbl:
            return !strcmp(a->lit.lblval, b->lit.lblval);
            break;
    }
    return 0;
}

/* name hashing */
ulong namehash(void *p)
{
    Node *n;

    n = p;
    return strhash(namestr(n)) ^ strhash(n->name.ns);
}

int nameeq(void *p1, void *p2)
{
    Node *a, *b;
    a = p1;
    b = p2;
    if (a == b)
        return 1;

    return streq(namestr(a), namestr(b)) && streq(a->name.ns, b->name.ns);
}

void setns(Node *n, char *ns)
{
    assert(!n->name.ns || !strcmp(n->name.ns, ns));
    n->name.ns = strdup(ns);
}

Op exprop(Node *e)
{
    assert(e->type == Nexpr);
    return e->expr.op;
}

char *namestr(Node *name)
{
    if (!name)
        return "";
    assert(name->type == Nname);
    return name->name.name;
}

static size_t did(Node *n)
{
    if (n->type == Ndecl) {
        return n->decl.did;
    } else if (n->type == Nexpr) {
        assert(exprop(n) == Ovar);
        return n->expr.did;
    }
    dump(n, stderr);
    die("Can't get did");
    return 0;
}

/* Hashes a Ovar expr or an Ndecl  */
ulong varhash(void *dcl)
{
    /* large-prime hash. meh. */
    return did(dcl) * 366787;
}

/* Checks if the did of two vars are equal */
int vareq(void *a, void *b)
{
    return did(a) == did(b);
}