ref: c0705c9a9457e5a13e20bb71d8b14e4399ffc02f
parent: c40815889c460edd815ead46f1593510e0c56147
parent: 635dfa9043c05bc875bc5c3a77b48ea768b730f0
author: Ori Bernstein <[email protected]>
date: Mon Oct 8 08:41:48 EDT 2012
Merge branch 'master' of git+ssh://git.eigenstate.org/git/ori/mc Conflicts: 6/main.c muse/muse.c
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -323,8 +323,8 @@
| type Tosqbrac expr Tcsqbrac {$$ = mktyarray($2->line, $1, $3);}
| type Tstar {$$ = mktyptr($2->line, $1);}
| Tat Tident {$$ = mktyparam($1->line, $2->str);}
- | name {$$ = mktyunres($1->line, $1);}
- | name Toparen typelist Tcparen {$$ = mktyunres($1->line, $1);}
+ | name {$$ = mktyunres($1->line, $1, NULL, 0);}
+ | name Toparen typelist Tcparen {$$ = mktyunres($1->line, $1, $3.types, $3.ntypes);}
;
functype: Toparen funcsig Tcparen {$$ = $2;}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -123,24 +123,34 @@
t = tf(st, t);
if (t->type != Typaram && t->nsub == 0)
return t;
-
- if (t->type == Typaram) {
- if (hthas(ht, t->pname))
- return htget(ht, t->pname);
- ret = mktyvar(t->line);
- htput(ht, t->pname, ret);
- return ret;
- } else if (t->type == 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));
- return mktyname(t->line, t->name, tyfreshen(st, ht, t->sub[0]));
- } else {
- ret = tydup(t);
- for (i = 0; i < t->nsub; i++)
- ret->sub[i] = tyfreshen(st, ht, t->sub[i]);
- return ret;
+ 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, tyfreshen(st, ht, t->sub[0]));
+ for (i = 0; i < t->nparam; i++)
+ lappend(&ret->param, &ret->nparam, tyfreshen(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:
+ ret = tydup(t);
+ for (i = 0; i < t->nsub; i++)
+ ret->sub[i] = tyfreshen(st, ht, t->sub[i]);
+ break;
}
+ return ret;
}
static Type *tyspecialize(Inferstate *st, Type *t)
@@ -224,7 +234,8 @@
infernode(st, t->sdecls[i], NULL, NULL);
} else if (t->type == Tyunion) {
for (i = 0; i < t->nmemb; i++) {
- tyresolve(st, t->udecls[i]->utype);
+ //tyresolve(st, t->udecls[i]->utype);
+ t->udecls[i]->utype = t;
t->udecls[i]->utype = tf(st, t->udecls[i]->utype);
if (t->udecls[i]->etype) {
tyresolve(st, t->udecls[i]->etype);
@@ -334,11 +345,11 @@
args = n->expr.args;
uc = getucon(curstab(), args[0]);
if (!uc)
- fatal(n->line, "No union constructor %s", ctxstr(st, args[0]));
+ fatal(n->line, "no union constructor `%s", ctxstr(st, args[0]));
if (!uc->etype && n->expr.nargs > 1)
- fatal(n->line, "nullary union constructor %s passed arg ", ctxstr(st, args[0]));
+ fatal(n->line, "nullary union constructor `%s passed arg ", ctxstr(st, args[0]));
else if (uc->etype && n->expr.nargs != 2)
- fatal(n->line, "union constructor %s needs arg ", ctxstr(st, args[0]));
+ fatal(n->line, "union constructor `%s needs arg ", ctxstr(st, args[0]));
return uc;
}
@@ -396,7 +407,8 @@
static void checkcast(Inferstate *st, Node *n)
{
- /* FIXME: actually verify the casts */
+ /* FIXME: actually verify the casts. Right now, it's ok to leave this
+ * unimplemented because bad casts get caught by the backend. */
}
/* Constrains a type to implement the required constraints. On
@@ -568,6 +580,26 @@
settype(st, n, ft->sub[0]);
}
+static void unifyparams(Inferstate *st, Node *ctx, Type *a, Type *b)
+{
+ size_t i;
+
+ /* The only types with unifiable params are Tyunres and Tyname.
+ * Tygeneric should always be freshened, and no other types have
+ * parameters attached.
+ *
+ * FIXME: Is it possible to have parameterized typarams? */
+ if (a->type != Tyunres && a->type != Tyname)
+ return;
+ if (b->type != Tyunres && b->type != Tyname)
+ return;
+
+ if (a->nparam != b->nparam)
+ fatal(ctx->line, "Mismatched parameter list sizes: %s with %s near %s", tystr(a), tystr(b), ctxstr(st, ctx));
+ for (i = 0; i < a->nparam; i++)
+ unify(st, ctx, a->param[i], b->param[i]);
+}
+
static void loaduses(Node *n)
{
size_t i;
@@ -951,6 +983,10 @@
Type *t;
t = tf(st, decltype(n));
+ if (t->type == Tygeneric) {
+ t = tyspecialize(st, t);
+ unifyparams(st, n, t, decltype(n));
+ }
settype(st, n, t);
if (n->decl.init) {
inferexpr(st, n->decl.init, NULL, NULL);
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -345,7 +345,7 @@
Type *mktyparam(int line, char *name);
Type *mktyname(int line, Node *name, Type *base);
Type *mktygeneric(int line, Node *name, Type **params, size_t nparams, Type *base);
-Type *mktyunres(int line, Node *name);
+Type *mktyunres(int line, Node *name, Type **params, size_t nparams);
Type *mktyarray(int line, Type *base, Node *sz);
Type *mktyslice(int line, Type *base);
Type *mktyidxhack(int line, Type *base);
--- a/parse/type.c
+++ b/parse/type.c
@@ -130,7 +130,7 @@
return t;
}
-Type *mktyunres(int line, Node *name)
+Type *mktyunres(int line, Node *name, Type **param, size_t nparam)
{
Type *t;
@@ -137,6 +137,8 @@
/* resolve it in the type inference stage */
t = mktype(line, Tyunres);
t->name = name;
+ t->param = param;
+ t->nparam = nparam;
return t;
}
@@ -277,7 +279,7 @@
Type *tybase(Type *t)
{
assert(t != NULL);
- while (t->type == Tyname)
+ while (t->type == Tyname || t->type == Tygeneric)
t = t->sub[0];
return t;
}
@@ -456,19 +458,28 @@
case Tyunres:
p += snprintf(p, end - p, "?"); /* indicate unresolved name. should not be seen by user. */
p += namefmt(p, end - p, t->name);
+ if (t->nparam) {
+ p += snprintf(p, end - p, "(");
+ for (i = 0; i < t->nparam; i++) {
+ p += snprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->param[i]);
+ sep = ", ";
+ }
+ p += snprintf(p, end - p, ")");
+ }
break;
case Tyname:
- p += snprintf(p, end - p, "%s", namestr(t->name));
- break;
case Tygeneric:
p += snprintf(p, end - p, "%s", namestr(t->name));
- p += snprintf(p, end - p, "(");
- for (i = 0; i < t->nparam; i++) {
- p += snprintf(p, end - p, "%s", sep);
- p += tybfmt(p, end - p, t->param[i]);
- sep = ", ";
+ if (t->nparam) {
+ p += snprintf(p, end - p, "(");
+ for (i = 0; i < t->nparam; i++) {
+ p += snprintf(p, end - p, "%s", sep);
+ p += tybfmt(p, end - p, t->param[i]);
+ sep = ", ";
+ }
+ p += snprintf(p, end - p, ")");
}
- p += snprintf(p, end - p, ")");
break;
case Tystruct: p += fmtstruct(p, end - p, t); break;
case Tyunion: p += fmtunion(p, end - p, t); break;