ref: e9f06c461c5d8eebd5de7ab7ff9ab3af765a3a63
parent: a64be799930f5f33d617f8e6933bfbcf5056080a
author: Ori Bernstein <[email protected]>
date: Tue Apr 2 07:10:18 EDT 2013
Add a delayed unification hash table. Now, there is a mechanism to say "Try to unify with this if you haven't figured out a more specific type" within the inferencer. This is used only for union constructors, but it should get used for integer defaulting and similar soon.
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -30,6 +30,9 @@
/* generic declarations to be specialized */
Node **genericdecls;
size_t ngenericdecls;
+ /* delayed unification -- we fall back to these types in a post pass if we
+ * haven't unifed to something more specific */
+ Htab *delayed;
/* the nodes that we've specialized them to, and the scopes they
* appear in */
Node **specializations;
@@ -306,6 +309,15 @@
return NULL;
}
+static Type *delayed(Inferstate *st, Type *fallback)
+{
+ Type *t;
+
+ t = mktylike(fallback->line, fallback->type);
+ htput(st->delayed, t, fallback);
+ return t;
+}
+
/* Finds the type of any typable node */
static Type *type(Inferstate *st, Node *n)
{
@@ -756,7 +768,7 @@
uc = uconresolve(st, n);
if (uc->etype)
unify(st, n, uc->etype, type(st, args[1]));
- settype(st, n, uc->utype);
+ settype(st, n, delayed(st, uc->utype));
break;
case Ovar:
s = getdcl(curstab(), args[0]);
@@ -950,7 +962,7 @@
uc = uconresolve(st, n);
if (uc->etype)
unify(st, n, uc->etype, type(st, args[1]));
- settype(st, n, uc->utype);
+ settype(st, n, delayed(st, uc->utype));
break;
case Otup:
types = xalloc(sizeof(Type *)*n->expr.nargs);
@@ -1147,6 +1159,8 @@
return tyint;
if (hascstr(t, cstrtab[Tcfloat]) && cstrcheck(t, tyflt))
return tyint;
+ if (hthas(st->delayed, t))
+ return htget(st->delayed, t);
} else if (!t->fixed) {
t->fixed = 1;
if (t->type == Tyarray) {
@@ -1345,11 +1359,23 @@
}
}
+static ulong tyhash(void *t)
+{
+ /* hash is just multiplying by an arbitrary large prime */
+ return ((Type *)t)->tid * 38733031;
+}
+
+static int tyeq(void *a, void *b)
+{
+ return ((Type *)a)->tid == ((Type *)b)->tid;
+}
+
void infer(Node *file)
{
Inferstate st = {0,};
assert(file->type == Nfile);
+ st.delayed = mkht(tyhash, tyeq);
loaduses(file);
mergeexports(&st, file);
infernode(&st, file, NULL, NULL);