Browse Source

Internal change: IntervalExpr is now a BinaryExpr

Ginger Bill 8 years ago
parent
commit
3fd37c6dc5
4 changed files with 61 additions and 65 deletions
  1. 0 5
      src/check_expr.c
  2. 7 5
      src/check_stmt.c
  3. 7 6
      src/ir.c
  4. 47 49
      src/parser.c

+ 0 - 5
src/check_expr.c

@@ -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
src/check_stmt.c

@@ -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) {
-					ast_node(ie, IntervalExpr, expr);
+				if (is_ast_node_a_range(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
src/ir.c

@@ -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) {
-			ir_build_range_interval(proc, &rs->expr->IntervalExpr, val_type, &val, &index, &loop, &done);
+		if (is_ast_node_a_range(expr)) {
+			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) {
-					ast_node(ie, IntervalExpr, expr);
+				if (is_ast_node_a_range(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
src/parser.c

@@ -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) {
-			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;
-			}
+			f->allow_range = prev_allow_range;
 
 
 			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);
-		for (;;) {
-			AstNode *e = parse_expr(f, false);
-			if (f->curr_token.kind == Token_Ellipsis ||
-			    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);
-		}
+		bool prev_allow_range = f->allow_range;
+		f->allow_range = true;
+		list = parse_rhs_expr_list(f);
+		f->allow_range = prev_allow_range;
 	} else {
 	} else {
 		expect_token(f, Token_default);
 		expect_token(f, Token_default);
 	}
 	}