summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2018-07-14 00:07:31 -0700
committerOri Bernstein <ori@eigenstate.org>2018-07-14 00:16:06 -0700
commite8121eb38f6c825fc4638d84521c51dc6cfe761b (patch)
treea2e37178de089f90db2c8115a41edcd299921433
parent76ce9de16baeec77b86ece6825b90715b08545ba (diff)
downloadmc-e8121eb38f6c825fc4638d84521c51dc6cfe761b.tar.gz
Push down named unions types into union tags
Currently, union tags are given the type of their enclosing union, by default: type u = union `Foo ;; var x = `Foo will currently infer the variable 'x' as having type 'union `Foo ;;'. To make the type of 'x' infer as 'foo', the code needs to force 'x' to unify with something that is explicitly declared as a 'u'. This change makes it so that union tags declared in the manner above will default to type 'u', instead. This is a special case, but it makes the behavior less surprising.
-rw-r--r--doc/lang.txt12
-rw-r--r--parse/gram.y16
-rw-r--r--parse/infer.c8
3 files changed, 32 insertions, 4 deletions
diff --git a/doc/lang.txt b/doc/lang.txt
index 459ac50..4dc9f12 100644
--- a/doc/lang.txt
+++ b/doc/lang.txt
@@ -1,6 +1,6 @@
The Myrddin Programming Language
Jul 2012
- Updated Feb 2017
+ Updated Jul 2018
Ori Bernstein
TABLE OF CONTENTS:
@@ -785,6 +785,16 @@ TABLE OF CONTENTS:
unconstrained type with $t :: numeric $t, floating $t is replaced with
flt64.
+ As a special case, a union type declared with the form
+
+ type u = union
+ `Foo
+ ;;
+
+ will have the default type set to the named type, and not the
+ union itself. This is slightly inconsistent, but it makes the
+ behavior less surprising.
+
4.6. Built In Traits:
4.6.1. numeric:
diff --git a/parse/gram.y b/parse/gram.y
index 146c842..7d95300 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -36,6 +36,7 @@ static void setattrs(Node *dcl, char **attrs, size_t nattrs);
static void setwith(Type *ty, Traitspec **spec, size_t nspec);
static void setupinit(Node *n);
static void addinit(Node *blk, Node *dcl);
+static void setuname(Type *ty);
%}
@@ -528,6 +529,7 @@ tydef : Ttype typeid traitspec {$$ = $2;}
$$.type = mktyname($2.loc, mkname($2.loc, $2.name), $5);
else
$$.type = mktygeneric($2.loc, mkname($2.loc, $2.name), $2.params, $2.nparams, $5);
+ setuname($$.type);
setwith($$.type, $3.spec, $3.nspec);
}
;
@@ -1147,6 +1149,17 @@ setupinit(Node *n)
n->decl.name->name.name = strdup(s);
}
+static void
+setuname(Type *ty)
+{
+ size_t i;
+
+ if (ty->sub[0]->type != Tyunion)
+ return;
+ for (i = 0; i < ty->sub[0]->nmemb; i++)
+ ty->sub[0]->udecls[i]->utype = ty;
+}
+
static Node *
mkpseudodecl(Srcloc l, Type *t)
{
@@ -1231,7 +1244,8 @@ installucons(Stab *st, Type *t)
break;
case Tyunion:
for (i = 0; i < b->nmemb; i++) {
- b->udecls[i]->utype = b;
+ if (!b->udecls[i]->utype)
+ b->udecls[i]->utype = b;
b->udecls[i]->id = i;
putucon(st, b->udecls[i]);
}
diff --git a/parse/infer.c b/parse/infer.c
index c5cad2f..8da7e02 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -514,7 +514,7 @@ tyresolve(Type *t)
case Tyunion:
inaggr++;
for (i = 0; i < t->nmemb; i++) {
- t->udecls[i]->utype = t;
+ assert(t->udecls[i]->utype);
t->udecls[i]->utype = tf(t->udecls[i]->utype);
if (t->udecls[i]->etype) {
tyresolve(t->udecls[i]->etype);
@@ -1498,7 +1498,11 @@ inferucon(Node *n, int *isconst)
*
* To make it compile, for now, we just bind the types in here.
*/
- t = tysubst(tf(uc->utype), uc->utype);
+ t = uc->utype;
+ if (t->type != Tyunion)
+ t = t->sub[0];
+ assert(t->type == Tyunion);
+ t = tysubst(tf(t), t);
uc = tybase(t)->udecls[uc->id];
if (uc->etype) {
inferexpr(&n->expr.args[1], NULL, NULL);