commit ef05ad6ff2560acd1364b1d90cf52ec95603bc9e
parent 9e40c0c4f8f15b13a2a39bab393f5a921ec83275
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 15 Apr 2014 11:18:54 +0200
Add logical negation
Logical negation are transformed into ternary operators.
Diffstat:
M | cc.h | | | 2 | +- |
M | expr.c | | | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
M | lex.c | | | 1 | - |
M | main.c | | | 4 | +++- |
4 files changed, 55 insertions(+), 15 deletions(-)
diff --git a/cc.h b/cc.h
@@ -225,7 +225,7 @@ enum {
OBXOR, OBOR, OASSIGN, OA_MUL, OA_DIV,
OA_MOD, OA_ADD, OA_SUB, OA_SHL, OA_SHR,
OA_AND, OA_XOR, OA_OR, OADDR, OAND, OOR,
- ONEG, OCPL,
+ ONEG, OCPL, OEXC
};
extern void
diff --git a/expr.c b/expr.c
@@ -5,8 +5,22 @@
#define SWAP(x1, x2, t) (t = x1, x1 = x2, x2 = t)
+static Symbol *zero, *one;
+
Node *expr(void);
+void
+init_expr(void)
+{
+ static Symbol zdummy, odummy;
+
+ zdummy.type = odummy.type = inttype;
+ zdummy.u.i = 0;
+ odummy.u.i = 1;
+ zero = &zdummy;
+ one = &odummy;
+}
+
static Node *
promote(Node *np)
{
@@ -243,6 +257,20 @@ error:
}
static Node *
+eval(Node *np, char neg)
+{
+ Node *ifyes, *ifno, *cmp;
+ char op;
+
+ ifyes = node(emitconst, inttype, SYM(one), 0);
+ ifno = node(emitconst, inttype, SYM(zero), 0);
+ cmp = node(emitconst, inttype, SYM(zero), 0);
+ op = (neg) ? OEQ : ONE;
+
+ return ternarycode(compare(op, np, cmp), ifyes, ifno);
+}
+
+static Node *
incdec(Node *np, char op)
{
Type *tp;
@@ -365,11 +393,11 @@ unary(void)
case INC: case DEC:
op = (yytoken == INC) ? OINC : ODEC;
next();
- return incdec(unary(), op);
- /* TODO: case '!': */
+ return incdec(unary(), op); /* TODO: unary or cast? */
+ case '!': op = OEXC; break;
/* TODO: case '&': */
/* TODO: case '*': */
- case '+': op = 0; break;
+ case '+': op = OADD; break;
case '~': op = OCPL; break;
case '-': op = ONEG; break;
default: return postfix();
@@ -380,21 +408,32 @@ unary(void)
t = BTYPE(np->type);
switch (op) {
- case OCPL:
+ case OEXC:
+ switch (t) {
+ case FTN: case ARY:
+ np = addr2ptr(np);
+ case INT: case FLOAT: case PTR:
+ np = eval(np, 1);
+ break;
+ default:
+ goto bad_operand;
+ }
+ break;
+ case OCPL: case OADD:
if (t != INT)
- goto bad_complement;
+ goto bad_operand;
+ if (op == OADD)
+ break;
case ONEG:
if (!isarith(t))
- goto bad_arithm;
+ goto bad_operand;
np = unarycode(op, np->type, np);
- case 0:
- return np;
}
-bad_complement:
- error("bad operand in bit-complement");
-bad_arithm:
- error("bad arithmetic operand in unary expression");
+ return np;
+
+bad_operand:
+ error("bad operand in unary expression");
}
static Node *
diff --git a/lex.c b/lex.c
@@ -28,7 +28,6 @@ integer(char *s, char base)
static char ch;
/* TODO: implement again */
-
type:
switch (ch = toupper(getc(yyin))) {
case 'L':
diff --git a/main.c b/main.c
@@ -4,7 +4,8 @@
#include "cc.h"
-extern void extdecl(void), init_keywords(void), open_file(const char *file);
+extern void extdecl(void), init_keywords(void),
+ open_file(const char *file), init_expr(void);
struct user_opt options;
@@ -12,6 +13,7 @@ int
main(int argc, char *argv[])
{
init_keywords();
+ init_expr();
open_file(NULL);
for (next(); yytoken != EOFTOK; extdecl());
/* nothing */;