ref: 47e2fe4b898f4260414f84424929d8a7e09cd021
parent: 9ab2a5a2a341794f93df6aee3859c90bbae3a9b0
author: Ori Bernstein <[email protected]>
date: Wed Jun 27 19:52:02 EDT 2012
Work towards supporting unions. Add ucon type, and work it in. This meant a bit of reworking how structs and such work.
--- a/8/reduce.c
+++ b/8/reduce.c
@@ -373,7 +373,7 @@
{
Type *ty;
Node **nl;
- size_t nn, i;
+ size_t i;
size_t off;
if (aggr->expr.type->type == Typtr)
@@ -382,9 +382,9 @@
ty = tybase(ty);
assert(ty->type == Tystruct);
- nl = aggrmemb(ty, &nn);
+ nl = ty->sdecls;
off = 0;
- for (i = 0; i < nn; i++) {
+ for (i = 0; i < ty->nmemb; i++) {
if (!strcmp(namestr(memb), declname(nl[i])))
return off;
off += size(nl[i]);
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -18,6 +18,7 @@
int yylex(void);
static Op binop(int toktype);
static Node *mkpseudodecl(Type *t);
+static void installucons(Stab *st, Type *t);
Stab *curscope;
%}
@@ -125,11 +126,13 @@
%type <node> exprln retexpr expr atomicexpr literal asnexpr lorexpr landexpr borexpr
%type <node> bandexpr cmpexpr unioncons addexpr mulexpr shiftexpr prefixexpr postfixexpr
%type <node> funclit arraylit name block blockbody stmt label use
-%type <node> decl declbody declcore structelt unionelt
+%type <node> decl declbody declcore structelt
%type <node> ifstmt forstmt whilestmt elifs optexprln
%type <node> castexpr
+%type <ucon> unionelt
-%type <nodelist> arglist argdefs structbody unionbody params
+%type <nodelist> arglist argdefs structbody params
+%type <uconlist> unionbody
%union {
struct {
@@ -139,6 +142,11 @@
} nodelist;
struct {
int line;
+ Ucon **ucl;
+ size_t nucl;
+ } uconlist;
+ struct {
+ int line;
Type **types;
size_t ntypes;
} tylist;
@@ -150,6 +158,7 @@
Node *node;
Tok *tok;
Type *ty;
+ Ucon *ucon;
}
%%
@@ -170,7 +179,8 @@
{lappend(&file->file.uses, &file->file.nuses, $1);}
| package
| tydef
- {puttype(file->file.globls, mkname($1.line, $1.name), $1.type);}
+ {puttype(file->file.globls, mkname($1.line, $1.name), $1.type);
+ installucons(file->file.globls, $1.type);}
| Tendln
;
@@ -315,22 +325,22 @@
uniondef
: Tunion unionbody Tendblk
- {$$ = mktyunion($1->line, $2.nl, $2.nn);}
+ {$$ = mktyunion($1->line, $2.ucl, $2.nucl);}
;
unionbody
: unionelt
- {$$.nl = NULL; $$.nn = 0;
- if ($1) {lappend(&$$.nl, &$$.nn, $1);}}
+ {$$.ucl = NULL; $$.nucl = 0;
+ if ($1) {lappend(&$$.ucl, &$$.nucl, $1);}}
| unionbody unionelt
- {if ($2) {lappend(&$$.nl, &$$.nn, $2);}}
+ {if ($2) {lappend(&$$.ucl, &$$.nucl, $2);}}
;
-unionelt
+unionelt /* nb: the ucon union type gets filled in when we have context */
: Ttick Tident type Tendln
- {$$ = mkdecl($2->line, mkname($2->line, $2->str), $3);}
+ {$$ = mkucon($2->line, mkname($2->line, $2->str), NULL, $3);}
| Ttick Tident Tendln
- {$$ = mkdecl($2->line, mkname($2->line, $2->str), NULL);}
+ {$$ = mkucon($2->line, mkname($2->line, $2->str), NULL, NULL);}
| visdef Tendln
{$$ = NULL;}
| Tendln
@@ -580,6 +590,19 @@
return mkdecl(-1, mkname(-1, buf), t);
}
+static void installucons(Stab *st, Type *t)
+{
+ Type *b;
+ size_t i;
+
+ b = tybase(t);
+ if (b->type != Tyunion)
+ return;
+ for (i = 0; i < b->nmemb; i++) {
+ b->udecls[i]->utype = t;
+ putucon(st, b->udecls[i]);
+ }
+}
void yyerror(const char *s)
{
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -87,19 +87,29 @@
static void tyresolve(Type *t)
{
- size_t i, nn;
+ size_t i;
Type *base;
- Node **n;
if (t->resolved)
return;
t->resolved = 1;
- n = aggrmemb(t, &nn);
- for (i = 0; i < nn; i++)
- infernode(n[i], NULL, NULL);
+ if (t->type == Tystruct) {
+ for (i = 0; i < t->nmemb; i++)
+ infernode(t->sdecls[i], NULL, NULL);
+ } else if (t->type == Tyunion) {
+ for (i = 0; i < t->nmemb; i++) {
+ tyresolve(t->udecls[i]->utype);
+ if (t->udecls[i]->etype)
+ tyresolve(t->udecls[i]->etype);
+ }
+ } else if (t->type == Tyarray) {
+ infernode(t->asize, NULL, NULL);
+ }
+
for (i = 0; i < t->nsub; i++)
t->sub[i] = tf(t->sub[i]);
base = tybase(t);
+ /* no-ops if base == t */
if (t->cstrs)
bsunion(t->cstrs, base->cstrs);
else
@@ -720,7 +730,7 @@
static void infercompn(Node *file)
{
- size_t i, j, nn;
+ size_t i, j;
Node *aggr;
Node *memb;
Node *n;
@@ -747,10 +757,11 @@
found = 1;
}
} else {
+ t = tybase(t);
if (t->type == Typtr)
t = tf(t->sub[0]);
- nl = aggrmemb(t, &nn);
- for (j = 0; j < nn; j++) {
+ nl = t->sdecls;
+ for (j = 0; j < t->nmemb; j++) {
if (!strcmp(namestr(memb), declname(nl[j]))) {
unify(n, type(n), decltype(nl[j]));
found = 1;
--- a/parse/node.c
+++ b/parse/node.c
@@ -219,6 +219,18 @@
return n;
}
+Ucon *mkucon(int line, Node *name, Type *ut, Type *et)
+{
+ Ucon *uc;
+
+ uc = zalloc(sizeof(Ucon));
+ uc->line = line;
+ uc->name = name;
+ uc->utype = ut;
+ uc->etype = et;
+ return uc;
+}
+
Node *mkbool(int line, int val)
{
Node *n;
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -10,6 +10,7 @@
typedef struct Tok Tok;
typedef struct Node Node;
+typedef struct Ucon Ucon;
typedef struct Stab Stab;
typedef struct Type Type;
@@ -78,10 +79,11 @@
/* Contents of stab.
* types and values are in separate namespaces. */
- Htab *ns;
Htab *dcl;
Htab *closure; /* the syms we close over */
+ Htab *ns;
Htab *ty;
+ Htab *uc;
};
struct Type {
@@ -99,10 +101,18 @@
Node *asize; /* array size */
char *pname; /* Typaram: name of type parameter */
Node **sdecls; /* Tystruct: decls in struct */
- Node **udecls; /* Tyunion: decls in union */
+ Ucon **udecls; /* Tyunion: decls in union */
};
};
+struct Ucon {
+ int line;
+ size_t id;
+ Node *name;
+ Type *utype;
+ Type *etype;
+};
+
struct Cstr {
int cid; /* unique id */
char *name;
@@ -194,6 +204,13 @@
} decl;
struct {
+ long uid;
+ Node *name;
+ Type *elt;
+ Type *alt;
+ } uelt;
+
+ struct {
Stab *scope;
Type *type;
size_t nargs;
@@ -271,11 +288,13 @@
void putns(Stab *st, Stab *scope);
void puttype(Stab *st, Node *n, Type *ty);
void updatetype(Stab *st, Node *n, Type *t);
-void putdcl(Stab *st, Node *s);
+void putdcl(Stab *st, Node *dcl);
+void putucon(Stab *st, Ucon *uc);
Stab *getns(Stab *st, Node *n);
Node *getdcl(Stab *st, Node *n);
Type *gettype(Stab *st, Node *n);
+Ucon *getucon(Stab *st, Node *n);
Stab *curstab(void);
void pushstab(Stab *st);
@@ -296,7 +315,7 @@
Type *mktyptr(int line, Type *base);
Type *mktyfunc(int line, Node **args, size_t nargs, Type *ret);
Type *mktystruct(int line, Node **decls, size_t ndecls);
-Type *mktyunion(int line, Node **decls, size_t ndecls);
+Type *mktyunion(int line, Ucon **decls, size_t ndecls);
Cstr *mkcstr(int line, char *name, Node **memb, size_t nmemb, Node **funcs, size_t nfuncs);
Type *tylike(Type *t, Ty ty); /* constrains tyvar t like it was builtin ty */
int istysigned(Type *t);
@@ -332,6 +351,7 @@
Node *mkdecl(int line, Node *name, Type *ty);
Node *mklbl(int line, char *lbl);
Node *mkslice(int line, Node *base, Node *off);
+Ucon *mkucon(int line, Node *name, Type *ut, Type *uet);
/* node util functions */
char *namestr(Node *name);
@@ -343,7 +363,6 @@
void setns(Node *n, char *ns);
void updatens(Stab *st, char *ns);
Op exprop(Node *n);
-Node **aggrmemb(Type *t, size_t *n);
/* specialize generics */
Node *specializedcl(Node *n, Type *to, Node **name);
--- a/parse/pickle.c
+++ b/parse/pickle.c
@@ -82,6 +82,33 @@
return st;
}
+static void wrucon(FILE *fd, Ucon *uc)
+{
+ wrint(fd, uc->line);
+ wrint(fd, uc->id);
+ pickle(uc->name, fd);
+ wrtype(fd, uc->utype);
+ wrtype(fd, uc->etype);
+}
+
+static Ucon *rducon(FILE *fd)
+{
+ Type *ut, *et;
+ Node *name;
+ Ucon *uc;
+ size_t id;
+ int line;
+
+ line = rdint(fd);
+ id = rdint(fd);
+ name = unpickle(fd);
+ ut = rdtype(fd);
+ et = rdtype(fd);
+ uc = mkucon(line, name, ut, et);
+ uc->id = id;
+ return uc;
+}
+
static void wrsym(FILE *fd, Node *val)
{
/* sym */
@@ -150,7 +177,7 @@
case Tyunion:
wrint(fd, ty->nmemb);
for (i = 0; i < ty->nmemb; i++)
- pickle(ty->udecls[i], fd);
+ wrucon(fd, ty->udecls[i]);
break;
case Tyarray:
wrtype(fd, ty->sub[0]);
@@ -199,7 +226,7 @@
ty->nmemb = rdint(fd);
ty->udecls = xalloc(ty->nmemb * sizeof(Node*));
for (i = 0; i < ty->nmemb; i++)
- ty->udecls[i] = unpickle(fd);
+ ty->udecls[i] = rducon(fd);
break;
case Tyarray:
ty->sub[0] = rdtype(fd);
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -62,6 +62,7 @@
st->ns = mkht(namehash, nameeq);
st->dcl = mkht(namehash, nameeq);
st->ty = mkht(namehash, nameeq);
+ st->uc = mkht(namehash, nameeq);
return st;
}
@@ -98,6 +99,18 @@
return NULL;
}
+Ucon *getucon(Stab *st, Node *n)
+{
+ Ucon *uc;
+
+ do {
+ if ((uc = htget(st->uc, n)))
+ return uc;
+ st = st->super;
+ } while (st);
+ return NULL;
+}
+
Cstr *getcstr(Stab *st, Node *n)
{
Cstrdefn *c;
@@ -154,6 +167,13 @@
td->name = n;
td->type = t;
htput(st->ty, td->name, td);
+}
+
+void putucon(Stab *st, Ucon *uc)
+{
+ if (getucon(st, uc->name))
+ fatal(uc->line, "union constructor %s already defined", namestr(uc->name));
+ htput(st->uc, uc->name, uc);
}
void putcstr(Stab *st, Node *n, Cstr *c)
--- a/parse/type.c
+++ b/parse/type.c
@@ -202,7 +202,7 @@
return t;
}
-Type *mktyunion(int line, Node **decls, size_t ndecls)
+Type *mktyunion(int line, Ucon **decls, size_t ndecls)
{
Type *t;
@@ -230,18 +230,6 @@
return t;
}
-Node **aggrmemb(Type *t, size_t *n)
-{
- t = tybase(t);
- *n = t->nmemb;
- switch (t->type) {
- case Tystruct: return t->sdecls; break;
- case Tyunion: return t->udecls; break;
- case Tyarray: return &t->asize; break;
- default: return NULL;
- }
-}
-
static int namefmt(char *buf, size_t len, Node *n)
{
char *p;
@@ -314,10 +302,20 @@
static int fmtunion(char *buf, size_t len, Type *t)
{
size_t i;
- *buf = 0;
- for (i = 0; i < t->nmemb; i++)
- dump(t->udecls[i], stdout);
- return 0;
+ char *end, *p;
+ char *name, *ty;
+
+ p = buf;
+ end = p + len;
+ p += snprintf(p, end - p, "struct ");
+ for (i = 0; i < t->nmemb; i++) {
+ name = namestr(t->udecls[i]->name);
+ ty = tystr(t->udecls[i]->etype);
+ p += snprintf(p, end - p, "`%s %s; ", name, ty);
+ free(ty);
+ }
+ p += snprintf(p, end - p, ";;");
+ return p - buf;
}
static int tybfmt(char *buf, size_t len, Type *t)