📄 expr.c
字号:
return this; }//error('d',"Nover %n %k",Nover,Nover->tp->base); base = G_CALL; /* e1.op(e2) or e1.op() */ e1 = new ref(DOT,e1,Nover); if (ee1) delete ee1; return typ(tbl); } if (n2 && e1==0) { /* look for unary operator */ Ptable ctbl = Pclass(n2->tp)->memtbl; Pname mname = ctbl->look(obb,0); if (mname == 0) goto glob; switch (mname->n_scope) { default: goto glob; case 0: case PUBLIC: break; /* try e2.op() */ } int mo = over_call(mname,0);/*error('d',"n2%n %d",mname,mo);*/ switch (mo) { case 0: if (1 < Nover_coerce) goto am2; goto glob; case 1: if (go == 2) goto glob; if (go == 1) { am2: error("ambiguous operandT%n for%k",n2,b); tp = any_type; return this; } break; case 2: if (go == 2) error("%k defined both as%n and%n",bb,gname,Nover); } base = G_CALL; /* e2.op() */ e1 = new ref(DOT,oe2,Nover); e2 = 0; if (ee2) delete ee2; if (ee1 && ee1!=ee2) delete ee1; return typ(tbl); } glob://error('d',"glob %d",nc); if (1 < nc) { error("ambiguous operandTs%t%t for%k",t1,t2,b); tp = any_type; return this; } if (go) { if (go == 1) { /* conversion necessary => binary */ if (n1) { Pclass cl = (Pclass)n1->tp; if (cl->conv) error('w',"overloaded%k may be ambiguous",bb);//error('d',"go n1"); } else if (n2) { Pclass cl = (Pclass)n2->tp; if (cl->conv) error('w',"overloaded%k may be ambiguous",bb);//error('d',"bb%k go n2 %n",bb,gname); } } base = G_CALL; /* op(e1,e2) or op(e1) or op(e2) */ e1 = gname; e2 = ee1; return typ(tbl); } if (ee2) delete ee2; if (ee1 && ee1!=ee2) delete ee1; e2 = oe2;//error('d',"bb%k",bb); switch(bb) { case ASSIGN: case ADDROF: break; case CALL: case DEREF: if (n1 == 0) break; default: /* look for conversions to basic types */ { int found = 0; if (n1) { int val = 0; Pclass cl = (Pclass)n1->tp; for ( Pname on = cl->conv; on; on=on->n_list) {//error('d',"oper_coerce n1%n %t",on,(on)?Pfct(on->tp)->returns:0); Pfct f = (Pfct)on->tp; if (bb==ANDAND || bb==OROR) { e1 = check_cond(e1,bb,tbl); goto not_overloaded; } if (n2 || (t2 && f->returns->check(t2,ASSIGN)==0) || (t2 && t2->check(f->returns,ASSIGN)==0)) { Ncoerce = on; val++; } } switch (val) { case 0: break; case 1: { Pref r = new ref(DOT,e1,Ncoerce); Pexpr rr = e1->typ(tbl); e1 = new expr(G_CALL,rr,0); found = 1; break; } default: error('s',"ambiguous coercion of%n to basicT",n1); } } if (n2) { int val = 0; Pclass cl = (Pclass)n2->tp; for ( Pname on = cl->conv; on; on=on->n_list) {//error('d',"oper_coerce n2%n %t",on,(on)?on->tp:0); Pfct f = (Pfct)on->tp; if (bb==ANDAND || bb==OROR || bb==NOT) { e2 = check_cond(e2,bb,tbl); goto not_overloaded; } if (n1 || (t1 && f->returns->check(t1,ASSIGN)==0) || (t1 && t1->check(f->returns,ASSIGN)==0)) { Ncoerce = on; val++; } } switch (val) { case 0: break; case 1: { Pref r = new ref(DOT,e2,Ncoerce); Pexpr rr = r->typ(tbl); e2 = new expr(G_CALL,rr,0); found++; break; } default: error('s',"ambiguous coercion of%n to basicT",n2); } } if (found) { /* if (found == 2) error('w',"coercions of operands of%k may be ambiguous",b);*/ return typ(tbl); } if (t1 && t2) error("bad operandTs%t%t for%k",t1,t2,b); else error("bad operandT%t for%k",t1?t1:t2,b); tp = any_type; return this; } }}not_overloaded: t = (t1==0) ? t2 : (t2==0) ? t1 : 0;/*fprintf(stderr,"%s: e1 %d %d e2 %d %d\n",oper_name(b),e1,e1?e1->base:0,e2,e2?e2->base:0);*/ switch (b) { /* are the operands of legal types */ case G_CALL: case CALL: tp = fct_call(tbl); /* two calls of use() for e1's names */ if (tp->base == RPTR) return contents(); return this; case DEREF://error('d',"deref %t",t?t:t1); if (e1 == dummy) error("O missing before []\n"); if (t) { /* *t */ t->vec_type(); tp = t->deref(); } else { // e1[e2] that is *(e1+e2) if (t1->vec_type()) { // e1[e2] t2->integral(b); tp = t1->deref(); } else if (t2->vec_type()) { // really e2[e1] t1->integral(b); tp = t2->deref(); } else { error("[] applied to nonPT:%t[%t]",t1,t2); tp = any_type; } } if (tp->base == RPTR) return contents(); return this; case G_ADDROF: case ADDROF: if (e2->lval(b) == 0) { tp = any_type; return this; } tp = t->addrof(); /* look for &p->member_function */ switch (e2->base) { case DOT: case REF: { Pname m = e2->mem; Pfct f = (Pfct)m->tp; if (f->base==FCT && (f->f_virtual==0 || m->n_qualifier)) { DEL(e2); e2 = m; } } } return this; case UMINUS: t->numeric(b); tp = t; return this; case UPLUS: t->num_ptr(b); error('s',"unary + (ignored)"); tp = t; base = PLUS; e1 = zero; return this; case NOT: e2 = check_cond(e2,NOT,tbl); tp = int_type; return this; case COMPL: t->integral(b); tp = t; return this; case INCR: case DECR: if (e1) e1->lval(b); if (e2) e2->lval(b); r1 = t->num_ptr(b); tp = t; return this; } if (e1==dummy || e2==dummy || e1==0 || e2==0) error("operand missing for%k",b); switch (b) { case MUL: case DIV: r1 = t1->numeric(b); r2 = t2->numeric(b); nppromote(b); break; case MOD: r1 = t1->integral(b); r2 = t2->integral(b); nppromote(b); break; case PLUS: r2 = t2->num_ptr(b); r1 = t1->num_ptr(b); if (r1==P && r2==P) error("P +P"); nppromote(b); tp = t; break; case MINUS: r2 = t2->num_ptr(b); r1 = t1->num_ptr(b); if (r2==P && r1!=P && r1!=A) error("P - nonP"); nppromote(b); tp = t; break; case LS: case RS: case AND: case OR: case ER: switch (e1->base) { case LT: case LE: case GT: case GE: case EQ: case NE: error('w',"%kE as operand for%k",e1->base,b); } switch (e2->base) { case LT: case LE: case GT: case GE: case EQ: case NE: error('w',"%kE as operand for%k",e2->base,b); } r1 = t1->integral(b); r2 = t2->integral(b); nppromote(b); break; case LT: case LE: case GT: case GE: case EQ: case NE: r1 = t1->num_ptr(b); r2 = t2->num_ptr(b); npcheck(b); t = int_type; break; case ANDAND: case OROR: e1 = check_cond(e1,b,tbl); e2 = check_cond(e2,b,tbl);// if (st2 != st3) error('s',"needs temporaryV to evaluateE after \"%k\" (please use ifS)",b); t = int_type; break; case QUEST: { Pname c1, c2; cond = check_cond(cond,b,tbl);// if (st1 != st2) error('s',"needs temporaryV to evaluateE after \"?\" (please use ifS)");// if (st2 != st3) error('s',"needs temporaryV to evaluateE after \":\" (please use ifS)"); // still doesn't do complete checking for possible conversions... if (t1==t2 || ( (c1=t1->is_cl_obj()) && (c2=t2->is_cl_obj()) && (c1->tp==c2->tp) )) t = t1; else { r1 = t1->num_ptr(b); r2 = t2->num_ptr(b);//error('d',"r1 %d r2 %d",r1,r2); if (r1==FCT && r2==FCT) { // fudge if (t1->check(t2,ASSIGN)) error("badTs in ?:E: %t and %t",t1,t2); t = t1; } else nppromote(b);//error('d',"t: %d %t t1: %d %t t2: %d %t",t,t,t1,t1,t2,t2); if (t!=t1 && t->check(t1,0)) { e1 = new texpr(CAST,t,e1); e1->tp = t; } if (t!=t2 && t->check(t2,0)) { e2 = new texpr(CAST,t,e2); e2->tp = t; } } } break; case ASPLUS: r1 = t1->num_ptr(b); r2 = t2->num_ptr(b); if (r1==P && r2==P) error("P +=P"); nppromote(b); goto ass; case ASMINUS: r1 = t1->num_ptr(b); r2 = t2->num_ptr(b); if (r2==P && r1!=P && r1!=A) error("P -= nonP"); nppromote(b); goto ass; case ASMUL: case ASDIV: r1 = t1->numeric(b); r2 = t1->numeric(b); nppromote(b); goto ass; case ASMOD: r1 = t1->integral(b); r2 = t2->integral(b); nppromote(b); goto ass; case ASAND: case ASOR: case ASER: case ASLS: case ASRS: r1 = t1->integral(b); r2 = t2->integral(b); npcheck(b); t = int_type; goto ass; ass: as_type = t; /* the type of the rhs */ t2 = t; case ASSIGN: if (e1->lval(b) == 0) { tp = any_type; return this; } lkj: switch (t1->base) { case INT: case CHAR: case SHORT: if (e2->base==ICON && e2->tp==long_type) error('w',"long constant assigned to%k",t1->base); case LONG: if (b==ASSIGN && Pbase(t1)->b_unsigned && e2->base==UMINUS && e2->e2->base==ICON) error('w',"negative assigned to unsigned"); break; case TYPE: t1 = Pbase(t1)->b_name->tp; goto lkj; case COBJ: { Pname c1 = t1->is_cl_obj(); if (c1) { Pname c2 = t2->is_cl_obj();//error('d',"%t=%t %d %d",t1,t2,c1,c2); if (c1 != c2) { e2 = new expr(ELIST,e2,0); e2 = new texpr(VALUE,t1,e2); e2->e2 = e1; e2 = e2->typ(tbl); *this = *e2; tp = t1; return this; } else { // check for bitwise copy Pclass cl = Pclass(c1->tp);//error('d',"bit %d",cl->bit_ass); if (cl->bit_ass == 0) error('s',"bitwise copy: %s has a member with operator=()",cl->string); else if (cl->itor && cl->has_dtor()) error('w',"bitwise copy: %s has destructor and %s(%s&) but not assignment",cl->string,cl->string,cl->string); } } break; } case PTR:/*error('d',"ptr %d %d",t1,t1?t1->base:0);*/ { Pfct ef = Pfct(Pptr(t1)->typ); if (ef->base == FCT) { Pfct f; Pname n = 0; switch (e2->base) { case NAME: f = (Pfct)e2->tp; n = Pname(e2); switch (f->base) { case FCT: case OVERLOAD: e2 = new expr(G_ADDROF,0,e2); e2->tp = f; } goto ad; case DOT: case REF:/*error('d',"dot %d %d",e2->mem->tp,e2->mem->tp?e2->mem->tp->base:0);*/ f = (Pfct)e2->mem->tp; switch (f->base) { case FCT: case OVERLOAD: n = Pname(e2->mem); e2 = new expr(G_ADDROF,0,e2); e2 = e2->typ(tbl); } goto ad; case ADDROF: case G_ADDROF: f = (Pfct)e2->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); tp = any_type; } else tp = t1; e2->e2 = n; n->lval(ADDROF); return this; } if (n) n->lval(ADDROF); } } break; } } { Pname cn; int i; if ((cn=t2->is_cl_obj()) && (i=can_coerce(t1,t2)) && Ncoerce) { if (1 < i) error("%d possible conversions for assignment",i);//error('d',"%t =%t",t1,t2); Pclass cl = (Pclass)cn->tp; Pref r = new ref(DOT,e2,Ncoerce); Pexpr rr = r->typ(tbl); Pexpr c = new expr(G_CALL,rr,0); c->fct_name = Ncoerce; c->tp = t1; e2 = c; tp = t1; return this; } }//error('d',"check(%t,%t)",e1->tp,t2); if (e1->tp->check(t2,ASSIGN)) error("bad assignmentT:%t =%t",e1->tp,t2); t = e1->tp; /* the type of the lhs */ break; case CM: t = t2; break; default: error('i',"unknown operator%k",b); } tp = t; return this;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -