forsyth20121205-174063a80cc13 years agoHistory
1367 lines · 24.2 KB · C
RawDownload
#include "limbo.h" char *storename[Dend]={	/* Dtype */	"type",	/* Dfn */	"function",	/* Dglobal */	"global",	/* Darg */	"argument",	/* Dlocal */	"local",	/* Dconst */	"con",	/* Dfield */	"field",	/* Dtag */	"pick tag",	/* Dimport */	"import",	/* Dunbound */	"unbound",	/* Dundef */	"undefined",	/* Dwundef */	"undefined",}; char *storeart[Dend] ={	/* Dtype */	"a ",	/* Dfn */	"a ",	/* Dglobal */	"a ",	/* Darg */	"an ",	/* Dlocal */	"a ",	/* Dconst */	"a ",	/* Dfield */	"a ",	/* Dtag */	"a",	/* Dimport */	"an ",	/* Dunbound */	"",	/* Dundef */	"",	/* Dwundef */	"",}; int storespace[Dend] ={	/* Dtype */	0,	/* Dfn */	0,	/* Dglobal */	1,	/* Darg */	1,	/* Dlocal */	1,	/* Dconst */	0,	/* Dfield */	1,	/* Dtag */	0,	/* Dimport */	0,	/* Dunbound */	0,	/* Dundef */	0,	/* Dwundef */	0,}; static	Decl	*scopes[MaxScope];static	Decl	*tails[MaxScope];static	Node *scopenode[MaxScope];static	uchar scopekind[MaxScope];static	Decl	zdecl; static	void	freeloc(Decl*); voidpopscopes(void){	Decl *d;	Dlist *id; 	/*	 * clear out any decls left in syms	 */	while(scope >= ScopeBuiltin){		for(d = scopes[scope--]; d != nil; d = d->next){			if(d->sym != nil){				d->sym->decl = d->old;				d->old = nil;			}		}	} 	for(id = impdecls; id != nil; id = id->next){		for(d = id->d->ty->ids; d != nil; d = d->next){			d->sym->decl = nil;			d->old = nil;		}	}	impdecls = nil; 	scope = ScopeBuiltin;	scopes[ScopeBuiltin] = nil;	tails[ScopeBuiltin] = nil;} voiddeclstart(void){	Decl *d; 	iota = mkids(&nosrc, enter("iota", 0), tint, nil);	iota->init = mkconst(&nosrc, 0); 	scope = ScopeNils;	scopes[ScopeNils] = nil;	tails[ScopeNils] = nil; 	nildecl = mkdecl(&nosrc, Dglobal, tany);	nildecl->sym = enter("nil", 0);	installids(Dglobal, nildecl);	d = mkdecl(&nosrc, Dglobal, tstring);	d->sym = enter("", 0);	installids(Dglobal, d); 	scope = ScopeGlobal;	scopes[ScopeGlobal] = nil;	tails[ScopeGlobal] = nil;} voidredecl(Decl *d){	Decl *old; 	old = d->sym->decl;	if(old->store == Dwundef)		return;	error(d->src.start, "redeclaration of %K, previously declared as %k on line %L",		d, old, old->src.start);} voidcheckrefs(Decl *d){	Decl *id, *m;	long refs; 	for(; d != nil; d = d->next){		if(d->das)			d->refs--;		switch(d->store){		case Dtype:			refs = d->refs;			if(d->ty->kind == Tadt){				for(id = d->ty->ids; id != nil; id = id->next){					d->refs += id->refs;					if(id->store != Dfn)						continue;					if(id->init == nil && id->link == nil && d->importid == nil)						error(d->src.start, "function %s.%s not defined", d->sym->name, id->sym->name);					if(superwarn && !id->refs && d->importid == nil)						warn(d->src.start, "function %s.%s not referenced", d->sym->name, id->sym->name);				}			}			if(d->ty->kind == Tmodule){				for(id = d->ty->ids; id != nil; id = id->next){					refs += id->refs;					if(id->iface != nil)						id->iface->refs += id->refs;					if(id->store == Dtype){						for(m = id->ty->ids; m != nil; m = m->next){							refs += m->refs;							if(m->iface != nil)								m->iface->refs += m->refs;						}					}				}				d->refs = refs;			}			if(superwarn && !refs && d->importid == nil)				warn(d->src.start, "%K not referenced", d);			break;		case Dglobal:			if(!superwarn)				break;		case Dlocal:		case Darg:			if(!d->refs && d->sym != nil			&& d->sym->name != nil && d->sym->name[0] != '.')				warn(d->src.start, "%K not referenced", d);			break;		case Dconst:			if(superwarn && !d->refs && d->sym != nil)				warn(d->src.start, "%K not referenced", d);			if(d->ty == tstring && d->init != nil)				d->init->decl->refs += d->refs;			break;		case Dfn:			if(d->init == nil && d->importid == nil)				error(d->src.start, "%K not defined", d);			if(superwarn && !d->refs)				warn(d->src.start, "%K not referenced", d);			break;		case Dimport:			if(superwarn && !d->refs)				warn(d->src.start, "%K not referenced", d);			break;		}		if(d->das)			d->refs++;	}} Node*vardecl(Decl *ids, Type *t){	Node *n; 	n = mkn(Ovardecl, mkn(Oseq, nil, nil), nil);	n->decl = ids;	n->ty = t;	return n;} voidvardecled(Node *n){	Decl *ids, *last;	Type *t;	int store; 	store = Dlocal;	if(scope == ScopeGlobal)		store = Dglobal;	if(n->ty->kind == Texception && n->ty->cons){		store = Dconst;		fatal("Texception in vardecled");	}	ids = n->decl;	installids(store, ids);	t = n->ty;	for(last = ids; ids != nil; ids = ids->next){		ids->ty = t;		last = ids;	}	n->left->decl = last;} Node*condecl(Decl *ids, Node *init){	Node *n; 	n = mkn(Ocondecl, mkn(Oseq, nil, nil), init);	n->decl = ids;	return n;} voidcondecled(Node *n){	Decl *ids, *last; 	ids = n->decl;	installids(Dconst, ids);	for(last = ids; ids != nil; ids = ids->next){		ids->ty = tunknown;		last = ids;	}	n->left->decl = last;} Node*exdecl(Decl *ids, Decl *tids){	Node *n;	Type *t; 	t = mktype(&ids->src.start, &ids->src.stop, Texception, nil, tids);	t->cons = 1;	n = mkn(Oexdecl, mkn(Oseq, nil, nil), nil);	n->decl = ids;	n->ty = t;	return n;} voidexdecled(Node *n){	Decl *ids, *last;	Type *t; 	ids = n->decl;	installids(Dconst, ids);	t = n->ty;	for(last = ids; ids != nil; ids = ids->next){		ids->ty = t;		last = ids;	}	n->left->decl = last;} Node*importdecl(Node *m, Decl *ids){	Node *n; 	n = mkn(Oimport, mkn(Oseq, nil, nil), m);	n->decl = ids;	return n;} voidimportdecled(Node *n){	Decl *ids, *last; 	ids = n->decl;	installids(Dimport, ids);	for(last = ids; ids != nil; ids = ids->next){		ids->ty = tunknown;		last = ids;	}	n->left->decl = last;} Node*mkscope(Node *body){	Node *n; 	n = mkn(Oscope, nil, body);	if(body != nil)		n->src = body->src;	return n;} Node*fndecl(Node *n, Type *t, Node *body){	n = mkbin(Ofunc, n, body);	n->ty = t;	return n;} voidfndecled(Node *n){	Decl *d;	Node *left; 	left = n->left;	if(left->op == Oname){		d = left->decl->sym->decl;		if(d == nil || d->store == Dimport){			d = mkids(&left->src, left->decl->sym, n->ty, nil);			installids(Dfn, d);		}		left->decl = d;		d->refs++;	}	if(left->op == Odot)		pushscope(nil, Sother);	if(n->ty->polys != nil){		pushscope(nil, Sother);		installids(Dtype, n->ty->polys);	}	pushscope(nil, Sother);	installids(Darg, n->ty->ids);	n->ty->ids = popscope();	if(n->ty->val != nil)		mergepolydecs(n->ty);	if(n->ty->polys != nil)		n->ty->polys = popscope();	if(left->op == Odot)		popscope();} /* * check the function declaration only * the body will be type checked later by fncheck */Decl *fnchk(Node *n){	int bad;	Decl *d, *inadt, *adtp;	Type *t; 	bad = 0;	d = n->left->decl;	if(n->left->op == Odot)		d = n->left->right->decl;	if(d == nil)		fatal("decl() fnchk nil");	n->left->decl = d;	if(d->store == Dglobal || d->store == Dfield)		d->store = Dfn;	if(d->store != Dfn || d->init != nil){		nerror(n, "redeclaration of function %D, previously declared as %k on line %L",			d, d, d->src.start);		if(d->store == Dfn && d->init != nil)			bad = 1;	}	d->init = n; 	t = n->ty;	inadt = d->dot;	if(inadt != nil && (inadt->store != Dtype || inadt->ty->kind != Tadt))		inadt = nil;	if(n->left->op == Odot){		pushscope(nil, Sother);		adtp = outerpolys(n->left);		if(adtp != nil)			installids(Dtype, adtp);		if(!polyequal(adtp, n->decl))			nerror(n, "adt polymorphic type mismatch");		n->decl = nil;	}	t = validtype(t, inadt);	if(n->left->op == Odot)		popscope();	if(debug['d'])		print("declare function %D ty %T newty %T\n", d, d->ty, t);	t = usetype(t); 	if(!polyequal(d->ty->polys, t->polys))		nerror(n, "function polymorphic type mismatch");	if(!tcompat(d->ty, t, 0))		nerror(n, "type mismatch: %D defined as %T declared as %T on line %L",			d, t, d->ty, d->src.start);	else if(!raisescompat(d->ty->u.eraises, t->u.eraises))		nerror(n, "raises mismatch: %D", d);	if(t->varargs != 0)		nerror(n, "cannot define functions with a '*' argument, such as %D", d); 	t->u.eraises = d->ty->u.eraises; 	d->ty = t;	d->offset = idoffsets(t->ids, MaxTemp, IBY2WD);	d->src = n->src; 	d->locals = nil; 	n->ty = t; 	return bad ? nil: d;} Node*globalas(Node *dst, Node *v, int valok){	Node *tv; 	if(v == nil)		return nil;	if(v->op == Oas || v->op == Odas){		v = globalas(v->left, v->right, valok);		if(v == nil)			return nil;	}else if(valok && !initable(dst, v, 0))		return nil;	switch(dst->op){	case Oname:		if(dst->decl->init != nil)			nerror(dst, "duplicate assignment to %V, previously assigned on line %L",				dst, dst->decl->init->src.start);		if(valok)			dst->decl->init = v;		return v;	case Otuple:		if(valok && v->op != Otuple)			fatal("can't deal with %n in tuple case of globalas", v);		tv = v->left;		for(dst = dst->left; dst != nil; dst = dst->right){			globalas(dst->left, tv->left, valok);			if(valok)				tv = tv->right;		}		return v;	}	fatal("can't deal with %n in globalas", dst);	return nil;} intneedsstore(Decl *d){	if(!d->refs)		return 0;	if(d->importid != nil)		return 0;	if(storespace[d->store])		return 1;	return 0;} /* * return the list of all referenced storage variables */Decl*vars(Decl *d){	Decl *v, *n; 	while(d != nil && !needsstore(d))		d = d->next;	for(v = d; v != nil; v = v->next){		while(v->next != nil){			n = v->next;			if(needsstore(n))				break;			v->next = n->next;		}	}	return d;

Lines 1–500 of 1367.