📄 expr.c
字号:
delete c; return this; } } switch (etp->base) { case VOID: if (tt->base == VOID) { tp = t; return this; } error("cast of void value"); case ANY: tp = any_type; return this; } legloop: switch (tt->base) { case TYPE: tt = Pbase(tt)->b_name->tp; goto legloop; case VOID: switch (etp->base) { case COBJ: switch (e1->base) { case VALUE: case CALL: case G_CALL: { Pname cln = etp->is_cl_obj(); Pclass cl = (Pclass)cln->tp; if (cl->has_dtor()) error('s',"cannot castCO to void"); } } break; } break; case PTR: switch (etp->base) { case COBJ: error("cannot castCO toP"); break; } break; case RPTR: // (x&)e: pretend e is an x if ((e1->base==CALL || e1->base==G_CALL || e1->lval(0)) && Pptr(tt)->typ->tsizeof()<=etp->tsizeof()) {//error('d',"%t(%t)",t,etp); e1 = e1->address(); // *(x*)&e tp = t; return contents(); } else error(0,"cannot cast%t to%t",etp,t); break; case COBJ://error('d',"%n ctor %d",cn,ctor); base = VALUE; // (x)e => x(e): construct an x from e e1 = new expr(ELIST,e1,0); return typ(tbl); case CHAR: case INT: case SHORT: case LONG: case FLOAT: case DOUBLE: switch (etp->base) { case COBJ: error("cannot castCO to%k",tt->base); break; } break; } tp = t; return this; } case VALUE: { Ptype tt = tp2; Pclass cl; Pname cn;//error('d',"value %d %d (%d %k)",tt,tt?tt->base:0,e1,e1?e1->base:0); tt->dcl(tbl); vv://error('d',"vv %d %d",tt,tt?tt->base:0); switch (tt->base) { case TYPE: tt = Pbase(tt)->b_name->tp; goto vv; case EOBJ: default: if (e1 == 0) { error("value missing in conversion to%t",tt); tp = any_type; return this; } base = CAST; e1 = e1->e1; // strip ELIST return typ(tbl); case CLASS: cl = (Pclass)tt; goto nn; case COBJ: cn = Pbase(tt)->b_name; cl = Pclass(cn->tp); nn: if (e1 && e1->e2==0) { /* single argument */ e1->e1 = e1->e1->typ(tbl); Pname acn=e1->e1->tp->is_cl_obj();//error('d',"acn%n itor%d",acn,acn?cl->itor:0); if (acn && acn->tp==cl && cl->has_itor()==0) { if (e2) { // x(x_obj) => e2=x_obj base = ASSIGN; Pexpr ee = e1->e1; e1 = e2; e2 = ee; tp = tp2; return this; } else // x(x_obj) => x_obj return e1->e1; } } { /* x(a) => obj.ctor(a); where e1==obj */ Pexpr ee; Pexpr a = e1; Pname ctor = cl->has_ctor(); if (ctor == 0) { error("cannot make a%n",cn); base = SM; e1 = dummy; e2 = 0; return this; }//error('d',"value %n.%n",e2,ctor); int tv = 0; if (e2 == 0) { /* x(a) => x temp; (temp.x(a),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('V');//error('d',"%s: %d %d",s,otbl,tbl); Pname n = new name(s); n->tp = tp2; n = n->dcl(tbl,ARG); /* no init! */ n->n_scope = FCT; n->assign(); e2 = n; ee = new expr(CM,this,n); tbl = otbl; tv = 1; } else ee = this; base = G_CALL; e1 = new ref(DOT,e2,ctor); e2 = a; ee = ee->typ(tbl);//error('d',"ee %t",ee->tp); if (tv == 0) { // deref value returned by constructor ee = new expr(DEREF,ee,0); ee->tp = ee->e1->tp; } return ee; } } } case NEW: { Ptype tt = tp2; Ptype tx = tt; bit v = 0; bit old = new_type; new_type = 1;/*error('d',"new%t e1 %d %d",tt,e1,e1?e1->base:0);*/ tt->dcl(tbl); new_type = old; if (e1) e1 = e1->typ(tbl); ll://error('d',"tt %d %d",tt,tt?tt->base:0); switch (tt->base) { default: if (e1) { error("Ir for nonCO created using \"new\""); e1 = 0; } break; case VEC: v = 1; tt = Pvec(tt)->typ; goto ll; case TYPE: tt = Pbase(tt)->b_name->tp; goto ll; case COBJ: { Pname cn = Pbase(tt)->b_name; Pclass cl = (Pclass)cn->tp; if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) { error("new%n;%n isU",cn,cn); } else { Pname ctor = cl->has_ctor(); TOK su; if (ctor) {/*error('d',"cobj%n tp%t",ctor,ctor->tp);*/ if (v) { Pname ic; if (e1) error('s',"Ir forvector ofCO created using \"new\""); else if ((ic = cl->has_ictor())==0) error("vector ofC%n that do not have a constructor taking noAs",cn); else if (Pfct(ic->tp)->nargs) error('s',"defaultAs for constructor for vector ofC%n",cn); } e1 = new call(ctor,e1); e1 = e1->typ(tbl); /*(void) e1->fct_call(tbl);*/ } else if (su=cl->is_simple()) { /*error('d',"simple cobj%k",su);*/ if (e1) error("new%n withIr",cn); } else {/*error('d',"not simple and no constructor?");*/ } } } }//error('d',"v==%d",v); tp = (v) ? (Ptype)tx : (Ptype)new ptr(PTR,tx,0); return this; } case DELETE: // delete e1 OR delete[e2] e1 { int i; if (e1->base == ADDROF) error('w',"delete &E"); e1 = e1->typ(tbl); i = e1->tp->num_ptr(DELETE); if (i != P) error("nonP deleted"); if (e2) { e2 = e2->typ(tbl); e2->tp->integral(DELETE); } tp = void_type; return this; } } if (e1==0 && e2==0) error('i',"no operands for%k",b); switch(b) { case ILIST: /* an ILIST is pointer to an ELIST */ e1 = e1->typ(tbl); tp = any_type; return this; case ELIST: { Pexpr e; Pexpr ex; if (e1 == dummy && e2==0) { error("emptyIrL"); tp = any_type; return this; } for (e=this; e; e=ex) { Pexpr ee = e->e1;/*error('d',"e %d %d ee %d %d",e,e?e->base:0,ee,ee?ee->base:0);*/ if (e->base != ELIST) error('i',"elist%k",e->base); if (ex = e->e2) { /* look ahead for end of list */ if (ee == dummy) error("EX in EL"); if (ex->e1 == dummy && ex->e2 == 0) { /* { ... , } */ DEL(ex); e->e2 = ex = 0; } } e->e1 = ee->typ(tbl); t = e->e1->tp; } tp = t; return this; } case DOT: case REF: { Pbase b; Ptable atbl; Pname nn; char* s; Pclass cl; e1 = e1->typ(tbl); t = e1->tp; if (base == REF) { xxx://error('d',"xxx %t",t); switch (t->base) { case TYPE: t = Pbase(t)->b_name->tp; goto xxx; default: error("nonP ->%n",mem); case ANY: atbl = any_tbl; goto mm; case PTR: case VEC: b = Pbase(Pptr(t)->typ); break; } } else { qqq: switch (t->base) { case TYPE: t = Pbase(t)->b_name->tp; goto qqq; default: error("nonO .%n",mem); case ANY: atbl = any_tbl; goto mm; case COBJ: break; }//error('d',"dot e1 %k %d",e1->base,e1->base); switch (e1->base) { /* FUDGE, but cannot use lval (consts) */ case CM: /* ( ... , x). => ( ... , &x)-> */ { Pexpr ex = e1; cfr: switch (ex->e2->base) { case NAME: base = REF; ex->e2 = ex->e2->address(); goto xde; case CM: ex = ex->e2; goto cfr; } } case CALL: case G_CALL://error('d',"call%d, %n %d %d",e1->fct_name,e1->fct_name,Pfct(e1->fct_name->tp)->f_inline,Pfct(e1->fct_name->tp)->f_virtual);#ifdef BSD if (e1->fct_name && Pfct(e1->fct_name->tp)->f_inline && Pfct(e1->fct_name->tp)->f_virtual==0) break;#else // if (e1->fct_name==0 // || Pfct(e1->fct_name->tp)->f_inline==0)#endif { /* f(). => (tmp=f(),&tmp)-> */ 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('T'); Pname tmp = new name(s); tmp->tp = e1->tp; tmp = tmp->dcl(tbl,ARG); /* no init! */ tmp->n_scope = FCT; e1 = new expr(ASSIGN,tmp,e1); e1->tp = tmp->tp; Pexpr aa = tmp->address(); e1 = new expr(CM,e1,aa); e1->tp = aa->tp; base = REF; tbl = otbl; } break; // case QUEST: // error("non-lvalue .%n",mem); // break; // case NAME: // Pname(e1)->take_addr(); // Pname(e1)->use(); } xde: b = Pbase(t); } xxxx: switch (b->base) { case TYPE: b = (Pbase) b->b_name->tp; goto xxxx; default: error("(%t) before %k%n (%n not aM)",e1->tp,base,mem,mem); case ANY: atbl = any_tbl; goto mm; case COBJ: if (atbl = b->b_table) goto mm; s = b->b_name->string; /* lookup the class name */ if (s == 0) error('i',"%kN missing",CLASS);//error('d',"lookup %s",s); nn = tbl->look(s,CLASS); if (nn == 0) error('i',"%k %sU",CLASS,s); if (nn != b->b_name) b->b_name = nn; cl = (Pclass) nn->tp; PERM(cl); if (cl == 0) error('i',"%k %s'sT missing",CLASS,s); b->b_table = atbl = cl->memtbl; mm: if (atbl->base != TABLE) error('i',"atbl(%d)",atbl->base); nn = (Pname)atbl->find_name(mem,2,0);//error('d',"nn%n %d %d",nn,nn->n_stclass,nn->n_scope); switch (nn->n_stclass) { case 0: mem = nn; tp = nn->tp; return this; case STATIC: return nn; } } } case CALL: /* handle undefined function names */ if (e1->base==NAME && e1->tp==0) {//error('d',"call %d %s",e1,e1->string); e1 = tbl->find_name(Pname(e1),1,e2); } break; case QUEST: cond = cond->typ(tbl); } if (e1) { e1 = e1->typ(tbl); if (e1->tp->base == RPTR) e1 = e1->contents(); t1 = e1->tp; } else t1 = 0; if (e2) { e2 = e2->typ(tbl); if (e2->tp->base == RPTR) e2 = e2->contents(); t2 = e2->tp; } else t2 = 0; TOK bb; switch (b) { /* filter non-overloadable operators out */ default: bb = b; break; case DEREF: bb = (e2) ? DEREF : MUL; break; case CM: case QUEST: case G_ADDROF: case G_CALL: goto not_overloaded; } Pname n1; if (e1) { Ptype tx = t1; while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp; n1 = tx->is_cl_obj(); } else n1 = 0; Pname n2; if (e2) { Ptype tx = t2; while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp; n2 = tx->is_cl_obj(); } else n2 = 0;//error('d',"overload %k: %s %s\n", bb, n1?n1->string:"1", n2?n2->string:"2"); if (n1==0 && n2==0) goto not_overloaded;{ /* first try for non-member function: op(e1,e2) or op(e2) or op(e1) */ Pexpr oe2 = e2; Pexpr ee2 = (e2 && e2->base!=ELIST) ? e2 = new expr(ELIST,e2,0) : 0; Pexpr ee1 = (e1) ? new expr(ELIST,e1,e2) : ee2; char* obb = oper_name(bb); Pname gname = gtbl->look(obb,0); int go = gname ? over_call(gname,ee1) : 0; int nc = Nover_coerce; // first look at member functions // then if necessary check for ambiguities if (go) gname = Nover;//error('d',"global%n go=%d nc=%d",gname,go,nc); if (n1) { /* look for member of n1 */ Ptable ctbl = Pclass(n1->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 e1.op(?) */ } int mo = over_call(mname,e2);//error('d',"n1%n %d",mname,mo); switch (mo) { case 0: if (go == 2) goto glob; if (1 < Nover_coerce) goto am1; goto glob; case 1: if (go == 2) goto glob; if (go == 1) { am1: error("ambiguous operandTs%n%t for%k",n1,t2,b); tp = any_type; return this; } else { Pclass cl = (Pclass)n1->tp; if (cl->conv) error('w',"overloaded%k may be ambiguous",bb); } break; case 2: if (go == 2) error("%k defined both as%n and%n",bb,gname,Nover); }//error('d',"%k mtbl %d ctbl %d",bb,mname->n_table,ctbl); if (bb==ASSIGN && mname->n_table!=ctbl) { /* inherited = */ //if (n1->tsizeof()!=mname->?) error("assignment not defined for class%n",n1); tp = any_type;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -