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);
+}