📄 expr.c
字号:
case OPRSHIFT: case OPLT: case OPGT: case OPLE: case OPGE: case OPEQ: case OPNE: case OPCONCAT: break; case OPMIN: case OPMAX: case OPASSIGN: case OPPLUSEQ: case OPSTAREQ: case OPCONV: case OPADDR: case OPCOMMA: case OPQUEST: case OPCOLON: break; default: fatal1("mkexpr: impossible opcode %d", opcode); }e = ALLOC(exprblock);e->tag = TEXPR;e->opcode = opcode;e->vtype = etype;e->leftp = lp;e->rightp = rp;if(ltag==TCONST && (rp==0 || rtag==TCONST) ) e = fold(e);return(e);retleft: frexpr(rp); return(lp);retright: frexpr(lp); return(rp);error: frexpr(lp); if(rp && opcode!=OPCALL && opcode!=OPCCALL) frexpr(rp); return( errnode() );}#define ERR(s) { errs = s; goto error; }cktype(op, lt, rt)register int op, lt, rt;{char *errs;if(lt==TYERROR || rt==TYERROR) goto error1;if(lt==TYUNKNOWN) return(TYUNKNOWN);if(rt==TYUNKNOWN) if(op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && op!=OPCCALL && op!=OPADDR) return(TYUNKNOWN);switch(op) { case OPPLUS: case OPMINUS: case OPSTAR: case OPSLASH: case OPPOWER: case OPMOD: if( ISNUMERIC(lt) && ISNUMERIC(rt) ) return( maxtype(lt, rt) ); ERR("nonarithmetic operand of arithmetic operator") case OPNEG: if( ISNUMERIC(lt) ) return(lt); ERR("nonarithmetic operand of negation") case OPNOT: if(lt == TYLOGICAL) return(TYLOGICAL); ERR("NOT of nonlogical") case OPAND: case OPOR: case OPEQV: case OPNEQV: if(lt==TYLOGICAL && rt==TYLOGICAL) return(TYLOGICAL); ERR("nonlogical operand of logical operator") case OPLT: case OPGT: case OPLE: case OPGE: case OPEQ: case OPNE: if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) { if(lt != rt) ERR("illegal comparison") } else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) ) { if(op!=OPEQ && op!=OPNE) ERR("order comparison of complex data") } else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) ) ERR("comparison of nonarithmetic data") return(TYLOGICAL); case OPCONCAT: if(lt==TYCHAR && rt==TYCHAR) return(TYCHAR); ERR("concatenation of nonchar data") case OPCALL: case OPCCALL: return(lt); case OPADDR: return(TYADDR); case OPCONV: if(rt == 0) return(0); if(lt==TYCHAR && ISINT(rt) ) return(TYCHAR); case OPASSIGN: case OPPLUSEQ: case OPSTAREQ: if( ISINT(lt) && rt==TYCHAR) return(lt); if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) if(op!=OPASSIGN || lt!=rt) {/* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); *//* debug fatal("impossible conversion. possible compiler bug"); */ ERR("impossible conversion") } return(lt); case OPMIN: case OPMAX: case OPBITOR: case OPBITAND: case OPBITXOR: case OPBITNOT: case OPLSHIFT: case OPRSHIFT: return(lt); case OPCOMMA: case OPQUEST: case OPCOLON: return(rt); default: fatal1("cktype: impossible opcode %d", op); }error: err(errs);error1: return(TYERROR);}LOCAL expptr fold(e)register struct exprblock *e;{struct constblock *p;#ifdef VERSION6 expptr lp, rp;#else register expptr lp, rp;#endifint etype, mtype, ltype, rtype, opcode;int i, ll, lr;char *q, *s;union constant lcon, rcon;opcode = e->opcode;etype = e->vtype;lp = e->leftp;ltype = lp->vtype;rp = e->rightp;if(rp == 0) switch(opcode) { case OPNOT: lp->const.ci = ! lp->const.ci; return(lp); case OPBITNOT: lp->const.ci = ~ lp->const.ci; return(lp); case OPNEG: consnegop(lp); return(lp); case OPCONV: case OPADDR: return(e); default: fatal1("fold: invalid unary operator %d", opcode); }rtype = rp->vtype;p = ALLOC(constblock);p->tag = TCONST;p->vtype = etype;p->vleng = e->vleng;switch(opcode) { case OPCOMMA: case OPQUEST: case OPCOLON: return(e); case OPAND: p->const.ci = lp->const.ci && rp->const.ci; break; case OPOR: p->const.ci = lp->const.ci || rp->const.ci; break; case OPEQV: p->const.ci = lp->const.ci == rp->const.ci; break; case OPNEQV: p->const.ci = lp->const.ci != rp->const.ci; break; case OPBITAND: p->const.ci = lp->const.ci & rp->const.ci; break; case OPBITOR: p->const.ci = lp->const.ci | rp->const.ci; break; case OPBITXOR: p->const.ci = lp->const.ci ^ rp->const.ci; break; case OPLSHIFT: p->const.ci = lp->const.ci << rp->const.ci; break; case OPRSHIFT: p->const.ci = lp->const.ci >> rp->const.ci; break; case OPCONCAT: ll = lp->vleng->const.ci; lr = rp->vleng->const.ci; p->const.ccp = q = (char *) ckalloc(ll+lr); p->vleng = ICON(ll+lr); s = lp->const.ccp; for(i = 0 ; i < ll ; ++i) *q++ = *s++; s = rp->const.ccp; for(i = 0; i < lr; ++i) *q++ = *s++; break; case OPPOWER: if( ! ISINT(rtype) ) return(e); conspower(&(p->const), lp, rp->const.ci); break; default: if(ltype == TYCHAR) { lcon.ci = cmpstr(lp->const.ccp, rp->const.ccp, lp->vleng->const.ci, rp->vleng->const.ci); rcon.ci = 0; mtype = tyint; } else { mtype = maxtype(ltype, rtype); consconv(mtype, &lcon, ltype, &(lp->const) ); consconv(mtype, &rcon, rtype, &(rp->const) ); } consbinop(opcode, mtype, &(p->const), &lcon, &rcon); break; }frexpr(e);return(p);}/* assign constant l = r , doing coercion */consconv(lt, lv, rt, rv)int lt, rt;register union constant *lv, *rv;{switch(lt) { case TYCHAR: *(lv->ccp = ckalloc(1)) = rv->ci; break; case TYSHORT: case TYLONG: if(rt == TYCHAR) lv->ci = rv->ccp[0]; else if( ISINT(rt) ) lv->ci = rv->ci; else lv->ci = rv->cd[0]; break; case TYCOMPLEX: case TYDCOMPLEX: switch(rt) { case TYSHORT: case TYLONG: /* fall through and do real assignment of first element */ case TYREAL: case TYDREAL: lv->cd[1] = 0; break; case TYCOMPLEX: case TYDCOMPLEX: lv->cd[1] = rv->cd[1]; break; } case TYREAL: case TYDREAL: if( ISINT(rt) ) lv->cd[0] = rv->ci; else lv->cd[0] = rv->cd[0]; break; case TYLOGICAL: lv->ci = rv->ci; break; }}consnegop(p)register struct constblock *p;{switch(p->vtype) { case TYSHORT: case TYLONG: p->const.ci = - p->const.ci; break; case TYCOMPLEX: case TYDCOMPLEX: p->const.cd[1] = - p->const.cd[1]; /* fall through and do the real parts */ case TYREAL: case TYDREAL: p->const.cd[0] = - p->const.cd[0]; break; default: fatal1("consnegop: impossible type %d", p->vtype); }}LOCAL conspower(powp, ap, n)register union constant *powp;struct constblock *ap;ftnint n;{register int type;union constant x;switch(type = ap->vtype) /* pow = 1 */ { case TYSHORT: case TYLONG: powp->ci = 1; break; case TYCOMPLEX: case TYDCOMPLEX: powp->cd[1] = 0; case TYREAL: case TYDREAL: powp->cd[0] = 1; break; default: fatal1("conspower: invalid type %d", type); }if(n == 0) return;if(n < 0) { if( ISINT(type) ) { err("integer ** negative power "); return; } n = - n; consbinop(OPSLASH, type, &x, powp, &(ap->const)); }else consbinop(OPSTAR, type, &x, powp, &(ap->const));for( ; ; ) { if(n & 01) consbinop(OPSTAR, type, powp, powp, &x); if(n >>= 1) consbinop(OPSTAR, type, &x, &x, &x); else break; }}/* do constant operation cp = a op b */LOCAL consbinop(opcode, type, cp, ap, bp)int opcode, type;register union constant *ap, *bp, *cp;{int k;double temp;switch(opcode) { case OPPLUS: switch(type) { case TYSHORT: case TYLONG: cp->ci = ap->ci + bp->ci; break; case TYCOMPLEX: case TYDCOMPLEX: cp->cd[1] = ap->cd[1] + bp->cd[1]; case TYREAL: case TYDREAL: cp->cd[0] = ap->cd[0] + bp->cd[0]; break; } break; case OPMINUS: switch(type) { case TYSHORT: case TYLONG: cp->ci = ap->ci - bp->ci; break; case TYCOMPLEX: case TYDCOMPLEX: cp->cd[1] = ap->cd[1] - bp->cd[1]; case TYREAL: case TYDREAL: cp->cd[0] = ap->cd[0] - bp->cd[0]; break; } break; case OPSTAR: switch(type) { case TYSHORT: case TYLONG: cp->ci = ap->ci * bp->ci; break; case TYREAL: case TYDREAL: cp->cd[0] = ap->cd[0] * bp->cd[0]; break; case TYCOMPLEX: case TYDCOMPLEX: temp = ap->cd[0] * bp->cd[0] - ap->cd[1] * bp->cd[1] ; cp->cd[1] = ap->cd[0] * bp->cd[1] + ap->cd[1] * bp->cd[0] ; cp->cd[0] = temp; break; } break; case OPSLASH: switch(type) { case TYSHORT: case TYLONG: cp->ci = ap->ci / bp->ci; break; case TYREAL: case TYDREAL: cp->cd[0] = ap->cd[0] / bp->cd[0]; break; case TYCOMPLEX: case TYDCOMPLEX: zdiv(cp,ap,bp); break; } break; case OPMOD: if( ISINT(type) ) { cp->ci = ap->ci % bp->ci; break; } else fatal("inline mod of noninteger"); default: /* relational ops */ switch(type) { case TYSHORT: case TYLONG: if(ap->ci < bp->ci) k = -1; else if(ap->ci == bp->ci) k = 0; else k = 1; break; case TYREAL: case TYDREAL: if(ap->cd[0] < bp->cd[0]) k = -1; else if(ap->cd[0] == bp->cd[0]) k = 0; else k = 1; break; case TYCOMPLEX: case TYDCOMPLEX: if(ap->cd[0] == bp->cd[0] && ap->cd[1] == bp->cd[1] ) k = 0; else k = 1; break; } switch(opcode) { case OPEQ: cp->ci = (k == 0); break; case OPNE: cp->ci = (k != 0); break; case OPGT: cp->ci = (k == 1); break; case OPLT: cp->ci = (k == -1); break; case OPGE: cp->ci = (k >= 0); break; case OPLE: cp->ci = (k <= 0); break; } break; }}conssgn(p)register expptr p;{if( ! ISCONST(p) ) fatal( "sgn(nonconstant)" );switch(p->vtype) { case TYSHORT: case TYLONG: if(p->const.ci > 0) return(1); if(p->const.ci < 0) return(-1); return(0); case TYREAL: case TYDREAL: if(p->const.cd[0] > 0) return(1); if(p->const.cd[0] < 0) return(-1); return(0); case TYCOMPLEX: case TYDCOMPLEX: return(p->const.cd[0]!=0 || p->const.cd[1]!=0); default: fatal1( "conssgn(type %d)", p->vtype); }/* NOTREACHED */}char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };LOCAL expptr mkpower(p)register struct exprblock *p;{register expptr q, lp, rp;int ltype, rtype, mtype;lp = p->leftp;rp = p->rightp;ltype = lp->vtype;rtype = rp->vtype;if(ISICON(rp)) { if(rp->const.ci == 0) { frexpr(p); if( ISINT(ltype) ) return( ICON(1) ); else return( putconst( mkconv(ltype, ICON(1))) ); } if(rp->const.ci < 0) { if( ISINT(ltype) ) { frexpr(p); err("integer**negative"); return( errnode() ); } rp->const.ci = - rp->const.ci; p->leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp)); } if(rp->const.ci == 1) { frexpr(rp); free(p); return(lp); } if( ONEOF(ltype, MSKINT|MSKREAL) ) { p->vtype = ltype; return(p); } }if( ISINT(rtype) ) { if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) ) q = call2(TYSHORT, "pow_hh", lp, rp); else { if(ltype == TYSHORT) { ltype = TYLONG; lp = mkconv(TYLONG,lp); } q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp)); } }else if( ISREAL( (mtype = maxtype(ltype,rtype)) )) q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));else { q = call2(TYDCOMPLEX, "pow_zz", mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp)); if(mtype == TYCOMPLEX) q = mkconv(TYCOMPLEX, q); }free(p);return(q);}/* Complex Division. Same code as in Runtime Library*/struct dcomplex { double dreal, dimag; };LOCAL zdiv(c, a, b)register struct dcomplex *a, *b, *c;{double ratio, den;double abr, abi;if( (abr = b->dreal) < 0.) abr = - abr;if( (abi = b->dimag) < 0.) abi = - abi;if( abr <= abi ) { if(abi == 0) fatal("complex division by zero"); ratio = b->dreal / b->dimag ; den = b->dimag * (1 + ratio*ratio); c->dreal = (a->dreal*ratio + a->dimag) / den; c->dimag = (a->dimag*ratio - a->dreal) / den; }else { ratio = b->dimag / b->dreal ; den = b->dreal * (1 + ratio*ratio); c->dreal = (a->dreal + a->dimag*ratio) / den; c->dimag = (a->dimag - a->dreal*ratio) / den; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -