1177 lines · 22.5 KB · Brainfuck
RawDownload
 storename := array[Dend] of{	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",}; storeart := array[Dend] of{	Dtype =>	"a ",	Dfn =>		"a ",	Dglobal =>	"a ",	Darg =>		"an ",	Dlocal =>	"a ",	Dconst =>	"a ",	Dfield =>	"a ",	Dtag =>		"a ",	Dimport =>	"an ",	Dunbound =>	"",	Dundef =>	"",	Dwundef =>	"",}; storespace := array[Dend] of{	Dtype =>	0,	Dfn =>		0,	Dglobal =>	1,	Darg =>		1,	Dlocal =>	1,	Dconst =>	0,	Dfield =>	1,	Dtag =>		0,	Dimport =>	0,	Dunbound =>	0,	Dundef =>	0,	Dwundef =>	0,}; impdecl:	ref Decl;impdecls:	ref Dlist;scopes :=	array[MaxScope] of ref Decl;tails :=	array[MaxScope] of ref Decl;scopekind := 	array[MaxScope] of byte;scopenode :=	array[MaxScope] of ref Node;iota:		ref Decl;zdecl:		Decl; popscopes(){	d: ref Decl; 	#	# 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;} declstart(){	iota = mkids(nosrc, enter("iota", 0), tint, nil);	iota.init = mkconst(nosrc, big 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 = enterstring("");	installids(Dglobal, d); 	scope = ScopeGlobal;	scopes[ScopeGlobal] = nil;	tails[ScopeGlobal] = nil;} redecl(d: ref Decl){	old := d.sym.decl;	if(old.store == Dwundef)		return;	error(d.src.start, "redeclaration of "+declconv(d)+", previously declared as "+storeconv(old)+" on line "+		lineconv(old.src.start));} checkrefs(d: ref Decl){	id, m: ref Decl;	refs: int; 	for(; d != nil; d = d.next){		if(d.das != byte 0)			d.refs--;		case d.store{		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 "+d.sym.name+"."+id.sym.name+" not defined");					if(superwarn && !id.refs && d.importid == nil)						warn(d.src.start, "function "+d.sym.name+"."+id.sym.name+" not referenced");				}			}			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, declconv(d)+" not referenced");		Dglobal =>			if(superwarn && !d.refs && d.sym != nil && d.sym.name[0] != '.')				warn(d.src.start, declconv(d)+" not referenced");		Dlocal or		Darg =>			if(!d.refs && d.sym != nil && d.sym.name != nil && d.sym.name[0] != '.')				warn(d.src.start, declconv(d)+" not referenced");		Dconst =>			if(superwarn && !d.refs && d.sym != nil)				warn(d.src.start, declconv(d)+" not referenced");		Dfn =>			if(d.init == nil && d.importid == nil)				error(d.src.start, declconv(d)+" not defined");			if(superwarn && !d.refs)				warn(d.src.start, declconv(d)+" not referenced");		Dimport =>			if(superwarn && !d.refs)				warn(d.src.start, declconv(d)+" not referenced");		}		if(d.das != byte 0)			d.refs++;	}} vardecl(ids: ref Decl, t: ref Type): ref Node{	n := mkn(Ovardecl, mkn(Oseq, nil, nil), nil);	n.decl = ids;	n.ty = t;	return n;} vardecled(n: ref Node){	store := Dlocal;	if(scope == ScopeGlobal)		store = Dglobal;	if(n.ty.kind == Texception && n.ty.cons == byte 1){		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;} condecl(ids: ref Decl, init: ref Node): ref Node{	n := mkn(Ocondecl, mkn(Oseq, nil, nil), init);	n.decl = ids;	return n;} condecled(n: ref Node){	ids := n.decl;	installids(Dconst, ids);	for(last := ids; ids != nil; ids = ids.next){		ids.ty = tunknown;		last = ids;	}	n.left.decl = last;} exdecl(ids: ref Decl, tids: ref Decl): ref Node{	n: ref Node;	t: ref Type; 	t = mktype(ids.src.start, ids.src.stop, Texception, nil, tids);	t.cons = byte 1;	n = mkn(Oexdecl, mkn(Oseq, nil, nil), nil);	n.decl = ids;	n.ty = t;	return n;} exdecled(n: ref Node){	ids, last: ref Decl;	t: ref Type; 	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;} importdecl(m: ref Node, ids: ref Decl): ref Node{	n := mkn(Oimport, mkn(Oseq, nil, nil), m);	n.decl = ids;	return n;} importdecled(n: ref Node){	ids := n.decl;	installids(Dimport, ids);	for(last := ids; ids != nil; ids = ids.next){		ids.ty = tunknown;		last = ids;	}	n.left.decl = last;} mkscope(body: ref Node): ref Node{	n := mkn(Oscope, nil, body);	if(body != nil)		n.src = body.src;	return n;} fndecl(n: ref Node, t: ref Type, body: ref Node): ref Node{	n = mkbin(Ofunc, n, body);	n.ty = t;	return n;} fndecled(n: ref Node){	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#fnchk(n: ref Node): ref Decl{	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 "+dotconv(d)+", previously declared as "			+storeconv(d)+" on line "+lineconv(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 %s ty %s newty %s\n", dotconv(d), typeconv(d.ty), typeconv(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: "+dotconv(d)+" defined as "			+typeconv(t)+" declared as "+typeconv(d.ty)+" on line "+lineconv(d.src.start));	else if(!raisescompat(d.ty.eraises, t.eraises))		nerror(n, "raises mismatch: " + dotconv(d));	if(t.varargs != byte 0)		nerror(n, "cannot define functions with a '*' argument, such as "+dotconv(d)); 	t.eraises = d.ty.eraises; 	d.ty = t;	d.offset = idoffsets(t.ids, MaxTemp, IBY2WD);	d.src = n.src; 	d.locals = nil; 	n.ty = t; 	if(bad)		return nil;	return d;} globalas(dst: ref Node, v: ref Node, valok: int): ref Node{	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;	case dst.op{	Oname =>		if(dst.decl.init != nil)			nerror(dst, "duplicate assignment to "+expconv(dst)+", previously assigned on line "				+lineconv(dst.decl.init.src.start));		if(valok)			dst.decl.init = v;		return v;	Otuple =>		if(valok && v.op != Otuple)			fatal("can't deal with "+nodeconv(v)+" in tuple case of globalas");		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 "+nodeconv(dst)+" in globalas");	return nil;} needsstore(d: ref Decl): int{	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#vars(d: ref Decl): ref Decl{	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;} ## declare variables from the left side of a := statement#recdasdecl(n: ref Node, store: int, nid: int): (int, int){	r: int; 	case n.op{	Otuple =>		ok := 1;		for(n = n.left; n != nil; n = n.right){			(r, nid) = recdasdecl(n.left, store, nid);			ok &= r;		}		return (ok, nid);	Oname =>		if(n.decl == nildecl)			return (1, -1);		d := mkids(n.src, n.decl.sym, nil, nil);		installids(store, d);		n.decl = d;		old := d.old;		if(old != nil		&& old.store != Dfn		&& old.store != Dwundef		&& old.store != Dundef)			warn(d.src.start, "redeclaration of "+declconv(d)+", previously declared as "				+storeconv(old)+" on line "+lineconv(old.src.start));		d.refs++;		d.das = byte 1;		if(nid >= 0)			nid++;		return (1, nid);	}	return (0, nid);} recmark(n: ref Node, nid: int): int{	case(n.op){	Otuple =>		for(n = n.left; n != nil; n = n.right)			nid = recmark(n.left, nid);	Oname =>		n.decl.nid = byte nid;		nid = 0;	}	return nid;} dasdecl(n: ref Node): int{	ok: int; 	nid := 0;

Lines 1–500 of 1177.