ref: e8121eb38f6c825fc4638d84521c51dc6cfe761b
parent: 76ce9de16baeec77b86ece6825b90715b08545ba
author: Ori Bernstein <[email protected]>
date: Fri Jul 13 20:07:31 EDT 2018
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.
--- 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:
@@ -784,6 +784,16 @@
with type $t :: numeric $t, integral $t is replaced with int. An
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:
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -36,6 +36,7 @@
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 @@
$$.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 @@
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 @@
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]);
}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -514,7 +514,7 @@
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 @@
*
* 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);