⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expr2.c

📁 CFront1.0的源代码,第一代C++编译器的思想...
💻 C
📖 第 1 页 / 共 2 页
字号:
					}					/* no break */				case PUBLIC:					if (Ebase					&& (cc->cot==0						|| ( Ebase!=cc->cot->clbase->tp						&& !Ebase->has_friend(cc->nof)))					) {					  error("%n is from a privateBC",found);					}				}			}		}		else {			error("badAL for overloaded%n",fn);			return any_type;		}		break;	}	case FCT:	case_fct:		f = (Pfct)t1;		if (fn)	fct_name = fn;		break;	}	if (no_virt) fct_name = 0;	t = f->returns;	x = f->nargs;	k = f->nargs_known;//error('d',"fct_name%n",fct_name);	if (k == 0) {		if (fct_void && fn && x==0 && arg)			if (no_of_badcall++ == 0) badcall = fn;		return t;	}	for (e=arg, nn=f->argtype, argno=1; e||nn; nn=nn->n_list, e=etail->e2, argno++) {		Pexpr a;		if (e) {			a = e->e1;//error('d',"e %d%k a %d%k e2 %d",e,e->base,a,a->base,e->e2);			etail = e;			if (nn) {	/* type check */				Ptype t1 = nn->tp;//error('d',"argname %n (%t)",nn,nn->tp);			lx:/*error('d',"lx: t1%t a->tp%t",t1,a->tp);*/				switch (t1->base) {				case TYPE:					t1 = Pbase(t1)->b_name->tp;					goto lx;				case RPTR:					e->e1 = ref_init(Pptr(t1),a,tbl);					break;				case COBJ:					e->e1 = class_init(0,t1,a,tbl);					break;				case ANY:					return t;		case PTR:		{	Pfct ef = (Pfct)Pptr(t1)->typ;			if (ef->base == FCT) {				Pfct f;				Pname n = 0;				switch (a->base) {				case NAME:					f = (Pfct)a->tp;					switch (f->base) {					case FCT:					case OVERLOAD:						e->e1 = new expr(G_ADDROF,0,a);						e->e1->tp = f;					}					n = Pname(a);					goto ad;				case DOT:				case REF:					f = (Pfct)a->mem->tp;					switch (f->base) {					case FCT:					case OVERLOAD:						n = Pname(a->mem);						a = new expr(G_ADDROF,0,a);						e->e1 = a->typ(tbl);					}					goto ad;				case ADDROF:				case G_ADDROF:					f = (Pfct)a->e2->tp;				ad:					if (f->base == OVERLOAD) {						Pgen g = (Pgen)f;						n = g->find(ef);						if (n == 0) {							error("cannot deduceT for &overloaded %s()",g->string);							return any_type;						}						e->e1->e2 = n;					}					if (n) n->lval(ADDROF);				}				break;							}			goto def;		}				case CHAR:				case SHORT:				case INT:					if (a->base==ICON && a->tp==long_type)						error('w',"long constantA for%n,%kX",fn,t1->base);				case LONG:					if (((Pbase)t1)->b_unsigned					&& a->base==UMINUS					&& a->e2->base==ICON)						error('w',"negativeA for%n, unsignedX",fn);				default:				def:					{	Pname cn;						int i;						if ((cn=a->tp->is_cl_obj())						&& (i=can_coerce(t1,a->tp))						&& Ncoerce) {							if (1 < i) error("%d possible conversions for%nA%d",i,fn,argno);//error('d',"%t<-%t",t1,a->tp);							Pclass cl = (Pclass)cn->tp;							Pref r = new ref(DOT,a,Ncoerce);							Pexpr rr = r->typ(tbl);							Pexpr c = new expr(G_CALL,rr,0);							c->fct_name = Ncoerce;							c->tp = t1;							e->e1 = c;									break;						}					}					if (t1->check(a->tp,ARG)) {						if (arg_err_suppress==0) error("badA %dT for%n:%t (%tX)",argno,fn,a->tp,nn->tp);						return any_type;					}				}			}			else {				if (k != ELLIPSIS) {					if (arg_err_suppress==0) error("unX %dA for%n",argno,fn);					return any_type;				}				return t;			}		}		else {	/* default argument? */			a = nn->n_initializer;//error('d',"arg missing: %n %d as %d",nn,a,arg_err_suppress);			if (a == 0) {				if (arg_err_suppress==0) error("A %d ofT%tX for%n",argno,nn->tp,fn);				return any_type;			}//error('d',"%n: perm=%d",nn,a->permanent);			a->permanent = 2;	// ought not be necessary, but it is			e = new expr(ELIST,a,0);			if (etail)				etail->e2 = e;			else				e2 = e;			etail = e;		}	}	return t;}int refd;Pexpr ref_init(Pptr p, Pexpr init, Ptable tbl)/*	initialize the "p" with the "init"*/{	register Ptype it = init->tp;	Ptype p1 = p->typ;	Pname c1;	Pexpr a;//error('d',"init %d",it->tconst());rloop://error('d',"rloop: %d%k",it,it->base);	switch (it->base) {	case TYPE:		it = Pbase(it)->b_name->tp; goto rloop;	default:		{	Ptype tt = it->addrof();			p->base = PTR;	// allow &x for y& when y : public x					// but not &char for int&			int x = p->check(tt,COERCE);			p->base = RPTR;//error('d',"p%t tt%t => %d (nstd %d)",p,tt,x,Nstd);			if (x == 0) {				if (init->lval(0)) return init->address();				if (init->base==G_CALL	// &inline function call?				&& init->fct_name				&& Pfct(init->fct_name->tp)->f_inline )					return init->address();				p1 = p->typ;				goto xxx;			}		}	}	c1 = p1->is_cl_obj();	if (c1) {//error('d',"c1%n",c1);		refd = 1;	/* disable itor */		a = class_init(0,p1,init,tbl);		refd = 0;//error('d',"a %d init %d",a,init);		if (a==init && init->tp!=any_type) goto xxx;		switch (a->base) {		case G_CALL:		case CM:			init = a;			goto xxx;		}		return a->address();	}	if (p1->check(it,0)) {		error("badIrT:%t (%tX)",it,p);		if (init->base != NAME) init->tp = any_type;		return init;	}xxx://error('d',"xxx: %k",init->base);	switch (init->base) {	case NAME:	case DEREF:	case REF:	case DOT:	// init => &init		if (it->tconst() && vec_const==0) goto def;		init->lval(ADDROF);		return init->address();	case CM:/*error('d',"cm%k",init->e2->base);*/		switch (init->e2->base) {	/* (a, b) => (a, &b) */		case NAME:		case DEREF:			return init->address();		}	default:	def:			/* init = > ( temp=init, &temp) */	{	Ptable otbl = tbl;		if (Cstmt) {	/*	make Cstmt into a block */			if (Cstmt->memtbl == 0) Cstmt->memtbl = new table(4,tbl,0);			tbl = Cstmt->memtbl;		}		char* s = make_name('I');		Pname n = new class name(s);//error('d',"ref_init tmp %s n=%d tbl %d init=%d%k",s,n,tbl,init,init->base);		if (tbl == gtbl) error('s',"Ir for static reference not an lvaue");				n->tp = p1;		n = n->dcl(tbl,ARG); /* no initialization! */		n->n_scope = FCT;		n->assign();		a = n->address();//error('d',"tp %t init->tp %t",n->tp,init->tp);		Pexpr as = new class expr(ASSIGN,n,init);		a = new class expr(CM,as,a);		a->tp = a->e2->tp;		tbl = otbl;		return a;	}	}}Pexpr class_init(Pexpr nn, Ptype tt, Pexpr init, Ptable tbl)/*	initialize "nn" of type "tt" with "init"	if nn==0 make a temporary,	nn may not be a name*/{	Pname c1 = tt->is_cl_obj();	Pname c2 = init->tp->is_cl_obj();//error('d',"class_init%n%n%n refd=%d",nn,c1,c2,refd);	if (c1) {		if (c1!=c2		|| (refd==0 && Pclass(c1->tp)->has_itor())) {			/*	really ought to make a temp if refd,				but ref_init can do that			*/			int i = can_coerce(tt,init->tp);//error('d',"i %d Ncoerce %d",i,Ncoerce);			switch (i) {			default:				error("%d ways of making a%n from a%t",i,c1,init->tp);				init->tp = any_type;				return init;			case 0:				error("cannot make a%n from a%t",c1,init->tp);				init->tp = any_type;				return init;			case 1:				if (Ncoerce == 0) {					Pexpr a = new class expr(ELIST,init,0);					a = new texpr(VALUE,tt,a);					a->e2 = nn;					return a->typ(tbl);				}				switch (init->base) {#ifdef BSD				case CALL:				case G_CALL:#endif				case CM:				case NAME:	/* init.coerce() */					{	Pref r = new ref(DOT,init,Ncoerce);					Pexpr rr = r->typ(tbl);					Pexpr c = new expr(G_CALL,rr,0);					c->fct_name = Ncoerce;					init = c;					break;				}				default:	/* (temp=init,temp.coerce()) */				{	Ptable otbl = tbl;					if (Cstmt) { /*	make Cstmt into a block */						if (Cstmt->memtbl == 0) Cstmt->memtbl = new table(4,tbl,0);						tbl = Cstmt->memtbl;					}					char* s = make_name('U');					Pname tmp = new name(s);					tmp->tp = init->tp;					tmp = tmp->dcl(tbl,ARG); /* no init! */					tmp->n_scope = FCT;					Pexpr ass = new expr(ASSIGN,tmp,init);					ass->tp = tt;					Pref r = new ref(DOT,tmp,Ncoerce);					Pexpr rr = r->typ(tbl);					Pexpr c = new expr(G_CALL,rr,0);					c->fct_name = Ncoerce;					init = new expr(CM,ass,c);					tbl = otbl;					}				}			}			return init->typ(tbl);		}		else if (refd==0) {	// bitwise copy, check for dtor & operator=			Pclass cl = Pclass(c1->tp);			if (cl->itor==0) {				if (cl->bit_ass == 0)					error('w',"bitwise copy: %s has a member with operator=()",cl->string);				else if (cl->has_dtor() && cl->has_oper(ASSIGN))					error('w',"bitwise copy: %s has assignment and destructor but not %s(%s&)",cl->string,cl->string,cl->string);			}		}//error('d',"class_init%n: init %d %d:%t",nn,init->tp,init->tp->base,init->tp);		return init;	}	if (tt->check(init->tp,ASSIGN) && refd==0) {		error("badIrT:%t (%tX)",init->tp,tt);		init->tp = any_type;	}	return init;}int char_to_int(char* s)/*	assume s points to a string:		'c'	or	'\c'	or	'\0'	or	'\ddd'	or multi-character versions of the above	(hex constants have been converted to octal by the parser)*/{	register int i = 0;	register char c, d, e;	switch (*s) {	default:		error('i',"char constant store corrupted");	case '`':		error('s',"bcd constant");		return 0;	case '\'':		break;	}	forever			/* also handle multi-character constants */	switch (c = *++s) {	case '\'':		return i;	case '\\':			/* special character */		switch (c = *++s) {		case '0': case '1': case '2': case '3': case '4':		case '5': case '6': case '7':	/* octal representation */			c -= '0';			switch (d = *++s) {		/* try for 2 */							case '0': case '1': case '2': case '3': case '4':			case '5': case '6': case '7':				d -= '0';				switch (e = *++s) {	/* try for 3 */									case '0': case '1': case '2': case '3': case '4':				case '5': case '6': case '7':					c = c*64+d*8+e-'0';					break;				default:					c = c*8+d;					s--;				}				break;			default:				s--;			}			break;		case 'b':			c = '\b';			break;		case 'f':			c = '\f';			break;		case 'n':			c = '\n';			break;		case 'r':			c = '\r';			break;		case 't':			c = '\t';			break;		case '\\':			c = '\\';			break;		case '\'':			c = '\'';			break;		}		/* no break */	default:		if (i) i <<= BI_IN_BYTE;		i += c;	}}const A10 = 'A'-10;const a10 = 'a'-10;int str_to_int(register char* p)/*	read decimal, octal, or hexadecimal integer*/{	register c;	register i = 0;	if ((c=*p++) == '0') {		switch (c = *p++) {		case 0:			return 0;		case 'l':		case 'L':	/* long zero */			return 0;		case 'x':		case 'X':	/* hexadecimal */			while (c=*p++)				switch (c) {				case 'l':				case 'L':					return i;				case 'A':				case 'B':				case 'C':				case 'D':				case 'E':				case 'F':					i = i*16 + c-A10;					break;				case 'a':				case 'b':				case 'c':				case 'd':				case 'e':				case 'f':					i = i*16 + c-a10;					break;				default:					i = i*16 + c-'0';				}			return i;		default:	/* octal */			do 				switch (c) {				case 'l':				case 'L':					return i;				default:					i = i*8 + c-'0';				}			while (c=*p++);			return i;		}	}					/* decimal */	i = c-'0';	while (c=*p++)		switch (c) {		case 'l':		case 'L':			return i;		default:			i = i*10 + c-'0';		}	return i;			}char* Neval;int expr.eval(){	if (Neval) return 1;	switch (base) {	case ZERO:	return 0;	case IVAL:	return (int)e1;	case ICON:	return str_to_int(string);	case CCON:	return char_to_int(string);	case FCON:	Neval = "float in constant expression"; return 1;	case STRING:	Neval = "string in constant expression"; return 1;	case EOBJ:	return Pname(this)->n_val;	case SIZEOF:	return tp2->tsizeof();	case NAME:	{	Pname n = (Pname)this; 		if (n->n_evaluated && n->n_scope!=ARG) return n->n_val;		Neval = "cannot evaluate constant";		return 1;	}	case ICALL:		if (e1) {			il->i_next = curr_icall;			curr_icall = il;			int i = e1->eval();			curr_icall = il->i_next;			return i;		}		Neval = "void inlineF";		return 1;	case ANAME:	{	Pname n = (Pname)this;		int argno = n->n_val;		Pin il;		for (il=curr_icall; il; il=il->i_next)			if (il->i_table == n->n_table) goto aok;		goto bok;	aok:		if (il->local[argno]) {	bok:			Neval = "inlineF call too complicated for constant expression";			return 1;		}		Pexpr aa = il->arg[argno];		return aa->eval();	}	case CAST:	{	int i = e1->eval();		/*			ignore cast and rely on error message from evaluation.			this will allow redundant casts only.			In, particular: case (int)0:		*/		// Neval = "cast in constant expression";		return i;	}	case UMINUS:	case UPLUS:	case NOT:	case COMPL:	case PLUS:	case MINUS:	case MUL:	case LS:	case RS:	case NE:	case LT:	case LE:	case GT:	case GE:	case AND:	case OR:	case ER:	case DIV:	case MOD:	case QUEST:	case EQ:	case ANDAND:	case OROR:		break;	default:		Neval = "bad operator in constant expression";		return 1;	}	int i1 = (e1) ? e1->eval() : 0;	int i2 = (e2) ? e2->eval() : 0;	switch (base) {	case UMINUS:	return -i2;	case UPLUS:	return i2;	case NOT:	return !i2;	case COMPL:	return ~i2;	case CAST:	return i1;	case PLUS:	return i1+i2;	case MINUS:	return i1-i2;	case MUL:	return i1*i2;	case LS:	return i1<<i2;	case RS:	return i1>>i2;	case NE:	return i1!=i2;	case EQ:	return i1==i2;	case LT:	return i1<i2;	case LE:	return i1<=i2;	case GT:	return i1>i2;	case GE:	return i1>=i2;	case AND:	return i1&i2;	case OR:	return i1|i2;	case OROR:	return i1||i2;	case ER:	return i1^i2;	case MOD:	return (i2==0) ? 1 : i1%i2;	case QUEST:	return (cond->eval()) ? i1 : i2;	case DIV:	if (i2==0) {				Neval = "divide by zero";				error('w',"divide by zero");				return 1;			}			return i1/i2;	}}bit classdef.has_friend(Pname f)/*	does this class have function "f" as its friend?*/{	Plist l;	Ptable ctbl = f->n_table;/*fprintf(stderr,"(%d %s)->has_friend(%d %s)\n",this,string,f,(f)?f->string:""); fflush(stderr);*/	for (l=friend_list; l; l=l->l) {		Pname fr = l->f;/*fprintf(stderr,"fr %d %d %d\n",fr,fr->tp,fr->tp->base); fflush(stderr);*/		switch (fr->tp->base) {		case CLASS:			if (Pclass(fr->tp)->memtbl == ctbl) return 1;			break;		case COBJ:			if (Pbase(fr->tp)->b_table == ctbl) return 1;			break;		case FCT:			if (fr == f) return 1;			break;		case OVERLOAD:		{/*	Pgen g = (Pgen)fr->tp;			Plist ll;			for (ll=g->fct_list; ll; ll=ll->l) {				if (ll->f == f) return 1;			}*/			l->f = fr = ((Pgen)fr->tp)->fct_list->f; /* first fct */			if (fr == f) return 1;			break;		}		default:			error('i',"bad friend %k",fr->tp->base);		}	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -