shithub: mc

ref: 290af5c176be42347969ad80ed9d73391a36c61e
dir: /parse/specialize.c/

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

static ulong tidhash(void *p)
{
    Type *t;

    t = p;
    return ptrhash((void*)(intptr_t)t->tid);
}

static int tideq(void *pa, void *pb)
{
    Type *a, *b;

    a = pa;
    b = pb;
    return a->tid == b->tid;
}

static int hasparams(Type *t)
{
    size_t i;

    if (t->type == Typaram)
        return 1;
    for (i = 0; i < t->nsub; i++)
        if (hasparams(t->sub[i]))
            return 1;
    return 0;
}

static Type *dosubst(Type *t, Htab *tsmap)
{
    Type *ret;
    size_t i;

    if (t->type == Typaram)
        return htget(tsmap, t);

    ret = tydup(t);
    for (i = 0; i < t->nsub; i++)
        ret->sub[i] = dosubst(t->sub[i], tsmap);
    return ret;
}

static Type *tysubst(Type *t, Htab *tsmap)
{
    if (hasparams(t))
        return dosubst(t, tsmap);
    else
        return t;
}

static void fillsubst(Htab *tsmap, Type *to, Type *from)
{
    size_t i;

    printf("Specialize %s => %s\n", tystr(from), tystr(to));
    htput(tsmap, from, to);
    if (to->nsub != from->nsub)
        return;
    for (i = 0; i < to->nsub; i++)
        fillsubst(tsmap, to->sub[i], from->sub[i]);
}

static Node *specializenode(Node *n, Htab *tsmap)
{
    Node *r;
    size_t i;

    r = mknode(n->line, n->type);
    switch (n->type) {
        case Nfile:
        case Nuse:
            die("Node %s not allowed here\n", nodestr(n->type));
            break;
        case Nexpr:
            r->expr.op = n->expr.op;
            r->expr.type = tysubst(n->expr.type, tsmap);
            r->expr.isconst = n->expr.isconst;
            r->expr.nargs = n->expr.nargs;
            r->expr.args = xalloc(n->expr.nargs * sizeof(Node*));
            for (i = 0; i < n->expr.nargs; i++)
                r->expr.args[i] = specializenode(n->expr.args[i], tsmap);
            break;
        case Nname:
            if (n->name.ns)
                r->name.ns = strdup(n->name.ns);
            r->name.name = strdup(n->name.name);
            break;
        case Nlit:
            r->lit.littype = n->lit.littype;
            r->lit.type = tysubst(n->expr.type, tsmap);
            switch (n->lit.littype) {
                case Lchr:      n->lit.chrval = n->lit.chrval;       break;
                case Lint:      n->lit.intval = n->lit.intval;       break;
                case Lflt:      n->lit.fltval = n->lit.fltval;       break;
                case Lstr:      n->lit.strval = n->lit.strval;       break;
                case Lbool:     n->lit.boolval = n->lit.boolval;     break;
                case Lfunc:     n->lit.fnval = specializenode(n->lit.fnval, tsmap);       break;
                case Larray:    n->lit.arrval = specializenode(n->lit.arrval, tsmap);     break;
            }
            break;
        case Nloopstmt:
            r->loopstmt.init = specializenode(n->loopstmt.init, tsmap);
            r->loopstmt.cond = specializenode(n->loopstmt.cond, tsmap);
            r->loopstmt.step = specializenode(n->loopstmt.step, tsmap);
            r->loopstmt.body = specializenode(n->loopstmt.body, tsmap);
            break;
        case Nifstmt:
            r->ifstmt.cond = specializenode(n->ifstmt.cond, tsmap);
            r->ifstmt.iftrue = specializenode(n->ifstmt.iftrue, tsmap);
            r->ifstmt.iffalse = specializenode(n->ifstmt.iffalse, tsmap);
            break;
        case Nblock:
            r->block.scope = mkstab();
            r->block.nstmts = n->block.nstmts;
            r->block.stmts = xalloc(sizeof(Node *)*n->block.nstmts);
            for (i = 0; i < n->block.nstmts; i++)
                r->block.stmts[i] = specializenode(n->block.stmts[i], tsmap);
            break;
        case Nlbl:
            r->lbl.name = strdup(n->lbl.name);
            break;
        case Ndecl:
            /* sym */
            r->decl.name = specializenode(n->decl.name, tsmap);
            n->decl.type = tysubst(n->decl.type, tsmap);

            /* symflags */
            r->decl.isconst = n->decl.isconst;
            r->decl.isgeneric = n->decl.isgeneric;
            r->decl.isextern = n->decl.isextern;

            /* init */
            r->decl.init = specializenode(n->decl.init, tsmap);
            break;
        case Nfunc:
            r->func.scope = mkstab();
            r->func.nargs = n->func.nargs;
            r->func.args = xalloc(sizeof(Node *)*n->func.nargs);
            for (i = 0; i < n->func.nargs; i++)
                r->func.args[i] = specializenode(n->func.args[i], tsmap);
            r->func.body = specializenode(n->func.body, tsmap);
            break;
        case Nnone:
            die("Nnone should not be seen as node type!");
            break;
    }
    return r;
}

Node *specialize(Node *n, Type *to, Type *from)
{
    Htab *tsmap;

    tsmap = mkht(tidhash, tideq);
    fillsubst(tsmap, to, from);
    return specializenode(n, tsmap);
}