Charles.Forsyth20080201-190845629f718 years agoHistory
3635 lines · 73.7 KB · C
RawDownload
#include "limbo.h"#include "y.tab.h" Node	**labstack;int	labdep;static Node* inexcept;static Decl* fndec; void checkraises(Node *n); static voidincrefs(Decl *id){	for( ; id != nil; id = id->link)		id->refs++;} static intfninline(Decl *d){	Node *n, *left, *right; 	left = right = nil;	n = d->init;	if(dontinline || d->caninline < 0 || d->locals != nil || ispoly(d) || n->ty->tof->kind == Tnone || nodes(n) >= 100)		return 0;	n = n->right;	if(n->op == Oseq && n->right == nil)		n = n->left;	/* 	  *	inline	  *		(a) return e;	  *		(b) if(c) return e1; else return e2;	  *		(c) if(c) return e1; return e2;	  */	switch(n->op){	case Oret:		break;	case Oif:		right = n->right;		if(right->right == nil || right->left->op != Oret || right->right->op != Oret || !tequal(right->left->left->ty, right->right->left->ty))			return 0;		break;	case Oseq:		left = n->left;		right = n->right;		if(left->op != Oif || left->right->right != nil || left->right->left->op != Oret || right->op != Oseq || right->right != nil || right->left->op != Oret || !tequal(left->right->left->left->ty, right->left->left->ty))			return 0;		break;	default:		return 0;	}	if(occurs(d, n) || hasasgns(n))		return 0;	if(n->op == Oseq){		left->right->right = right->left;		n = left;		right = n->right;		d->init->right->right = nil;	}	if(n->op == Oif){		n->ty = right->ty = right->left->left->ty;		right->left = right->left->left;		right->right = right->right->left;		d->init->right->left = mkunary(Oret, n);	}	return 1;} static intisfnrefty(Type *t){	return t->kind == Tref && t->tof->kind == Tfn;} static intisfnref(Decl *d){	switch(d->store){	case Dglobal:	case Darg:	case Dlocal:	case Dfield:	case Dimport:		return isfnrefty(d->ty);	}	return 0;} intargncompat(Node *n, Decl *f, Node *a){	for(; a != nil; a = a->right){		if(f == nil){			nerror(n, "%V: too many function arguments", n->left);			return 0;		}		f = f->next;	}	if(f != nil){		nerror(n, "%V: too few function arguments", n->left);		return 0;	}	return 1;} static voidrewind(Node *n){	Node *r, *nn; 	r = n;	nn = n->left;	for(n = n->right; n != nil; n = n->right){		if(n->right == nil){			r->left = nn;			r->right = n->left;		}		else			nn = mkbin(Oindex, nn, n->left);	}} static voidckmod(Node *n, Decl *id){	Type *t;	Decl *d, *idc;	Node *mod; 	if(id == nil)		fatal("can't find function: %n", n);	idc = nil;	mod = nil;	if(n->op == Oname){		idc = id;		mod = id->eimport;	}	else if(n->op == Omdot)		mod = n->left;	else if(n->op == Odot){		idc = id->dot;		t = n->left->ty;		if(t->kind == Tref)			t = t->tof;		if(t->kind == Tadtpick)			t = t->decl->dot->ty;		d = t->decl;		while(d != nil && d->link != nil)			d = d->link;		if(d != nil && d->timport != nil)			mod = d->timport->eimport;		n->right->left = mod;	}	if(mod != nil && mod->ty->kind != Tmodule){		nerror(n, "cannot use %V as a function reference", n);		return;	}	if(mod != nil){		if(valistype(mod)){			nerror(n, "cannot use %V as a function reference because %V is a module interface", n, mod);			return;		}	}else if(idc != nil && idc->dot != nil && !isimpmod(idc->dot->sym)){		nerror(n, "cannot use %V without importing %s from a variable", n, idc->sym->name);		return;	}	if(mod != nil)		modrefable(n->ty);} static voidaddref(Node *n){	Node *nn; 	nn = mkn(0, nil, nil);	*nn = *n;	n->op = Oref;	n->left = nn;	n->right = nil;	n->decl = nil;	n->ty = usetype(mktype(&n->src.start, &n->src.stop, Tref, nn->ty, nil));} static voidfnref(Node *n, Decl *id){	id->caninline = -1;	ckmod(n, id);	addref(n);	while(id->link != nil)		id = id->link;	if(ispoly(id) && encpolys(id) != nil)		nerror(n, "cannot have a polymorphic adt function reference %s", id->sym->name);} Decl*typecheck(int checkimp){	Decl *entry, *m, *d;	Sym *s;	int i; 	if(errors)		return nil; 	/*	 * generate the set of all functions	 * compile one function at a time	 */	gdecl(tree);	gbind(tree);	fns = allocmem(nfns * sizeof(Decl));	i = gcheck(tree, fns, 0);	if(i != nfns)		fatal("wrong number of functions found in gcheck"); 	maxlabdep = 0;	for(i = 0; i < nfns; i++){		d = fns[i];		if(d != nil)			fndec = d;		if(d != nil)			fncheck(d);		fndec = nil;	} 	if(errors)		return nil; 	entry = nil;	if(checkimp){		Decl *im;		Dlist *dm; 		if(impmods == nil){			yyerror("no implementation module");			return nil;		}		for(im = impmods; im != nil; im = im->next){			for(dm = impdecls; dm != nil; dm = dm->next)				if(dm->d->sym == im->sym)					break;			if(dm == nil || dm->d->ty == nil){				yyerror("no definition for implementation module %s", im->sym->name);				return nil;			}		}			/*		 * can't check the module spec until all types and imports are determined,		 * which happens in scheck		 */		for(dm = impdecls; dm != nil; dm = dm->next){			im = dm->d;			im->refs++;			im->ty = usetype(im->ty);			if(im->store != Dtype || im->ty->kind != Tmodule){				error(im->src.start, "cannot implement %K", im);				return nil;			}		}			/* now check any multiple implementations */		impdecl = modimp(impdecls, impmods); 		s = enter("init", 0);		entry = nil;		for(dm = impdecls; dm != nil; dm = dm->next){			im = dm->d;			for(m = im->ty->ids; m != nil; m = m->next){				m->ty = usetype(m->ty);				m->refs++;					if(m->sym == s && m->ty->kind == Tfn && entry == nil)					entry = m;					if(m->store == Dglobal || m->store == Dfn)					modrefable(m->ty);					if(m->store == Dtype && m->ty->kind == Tadt){					for(d = m->ty->ids; d != nil; d = d->next){						d->ty = usetype(d->ty);						modrefable(d->ty);						d->refs++;					}				}			}			checkrefs(im->ty->ids);		}	} 	if(errors)		return nil;	gsort(tree);	tree = nil;	return entry;}	/* * introduce all global declarations * also adds all fields to adts and modules * note the complications due to nested Odas expressions */voidgdecl(Node *n){	for(;;){		if(n == nil)			return;		if(n->op != Oseq)			break;		gdecl(n->left);		n = n->right;	}	switch(n->op){	case Oimport:		importdecled(n);		gdasdecl(n->right);		break;	case Oadtdecl:		adtdecled(n);		break;	case Ocondecl:		condecled(n);		gdasdecl(n->right);		break;	case Oexdecl:		exdecled(n);		break;	case Omoddecl:		moddecled(n);		break;	case Otypedecl:		typedecled(n);		break;	case Ovardecl:		vardecled(n);		break;	case Ovardecli:		vardecled(n->left);		gdasdecl(n->right);		break;	case Ofunc:		fndecled(n);		break;	case Oas:	case Odas:	case Onothing:		gdasdecl(n);		break;	default:		fatal("can't deal with %O in gdecl", n->op);	}} /* * bind all global type ids, * including those nested inside modules * this needs to be done, since we may use such * a type later in a nested scope, so if we bound * the type ids then, the type could get bound * to a nested declaration */voidgbind(Node *n){	Decl *d, *ids; 	for(;;){		if(n == nil)			return;		if(n->op != Oseq)			break;		gbind(n->left);		n = n->right;	}	switch(n->op){	case Oas:	case Ocondecl:	case Odas:	case Oexdecl:	case Ofunc:	case Oimport:	case Onothing:	case Ovardecl:	case Ovardecli:		break;	case Ofielddecl:		bindtypes(n->decl->ty);		break;	case Otypedecl:		bindtypes(n->decl->ty);		if(n->left != nil)			gbind(n->left);		break;	case Opickdecl:		gbind(n->left);		d = n->right->left->decl;		bindtypes(d->ty);		repushids(d->ty->ids);		gbind(n->right->right);		/* get new ids for undefined types; propagate outwards */		ids = popids(d->ty->ids);		if(ids != nil)			installids(Dundef, ids);		break;	case Oadtdecl:	case Omoddecl:		bindtypes(n->ty);		if(n->ty->polys != nil)			repushids(n->ty->polys);		repushids(n->ty->ids);		gbind(n->left);		/* get new ids for undefined types; propagate outwards */		ids = popids(n->ty->ids);		if(ids != nil)			installids(Dundef, ids);		if(n->ty->polys != nil)			popids(n->ty->polys);		break;	default:		fatal("can't deal with %O in gbind", n->op);	}} /* * check all of the > declarations * bind all type ids referred to within types at the global level * record decls for defined functions */intgcheck(Node *n, Decl **fns, int nfns){	Ok rok;	Decl *d; 	for(;;){		if(n == nil)			return nfns;		if(n->op != Oseq)			break;		nfns = gcheck(n->left, fns, nfns);		n = n->right;	} 	switch(n->op){	case Ofielddecl:		if(n->decl->ty->u.eraises)			raisescheck(n->decl->ty);		break;	case Onothing:	case Opickdecl:		break;	case Otypedecl:		tcycle(n->ty);		break;	case Oadtdecl:	case Omoddecl:		if(n->ty->polys != nil)			repushids(n->ty->polys);		repushids(n->ty->ids);		if(gcheck(n->left, nil, 0))			fatal("gcheck fn decls nested in modules or adts");		if(popids(n->ty->ids) != nil)			fatal("gcheck installs new ids in a module or adt");		if(n->ty->polys != nil)			popids(n->ty->polys);		break;	case Ovardecl:		varcheck(n, 1);		break;	case Ocondecl:		concheck(n, 1);		break;	case Oexdecl:		excheck(n, 1);		break;	case Oimport:		importcheck(n, 1);		break;	case Ovardecli:		varcheck(n->left, 1);		rok = echeck(n->right, 0, 1, nil);		if(rok.ok){			if(rok.allok)				n->right = fold(n->right);			globalas(n->right->left, n->right->right, rok.allok);		}		break;	case Oas:	case Odas:		rok = echeck(n, 0, 1, nil);		if(rok.ok){			if(rok.allok)				n = fold(n);			globalas(n->left, n->right, rok.allok);		}		break;

Lines 1–500 of 3635.