Internal change: IntervalExpr is now a BinaryExpr

This commit is contained in:
Ginger Bill
2017-04-22 10:10:49 +01:00
parent 0ea815db49
commit 3fd37c6dc5
4 changed files with 61 additions and 65 deletions
-5
View File
@@ -4921,11 +4921,6 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
return kind; return kind;
case_end; case_end;
case_ast_node(i, IntervalExpr, node);
error_node(node, "Invalid use of an interval expression");
return kind;
case_end;
case_ast_node(i, Implicit, node) case_ast_node(i, Implicit, node)
switch (i->kind) { switch (i->kind) {
case Token_context: case Token_context:
+7 -5
View File
@@ -712,9 +712,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Entity *entities[2] = {0}; Entity *entities[2] = {0};
isize entity_count = 0; isize entity_count = 0;
AstNode *expr = unparen_expr(rs->expr);
if (rs->expr != NULL && rs->expr->kind == AstNode_IntervalExpr) {
ast_node(ie, IntervalExpr, rs->expr); if (is_ast_node_a_range(expr)) {
ast_node(ie, BinaryExpr, expr);
Operand x = {Addressing_Invalid}; Operand x = {Addressing_Invalid};
Operand y = {Addressing_Invalid}; Operand y = {Addressing_Invalid};
@@ -966,10 +968,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
ast_node(cc, CaseClause, stmt); ast_node(cc, CaseClause, stmt);
for_array(j, cc->list) { for_array(j, cc->list) {
AstNode *expr = cc->list.e[j]; AstNode *expr = unparen_expr(cc->list.e[j]);
if (expr->kind == AstNode_IntervalExpr) { if (is_ast_node_a_range(expr)) {
ast_node(ie, IntervalExpr, expr); ast_node(ie, BinaryExpr, expr);
Operand lhs = {0}; Operand lhs = {0};
Operand rhs = {0}; Operand rhs = {0};
check_expr(c, &lhs, ie->left); check_expr(c, &lhs, ie->left);
+7 -6
View File
@@ -5535,7 +5535,7 @@ void ir_build_range_string(irProcedure *proc, irValue *expr, Type *val_type,
if (done_) *done_ = done; if (done_) *done_ = done;
} }
void ir_build_range_interval(irProcedure *proc, AstNodeIntervalExpr *node, Type *val_type, void ir_build_range_interval(irProcedure *proc, AstNodeBinaryExpr *node, Type *val_type,
irValue **val_, irValue **idx_, irBlock **loop_, irBlock **done_) { irValue **val_, irValue **idx_, irBlock **loop_, irBlock **done_) {
// TODO(bill): How should the behaviour work for lower and upper bounds checking for iteration? // TODO(bill): How should the behaviour work for lower and upper bounds checking for iteration?
// If `lower` is changed, should `val` do so or is that not typical behaviour? // If `lower` is changed, should `val` do so or is that not typical behaviour?
@@ -6038,9 +6038,10 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
irValue *index = NULL; irValue *index = NULL;
irBlock *loop = NULL; irBlock *loop = NULL;
irBlock *done = NULL; irBlock *done = NULL;
AstNode *expr = unparen_expr(rs->expr);
if (rs->expr->kind == AstNode_IntervalExpr) { if (is_ast_node_a_range(expr)) {
ir_build_range_interval(proc, &rs->expr->IntervalExpr, val_type, &val, &index, &loop, &done); ir_build_range_interval(proc, &expr->BinaryExpr, val_type, &val, &index, &loop, &done);
} else { } else {
Type *expr_type = type_of_expr(proc->module->info, rs->expr); Type *expr_type = type_of_expr(proc->module->info, rs->expr);
Type *et = base_type(type_deref(expr_type)); Type *et = base_type(type_deref(expr_type));
@@ -6194,11 +6195,11 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
irBlock *next_cond = NULL; irBlock *next_cond = NULL;
for_array(j, cc->list) { for_array(j, cc->list) {
AstNode *expr = cc->list.e[j]; AstNode *expr = unparen_expr(cc->list.e[j]);
next_cond = ir_new_block(proc, clause, "match.case.next"); next_cond = ir_new_block(proc, clause, "match.case.next");
irValue *cond = v_false; irValue *cond = v_false;
if (expr->kind == AstNode_IntervalExpr) { if (is_ast_node_a_range(expr)) {
ast_node(ie, IntervalExpr, expr); ast_node(ie, BinaryExpr, expr);
TokenKind op = {0}; TokenKind op = {0};
switch (ie->op.kind) { switch (ie->op.kind) {
case Token_Ellipsis: op = Token_LtEq; break; case Token_Ellipsis: op = Token_LtEq; break;
+47 -49
View File
@@ -30,6 +30,7 @@ typedef struct AstFile {
// < 0: In Control Clause // < 0: In Control Clause
// NOTE(bill): Used to prevent type literals in control clauses // NOTE(bill): Used to prevent type literals in control clauses
isize expr_level; isize expr_level;
bool allow_range;
AstNodeArray decls; AstNodeArray decls;
bool is_global_scope; bool is_global_scope;
@@ -181,7 +182,6 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
AST_NODE_KIND(CastExpr, "cast expression", struct { Token token; AstNode *type, *expr; Token open, close; }) \ AST_NODE_KIND(CastExpr, "cast expression", struct { Token token; AstNode *type, *expr; Token open, close; }) \
AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \ AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \
AST_NODE_KIND(TernaryExpr, "ternary expression", struct { AstNode *cond, *x, *y; }) \ AST_NODE_KIND(TernaryExpr, "ternary expression", struct { AstNode *cond, *x, *y; }) \
AST_NODE_KIND(IntervalExpr, "interval expression", struct { Token op; AstNode *left, *right; }) \
AST_NODE_KIND(_ExprEnd, "", i32) \ AST_NODE_KIND(_ExprEnd, "", i32) \
AST_NODE_KIND(_StmtBegin, "", i32) \ AST_NODE_KIND(_StmtBegin, "", i32) \
AST_NODE_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \ AST_NODE_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \
@@ -485,7 +485,6 @@ Token ast_node_token(AstNode *node) {
case AstNode_FieldValue: return node->FieldValue.eq; case AstNode_FieldValue: return node->FieldValue.eq;
case AstNode_DerefExpr: return node->DerefExpr.op; case AstNode_DerefExpr: return node->DerefExpr.op;
case AstNode_TernaryExpr: return ast_node_token(node->TernaryExpr.cond); case AstNode_TernaryExpr: return ast_node_token(node->TernaryExpr.cond);
case AstNode_IntervalExpr: return ast_node_token(node->IntervalExpr.left);
case AstNode_BadStmt: return node->BadStmt.begin; case AstNode_BadStmt: return node->BadStmt.begin;
case AstNode_EmptyStmt: return node->EmptyStmt.token; case AstNode_EmptyStmt: return node->EmptyStmt.token;
@@ -710,16 +709,6 @@ AstNode *ast_deref_expr(AstFile *f, AstNode *expr, Token op) {
return result; return result;
} }
AstNode *ast_interval_expr(AstFile *f, Token op, AstNode *left, AstNode *right) {
AstNode *result = make_ast_node(f, AstNode_IntervalExpr);
result->IntervalExpr.op = op;
result->IntervalExpr.left = left;
result->IntervalExpr.right = right;
return result;
}
@@ -1232,6 +1221,9 @@ Token expect_operator(AstFile *f) {
if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) { if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
syntax_error(f->curr_token, "Expected an operator, got `%.*s`", syntax_error(f->curr_token, "Expected an operator, got `%.*s`",
LIT(token_strings[prev.kind])); LIT(token_strings[prev.kind]));
} else if (!f->allow_range && (prev.kind == Token_Ellipsis || prev.kind == Token_HalfClosed)) {
syntax_error(f->curr_token, "Expected an non-range operator, got `%.*s`",
LIT(token_strings[prev.kind]));
} }
next_token(f); next_token(f);
return prev; return prev;
@@ -1977,6 +1969,9 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
if (lhs) { if (lhs) {
// TODO(bill): Handle this // TODO(bill): Handle this
} }
bool prev_allow_range = f->allow_range;
f->allow_range = false;
Token open = {0}, close = {0}, interval = {0}; Token open = {0}, close = {0}, interval = {0};
AstNode *indices[3] = {0}; AstNode *indices[3] = {0};
isize ellipsis_count = 0; isize ellipsis_count = 0;
@@ -2026,6 +2021,8 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
} else { } else {
operand = ast_index_expr(f, operand, indices[0], open, close); operand = ast_index_expr(f, operand, indices[0], open, close);
} }
f->allow_range = prev_allow_range;
} break; } break;
case Token_Pointer: // Deference case Token_Pointer: // Deference
@@ -2090,27 +2087,49 @@ AstNode *parse_unary_expr(AstFile *f, bool lhs) {
return parse_atom_expr(f, lhs); return parse_atom_expr(f, lhs);
} }
bool is_ast_node_a_range(AstNode *expr) {
if (expr == NULL) {
return false;
}
if (expr->kind != AstNode_BinaryExpr) {
return false;
}
TokenKind op = expr->BinaryExpr.op.kind;
switch (op) {
case Token_Ellipsis:
case Token_HalfClosed:
return true;
}
return false;
}
// NOTE(bill): result == priority // NOTE(bill): result == priority
i32 token_precedence(TokenKind t) { i32 token_precedence(AstFile *f, TokenKind t) {
switch (t) { switch (t) {
case Token_Question: case Token_Question:
return 1; return 1;
case Token_Ellipsis:
case Token_HalfClosed:
if (f->allow_range) {
return 2;
}
return 0;
case Token_CmpOr: case Token_CmpOr:
return 2;
case Token_CmpAnd:
return 3; return 3;
case Token_CmpAnd:
return 4;
case Token_CmpEq: case Token_CmpEq:
case Token_NotEq: case Token_NotEq:
case Token_Lt: case Token_Lt:
case Token_Gt: case Token_Gt:
case Token_LtEq: case Token_LtEq:
case Token_GtEq: case Token_GtEq:
return 4; return 5;
case Token_Add: case Token_Add:
case Token_Sub: case Token_Sub:
case Token_Or: case Token_Or:
case Token_Xor: case Token_Xor:
return 5; return 6;
case Token_Mul: case Token_Mul:
case Token_Quo: case Token_Quo:
case Token_Mod: case Token_Mod:
@@ -2118,17 +2137,17 @@ i32 token_precedence(TokenKind t) {
case Token_AndNot: case Token_AndNot:
case Token_Shl: case Token_Shl:
case Token_Shr: case Token_Shr:
return 6; return 7;
} }
return 0; return 0;
} }
AstNode *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) { AstNode *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
AstNode *expr = parse_unary_expr(f, lhs); AstNode *expr = parse_unary_expr(f, lhs);
for (i32 prec = token_precedence(f->curr_token.kind); prec >= prec_in; prec--) { for (i32 prec = token_precedence(f, f->curr_token.kind); prec >= prec_in; prec--) {
for (;;) { for (;;) {
Token op = f->curr_token; Token op = f->curr_token;
i32 op_prec = token_precedence(op.kind); i32 op_prec = token_precedence(f, op.kind);
if (op_prec != prec) { if (op_prec != prec) {
// NOTE(bill): This will also catch operators that are not valid "binary" operators // NOTE(bill): This will also catch operators that are not valid "binary" operators
break; break;
@@ -2144,7 +2163,7 @@ AstNode *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) {
expr = ast_ternary_expr(f, cond, x, y); expr = ast_ternary_expr(f, cond, x, y);
} else { } else {
AstNode *right = parse_binary_expr(f, false, prec+1); AstNode *right = parse_binary_expr(f, false, prec+1);
if (!right) { if (right == NULL) {
syntax_error(op, "Expected expression on the right-hand side of the binary operator"); syntax_error(op, "Expected expression on the right-hand side of the binary operator");
} }
expr = ast_binary_expr(f, op, expr, right); expr = ast_binary_expr(f, op, expr, right);
@@ -2308,16 +2327,10 @@ AstNode *parse_simple_stmt(AstFile *f, bool in_stmt_ok) {
case Token_in: case Token_in:
if (in_stmt_ok) { if (in_stmt_ok) {
allow_token(f, Token_in); allow_token(f, Token_in);
bool prev_allow_range = f->allow_range;
f->allow_range = true;
AstNode *expr = parse_expr(f, false); AstNode *expr = parse_expr(f, false);
switch (f->curr_token.kind) { f->allow_range = prev_allow_range;
case Token_HalfClosed:
case Token_Ellipsis: {
Token op = f->curr_token;
next_token(f);
AstNode *right = parse_expr(f, false);
expr = ast_interval_expr(f, op, expr, right);
} break;
}
AstNodeArray rhs = {0}; AstNodeArray rhs = {0};
array_init_count(&rhs, heap_allocator(), 1); array_init_count(&rhs, heap_allocator(), 1);
@@ -3088,25 +3101,10 @@ AstNode *parse_case_clause(AstFile *f) {
Token token = f->curr_token; Token token = f->curr_token;
AstNodeArray list = make_ast_node_array(f); AstNodeArray list = make_ast_node_array(f);
if (allow_token(f, Token_case)) { if (allow_token(f, Token_case)) {
list = make_ast_node_array(f); bool prev_allow_range = f->allow_range;
for (;;) { f->allow_range = true;
AstNode *e = parse_expr(f, false); list = parse_rhs_expr_list(f);
if (f->curr_token.kind == Token_Ellipsis || f->allow_range = prev_allow_range;
f->curr_token.kind == Token_HalfClosed) {
Token op = f->curr_token;
next_token(f);
AstNode *lhs = e;
AstNode *rhs = parse_expr(f, false);
e = ast_interval_expr(f, op, lhs, rhs);
}
array_add(&list, e);
if (f->curr_token.kind != Token_Comma ||
f->curr_token.kind == Token_EOF) {
break;
}
next_token(f);
}
} else { } else {
expect_token(f, Token_default); expect_token(f, Token_default);
} }