📄 expr.c
字号:
return a; } } else { if (dolongcast(a->args[i], tolong)) return a; } break; case EK_AND: /* operators which always return int */ case EK_OR: case EK_EQ: case EK_NE: case EK_LT: case EK_GT: case EK_LE: case EK_GE: if (tolong&1) break; return a; default: break; } return NULL;}/* Return -1 if short int or plain int, 1 if long, 0 if can't tell */int exprlongness(ex)Expr *ex;{ if (sizeof_int >= 32) return -1; return (dolongcast(ex, 3) != NULL) - (dolongcast(ex, 2) != NULL);}Expr *makeexpr_longcast(a, tolong)Expr *a;int tolong;{ Expr *ex; Type *type; if (sizeof_int >= 32) return a; type = ord_type(a->val.type); if (type->kind != TK_INTEGER && type->kind != TK_SMALLSET) return a; a = makeexpr_unlongcast(a); if (tolong) { ex = dolongcast(a, 1); } else { ex = dolongcast(copyexpr(a), 0); if (ex) { if (!dolongcast(ex, 2)) { freeexpr(ex); ex = NULL; } } } if (ex) return ex; return makeexpr_un(EK_CAST, (tolong) ? tp_integer : tp_int, a);}Expr *makeexpr_arglong(a, tolong)Expr *a;int tolong;{ int cast = castlongargs; if (cast < 0) cast = castargs; if (cast > 0 || (cast < 0 && prototypes == 0)) { return makeexpr_longcast(a, tolong); } return a;}Expr *makeexpr_unlongcast(a)Expr *a;{ switch (a->kind) { case EK_LONGCONST: if (a->val.i >= -32767 && a->val.i <= 32767) a->kind = EK_CONST; break; case EK_CAST: if ((a->val.type == tp_integer || a->val.type == tp_int) && ord_type(a->args[0]->val.type)->kind == TK_INTEGER) { a = grabarg(a, 0); } break; default: break; } return a;}Expr *makeexpr_forcelongness(a) /* force a to have a definite longness */Expr *a;{ Expr *ex; ex = makeexpr_unlongcast(copyexpr(a)); if (exprlongness(ex)) { freeexpr(a); return ex; } freeexpr(ex); if (exprlongness(a) == 0) return makeexpr_longcast(a, 1); else return a;}Expr *makeexpr_ord(ex)Expr *ex;{ ex = makeexpr_charcast(ex); switch (ord_type(ex->val.type)->kind) { case TK_ENUM: return makeexpr_cast(ex, tp_int); case TK_CHAR: if (ex->kind == EK_CONST && (ex->val.i >= 32 && ex->val.i < 127)) { insertarg(&ex, 0, makeexpr_name("'%lc'", tp_integer)); } ex->val.type = tp_int; return ex; case TK_BOOLEAN: ex->val.type = tp_int; return ex; case TK_POINTER: return makeexpr_cast(ex, tp_integer); default: return ex; }}/* Tell whether an expression "looks" negative */int expr_looks_neg(ex)Expr *ex;{ int i; switch (ex->kind) { case EK_NEG: return 1; case EK_CONST: case EK_LONGCONST: switch (ord_type(ex->val.type)->kind) { case TK_INTEGER: case TK_CHAR: return (ex->val.i < 0); case TK_REAL: return (ex->val.s && ex->val.s[0] == '-'); default: return 0; } case EK_TIMES: case EK_DIVIDE: for (i = 0; i < ex->nargs; i++) { if (expr_looks_neg(ex->args[i])) return 1; } return 0; case EK_CAST: return expr_looks_neg(ex->args[0]); default: return 0; }}/* Tell whether an expression is probably negative */int expr_is_neg(ex)Expr *ex;{ int i; i = possiblesigns(ex) & (1|4); if (i == 1) return 1; /* if expression really is negative! */ if (i == 4) return 0; /* if expression is definitely positive. */ return expr_looks_neg(ex);}int expr_neg_cost(a)Expr *a;{ int i, c; switch (a->kind) { case EK_CONST: case EK_LONGCONST: switch (ord_type(a->val.type)->kind) { case TK_INTEGER: case TK_CHAR: case TK_REAL: return 0; default: return 1; } case EK_NEG: return -1; case EK_TIMES: case EK_DIVIDE: for (i = 0; i < a->nargs; i++) { c = expr_neg_cost(a->args[i]); if (c <= 0) return c; } return 1; case EK_PLUS: for (i = 0; i < a->nargs; i++) { if (expr_looks_neg(a->args[i])) return 0; } return 1; default: return 1; }}Expr *enum_to_int(a)Expr *a;{ if (ord_type(a->val.type)->kind == TK_ENUM) { if (a->kind == EK_CAST && ord_type(a->args[0]->val.type)->kind == TK_INTEGER) return grabarg(a, 0); else return makeexpr_cast(a, tp_integer); } else return a;}Expr *neg_inside_sum(a)Expr *a;{ int i; for (i = 0; i < a->nargs; i++) a->args[i] = makeexpr_neg(a->args[i]); return a;}Expr *makeexpr_neg(a)Expr *a;{ int i; if (debug>2) { fprintf(outf,"makeexpr_neg("); dumpexpr(a); fprintf(outf,")\n"); } a = enum_to_int(a); switch (a->kind) { case EK_CONST: case EK_LONGCONST: switch (ord_type(a->val.type)->kind) { case TK_INTEGER: case TK_CHAR: if (a->val.i == MININT) valrange(); else a->val.i = - a->val.i; return a; case TK_REAL: if (!realzero(a->val.s)) { if (a->val.s[0] == '-') strchange(&a->val.s, a->val.s+1); else strchange(&a->val.s, format_s("-%s", a->val.s)); } return a; default: break; } break; case EK_PLUS: if (expr_neg_cost(a) <= 0) return neg_inside_sum(a); break; case EK_TIMES: case EK_DIVIDE: for (i = 0; i < a->nargs; i++) { if (expr_neg_cost(a->args[i]) <= 0) { a->args[i] = makeexpr_neg(a->args[i]); return a; } } break; case EK_CAST: if (a->val.type != tp_unsigned && a->val.type != tp_uint && a->val.type != tp_ushort && a->val.type != tp_ubyte && a->args[0]->val.type != tp_unsigned && a->args[0]->val.type != tp_uint && a->args[0]->val.type != tp_ushort && a->args[0]->val.type != tp_ubyte && expr_looks_neg(a->args[0])) { a->args[0] = makeexpr_neg(a->args[0]); return a; } break; case EK_NEG: return grabarg(a, 0); default: break; } return makeexpr_un(EK_NEG, promote_type(a->val.type), a);}#define ISCONST(kind) ((kind)==EK_CONST || (kind)==EK_LONGCONST)#define MOVCONST(ex) (ISCONST((ex)->kind) && (ex)->val.type->kind != TK_STRING)#define COMMUTATIVE (kind != EK_COMMA && type->kind != TK_REAL)Type *true_type(ex)Expr *ex;{ Meaning *mp; Type *type, *tp; while (ex->kind == EK_CAST) ex = ex->args[0]; type = ex->val.type; if (ex->kind == EK_VAR || ex->kind == EK_FUNCTION || ex->kind == EK_DOT) { mp = (Meaning *)ex->val.i; if (mp && mp->type && mp->type->kind != TK_VOID) type = mp->type; } if (ex->kind == EK_INDEX) { tp = true_type(ex->args[0]); if ((tp->kind == TK_ARRAY || tp->kind == TK_SMALLARRAY || tp->kind == TK_STRING) && tp->basetype && tp->basetype->kind != TK_VOID) type = tp->basetype; } if (type->kind == TK_SUBR) type = findbasetype(type, ODECL_NOPRES); return type;}int ischartype(ex)Expr *ex;{ if (ord_type(ex->val.type)->kind == TK_CHAR) return 1; if (true_type(ex)->kind == TK_CHAR) return 1; if (ISCONST(ex->kind) && ex->nargs > 0 && ex->args[0]->kind == EK_NAME && ex->args[0]->val.s[0] == '\'') return 1; return 0;}Static Expr *commute(a, b, kind)Expr *a, *b;enum exprkind kind;{ int i, di; Type *type; if (debug>2) { fprintf(outf,"commute("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); }#if 1 type = promote_type_bin(a->val.type, b->val.type);#else type = a->val.type; if (b->val.type->kind == TK_REAL) type = b->val.type;#endif if (MOVCONST(a) && !MOVCONST(b) && COMMUTATIVE) swapexprs(a, b); /* put constant last */ if (a->kind == kind) { di = (MOVCONST(a->args[a->nargs-1]) && COMMUTATIVE) ? -1 : 0; if (b->kind == kind) { for (i = 0; i < b->nargs; i++) insertarg(&a, a->nargs + di, b->args[i]); FREE(b); } else insertarg(&a, a->nargs + di, b); a->val.type = type; } else if (b->kind == kind) { if (MOVCONST(a) && COMMUTATIVE) insertarg(&b, b->nargs, a); else insertarg(&b, 0, a); a = b; a->val.type = type; } else { a = makeexpr_bin(kind, type, a, b); } if (debug>2) { fprintf(outf,"commute returns "); dumpexpr(a); fprintf(outf,"\n"); } return a;}int chararith = 0;Expr *makeexpr_plus(a, b)Expr *a, *b;{ int i, j, k, castdouble = 0; Type *type; if (debug>2) { fprintf(outf,"makeexpr_plus("); dumpexpr(a); fprintf(outf,", "); dumpexpr(b); fprintf(outf,")\n"); } if (!a) return b; if (!b) return a; if (a->kind == EK_NEG && a->args[0]->kind == EK_PLUS) a = neg_inside_sum(grabarg(a, 0)); if (b->kind == EK_NEG && b->args[0]->kind == EK_PLUS) b = neg_inside_sum(grabarg(b, 0)); a = commute(enum_to_int(a), enum_to_int(b), EK_PLUS); type = NULL; for (i = 0; i < a->nargs; i++) { if (ord_type(a->args[i]->val.type)->kind == TK_CHAR || a->args[i]->val.type->kind == TK_POINTER || a->args[i]->val.type->kind == TK_STRING) { /* for string literals */ if (type == ord_type(a->args[i]->val.type)) type = tp_integer; /* 'z'-'a' and p1-p2 are integers */ else type = ord_type(a->args[i]->val.type); } } if (type) a->val.type = type; for (i = 0; i < a->nargs && !ISCONST(a->args[i]->kind); i++) ; if (i < a->nargs-1) { for (j = i+1; j < a->nargs; j++) { if (ISCONST(a->args[j]->kind)) { if ((ord_type(a->args[i]->val.type) == ord_type(a->args[j]->val.type) || ord_type(a->args[i]->val.type)->kind == TK_INTEGER || ord_type(a->args[j]->val.type)->kind == TK_INTEGER) && (!(ischartype(a->args[i]) || ischartype(a->args[j])) || chararith || a->args[i]->val.i == - a->args[j]->val.i || a->args[i]->val.i == 0 || a->args[j]->val.i == 0) && (a->args[i]->val.type->kind != TK_REAL && a->args[i]->val.type->kind != TK_STRING && a->args[j]->val.type->kind != TK_REAL && a->args[j]->val.type->kind != TK_STRING)) { a->args[i]->val.i += a->args[j]->val.i; delfreearg(&a, j); j--; } else if (a->args[i]->val.type->kind == TK_STRING && ord_type(a->args[j]->val.type)->kind == TK_INTEGER && a->args[j]->val.i < 0 && a->args[j]->val.i >= -stringleaders) { /* strictly speaking, the following is illegal pointer arithmetic */ a->args[i] = makeexpr_lstring(a->args[i]->val.s + a->args[j]->val.i, a->args[i]->val.i - a->args[j]->val.i); for (k = 0; k < - a->args[j]->val.i; k++) a->args[i]->val.s[k] = '>'; delfreearg(&a, j); j--; } } } } if (checkconst(a->args[a->nargs-1], 0)) { 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); } for (i = 0; i < a->nargs; i++) { if (a->args[i]->kind == EK_NEG && nosideeffects(a->args[i], 1)) { for (j = 0; j < a->nargs; j++) { if (exprsame(a->args[j], a->args[i]->args[0], 1)) { delfreearg(&a, i); if (i < j) j--; else i--; delfreearg(&a, j); i--; break; } } } } if (a->nargs == 0) { type = a->val.type; FREE(a); a = gentle_cast(makeexpr_long(0), type); a->val.type = type; return a; } else if (a->nargs == 1) { b = a->args[0]; FREE(a); a = b; } else { if (a->nargs == 2 && ISCONST(a->args[1]->kind) && a->args[1]->val.i <= -127 && true_type(a->args[0]) == tp_char && signedchars != 0) { a->args[0] = force_unsigned(a->args[0]); } if (a->nargs > 2 && ISCONST(a->args[a->nargs-1]->kind) && ISCONST(a->args[a->nargs-2]->kind) && ischartype(a->args[a->nargs-1]) && ischartype(a->args[a->nargs-2])) { i = a->args[a->nargs-1]->val.i; j = a->args[a->nargs-2]->val.i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -