ref: 5fd0c284bc486fd0496e2bc10057946dbf9be2b2
parent: 57114efd8d6aadc94466e0a8ff26fa613d9c3e8f
author: Ori Bernstein <[email protected]>
date: Thu Oct 18 14:05:39 EDT 2012
Remove redundant code. We had duplicated type freshening/specializing code. Fix.
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -115,76 +115,22 @@
return 0;
}
-/* Returns a fresh type with all unbound type
- * parameters (type schemes in most literature)
- * replaced with type variables that we can unify
- * against */
-static Type *tyspecialize(Inferstate *st, Htab *ht, Type *t)
+/* Freshens the type of a declaration. */
+static Type *tyfreshen(Inferstate *st, Type *t)
{
- Type *ret;
- size_t i;
+ Htab *ht;
st->ingeneric++;
t = tf(st, t);
st->ingeneric--;
- switch (t->type) {
- case Typaram:
- if (hthas(ht, t->pname))
- return htget(ht, t->pname);
- ret = mktyvar(t->line);
- htput(ht, t->pname, ret);
- break;
- case Tygeneric:
- for (i = 0; i < t->nparam; i++)
- if (!hthas(ht, t->param[i]->pname))
- htput(ht, t->param[i]->pname, mktyvar(t->param[i]->line));
- ret = mktyname(t->line, t->name, tyspecialize(st, ht, t->sub[0]));
- for (i = 0; i < t->nparam; i++)
- lappend(&ret->param, &ret->nparam, tyspecialize(st, ht, t->param[i]));
- break;
- case Tystruct:
- die("Freshening structs is not yet implemented");
- break;
- case Tyunion:
- die("Freshening unions is not yet implemented");
- break;
- default:
- if (t->nsub > 0) {
- ret = tydup(t);
- for (i = 0; i < t->nsub; i++)
- ret->sub[i] = tyspecialize(st, ht, t->sub[i]);
- } else {
- ret = t;
- }
- break;
- }
- return ret;
-}
-
-static Type *tyfreshen(Inferstate *st, Type *t)
-{
- Htab *ht;
-
- assert(t->type == Tygeneric);
ht = mkht(strhash, streq);
- t = tyspecialize(st, ht, t);
+ t = tyspecialize(t, ht);
htfree(ht);
return t;
}
-/* Freshens the type of a declaration. */
-static Type *freshen(Inferstate *st, Type *t)
-{
- Htab *ht;
-
- ht = mkht(strhash, streq);
- t = tyspecialize(st, ht, t);
- htfree(ht);
- return t;
-}
-
/* Checks if a type that directly contains itself.
* Recursive types that contain themselves through
* pointers or slices are fine, but any other self-inclusion
@@ -740,7 +686,7 @@
var = mkexpr(n->line, Ovar, nsname, NULL);
var->expr.did = s->decl.did;
if (s->decl.isgeneric)
- settype(st, var, freshen(st, s->decl.type));
+ settype(st, var, tyfreshen(st, s->decl.type));
else
settype(st, var, s->decl.type);
if (s->decl.isgeneric) {
@@ -789,7 +735,7 @@
s = getdcl(curstab(), args[0]);
if (s) {
if (s->decl.isgeneric)
- t = freshen(st, s->decl.type);
+ t = tyfreshen(st, s->decl.type);
else if (s->decl.isconst)
t = s->decl.type;
else
@@ -962,7 +908,7 @@
fatal(n->line, "Undeclared var %s", ctxstr(st, args[0]));
if (s->decl.isgeneric)
- t = freshen(st, s->decl.type);
+ t = tyfreshen(st, s->decl.type);
else
t = s->decl.type;
settype(st, n, t);
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -410,6 +410,7 @@
/* specialize generics */
Node *specializedcl(Node *n, Type *to, Node **name);
+Type *tyspecialize(Type *t, Htab *tymap);
/* usefiles */
int loaduse(FILE *f, Stab *into);
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -11,26 +11,6 @@
#include "parse.h"
-static ulong typaramhash(void *p)
-{
- Type *t;
-
- t = p;
- assert(t->type == Typaram);
- return strhash(t->pname);
-}
-
-static int typarameq(void *pa, void *pb)
-{
- Type *a, *b;
-
- a = pa;
- b = pb;
- assert(a->type == Typaram);
- assert(b->type == Typaram);
- return streq(a->pname, b->pname);
-}
-
/*
* Checks if a type contains any type
* parameers at all (ie, if it generic).
@@ -41,6 +21,8 @@
if (t->type == Typaram)
return 1;
+ if (t->type == Tygeneric)
+ return 1;
for (i = 0; i < t->nsub; i++)
if (hasparams(t->sub[i]))
return 1;
@@ -52,19 +34,45 @@
* parameters substituted with the substitions
* described in 'tsmap'
*/
-static Type *dosubst(Type *t, Htab *tsmap)
+/* Returns a fresh type with all unbound type
+ * parameters (type schemes in most literature)
+ * replaced with type variables that we can unify
+ * against */
+Type *tyspecialize(Type *t, Htab *ht)
{
Type *ret;
- size_t i;
- if (t->type == Typaram) {
- ret = htget(tsmap, t);
- } else {
- ret = tydup(t);
- for (i = 0; i < t->nsub; i++)
- ret->sub[i] = dosubst(t->sub[i], tsmap);
+ size_t i;
+ switch (t->type) {
+ case Typaram:
+ if (hthas(ht, t->pname))
+ return htget(ht, t->pname);
+ ret = mktyvar(t->line);
+ htput(ht, t->pname, ret);
+ break;
+ case Tygeneric:
+ for (i = 0; i < t->nparam; i++)
+ if (!hthas(ht, t->param[i]->pname))
+ htput(ht, t->param[i]->pname, mktyvar(t->param[i]->line));
+ ret = mktyname(t->line, t->name, tyspecialize(t->sub[0], ht));
+ for (i = 0; i < t->nparam; i++)
+ lappend(&ret->param, &ret->nparam, tyspecialize(t->param[i], ht));
+ break;
+ case Tystruct:
+ break;
+ case Tyunion:
+ die("Freshening unions is not yet implemented");
+ break;
+ default:
+ if (t->nsub > 0) {
+ ret = tydup(t);
+ for (i = 0; i < t->nsub; i++)
+ ret->sub[i] = tyspecialize(t->sub[i], ht);
+ } else {
+ ret = t;
+ }
+ break;
}
- assert(ret != NULL);
return ret;
}
@@ -74,7 +82,7 @@
static Type *tysubst(Type *t, Htab *tsmap)
{
if (hasparams(t))
- return dosubst(t, tsmap);
+ return tyspecialize(t, tsmap);
else
return t;
}
@@ -88,7 +96,7 @@
size_t i;
if (from->type == Typaram) {
- htput(tsmap, from, to);
+ htput(tsmap, from->pname, to);
}
if (to->nsub != from->nsub)
return;
@@ -343,7 +351,7 @@
}
/* specialize */
- tsmap = mkht(typaramhash, typarameq);
+ tsmap = mkht(strhash, streq);
fillsubst(tsmap, to, n->decl.type);
d = mkdecl(n->line, *name, tysubst(n->decl.type, tsmap));
--- a/parse/type.c
+++ b/parse/type.c
@@ -44,7 +44,7 @@
}
/*
- * Duplicates a type, so we can frob
+ * Shallowly duplicates a type, so we can frob
* its internals later
*/
Type *tydup(Type *t)