Add && and ||
This commit is contained in:
parent
b4272a67d1
commit
13333c971a
@ -73,6 +73,9 @@ typedef enum ENUMPAK {
|
||||
BINOP_LEQUAL = 13,
|
||||
BINOP_GEQUAL = 14,
|
||||
|
||||
BINOP_LOGICAL_AND = 15,
|
||||
BINOP_LOGICAL_OR = 16,
|
||||
|
||||
BINOP_WTF = 999,
|
||||
} BinaryOp;
|
||||
|
||||
|
@ -129,6 +129,12 @@ static char *ast_dumpe(AST *tlc, AST *e) {
|
||||
case BINOP_MULHI:
|
||||
op = "*^";
|
||||
break;
|
||||
case BINOP_LOGICAL_AND:
|
||||
op = "&&";
|
||||
break;
|
||||
case BINOP_LOGICAL_OR:
|
||||
op = "||";
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
@ -143,9 +143,17 @@ Token nct_tokenize(FILE *f) {
|
||||
return tok;
|
||||
} else if(c == '&') {
|
||||
tok.type = TOKEN_AMPERSAND;
|
||||
int c = nextc(f);
|
||||
if(c == '&') {
|
||||
tok.type = TOKEN_DOUBLE_AMPERSAND;
|
||||
} else ungetc(c, f);
|
||||
return tok;
|
||||
} else if(c == '|') {
|
||||
tok.type = TOKEN_VERTICAL_BAR;
|
||||
int c = nextc(f);
|
||||
if(c == '|') {
|
||||
tok.type = TOKEN_DOUBLE_VERTICAL_BAR;
|
||||
} else ungetc(c, f);
|
||||
return tok;
|
||||
} else if(c == '^') {
|
||||
tok.type = TOKEN_CARET;
|
||||
|
@ -27,7 +27,9 @@ typedef enum {
|
||||
TOKEN_BREAK,
|
||||
TOKEN_COMMA,
|
||||
TOKEN_AMPERSAND,
|
||||
TOKEN_DOUBLE_AMPERSAND,
|
||||
TOKEN_VERTICAL_BAR,
|
||||
TOKEN_DOUBLE_VERTICAL_BAR,
|
||||
TOKEN_CARET,
|
||||
TOKEN_TILDE,
|
||||
TOKEN_DOUBLE_EQUALS,
|
||||
|
43
src/parse.c
43
src/parse.c
@ -250,7 +250,7 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
||||
}
|
||||
}
|
||||
|
||||
if(lOP == 6) {
|
||||
if(lOP == 7) {
|
||||
AST *e = NULL;
|
||||
|
||||
if(peek(P, 0).type == TOKEN_NUMBER) {
|
||||
@ -347,7 +347,7 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
||||
}
|
||||
|
||||
return e;
|
||||
} else if(lOP == 5) {
|
||||
} else if(lOP == 6) {
|
||||
if(maybe(P, TOKEN_STAR)) {
|
||||
ASTExprUnaryOp *astop = alloc_node(P, sizeof(*astop));
|
||||
astop->nodeKind = AST_EXPR_UNARY_OP;
|
||||
@ -401,7 +401,7 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
||||
return (AST *) astop;
|
||||
}
|
||||
} else return nct_parse_expression(P, lOP + 1);
|
||||
} else if(lOP == 4) {
|
||||
} else if(lOP == 5) {
|
||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
||||
|
||||
while(peek(P, 0).type == TOKEN_PAREN_L || peek(P, 0).type == TOKEN_SQUAREN_L) {
|
||||
@ -524,7 +524,7 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else if(lOP == 3) {
|
||||
} else if(lOP == 4) {
|
||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
||||
|
||||
if(peek(P, 0).type == TOKEN_STAR || peek(P, 0).type == TOKEN_SLASH || peek(P, 0).type == TOKEN_STAR_CARET) {
|
||||
@ -564,7 +564,7 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else if(lOP == 2) {
|
||||
} else if(lOP == 3) {
|
||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
||||
|
||||
if(
|
||||
@ -603,7 +603,7 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else if(lOP == 1) {
|
||||
} else if(lOP == 2) {
|
||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
||||
|
||||
while(maybe(P, TOKEN_AS)) {
|
||||
@ -611,6 +611,35 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
||||
ret = ast_cast_expr(ret, castTo);
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else if(lOP == 1) {
|
||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
||||
|
||||
if(peek(P, 0).type == TOKEN_DOUBLE_AMPERSAND || peek(P, 0).type == TOKEN_DOUBLE_VERTICAL_BAR) {
|
||||
while(1) {
|
||||
BinaryOp op;
|
||||
if(maybe(P, TOKEN_DOUBLE_AMPERSAND)) op = BINOP_LOGICAL_AND;
|
||||
else if(maybe(P, TOKEN_DOUBLE_VERTICAL_BAR)) op = BINOP_LOGICAL_OR;
|
||||
else break;
|
||||
|
||||
ASTExprBinaryOp *astop = alloc_node(P, sizeof(*astop));
|
||||
astop->nodeKind = AST_EXPR_BINARY_OP;
|
||||
astop->type = NULL;
|
||||
astop->operator = op;
|
||||
astop->operands[0] = ret;
|
||||
|
||||
ASTExpr *operand = &(astop->operands[1] = nct_parse_expression(P, lOP + 1))->expression;
|
||||
|
||||
if(operand->type->type != TYPE_TYPE_PRIMITIVE) {
|
||||
stahp_token(&P->tokens[P->i], "Invalid combination of operator and operand types.");
|
||||
}
|
||||
|
||||
binop_implicit_cast(astop);
|
||||
|
||||
ret = (AST*) astop;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else if(lOP == 0) {
|
||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
||||
@ -644,8 +673,6 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
||||
}
|
||||
}
|
||||
|
||||
//ret = ast_expression_optimize(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
|
@ -117,9 +117,106 @@ static void dumben_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *
|
||||
this->effective = 1;
|
||||
}
|
||||
|
||||
} else if(e->nodeKind == AST_EXPR_UNARY_OP && e->exprUnOp.operator == UNOP_NOT && e->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && (e->exprUnOp.operand->exprBinOp.operator == BINOP_LOGICAL_AND || e->exprUnOp.operand->exprBinOp.operator == BINOP_LOGICAL_OR)) {
|
||||
|
||||
AST *binop = e->exprUnOp.operand;
|
||||
|
||||
e->exprUnOp.operand = binop->exprBinOp.operands[0];
|
||||
binop->exprBinOp.operands[0] = e;
|
||||
|
||||
AST *unop2 = calloc(1, sizeof(ASTExprUnaryOp));
|
||||
unop2->nodeKind = AST_EXPR_UNARY_OP;
|
||||
unop2->expression.type = binop->exprBinOp.operands[1]->expression.type;
|
||||
unop2->exprUnOp.operator = UNOP_NOT;
|
||||
unop2->exprUnOp.operand = binop->exprBinOp.operands[1];
|
||||
binop->exprBinOp.operands[1] = unop2;
|
||||
|
||||
binop->exprBinOp.operator = binop->exprBinOp.operator == BINOP_LOGICAL_AND ? BINOP_LOGICAL_OR : BINOP_LOGICAL_AND;
|
||||
|
||||
s->stmtJump.condition = binop;
|
||||
|
||||
ast_denoop(tlc, &s->stmtJump.condition);
|
||||
|
||||
this->effective = 1;
|
||||
|
||||
} else if(e->nodeKind == AST_EXPR_BINARY_OP && e->exprBinOp.operator == BINOP_LOGICAL_OR) {
|
||||
|
||||
AST *cond0 = e->exprBinOp.operands[0];
|
||||
AST *cond1 = e->exprBinOp.operands[1];
|
||||
|
||||
s->stmtJump.condition = cond0;
|
||||
|
||||
AST *jump2 = calloc(1, sizeof(ASTStmtJump));
|
||||
jump2->nodeKind = AST_STMT_JUMP;
|
||||
jump2->stmtJump.condition = cond1;
|
||||
jump2->stmtJump.label = strdup(s->stmtJump.label);
|
||||
jump2->statement.next = s->statement.next;
|
||||
s->statement.next = jump2;
|
||||
|
||||
this->effective = 1;
|
||||
|
||||
} else if(e->nodeKind == AST_EXPR_BINARY_OP && e->exprBinOp.operator == BINOP_LOGICAL_AND) {
|
||||
|
||||
static size_t idx = 0;
|
||||
|
||||
AST *cond0 = e->exprBinOp.operands[0];
|
||||
AST *cond1 = e->exprBinOp.operands[1];
|
||||
|
||||
AST *lbl = calloc(1, sizeof(ASTStmtLabel));
|
||||
lbl->nodeKind = AST_STMT_LABEL;
|
||||
lbl->stmtLabel.name = malp("$dla%lu", idx++);
|
||||
lbl->statement.next = s->statement.next;
|
||||
|
||||
AST *unop = calloc(1, sizeof(ASTExprUnaryOp));
|
||||
unop->nodeKind = AST_EXPR_UNARY_OP;
|
||||
unop->expression.type = cond0->expression.type;
|
||||
unop->exprUnOp.operator = UNOP_NOT;
|
||||
unop->exprUnOp.operand = cond0;
|
||||
s->stmtJump.condition = unop;
|
||||
|
||||
AST *jump2 = calloc(1, sizeof(ASTStmtJump));
|
||||
jump2->nodeKind = AST_STMT_JUMP;
|
||||
jump2->stmtJump.condition = cond1;
|
||||
jump2->stmtJump.label = strdup(s->stmtJump.label);
|
||||
jump2->statement.next = lbl;
|
||||
|
||||
s->stmtJump.label = strdup(lbl->stmtLabel.name);
|
||||
|
||||
s->statement.next = jump2;
|
||||
|
||||
ast_denoop(tlc, &s->stmtJump.condition);
|
||||
|
||||
this->effective = 1;
|
||||
|
||||
} else {
|
||||
|
||||
s->stmtJump.condition = varify(tlc, chu, stmtPrev, s, e);
|
||||
AST *v = e;
|
||||
|
||||
bool not = v->nodeKind == AST_EXPR_UNARY_OP && v->exprUnOp.operator == UNOP_NOT;
|
||||
if(not) {
|
||||
v = v->exprUnOp.operand;
|
||||
}
|
||||
|
||||
if(v->nodeKind != AST_EXPR_VAR) {
|
||||
v = varify(tlc, chu, stmtPrev, s, e);
|
||||
}
|
||||
|
||||
AST *zero = calloc(1, sizeof(ASTExprPrimitive));
|
||||
zero->nodeKind = AST_EXPR_PRIMITIVE;
|
||||
zero->expression.type = v->expression.type;
|
||||
zero->exprPrim.val = 0;
|
||||
|
||||
AST *binop = calloc(1, sizeof(ASTExprBinaryOp));
|
||||
binop->nodeKind = AST_EXPR_BINARY_OP;
|
||||
binop->expression.type = v->expression.type;
|
||||
binop->exprBinOp.operator = not ? BINOP_EQUAL : BINOP_NEQUAL;
|
||||
binop->exprBinOp.operands[0] = v;
|
||||
binop->exprBinOp.operands[1] = zero;
|
||||
|
||||
s->stmtJump.condition = binop;
|
||||
|
||||
ast_denoop(tlc, &s->stmtJump.condition);
|
||||
|
||||
this->effective = 1;
|
||||
|
||||
}
|
||||
@ -507,13 +604,19 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST
|
||||
*nptr = n->exprBinOp.operands[0];
|
||||
|
||||
*success = true;
|
||||
} else if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_NOT && n->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP) {
|
||||
} else if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_NOT && n->exprUnOp.operand->nodeKind == AST_EXPR_BINARY_OP && binop_comp_opposite(n->exprUnOp.operand->exprBinOp.operator) != BINOP_WTF) {
|
||||
// Turn `!(a op b)` to `(a !op b)`
|
||||
|
||||
n->exprUnOp.operand->exprBinOp.operator = binop_comp_opposite(n->exprUnOp.operand->exprBinOp.operator);
|
||||
|
||||
*nptr = n->exprUnOp.operand;
|
||||
|
||||
*success = true;
|
||||
} else if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_NOT && n->exprUnOp.operand->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operand->exprUnOp.operator == UNOP_NOT) {
|
||||
// Turn `!!x` to `x`
|
||||
|
||||
*nptr = n->exprUnOp.operand->exprUnOp.operand;
|
||||
|
||||
*success = true;
|
||||
} else if(n->nodeKind == AST_EXPR_CAST && n->exprCast.what->expression.type->type == TYPE_TYPE_POINTER && n->exprCast.to->type == TYPE_TYPE_POINTER) {
|
||||
// Turn (x as A*) into x, since all pointer types are identical in Nectar's AST
|
||||
@ -540,6 +643,18 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST
|
||||
}
|
||||
}
|
||||
|
||||
void ast_denoop(AST *tlc, AST **node) {
|
||||
if(!node) {
|
||||
node = &tlc;
|
||||
}
|
||||
|
||||
struct DenoopState state = {.targetTLC = tlc};
|
||||
do {
|
||||
state.success = false;
|
||||
generic_visitor(node, NULL, NULL, tlc, tlc, &state, denoop_visitor, NULL);
|
||||
} while(state.success);
|
||||
}
|
||||
|
||||
void dumben_pre(AST *tlc) {
|
||||
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, pre_dumb_visitor, NULL);
|
||||
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, decompose_symbol_record_field_access, NULL);
|
||||
@ -552,25 +667,9 @@ void dumben_pre(AST *tlc) {
|
||||
}
|
||||
}
|
||||
|
||||
if(ntc_get_int("pdbg")) {
|
||||
char *astdump = ast_dump(tlc);
|
||||
fprintf(stderr, "### BEFORE DENOOP ###\n%s\n", astdump);
|
||||
free(astdump);
|
||||
}
|
||||
|
||||
struct DenoopState state = {.targetTLC = tlc};
|
||||
do {
|
||||
state.success = false;
|
||||
generic_visitor(&tlc, NULL, NULL, tlc, tlc, &state, denoop_visitor, NULL);
|
||||
} while(state.success);
|
||||
ast_denoop(tlc, NULL);
|
||||
|
||||
ast_commutativity_pass(tlc);
|
||||
|
||||
if(ntc_get_int("pdbg")) {
|
||||
char *astdump = ast_dump(tlc);
|
||||
fprintf(stderr, "### AFTER DENOOP ###\n%s\n", astdump);
|
||||
free(astdump);
|
||||
}
|
||||
}
|
||||
|
||||
void dumben_go(AST* tlc) {
|
||||
|
Loading…
Reference in New Issue
Block a user