📄 expr.c
字号:
if ((i == 'a' || i == 'A' || i == -'a' || i == -'A') && (j == 'a' || j == 'A' || j == -'a' || j == -'A')) { if (abs(i+j) == 32) { delfreearg(&a, a->nargs-1); delsimpfreearg(&a, a->nargs-1); a = makeexpr_bicall_1((i+j > 0) ? "_tolower" : "_toupper", tp_char, a); } } } } if (castdouble) a = makeexpr_cast(a, tp_real); return a;}Expr *makeexpr_minus(a, b)Expr *a, *b;{ int okneg; if (debug>2) { fprintf(outf,"makeexpr_minus("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); } if (ISCONST(b->kind) && b->val.i == 0 && /* kludge for array indexing */ ord_type(b->val.type)->kind == TK_ENUM) { b->val.type = tp_integer; } okneg = (a->kind != EK_PLUS && b->kind != EK_PLUS); a = makeexpr_plus(a, makeexpr_neg(b)); if (okneg && a->kind == EK_PLUS) a->val.i = 1; /* this flag says to write as "a-b" if possible */ return a;}Expr *makeexpr_inc(a, b)Expr *a, *b;{ Type *type; type = a->val.type; a = makeexpr_plus(makeexpr_charcast(a), b); if (ord_type(type)->kind != TK_INTEGER && ord_type(type)->kind != TK_CHAR) a = makeexpr_cast(a, type); return a;}/* Apply the distributive law for a sum of products */Expr *distribute_plus(ex)Expr *ex;{ int i, j, icom; Expr *common, *outer, *ex2, **exp; if (debug>2) { fprintf(outf,"distribute_plus("); dumpexpr(ex); fprintf(outf,")\n"); } if (ex->kind != EK_PLUS) return ex; for (i = 0; i < ex->nargs; i++) if (ex->args[i]->kind == EK_TIMES) break; if (i == ex->nargs) return ex; outer = NULL; icom = 0; for (;;) { ex2 = ex->args[0]; if (ex2->kind == EK_NEG) ex2 = ex2->args[0]; if (ex2->kind == EK_TIMES) { if (icom >= ex2->nargs) break; common = ex2->args[icom]; if (common->kind == EK_NEG) common = common->args[0]; } else { if (icom > 0) break; common = ex2; icom++; } for (i = 1; i < ex->nargs; i++) { ex2 = ex->args[i]; if (ex2->kind == EK_NEG) ex2 = ex2->args[i]; if (ex2->kind == EK_TIMES) { for (j = ex2->nargs; --j >= 0; ) { if (exprsame(ex2->args[j], common, 1) || (ex2->args[j]->kind == EK_NEG && exprsame(ex2->args[j]->args[0], common, 1))) break; } if (j < 0) break; } else { if (!exprsame(ex2, common, 1)) break; } } if (i == ex->nargs) { if (debug>2) { fprintf(outf,"distribute_plus does "); dumpexpr(common); fprintf(outf,"\n"); } common = copyexpr(common); for (i = 0; i < ex->nargs; i++) { if (ex->args[i]->kind == EK_NEG) ex2 = *(exp = &ex->args[i]->args[0]); else ex2 = *(exp = &ex->args[i]); if (ex2->kind == EK_TIMES) { for (j = ex2->nargs; --j >= 0; ) { if (exprsame(ex2->args[j], common, 1)) { delsimpfreearg(exp, j); break; } else if (ex2->args[j]->kind == EK_NEG && exprsame(ex2->args[j]->args[0], common,1)) { freeexpr(ex2->args[j]); ex2->args[j] = makeexpr_long(-1); break; } } } else { freeexpr(ex2); *exp = makeexpr_long(1); } ex->args[i] = resimplify(ex->args[i]); } outer = makeexpr_times(common, outer); } else icom++; } return makeexpr_times(resimplify(ex), outer);}Expr *makeexpr_times(a, b)Expr *a, *b;{ int i, n, castdouble = 0; Type *type; if (debug>2) { fprintf(outf,"makeexpr_times("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); } if (!a) return b; if (!b) return a; a = commute(a, b, EK_TIMES); if (a->val.type->kind == TK_INTEGER) { i = a->nargs-1; if (i > 0 && ISCONST(a->args[i-1]->kind)) { a->args[i-1]->val.i *= a->args[i]->val.i; delfreearg(&a, i); } } for (i = n = 0; i < a->nargs; i++) { if (expr_neg_cost(a->args[i]) < 0) n++; } if (n & 1) { for (i = 0; i < a->nargs; i++) { if (ISCONST(a->args[i]->kind) && expr_neg_cost(a->args[i]) >= 0) { a->args[i] = makeexpr_neg(a->args[i]); n++; break; } } } else n++; for (i = 0; i < a->nargs && n >= 2; i++) { if (expr_neg_cost(a->args[i]) < 0) { a->args[i] = makeexpr_neg(a->args[i]); n--; } } if (checkconst(a->args[a->nargs-1], 1)) { if (a->args[a->nargs-1]->val.type->kind == TK_REAL && a->args[0]->val.type->kind != TK_REAL) castdouble = 1; delfreearg(&a, a->nargs-1); } else if (checkconst(a->args[a->nargs-1], -1)) { if (a->args[a->nargs-1]->val.type->kind == TK_REAL && a->args[0]->val.type->kind != TK_REAL) castdouble = 1; delfreearg(&a, a->nargs-1); a->args[0] = makeexpr_neg(a->args[0]); } else if (checkconst(a->args[a->nargs-1], 0) && nosideeffects(a, 1)) { if (a->args[a->nargs-1]->val.type->kind == TK_REAL) type = a->args[a->nargs-1]->val.type; else type = a->val.type; return makeexpr_cast(grabarg(a, a->nargs-1), type); } if (a->nargs < 2) { if (a->nargs < 1) { FREE(a); a = makeexpr_long(1); } else { b = a->args[0]; FREE(a); a = b; } } if (castdouble) a = makeexpr_cast(a, tp_real); return a;}Expr *makeexpr_sqr(ex, cube)Expr *ex;int cube;{ Expr *ex2; Meaning *tvar; Type *type; if (exprspeed(ex) <= 2 && nosideeffects(ex, 0)) { ex2 = NULL; } else { type = (ex->val.type->kind == TK_REAL) ? tp_longreal : tp_integer; tvar = makestmttempvar(type, name_TEMP); ex2 = makeexpr_assign(makeexpr_var(tvar), ex); ex = makeexpr_var(tvar); } if (cube) ex = makeexpr_times(ex, makeexpr_times(copyexpr(ex), copyexpr(ex))); else ex = makeexpr_times(ex, copyexpr(ex)); return makeexpr_comma(ex2, ex);}Expr *makeexpr_divide(a, b)Expr *a, *b;{ Expr *ex; int p; if (debug>2) { fprintf(outf,"makeexpr_divide("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); } if (a->val.type->kind != TK_REAL && b->val.type->kind != TK_REAL) { /* must do a real division */ ex = docast(a, tp_longreal); if (ex) a = ex; else { ex = docast(b, tp_longreal); if (ex) b = ex; else a = makeexpr_cast(a, tp_longreal); } } if (a->kind == EK_TIMES) { for (p = 0; p < a->nargs; p++) if (exprsame(a->args[p], b, 1)) break; if (p < a->nargs) { delfreearg(&a, p); freeexpr(b); if (a->nargs == 1) return grabarg(a, 0); else return a; } } if (expr_neg_cost(a) < 0 && expr_neg_cost(b) < 0) { a = makeexpr_neg(a); b = makeexpr_neg(b); } if (checkconst(b, 0)) warning("Division by zero [163]"); return makeexpr_bin(EK_DIVIDE, tp_longreal, a, b);}int gcd(a, b)int a, b;{ if (a < 0) a = -a; if (b < 0) b = -b; while (a != 0) { b %= a; if (b != 0) a %= b; else return a; } return b;}/* possible signs of ex: 1=may be neg, 2=may be zero, 4=may be pos */int negsigns(mask)int mask;{ return (mask & 2) | ((mask & 1) << 2) | ((mask & 4) >> 2);}int possiblesigns(ex)Expr *ex;{ Value val; Type *tp; char *cp; int i, mask, mask2; if (isliteralconst(ex, &val) && val.type) { if (val.type == tp_real || val.type == tp_longreal) { if (realzero(val.s)) return 2; if (*val.s == '-') return 1; return 4; } else return (val.i < 0) ? 1 : (val.i == 0) ? 2 : 4; } if (ex->kind == EK_CAST && similartypes(ex->val.type, ex->args[0]->val.type)) return possiblesigns(ex->args[0]); if (ex->kind == EK_NEG) return negsigns(possiblesigns(ex->args[0])); if (ex->kind == EK_TIMES || ex->kind == EK_DIVIDE) { mask = possiblesigns(ex->args[0]); for (i = 1; i < ex->nargs; i++) { mask2 = possiblesigns(ex->args[i]); if (mask2 & 2) mask |= 2; if ((mask2 & (1|4)) == 1) mask = negsigns(mask); else if ((mask2 & (1|4)) != 4) mask = 1|2|4; } return mask; } if (ex->kind == EK_DIV || ex->kind == EK_MOD) { mask = possiblesigns(ex->args[0]); mask2 = possiblesigns(ex->args[1]); if (!((mask | mask2) & 1)) return 2|4; } if (ex->kind == EK_PLUS) { mask = 0; for (i = 0; i < ex->nargs; i++) { mask2 = possiblesigns(ex->args[i]); if ((mask & negsigns(mask2)) & (1|4)) mask |= (1|2|4); else mask |= mask2; } return mask; } if (ex->kind == EK_COND) { return possiblesigns(ex->args[1]) | possiblesigns(ex->args[2]); } if (ex->kind == EK_EQ || ex->kind == EK_LT || ex->kind == EK_GT || ex->kind == EK_NE || ex->kind == EK_LE || ex->kind == EK_GE || ex->kind == EK_AND || ex->kind == EK_OR || ex->kind == EK_NOT) return 2|4; if (ex->kind == EK_BICALL) { cp = ex->val.s; if (!strcmp(cp, "strlen") || !strcmp(cp, "abs") || !strcmp(cp, "labs") || !strcmp(cp, "fabs")) return 2|4; } tp = (ex->kind == EK_VAR) ? ((Meaning *)ex->val.i)->type : ex->val.type; if (ord_range(ex->val.type, &val.i, NULL)) { if (val.i > 0) return 4; if (val.i >= 0) return 2|4; } if (ord_range(ex->val.type, NULL, &val.i)) { if (val.i < 0) return 1; if (val.i <= 0) return 1|2; } return 1|2|4;}Expr *dodivmod(funcname, ekind, a, b)char *funcname;enum exprkind ekind;Expr *a, *b;{ Meaning *tvar; Type *type; Expr *asn; int sa, sb; type = promote_type_bin(a->val.type, b->val.type); tvar = NULL; sa = possiblesigns(a); sb = possiblesigns(b); if ((sa & 1) || (sb & 1)) { if (*funcname) { asn = NULL; if (*funcname == '*') { if (exprspeed(a) >= 5 || !nosideeffects(a, 0)) { tvar = makestmttempvar(a->val.type, name_TEMP); asn = makeexpr_assign(makeexpr_var(tvar), a); a = makeexpr_var(tvar); } if (exprspeed(b) >= 5 || !nosideeffects(b, 0)) { tvar = makestmttempvar(b->val.type, name_TEMP); asn = makeexpr_comma(asn, makeexpr_assign(makeexpr_var(tvar), b)); b = makeexpr_var(tvar); } } return makeexpr_comma(asn, makeexpr_bicall_2(funcname, type, a, b)); } else { if ((sa & 1) && (ekind == EK_MOD)) note("Using % for possibly-negative arguments [317]"); return makeexpr_bin(ekind, type, a, b); } } else return makeexpr_bin(ekind, type, a, b);}Expr *makeexpr_div(a, b)Expr *a, *b;{ Meaning *mp; Type *type; long i; int p; if (ISCONST(a->kind) && ISCONST(b->kind)) { if (a->val.i >= 0 && b->val.i > 0) { a->val.i /= b->val.i; freeexpr(b); return a; } i = gcd(a->val.i, b->val.i); if (i >= 0) { a->val.i /= i; b->val.i /= i; } } if (((b->kind == EK_CONST && (i = b->val.i)) || (b->kind == EK_VAR && (mp = (Meaning *)b->val.i)->kind == MK_CONST && mp->val.type && (i = mp->val.i) && foldconsts != 0)) && i > 0) { if (i == 1) return a; if (div_po2 > 0) { p = 0; while (!(i&1)) p++, i >>= 1; if (i == 1) { type = promote_type_bin(a->val.type, b->val.type); return makeexpr_bin(EK_RSH, type, a, makeexpr_long(p)); } } } if (a->kind == EK_TIMES) { for (p = 0; p < a->nargs; p++) { if (exprsame(a->args[p], b, 1)) { delfreearg(&a, p); freeexpr(b); if (a->nargs == 1) return grabarg(a, 0); else return a; } else if (ISCONST(a->args[p]->kind) && ISCONST(b->kind)) { i = gcd(a->args[p]->val.i, b->val.i); if (i > 1) { a->args[p]->val.i /= i; b->val.i /= i; i = a->args[p]->val.i; delfreearg(&a, p); a = makeexpr_times(a, makeexpr_long(i)); /* resimplify */ p = -1; /* start the loop over */ } } } } if (checkconst(b, 1)) { freeexpr(b); return a; } else if (checkconst(b, -1)) { freeexpr(b); return makeexpr_neg(a); } else { if (checkconst(b, 0)) warning("Division by zero [163]"); return dodivmod(divname, EK_DIV, a, b); }}Expr *makeexpr_mod(a, b)Expr *a, *b;{ Meaning *mp; Type *type; long i; if (a->kind == EK_CONST && b->kind == EK_CONST && a->val.i >= 0 && b->val.i > 0) { a->val.i %= b->val.i; freeexpr(b); return a; } if (((b->kind == EK_CONST && (i = b->val.i)) || (b->kind == EK_VAR && (mp = (Meaning *)b->val.i)->kind == MK_CONST && mp->val.type && (i = mp->val.i) && foldconsts != 0)) && i > 0) { if (i == 1) return makeexpr_long(0); if (mod_po2 != 0) { while (!(i&1)) i >>= 1; if (i == 1) { type = promote_type_bin(a->val.type, b->val.type); return makeexpr_bin(EK_BAND, type, a, makeexpr_minus(b, makeexpr_long(1))); } } } if (checkconst(b, 0)) warning("Division by zero [163]"); return dodivmod(modname, EK_MOD, a, b);}Expr *makeexpr_rem(a, b)Expr *a, *b;{ if (!(possiblesigns(a) & 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -