shithub: mc

Download patch

ref: 361fe40c15b2303421fe7b7df59712426e187104
parent: 134217a2c718527a3e38abd5a60467ecb586fea9
author: Ori Bernstein <[email protected]>
date: Fri Jun 22 06:27:08 EDT 2012

Add untested code to specialize nodes.

    This is going to eventually be used for generics.

--- a/parse/Makefile
+++ b/parse/Makefile
@@ -7,6 +7,7 @@
     names.o \
     node.o \
     pickle.o \
+    specialize.o \
     stab.o \
     tok.o \
     type.o \
--- a/parse/htab.c
+++ b/parse/htab.c
@@ -172,7 +172,15 @@
 
 ulong ptrhash(void *key)
 {
-    return (ulong)key;
+    intptr_t h;
+
+    h = (intptr_t) key;
+    h *= 357913941;
+    h ^= h << 24;
+    h += ~357913941;
+    h ^= h >> 31;
+    h ^= h << 31;
+    return h;
 }
 
 int ptreq(void *a, void *b)
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -345,6 +345,9 @@
 Op exprop(Node *n);
 Node **aggrmemb(Type *t, size_t *n);
 
+/* specialize generics */
+Node *specialize(Node *n, Type *to, Type *from);
+
 /* usefiles */
 void readuse(Node *use, Stab *into);
 void writeuse(Node *file, FILE *out);
@@ -362,7 +365,7 @@
 char *tidstr(Ty tid);
 
 /* convenience funcs */
-void lappend(void *l, size_t *len, void *n); /* ugly hack; nl is void* because void*** is incompatible with T*** */
+void lappend(void *l, size_t *len, void *n); /* hack; nl is void* b/c void*** is incompatible with T*** */
 void linsert(void *l, size_t *len, size_t idx, void *n);
 void *lpop(void *l, size_t *len);
 void ldel(void *l, size_t *len, size_t idx);
--- /dev/null
+++ b/parse/specialize.c
@@ -1,0 +1,171 @@
+#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);
+}