1173 lines · 24.0 KB · C
RawDownload
#include <assert.h>#include <stdlib.h>#include <stdio.h>#include <stdarg.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 "util.h"#include "parse.h" typedef struct Typename Typename;typedef struct Typair Typair;Type **tytab = NULL;Type **types = NULL;size_t ntypes;Trait **traittab;size_t ntraittab;Node **impltab;size_t nimpltab;Htab *eqcache; struct Typair {	uint32_t atid;	uint32_t btid;};	 static Htab *tydeduptab;/* Built in type constraints */static int tybfmt(char *buf, size_t len, Bitset *visted, Type *t); char stackness[] = {#define Ty(t, n, stk) stk,#include "types.def"#undef Ty}; intisstacktype(Type *t){	t = tybase(t);	if (t->type == Tyunion)		return !isenum(t);	return stackness[t->type];} intisenum(Type *t){	size_t i;	char isenum; 	assert(t->type == Tyunion); 	/* t->isenum is lazily set:	 * a value of 0 means that it was not computed,	 * a value of 1 means that the type is an enum	 * (i.e., it only has nullary constructors)	 * a value of 2 means that the type is not an enum	 */	if (t->isenum == 0) {		/* initialize it */		isenum = 1;		for (i = 0; i < t->nmemb; i++)			if (t->udecls[i]->etype) {				isenum = 2;				break;			}		t->isenum = isenum;	}	return t->isenum == 1;} Type *tydedup(Type *ty){	Type *had; 	had = htget(tydeduptab, ty);	if (!had) {		htput(tydeduptab, ty, ty);		return ty;	}	/* if one is emitted, both are */	ty->isemitted = ty->isemitted || had->isemitted;	return had;} Type *mktype(Srcloc loc, Ty ty){	Type *t; 	/* the first 'n' types will be identity mapped: tytab[Tyint], eg,	 * will map to an instantitaion of Tyint.	 *	 * This is accomplished at program startup by calling mktype() on	 * each builtin type in order. As we do this, we put the type into	 * the table as ususal, which gives us an identity mapping.	 */	if (ty <= Tyvalist && ty < ntypes)		return types[ty]; 	t = zalloc(sizeof(Type));	t->type = ty;	t->tid = ntypes++;	t->loc = loc;	tytab = xrealloc(tytab, ntypes * sizeof(Type *));	tytab[t->tid] = NULL;	types = xrealloc(types, ntypes * sizeof(Type *));	types[t->tid] = t;	if (ty <= Tyvalist) /* the last builtin atomic type */		t->vis = Visbuiltin; 	return t;} /* * Shallowly duplicates a type, so we can frob * its internals later */Type *tydup(Type *t){	Type *r; 	r = mktype(t->loc, t->type);	r->resolved = 0;	/* re-resolving doesn't hurt */	r->fixed = 0;		/* re-resolving doesn't hurt */ 	r->arg = memdup(t->arg, t->narg * sizeof(Type *));	r->narg = t->narg;	r->inst = memdup(t->arg, t->narg * sizeof(Type *));	r->ninst = t->ninst; 	r->sub = memdup(t->sub, t->nsub * sizeof(Type *));	r->nsub = t->nsub;	r->nmemb = t->nmemb;	switch (t->type) {	case Tyname:	r->name = t->name;	break;	case Tyunres:	r->name = t->name;	break;	case Tyarray:	r->asize = t->asize;	break;	case Typaram:	r->pname = strdup(t->pname);	break;	case Tystruct:	r->sdecls = memdup(t->sdecls, t->nmemb * sizeof(Node *));	break;	case Tyunion:	r->udecls = memdup(t->udecls, t->nmemb * sizeof(Node *));	break;	default: break;	}	return r;} /* steals memb, funcs */Trait *mktrait(Srcloc loc, Node *name, Type *param,	Type **aux, size_t naux,	Node **proto, size_t nproto,	int isproto){	Trait *t;	size_t i; 	t = zalloc(sizeof(Trait));	t->uid = ntraittab++;	t->loc = loc;	if (t->uid < Ntraits)		t->vis = Visbuiltin;	t->vis = Visintern;	t->name = name;	t->param = param;	t->proto = proto;	t->nproto = nproto;	t->aux = aux;	t->env = mkenv();	t->naux = naux;	t->isproto = isproto; 	bindtype(t->env, param);	for (i = 0; i < naux; i++)		bindtype(t->env, aux[i]); 	for (i = 0; i < nproto; i++)		if (proto[i]->decl.env)			proto[i]->decl.env->super = t->env;  	traittab = xrealloc(traittab, ntraittab * sizeof(Trait *));	traittab[t->uid] = t;	return t;} Type *mktyvar(Srcloc loc){	Type *t; 	t = mktype(loc, Tyvar);	return t;} Type *mktyparam(Srcloc loc, char *name){	Type *t; 	t = mktype(loc, Typaram);	t->pname = strdup(name);	return t;} Type *mktyunres(Srcloc loc, Node *name, Type **arg, size_t narg){	size_t i;	Type *t; 	/* resolve it in the type inference stage */	t = mktype(loc, Tyunres);	t->name = name;	t->arg = arg;	t->narg = narg;	t->env = mkenv();	for (i = 0; i < narg; i++)		bindtype(t->env, arg[i]);	return t;} Type *mktygeneric(Srcloc loc, Node *name, Type **param, size_t nparam, Type *base){	Type *t;	int i; 	t = mktype(loc, Tygeneric);	t->name = name;	t->nsub = 1;	t->sub = xalloc(sizeof(Type *));	t->sub[0] = base;	t->gparam = param;	t->ngparam = nparam;	t->env = mkenv();	for (i = 0; i < nparam; i++)		bindtype(t->env, param[i]);	if (!base->env)		base->env = t->env;	return t;} Type *mktyname(Srcloc loc, Node *name, Type *base){	Type *t; 	t = mktype(loc, Tyname);	t->name = name;	t->nsub = 1;	t->sub = xalloc(sizeof(Type *));	t->sub[0] = base;	return t;} Type *mktyarray(Srcloc loc, Type *base, Node *sz){	Type *t; 	t = mktype(loc, Tyarray);	t->nsub = 1;	t->nmemb = 1; /* the size is a "member" */	t->sub = xalloc(sizeof(Type *));	t->sub[0] = base;	t->asize = sz; 	return t;} Type *mktyslice(Srcloc loc, Type *base){	Type *t; 	t = mktype(loc, Tyslice);	t->nsub = 1;	t->sub = xalloc(sizeof(Type *));	t->sub[0] = base;	return t;} Type *mktyptr(Srcloc loc, Type *base){	Type *t; 	t = mktype(loc, Typtr);	t->nsub = 1;	t->sub = xalloc(sizeof(Type *));	t->sub[0] = base;	return t;} Type *mktytuple(Srcloc loc, Type **sub, size_t nsub){	Type *t;	size_t i; 	t = mktype(loc, Tytuple);	t->nsub = nsub;	t->sub = xalloc(nsub * sizeof(Type *));	for (i = 0; i < nsub; i++)		t->sub[i] = sub[i];	return t;} Type *mktyfunc(Srcloc loc, Node **args, size_t nargs, Type *ret){	Type *t;	size_t i; 	t = mktype(loc, Tyfunc);	t->nsub = nargs + 1;	t->sub = xalloc((1 + nargs) * sizeof(Type *));	t->sub[0] = ret;	t->env = mkenv();	for (i = 0; i < nargs; i++)		t->sub[i + 1] = nodetype(args[i]);	for (i = 0; i < t->nsub; i++)		bindtype(t->env, t->sub[i]);	return t;} Type *mktystruct(Srcloc loc, Node **decls, size_t ndecls){	Type *t;	Htab *ht;	int i;	char *s; 	t = mktype(loc, Tystruct);	t->nsub = 0;	t->nmemb = ndecls; 	ht = mkht(strhash, streq);	for (i = 0; i < ndecls; i++) {		s = declname(decls[i]);		if (hthas(ht, s))			fatal(decls[i], "duplicate struct member %s\n", declname(decls[i]));		htput(ht, s, s);	}	htfree(ht); 	t->sdecls = memdup(decls, ndecls * sizeof(Node *));	return t;} Type *mktyunion(Srcloc loc, Ucon **decls, size_t ndecls){	Type *t; 	t = mktype(loc, Tyunion);	t->nmemb = ndecls;	t->udecls = decls;	return t;} Ucon *finducon(Type *ty, Node *name){	size_t i; 	ty = tybase(ty);	for (i = 0; i < ty->nmemb; i++)		if (!strcmp(namestr(ty->udecls[i]->name), namestr(name)))			return ty->udecls[i];	return NULL;} intistyunsigned(Type *t){	switch (tybase(t)->type) {	case Tybyte:	case Tyuint8:	case Tyuint16:	case Tyuint:	case Tychar:	case Tyuint32:	case Tyuint64:	case Tybool: return 1;	default: return 0;	}} intistysigned(Type *t){	switch (tybase(t)->type) {	case Tyint8:	case Tyint16:	case Tyint:	case Tyint32:	case Tyint64: return 1;	default: return 0;	}} intistyint(Type *t){	return istysigned(t) || istyunsigned(t);}  intistyfloat(Type *t){	t = tybase(t);	return t->type == Tyflt32 || t->type == Tyflt64;} intistyprimitive(Type *t) { return istysigned(t) || istyunsigned(t) || istyfloat(t); } /* * Checks if a type contains any type * parameers at all (ie, if it generic). */inthasparamsrec(Type *t, Bitset *visited){	size_t i; 	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 (hasparamsrec(t->arg[i], visited))				return 1;		return hasparamsrec(t->sub[0], visited);	case Tyunres:		for (i = 0; i < t->narg; i++)			if (hasparamsrec(t->arg[i], visited))				return 1;		break;	case Tystruct:		for (i = 0; i < t->nmemb; i++)			if (hasparamsrec(t->sdecls[i]->decl.type, visited))				return 1;		break;	case Tyunion:		for (i = 0; i < t->nmemb; i++)			if (t->udecls[i]->etype && hasparamsrec(t->udecls[i]->etype, visited))				return 1;		break;	default:		for (i = 0; i < t->nsub; i++)			if (hasparamsrec(t->sub[i], visited))				return 1;		break;	}	return 0;} inthasparams(Type *t){	Bitset *visited; 	if (t->hasparams)		return 1;	visited = mkbs();	t->hasparams = hasparamsrec(t, visited);	bsfree(visited);	return t->hasparams;} Type *tybase(Type *t){	assert(t != NULL);	while (t->type == Tyname || t->type == Tygeneric)		t = t->sub[0];	return t;} static intnamefmt(char *buf, size_t len, Node *n){	char *p;

Lines 1–500 of 1173.