Add && and ||
This commit is contained in:
parent
b4272a67d1
commit
13333c971a
@ -73,6 +73,9 @@ typedef enum ENUMPAK {
|
|||||||
BINOP_LEQUAL = 13,
|
BINOP_LEQUAL = 13,
|
||||||
BINOP_GEQUAL = 14,
|
BINOP_GEQUAL = 14,
|
||||||
|
|
||||||
|
BINOP_LOGICAL_AND = 15,
|
||||||
|
BINOP_LOGICAL_OR = 16,
|
||||||
|
|
||||||
BINOP_WTF = 999,
|
BINOP_WTF = 999,
|
||||||
} BinaryOp;
|
} BinaryOp;
|
||||||
|
|
||||||
|
@ -129,6 +129,12 @@ static char *ast_dumpe(AST *tlc, AST *e) {
|
|||||||
case BINOP_MULHI:
|
case BINOP_MULHI:
|
||||||
op = "*^";
|
op = "*^";
|
||||||
break;
|
break;
|
||||||
|
case BINOP_LOGICAL_AND:
|
||||||
|
op = "&&";
|
||||||
|
break;
|
||||||
|
case BINOP_LOGICAL_OR:
|
||||||
|
op = "||";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -143,9 +143,17 @@ Token nct_tokenize(FILE *f) {
|
|||||||
return tok;
|
return tok;
|
||||||
} else if(c == '&') {
|
} else if(c == '&') {
|
||||||
tok.type = TOKEN_AMPERSAND;
|
tok.type = TOKEN_AMPERSAND;
|
||||||
|
int c = nextc(f);
|
||||||
|
if(c == '&') {
|
||||||
|
tok.type = TOKEN_DOUBLE_AMPERSAND;
|
||||||
|
} else ungetc(c, f);
|
||||||
return tok;
|
return tok;
|
||||||
} else if(c == '|') {
|
} else if(c == '|') {
|
||||||
tok.type = TOKEN_VERTICAL_BAR;
|
tok.type = TOKEN_VERTICAL_BAR;
|
||||||
|
int c = nextc(f);
|
||||||
|
if(c == '|') {
|
||||||
|
tok.type = TOKEN_DOUBLE_VERTICAL_BAR;
|
||||||
|
} else ungetc(c, f);
|
||||||
return tok;
|
return tok;
|
||||||
} else if(c == '^') {
|
} else if(c == '^') {
|
||||||
tok.type = TOKEN_CARET;
|
tok.type = TOKEN_CARET;
|
||||||
|
@ -27,7 +27,9 @@ typedef enum {
|
|||||||
TOKEN_BREAK,
|
TOKEN_BREAK,
|
||||||
TOKEN_COMMA,
|
TOKEN_COMMA,
|
||||||
TOKEN_AMPERSAND,
|
TOKEN_AMPERSAND,
|
||||||
|
TOKEN_DOUBLE_AMPERSAND,
|
||||||
TOKEN_VERTICAL_BAR,
|
TOKEN_VERTICAL_BAR,
|
||||||
|
TOKEN_DOUBLE_VERTICAL_BAR,
|
||||||
TOKEN_CARET,
|
TOKEN_CARET,
|
||||||
TOKEN_TILDE,
|
TOKEN_TILDE,
|
||||||
TOKEN_DOUBLE_EQUALS,
|
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;
|
AST *e = NULL;
|
||||||
|
|
||||||
if(peek(P, 0).type == TOKEN_NUMBER) {
|
if(peek(P, 0).type == TOKEN_NUMBER) {
|
||||||
@ -347,7 +347,7 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
} else if(lOP == 5) {
|
} else if(lOP == 6) {
|
||||||
if(maybe(P, TOKEN_STAR)) {
|
if(maybe(P, TOKEN_STAR)) {
|
||||||
ASTExprUnaryOp *astop = alloc_node(P, sizeof(*astop));
|
ASTExprUnaryOp *astop = alloc_node(P, sizeof(*astop));
|
||||||
astop->nodeKind = AST_EXPR_UNARY_OP;
|
astop->nodeKind = AST_EXPR_UNARY_OP;
|
||||||
@ -401,7 +401,7 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
return (AST *) astop;
|
return (AST *) astop;
|
||||||
}
|
}
|
||||||
} else return nct_parse_expression(P, lOP + 1);
|
} else return nct_parse_expression(P, lOP + 1);
|
||||||
} else if(lOP == 4) {
|
} else if(lOP == 5) {
|
||||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
AST *ret = nct_parse_expression(P, lOP + 1);
|
||||||
|
|
||||||
while(peek(P, 0).type == TOKEN_PAREN_L || peek(P, 0).type == TOKEN_SQUAREN_L) {
|
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;
|
return ret;
|
||||||
} else if(lOP == 3) {
|
} else if(lOP == 4) {
|
||||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
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) {
|
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;
|
return ret;
|
||||||
} else if(lOP == 2) {
|
} else if(lOP == 3) {
|
||||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
AST *ret = nct_parse_expression(P, lOP + 1);
|
||||||
|
|
||||||
if(
|
if(
|
||||||
@ -603,7 +603,7 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
} else if(lOP == 1) {
|
} else if(lOP == 2) {
|
||||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
AST *ret = nct_parse_expression(P, lOP + 1);
|
||||||
|
|
||||||
while(maybe(P, TOKEN_AS)) {
|
while(maybe(P, TOKEN_AS)) {
|
||||||
@ -611,6 +611,35 @@ AST *nct_parse_expression(Parser *P, int lOP) {
|
|||||||
ret = ast_cast_expr(ret, castTo);
|
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;
|
return ret;
|
||||||
} else if(lOP == 0) {
|
} else if(lOP == 0) {
|
||||||
AST *ret = nct_parse_expression(P, lOP + 1);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -116,10 +116,107 @@ static void dumben_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *
|
|||||||
e->exprBinOp.operands[1] = varify(tlc, chu, stmtPrev, s, e->exprBinOp.operands[1]);
|
e->exprBinOp.operands[1] = varify(tlc, chu, stmtPrev, s, e->exprBinOp.operands[1]);
|
||||||
this->effective = 1;
|
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 {
|
} 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;
|
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];
|
*nptr = n->exprBinOp.operands[0];
|
||||||
|
|
||||||
*success = true;
|
*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)`
|
// Turn `!(a op b)` to `(a !op b)`
|
||||||
|
|
||||||
n->exprUnOp.operand->exprBinOp.operator = binop_comp_opposite(n->exprUnOp.operand->exprBinOp.operator);
|
n->exprUnOp.operand->exprBinOp.operator = binop_comp_opposite(n->exprUnOp.operand->exprBinOp.operator);
|
||||||
|
|
||||||
*nptr = n->exprUnOp.operand;
|
*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;
|
*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) {
|
} 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
|
// 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) {
|
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, pre_dumb_visitor, NULL);
|
||||||
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, decompose_symbol_record_field_access, 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")) {
|
ast_denoop(tlc, NULL);
|
||||||
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_commutativity_pass(tlc);
|
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) {
|
void dumben_go(AST* tlc) {
|
||||||
|
Loading…
Reference in New Issue
Block a user