#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <inttypes.h>#include <inttypes.h>#include <ctype.h>#include <string.h>#include <assert.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <assert.h> #include "util.h"#include "parse.h" typedef struct Traitmap Traitmap;typedef struct Postcheck Postcheck; struct Traitmap { Bitset *traits; Traitmap *sub[Ntypes]; Htab *name; /* name => bitset(traits) */ Type **filter; size_t nfilter; Trait **filtertr; size_t nfiltertr;}; struct Postcheck { Node *node; Stab *stab; Tyenv *env;}; int allowhidden; static void infernode(Node **np, Type *ret, int *sawret);static void inferexpr(Node **np, Type *ret, int *sawret);static void inferdecl(Node *n);static int tryconstrain(Type *ty, Trait *tr, int update); static Type *tyfreshen(Tysubst *subst, Type *orig);static Type *tf(Type *t);static Type *basetype(Type *a); static Type *unify(Node *ctx, Type *a, Type *b);static Type *tyfix(Node *ctx, Type *orig, int noerr);static void typesub(Node *n, int noerr); /* tracking where we are in the inference */static int ingeneric;static int inaggr;static int indentdepth;static Srcloc *unifysrc;static size_t nunifysrc; /* post-inference checking/unification */static Htab *delayed;static Postcheck **postcheck;static size_t npostcheck; /* generic declarations to be specialized */static Node **genericdecls;static size_t ngenericdecls;static Node **impldecl;static size_t nimpldecl; /* specializations of generics */static Node **specializations;static size_t nspecializations;static Stab **specializationscope;static size_t nspecializationscope;static Traitmap *traitmap;static Bitset *tytraits[Ntypes]; static voidctxstrcall(char *buf, size_t sz, Node *n){ char *p, *end, *sep, *t; size_t nargs, i; Node **args; Type *et; args = n->expr.args; nargs = n->expr.nargs; p = buf; end = buf + sz; sep = ""; if (exprop(args[0]) == Ovar) p += bprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0])); else p += bprintf(p, end - p, "<e>("); for (i = 1; i < nargs; i++) { et = tyfix(NULL, exprtype(args[i]), 1); if (et != NULL) t = tystr(et); else t = strdup("?"); if (exprop(args[i]) == Ovar) p += bprintf(p, end - p, "%s%s:%s", sep, namestr(args[i]->expr.args[0]), t); else p += bprintf(p, end - p, "%s<e%zd>:%s", sep, i, t); sep = ", "; free(t); } if (exprtype(args[0])->nsub) t = tystr(tyfix(NULL, exprtype(args[0])->sub[0], 1)); else t = strdup("unknown"); p += bprintf(p, end - p, "): %s", t); free(t);} static char *nodetystr(Node *n){ Type *t; t = NULL; if (n->type == Nexpr && exprtype(n) != NULL) t = tysearch(exprtype(n)); else if (n->type == Ndecl && decltype(n) != NULL) t = tysearch(decltype(n)); if (t && tybase(t)->type != Tyvar) return tystr(t); else return strdup("unknown");} static voidmarksrc(Type *t, Srcloc l){ t = tf(t); if (t->tid >= nunifysrc) { unifysrc = zrealloc(unifysrc, nunifysrc*sizeof(Srcloc), (t->tid + 1)*sizeof(Srcloc)); nunifysrc = t->tid + 1; } if (unifysrc[t->tid].line <= 0) unifysrc[t->tid] = l;} static char *srcstr(Type *ty){ char src[128]; Srcloc l; char *s; src[0] = 0; if (nunifysrc > ty->tid && unifysrc[ty->tid].line > 0) { l = unifysrc[ty->tid]; s = tystr(ty); snprintf(src, sizeof src, "\n\t%s from %s:%d", s, fname(l), lnum(l)); free(s); } return strdup(src);} /* Tries to give a good string describing the context * for the sake of error messages. */static char *ctxstr(Node *n){ char *t, *t1, *t2, *t3; char *s, *d; size_t nargs; Node **args; char buf[512]; if (!n) return strdup("???"); switch (n->type) { default: s = strdup(nodestr[n->type]); break; case Ndecl: d = declname(n); t = nodetystr(n); bprintf(buf, sizeof buf, "%s:%s", d, t); s = strdup(buf); free(t); break; case Nname: s = strdup(namestr(n)); break; case Nexpr: args = n->expr.args; nargs = n->expr.nargs; t1 = NULL; t2 = NULL; t3 = NULL; if (exprop(n) == Ovar) d = namestr(args[0]); else d = opstr[exprop(n)]; t = nodetystr(n); if (nargs >= 1) t1 = nodetystr(args[0]); if (nargs >= 2) t2 = nodetystr(args[1]); if (nargs >= 3) t3 = nodetystr(args[2]); switch (opclass[exprop(n)]) { case OTpre: bprintf(buf, sizeof buf, "%s<e:%s>", oppretty[exprop(n)], t1); break; case OTpost: bprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]); break; case OTzarg: bprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]); break; case OTbin: bprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2); break; case OTmisc: switch (exprop(n)) { case Ovar: bprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t); break; case Ocall: ctxstrcall(buf, sizeof buf,n); break; case Oidx: if (exprop(args[0]) == Ovar) bprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2); else bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2); break; case Oslice: if (exprop(args[0]) == Ovar) bprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3); else bprintf( buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3); break; case Omemb: bprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1])); break; case Otupmemb: bprintf(buf, sizeof buf, "<%s>.%llu", t1, args[1]->lit.intval); break; default: bprintf(buf, sizeof buf, "%s:%s", d, t); break; } break; default: bprintf(buf, sizeof buf, "%s", d); break; } free(t); free(t1); free(t2); free(t3); s = strdup(buf); break; } return s;} static voidaddspecialization(Node *n, Stab *stab){ Node *dcl; dcl = decls[n->expr.did]; lappend(&specializationscope, &nspecializationscope, stab); lappend(&specializations, &nspecializations, n); lappend(&genericdecls, &ngenericdecls, dcl);} static voidadddispspecialization(Node *n, Stab *stab){ Trait *tr; Type *ty; tr = traittab[Tcdisp]; ty = exprtype(n); assert(tr->nproto == 1); if (hthas(tr->proto[0]->decl.impls, ty)) return; lappend(&specializationscope, &nspecializationscope, stab); lappend(&specializations, &nspecializations, n); lappend(&genericdecls, &ngenericdecls, tr->proto[0]);} static voidadditerspecialization(Node *n, Stab *stab){ Trait *tr; Type *ty; size_t i; tr = traittab[Tciter]; ty = exprtype(n->iterstmt.seq); if (ty->type == Tyslice || ty->type == Tyarray || ty->type == Typtr) return; ty = tyfreshen(NULL, ty); for (i = 0; i < tr->nproto; i++) { ty = exprtype(n->iterstmt.seq); if (hthas(tr->proto[i]->decl.impls, ty)) continue; lappend(&specializationscope, &nspecializationscope, stab); lappend(&specializations, &nspecializations, n); lappend(&genericdecls, &ngenericdecls, tr->proto[i]); }} static voiddelayedcheck(Node *n){ Postcheck *pc; pc = xalloc(sizeof(Postcheck)); pc->node = n; pc->stab = curstab(); pc->env = curenv(); lappend(&postcheck, &npostcheck, pc);} static voidtypeerror(Type *a, Type *b, Node *ctx, char *msg){ char *t1, *t2, *s1, *s2, *c; t1 = tystr(tyfix(NULL, a, 1)); t2 = tystr(tyfix(NULL, b, 1)); s1 = srcstr(a); s2 = srcstr(b); c = ctxstr(ctx); if (msg) fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s: %s%s%s", t1, t2, c, msg, s1, s2); else fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s%s%s", t1, t2, c, s1, s2); free(t1); free(t2); free(s1); free(s2); free(c);} /* Set a scope's enclosing scope up correctly. */static voidsetsuperenv(Tyenv *e, Tyenv *super){ if (e) e->super = super;} /* Set a scope's enclosing scope up correctly. */static voidsetsuper(Stab *st, Stab *super){ Stab *s; /* verify that we don't accidentally create loops */ for (s = super; s; s = s->super) assert(s->super != st); st->super = super;} /* Checks if a type that directly contains itself. * Recursive types that contain themselves through * pointers or slices are fine, but any other self-inclusion * would lead to a value of infinite size */static intoccurs_rec(Type *sub, Bitset *bs){ size_t i; sub = tf(sub); if (bshas(bs, sub->tid)) return 1; bsput(bs, sub->tid); switch (sub->type) { case Typtr: case Tyslice: break; case Tystruct: for (i = 0; i < sub->nmemb; i++) if (occurs_rec(decltype(sub->sdecls[i]), bs)) return 1; break; case Tyunion: for (i = 0; i < sub->nmemb; i++) { if (!sub->udecls[i]->etype) continue; if (occurs_rec(sub->udecls[i]->etype, bs)) return 1; } break; default: for (i = 0; i < sub->nsub; i++) if (occurs_rec(sub->sub[i], bs)) return 1; break; } bsdel(bs, sub->tid); return 0;} static intoccursin(Type *a, Type *b){ Bitset *bs; int r; bs = mkbs(); a = tf(a); bsput(bs, a->tid); r = occurs_rec(b, bs); bsfree(bs); return r;} static intoccurs(Type *t){ Bitset *bs; int r; bs = mkbs(); r = occurs_rec(t, bs); bsfree(bs); return r;} static intneedfreshenrec(Type *t, Bitset *visited){ size_t i; t = tysearch(t); if (bshas(visited, t->tid)) return 0; bsput(visited, t->tid); switch (t->type) { case Typaram: return 1; case Tygeneric: return 1; case Tyname: for (i = 0; i < t->narg; i++) if (needfreshenrec(t->arg[i], visited)) return 1; return needfreshenrec(t->sub[0], visited); case Tystruct: for (i = 0; i < t->nmemb; i++) if (needfreshenrec(decltype(t->sdecls[i]), visited)) return 1; break; case Tyunion: for (i = 0; i < t->nmemb; i++) if (t->udecls[i]->etype && needfreshenrec(t->udecls[i]->etype, visited)) return 1; break; default: for (i = 0; i < t->nsub; i++) if (needfreshenrec(t->sub[i], visited)) return 1; break; } return 0;} static intneedfreshen(Type *t){ Bitset *visited; int ret; visited = mkbs(); ret = needfreshenrec(t, visited); bsfree(visited); return ret;} /* Freshens the type of a declaration. */static Type *tyfreshen(Tysubst *subst, Type *orig){ Type *ty, *base; if (!needfreshen(orig)) return orig; pushenv(orig->env); if (!subst) { subst = mksubst(); ty = tyspecialize(orig, subst, delayed); substfree(subst); } else { ty = tyspecialize(orig, subst, delayed); } ty->spec = orig->spec; ty->nspec = orig->nspec; base = basetype(ty); if (base) ty->seqaux = base; popenv(orig->env); return ty;} /* Resolves a type and all its subtypes recursively. */static voidtyresolve(Type *t)Lines 1–500 of 3038. Load more
#include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <inttypes.h> #include <inttypes.h> #include <ctype.h> #include <string.h> #include <assert.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <assert.h> #include "util.h" #include "parse.h" typedef struct Traitmap Traitmap; typedef struct Postcheck Postcheck; struct Traitmap { Bitset *traits; Traitmap *sub[Ntypes]; Htab *name; /* name => bitset(traits) */ Type **filter; size_t nfilter; Trait **filtertr; size_t nfiltertr; }; struct Postcheck { Node *node; Stab *stab; Tyenv *env; }; int allowhidden; static void infernode(Node **np, Type *ret, int *sawret); static void inferexpr(Node **np, Type *ret, int *sawret); static void inferdecl(Node *n); static int tryconstrain(Type *ty, Trait *tr, int update); static Type *tyfreshen(Tysubst *subst, Type *orig); static Type *tf(Type *t); static Type *basetype(Type *a); static Type *unify(Node *ctx, Type *a, Type *b); static Type *tyfix(Node *ctx, Type *orig, int noerr); static void typesub(Node *n, int noerr); /* tracking where we are in the inference */ static int ingeneric; static int inaggr; static int indentdepth; static Srcloc *unifysrc; static size_t nunifysrc; /* post-inference checking/unification */ static Htab *delayed; static Postcheck **postcheck; static size_t npostcheck; /* generic declarations to be specialized */ static Node **genericdecls; static size_t ngenericdecls; static Node **impldecl; static size_t nimpldecl; /* specializations of generics */ static Node **specializations; static size_t nspecializations; static Stab **specializationscope; static size_t nspecializationscope; static Traitmap *traitmap; static Bitset *tytraits[Ntypes]; static void ctxstrcall(char *buf, size_t sz, Node *n) { char *p, *end, *sep, *t; size_t nargs, i; Node **args; Type *et; args = n->expr.args; nargs = n->expr.nargs; p = buf; end = buf + sz; sep = ""; if (exprop(args[0]) == Ovar) p += bprintf(p, end - p, "%s(", namestr(args[0]->expr.args[0])); else p += bprintf(p, end - p, "<e>("); for (i = 1; i < nargs; i++) { et = tyfix(NULL, exprtype(args[i]), 1); if (et != NULL) t = tystr(et); else t = strdup("?"); if (exprop(args[i]) == Ovar) p += bprintf(p, end - p, "%s%s:%s", sep, namestr(args[i]->expr.args[0]), t); else p += bprintf(p, end - p, "%s<e%zd>:%s", sep, i, t); sep = ", "; free(t); } if (exprtype(args[0])->nsub) t = tystr(tyfix(NULL, exprtype(args[0])->sub[0], 1)); else t = strdup("unknown"); p += bprintf(p, end - p, "): %s", t); free(t); } static char * nodetystr(Node *n) { Type *t; t = NULL; if (n->type == Nexpr && exprtype(n) != NULL) t = tysearch(exprtype(n)); else if (n->type == Ndecl && decltype(n) != NULL) t = tysearch(decltype(n)); if (t && tybase(t)->type != Tyvar) return tystr(t); else return strdup("unknown"); } static void marksrc(Type *t, Srcloc l) { t = tf(t); if (t->tid >= nunifysrc) { unifysrc = zrealloc(unifysrc, nunifysrc*sizeof(Srcloc), (t->tid + 1)*sizeof(Srcloc)); nunifysrc = t->tid + 1; } if (unifysrc[t->tid].line <= 0) unifysrc[t->tid] = l; } static char * srcstr(Type *ty) { char src[128]; Srcloc l; char *s; src[0] = 0; if (nunifysrc > ty->tid && unifysrc[ty->tid].line > 0) { l = unifysrc[ty->tid]; s = tystr(ty); snprintf(src, sizeof src, "\n\t%s from %s:%d", s, fname(l), lnum(l)); free(s); } return strdup(src); } /* Tries to give a good string describing the context * for the sake of error messages. */ static char * ctxstr(Node *n) { char *t, *t1, *t2, *t3; char *s, *d; size_t nargs; Node **args; char buf[512]; if (!n) return strdup("???"); switch (n->type) { default: s = strdup(nodestr[n->type]); break; case Ndecl: d = declname(n); t = nodetystr(n); bprintf(buf, sizeof buf, "%s:%s", d, t); s = strdup(buf); free(t); break; case Nname: s = strdup(namestr(n)); break; case Nexpr: args = n->expr.args; nargs = n->expr.nargs; t1 = NULL; t2 = NULL; t3 = NULL; if (exprop(n) == Ovar) d = namestr(args[0]); else d = opstr[exprop(n)]; t = nodetystr(n); if (nargs >= 1) t1 = nodetystr(args[0]); if (nargs >= 2) t2 = nodetystr(args[1]); if (nargs >= 3) t3 = nodetystr(args[2]); switch (opclass[exprop(n)]) { case OTpre: bprintf(buf, sizeof buf, "%s<e:%s>", oppretty[exprop(n)], t1); break; case OTpost: bprintf(buf, sizeof buf, "<e:%s>%s", t1, oppretty[exprop(n)]); break; case OTzarg: bprintf(buf, sizeof buf, "%s", oppretty[exprop(n)]); break; case OTbin: bprintf(buf, sizeof buf, "<e1:%s> %s <e2:%s>", t1, oppretty[exprop(n)], t2); break; case OTmisc: switch (exprop(n)) { case Ovar: bprintf(buf, sizeof buf, "%s:%s", namestr(args[0]), t); break; case Ocall: ctxstrcall(buf, sizeof buf,n); break; case Oidx: if (exprop(args[0]) == Ovar) bprintf(buf, sizeof buf, "%s[<e1:%s>]", namestr(args[0]->expr.args[0]), t2); else bprintf(buf, sizeof buf, "<sl:%s>[<e1%s>]", t1, t2); break; case Oslice: if (exprop(args[0]) == Ovar) bprintf(buf, sizeof buf, "%s[<e1:%s>:<e2:%s>]", namestr(args[0]->expr.args[0]), t2, t3); else bprintf( buf, sizeof buf, "<sl:%s>[<e1%s>:<e2:%s>]", t1, t2, t3); break; case Omemb: bprintf(buf, sizeof buf, "<%s>.%s", t1, namestr(args[1])); break; case Otupmemb: bprintf(buf, sizeof buf, "<%s>.%llu", t1, args[1]->lit.intval); break; default: bprintf(buf, sizeof buf, "%s:%s", d, t); break; } break; default: bprintf(buf, sizeof buf, "%s", d); break; } free(t); free(t1); free(t2); free(t3); s = strdup(buf); break; } return s; } static void addspecialization(Node *n, Stab *stab) { Node *dcl; dcl = decls[n->expr.did]; lappend(&specializationscope, &nspecializationscope, stab); lappend(&specializations, &nspecializations, n); lappend(&genericdecls, &ngenericdecls, dcl); } static void adddispspecialization(Node *n, Stab *stab) { Trait *tr; Type *ty; tr = traittab[Tcdisp]; ty = exprtype(n); assert(tr->nproto == 1); if (hthas(tr->proto[0]->decl.impls, ty)) return; lappend(&specializationscope, &nspecializationscope, stab); lappend(&specializations, &nspecializations, n); lappend(&genericdecls, &ngenericdecls, tr->proto[0]); } static void additerspecialization(Node *n, Stab *stab) { Trait *tr; Type *ty; size_t i; tr = traittab[Tciter]; ty = exprtype(n->iterstmt.seq); if (ty->type == Tyslice || ty->type == Tyarray || ty->type == Typtr) return; ty = tyfreshen(NULL, ty); for (i = 0; i < tr->nproto; i++) { ty = exprtype(n->iterstmt.seq); if (hthas(tr->proto[i]->decl.impls, ty)) continue; lappend(&specializationscope, &nspecializationscope, stab); lappend(&specializations, &nspecializations, n); lappend(&genericdecls, &ngenericdecls, tr->proto[i]); } } static void delayedcheck(Node *n) { Postcheck *pc; pc = xalloc(sizeof(Postcheck)); pc->node = n; pc->stab = curstab(); pc->env = curenv(); lappend(&postcheck, &npostcheck, pc); } static void typeerror(Type *a, Type *b, Node *ctx, char *msg) { char *t1, *t2, *s1, *s2, *c; t1 = tystr(tyfix(NULL, a, 1)); t2 = tystr(tyfix(NULL, b, 1)); s1 = srcstr(a); s2 = srcstr(b); c = ctxstr(ctx); if (msg) fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s: %s%s%s", t1, t2, c, msg, s1, s2); else fatal(ctx, "type \"%s\" incompatible with \"%s\" near %s%s%s", t1, t2, c, s1, s2); free(t1); free(t2); free(s1); free(s2); free(c); } /* Set a scope's enclosing scope up correctly. */ static void setsuperenv(Tyenv *e, Tyenv *super) { if (e) e->super = super; } /* Set a scope's enclosing scope up correctly. */ static void setsuper(Stab *st, Stab *super) { Stab *s; /* verify that we don't accidentally create loops */ for (s = super; s; s = s->super) assert(s->super != st); st->super = super; } /* Checks if a type that directly contains itself. * Recursive types that contain themselves through * pointers or slices are fine, but any other self-inclusion * would lead to a value of infinite size */ static int occurs_rec(Type *sub, Bitset *bs) { size_t i; sub = tf(sub); if (bshas(bs, sub->tid)) return 1; bsput(bs, sub->tid); switch (sub->type) { case Typtr: case Tyslice: break; case Tystruct: for (i = 0; i < sub->nmemb; i++) if (occurs_rec(decltype(sub->sdecls[i]), bs)) return 1; break; case Tyunion: for (i = 0; i < sub->nmemb; i++) { if (!sub->udecls[i]->etype) continue; if (occurs_rec(sub->udecls[i]->etype, bs)) return 1; } break; default: for (i = 0; i < sub->nsub; i++) if (occurs_rec(sub->sub[i], bs)) return 1; break; } bsdel(bs, sub->tid); return 0; } static int occursin(Type *a, Type *b) { Bitset *bs; int r; bs = mkbs(); a = tf(a); bsput(bs, a->tid); r = occurs_rec(b, bs); bsfree(bs); return r; } static int occurs(Type *t) { Bitset *bs; int r; bs = mkbs(); r = occurs_rec(t, bs); bsfree(bs); return r; } static int needfreshenrec(Type *t, Bitset *visited) { size_t i; t = tysearch(t); if (bshas(visited, t->tid)) return 0; bsput(visited, t->tid); switch (t->type) { case Typaram: return 1; case Tygeneric: return 1; case Tyname: for (i = 0; i < t->narg; i++) if (needfreshenrec(t->arg[i], visited)) return 1; return needfreshenrec(t->sub[0], visited); case Tystruct: for (i = 0; i < t->nmemb; i++) if (needfreshenrec(decltype(t->sdecls[i]), visited)) return 1; break; case Tyunion: for (i = 0; i < t->nmemb; i++) if (t->udecls[i]->etype && needfreshenrec(t->udecls[i]->etype, visited)) return 1; break; default: for (i = 0; i < t->nsub; i++) if (needfreshenrec(t->sub[i], visited)) return 1; break; } return 0; } static int needfreshen(Type *t) { Bitset *visited; int ret; visited = mkbs(); ret = needfreshenrec(t, visited); bsfree(visited); return ret; } /* Freshens the type of a declaration. */ static Type * tyfreshen(Tysubst *subst, Type *orig) { Type *ty, *base; if (!needfreshen(orig)) return orig; pushenv(orig->env); if (!subst) { subst = mksubst(); ty = tyspecialize(orig, subst, delayed); substfree(subst); } else { ty = tyspecialize(orig, subst, delayed); } ty->spec = orig->spec; ty->nspec = orig->nspec; base = basetype(ty); if (base) ty->seqaux = base; popenv(orig->env); return ty; } /* Resolves a type and all its subtypes recursively. */ static void tyresolve(Type *t)