mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 14:03:35 +00:00
internal: merge hir::BinaryOp and ast::BinOp
This commit is contained in:
parent
fe4f059450
commit
90357a9090
12 changed files with 160 additions and 233 deletions
|
@ -27,8 +27,8 @@ use crate::{
|
||||||
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
|
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{
|
expr::{
|
||||||
dummy_expr_id, Array, BinaryOp, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal,
|
dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal, MatchArm,
|
||||||
MatchArm, MatchGuard, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
|
MatchGuard, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
|
||||||
},
|
},
|
||||||
intern::Interned,
|
intern::Interned,
|
||||||
item_scope::BuiltinShadowMode,
|
item_scope::BuiltinShadowMode,
|
||||||
|
@ -508,7 +508,7 @@ impl ExprCollector<'_> {
|
||||||
ast::Expr::BinExpr(e) => {
|
ast::Expr::BinExpr(e) => {
|
||||||
let lhs = self.collect_expr_opt(e.lhs());
|
let lhs = self.collect_expr_opt(e.lhs());
|
||||||
let rhs = self.collect_expr_opt(e.rhs());
|
let rhs = self.collect_expr_opt(e.rhs());
|
||||||
let op = e.op_kind().map(BinaryOp::from);
|
let op = e.op_kind();
|
||||||
self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
|
self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
|
||||||
}
|
}
|
||||||
ast::Expr::TupleExpr(e) => {
|
ast::Expr::TupleExpr(e) => {
|
||||||
|
|
|
@ -26,7 +26,13 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<(
|
||||||
let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
|
let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
|
||||||
let op = expr.op_kind()?;
|
let op = expr.op_kind()?;
|
||||||
let op_range = expr.op_token()?.text_range();
|
let op_range = expr.op_token()?.text_range();
|
||||||
let opposite_op = opposite_logic_op(op)?;
|
|
||||||
|
let opposite_op = match op {
|
||||||
|
ast::BinaryOp::LogicOp(ast::LogicOp::And) => "||",
|
||||||
|
ast::BinaryOp::LogicOp(ast::LogicOp::Or) => "&&",
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
let cursor_in_range = op_range.contains_range(ctx.frange.range);
|
let cursor_in_range = op_range.contains_range(ctx.frange.range);
|
||||||
if !cursor_in_range {
|
if !cursor_in_range {
|
||||||
return None;
|
return None;
|
||||||
|
@ -136,15 +142,6 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext) -> Option<(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the opposite text for a given logical operator, if it makes sense
|
|
||||||
fn opposite_logic_op(kind: ast::BinOp) -> Option<&'static str> {
|
|
||||||
match kind {
|
|
||||||
ast::BinOp::BooleanOr => Some("&&"),
|
|
||||||
ast::BinOp::BooleanAnd => Some("||"),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests::{check_assist, check_assist_not_applicable};
|
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||||
|
|
|
@ -892,7 +892,7 @@ fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Optio
|
||||||
let parent = expr.syntax().parent()?;
|
let parent = expr.syntax().parent()?;
|
||||||
|
|
||||||
if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) {
|
if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) {
|
||||||
if bin_expr.op_kind()?.is_assignment() {
|
if matches!(bin_expr.op_kind()?, ast::BinaryOp::Assignment { .. }) {
|
||||||
return Some(bin_expr.lhs()?.syntax() == expr.syntax());
|
return Some(bin_expr.lhs()?.syntax() == expr.syntax());
|
||||||
}
|
}
|
||||||
return Some(false);
|
return Some(false);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use syntax::ast::{AstNode, BinExpr, BinOp};
|
use syntax::ast::{self, AstNode, BinExpr};
|
||||||
|
|
||||||
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
||||||
|
|
||||||
|
@ -56,14 +56,19 @@ enum FlipAction {
|
||||||
DontFlip,
|
DontFlip,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BinOp> for FlipAction {
|
impl From<ast::BinaryOp> for FlipAction {
|
||||||
fn from(op_kind: BinOp) -> Self {
|
fn from(op_kind: ast::BinaryOp) -> Self {
|
||||||
match op_kind {
|
match op_kind {
|
||||||
kind if kind.is_assignment() => FlipAction::DontFlip,
|
ast::BinaryOp::Assignment { .. } => FlipAction::DontFlip,
|
||||||
BinOp::GreaterTest => FlipAction::FlipAndReplaceOp("<"),
|
ast::BinaryOp::CmpOp(ast::CmpOp::Ord { ordering, strict }) => {
|
||||||
BinOp::GreaterEqualTest => FlipAction::FlipAndReplaceOp("<="),
|
let rev_op = match (ordering, strict) {
|
||||||
BinOp::LesserTest => FlipAction::FlipAndReplaceOp(">"),
|
(ast::Ordering::Less, true) => ">",
|
||||||
BinOp::LesserEqualTest => FlipAction::FlipAndReplaceOp(">="),
|
(ast::Ordering::Less, false) => ">=",
|
||||||
|
(ast::Ordering::Greater, true) => "<",
|
||||||
|
(ast::Ordering::Greater, false) => "<=",
|
||||||
|
};
|
||||||
|
FlipAction::FlipAndReplaceOp(rev_op)
|
||||||
|
}
|
||||||
_ => FlipAction::Flip,
|
_ => FlipAction::Flip,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub(crate) fn pull_assignment_up(acc: &mut Assists, ctx: &AssistContext) -> Opti
|
||||||
let assign_expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
|
let assign_expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
|
||||||
|
|
||||||
let op_kind = assign_expr.op_kind()?;
|
let op_kind = assign_expr.op_kind()?;
|
||||||
if op_kind != ast::BinOp::Assignment {
|
if op_kind != (ast::BinaryOp::Assignment { op: None }) {
|
||||||
cov_mark::hit!(test_cant_pull_non_assignments);
|
cov_mark::hit!(test_cant_pull_non_assignments);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ impl<'a> AssignmentsCollector<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_expr(&mut self, expr: &ast::BinExpr) -> Option<()> {
|
fn collect_expr(&mut self, expr: &ast::BinExpr) -> Option<()> {
|
||||||
if expr.op_kind()? == ast::BinOp::Assignment
|
if expr.op_kind()? == (ast::BinaryOp::Assignment { op: None })
|
||||||
&& is_equivalent(self.sema, &expr.lhs()?, &self.common_lhs)
|
&& is_equivalent(self.sema, &expr.lhs()?, &self.common_lhs)
|
||||||
{
|
{
|
||||||
self.assignments.push((expr.clone(), expr.rhs()?));
|
self.assignments.push((expr.clone(), expr.rhs()?));
|
||||||
|
|
|
@ -210,12 +210,17 @@ pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr {
|
||||||
fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
|
fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expr::BinExpr(bin) => match bin.op_kind()? {
|
ast::Expr::BinExpr(bin) => match bin.op_kind()? {
|
||||||
ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()),
|
ast::BinaryOp::CmpOp(op) => {
|
||||||
ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()),
|
let rev_op = match op {
|
||||||
ast::BinOp::LesserTest => bin.replace_op(T![>=]).map(|it| it.into()),
|
ast::CmpOp::Eq { negated: false } => T![!=],
|
||||||
ast::BinOp::LesserEqualTest => bin.replace_op(T![>]).map(|it| it.into()),
|
ast::CmpOp::Eq { negated: true } => T![==],
|
||||||
ast::BinOp::GreaterTest => bin.replace_op(T![<=]).map(|it| it.into()),
|
ast::CmpOp::Ord { ordering: ast::Ordering::Less, strict: true } => T![>=],
|
||||||
ast::BinOp::GreaterEqualTest => bin.replace_op(T![<]).map(|it| it.into()),
|
ast::CmpOp::Ord { ordering: ast::Ordering::Less, strict: false } => T![>],
|
||||||
|
ast::CmpOp::Ord { ordering: ast::Ordering::Greater, strict: true } => T![<=],
|
||||||
|
ast::CmpOp::Ord { ordering: ast::Ordering::Greater, strict: false } => T![<],
|
||||||
|
};
|
||||||
|
bin.replace_op(rev_op).map(ast::Expr::from)
|
||||||
|
}
|
||||||
// Parenthesize other expressions before prefixing `!`
|
// Parenthesize other expressions before prefixing `!`
|
||||||
_ => Some(make::expr_prefix(T![!], make::expr_paren(expr.clone()))),
|
_ => Some(make::expr_prefix(T![!], make::expr_paren(expr.clone()))),
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! This module contains functions to generate default trait impl function bodies where possible.
|
//! This module contains functions to generate default trait impl function bodies where possible.
|
||||||
|
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner},
|
ast::{self, edit::AstNodeEdit, make, AstNode, BinaryOp, CmpOp, LogicOp, NameOwner},
|
||||||
ted,
|
ted,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
fn gen_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::Expr> {
|
fn gen_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::Expr> {
|
||||||
match expr {
|
match expr {
|
||||||
Some(expr) => Some(make::expr_op(ast::BinOp::BooleanAnd, expr, cmp)),
|
Some(expr) => Some(make::expr_bin_op(expr, BinaryOp::LogicOp(LogicOp::And), cmp)),
|
||||||
None => Some(cmp),
|
None => Some(cmp),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -362,7 +362,8 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
let lhs = make::expr_call(make_discriminant()?, make::arg_list(Some(lhs_name.clone())));
|
let lhs = make::expr_call(make_discriminant()?, make::arg_list(Some(lhs_name.clone())));
|
||||||
let rhs_name = make::expr_path(make::ext::ident_path("other"));
|
let rhs_name = make::expr_path(make::ext::ident_path("other"));
|
||||||
let rhs = make::expr_call(make_discriminant()?, make::arg_list(Some(rhs_name.clone())));
|
let rhs = make::expr_call(make_discriminant()?, make::arg_list(Some(rhs_name.clone())));
|
||||||
let eq_check = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs);
|
let eq_check =
|
||||||
|
make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs);
|
||||||
|
|
||||||
let mut case_count = 0;
|
let mut case_count = 0;
|
||||||
let mut arms = vec![];
|
let mut arms = vec![];
|
||||||
|
@ -386,7 +387,11 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
|
|
||||||
let lhs = make::expr_path(make::ext::ident_path(l_name));
|
let lhs = make::expr_path(make::ext::ident_path(l_name));
|
||||||
let rhs = make::expr_path(make::ext::ident_path(r_name));
|
let rhs = make::expr_path(make::ext::ident_path(r_name));
|
||||||
let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs);
|
let cmp = make::expr_bin_op(
|
||||||
|
lhs,
|
||||||
|
BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
|
||||||
|
rhs,
|
||||||
|
);
|
||||||
expr = gen_eq_chain(expr, cmp);
|
expr = gen_eq_chain(expr, cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +420,11 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
|
|
||||||
let lhs = make::expr_path(make::ext::ident_path(&l_name));
|
let lhs = make::expr_path(make::ext::ident_path(&l_name));
|
||||||
let rhs = make::expr_path(make::ext::ident_path(&r_name));
|
let rhs = make::expr_path(make::ext::ident_path(&r_name));
|
||||||
let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs);
|
let cmp = make::expr_bin_op(
|
||||||
|
lhs,
|
||||||
|
BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
|
||||||
|
rhs,
|
||||||
|
);
|
||||||
expr = gen_eq_chain(expr, cmp);
|
expr = gen_eq_chain(expr, cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,7 +464,8 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
let lhs = make::expr_field(lhs, &field.name()?.to_string());
|
let lhs = make::expr_field(lhs, &field.name()?.to_string());
|
||||||
let rhs = make::expr_path(make::ext::ident_path("other"));
|
let rhs = make::expr_path(make::ext::ident_path("other"));
|
||||||
let rhs = make::expr_field(rhs, &field.name()?.to_string());
|
let rhs = make::expr_field(rhs, &field.name()?.to_string());
|
||||||
let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs);
|
let cmp =
|
||||||
|
make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs);
|
||||||
expr = gen_eq_chain(expr, cmp);
|
expr = gen_eq_chain(expr, cmp);
|
||||||
}
|
}
|
||||||
make::block_expr(None, expr).indent(ast::edit::IndentLevel(1))
|
make::block_expr(None, expr).indent(ast::edit::IndentLevel(1))
|
||||||
|
@ -469,7 +479,8 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
|
||||||
let lhs = make::expr_field(lhs, &idx);
|
let lhs = make::expr_field(lhs, &idx);
|
||||||
let rhs = make::expr_path(make::ext::ident_path("other"));
|
let rhs = make::expr_path(make::ext::ident_path("other"));
|
||||||
let rhs = make::expr_field(rhs, &idx);
|
let rhs = make::expr_field(rhs, &idx);
|
||||||
let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs);
|
let cmp =
|
||||||
|
make::expr_bin_op(lhs, BinaryOp::CmpOp(CmpOp::Eq { negated: false }), rhs);
|
||||||
expr = gen_eq_chain(expr, cmp);
|
expr = gen_eq_chain(expr, cmp);
|
||||||
}
|
}
|
||||||
make::block_expr(None, expr).indent(ast::edit::IndentLevel(1))
|
make::block_expr(None, expr).indent(ast::edit::IndentLevel(1))
|
||||||
|
|
|
@ -655,7 +655,7 @@ fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<Referen
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match (node) {
|
match (node) {
|
||||||
ast::BinExpr(expr) => {
|
ast::BinExpr(expr) => {
|
||||||
if expr.op_kind()?.is_assignment() {
|
if matches!(expr.op_kind()?, ast::BinaryOp::Assignment { .. }) {
|
||||||
// If the variable or field ends on the LHS's end then it's a Write (covers fields and locals).
|
// If the variable or field ends on the LHS's end then it's a Write (covers fields and locals).
|
||||||
// FIXME: This is not terribly accurate.
|
// FIXME: This is not terribly accurate.
|
||||||
if let Some(lhs) = expr.lhs() {
|
if let Some(lhs) = expr.lhs() {
|
||||||
|
|
|
@ -18,13 +18,13 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{
|
||||||
expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind},
|
expr_ext::{ArrayExprKind, Effect, ElseBranch, LiteralKind},
|
||||||
generated::{nodes::*, tokens::*},
|
generated::{nodes::*, tokens::*},
|
||||||
node_ext::{
|
node_ext::{
|
||||||
AttrKind, AttrsOwnerNode, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind,
|
AttrKind, AttrsOwnerNode, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind,
|
||||||
SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind,
|
SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind,
|
||||||
},
|
},
|
||||||
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, RangeOp, UnaryOp, Ordering},
|
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp},
|
||||||
token_ext::{
|
token_ext::{
|
||||||
CommentKind, CommentPlacement, CommentShape, FormatSpecifier, HasFormatSpecifier, IsString,
|
CommentKind, CommentPlacement, CommentShape, FormatSpecifier, HasFormatSpecifier, IsString,
|
||||||
QuoteOffsets, Radix,
|
QuoteOffsets, Radix,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use rowan::WalkEvent;
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
self,
|
self,
|
||||||
operators::{RangeOp, UnaryOp},
|
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp},
|
||||||
support, AstChildren, AstNode,
|
support, AstChildren, AstNode,
|
||||||
},
|
},
|
||||||
AstToken,
|
AstToken,
|
||||||
|
@ -213,127 +213,51 @@ impl ast::PrefixExpr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
|
||||||
pub enum BinOp {
|
|
||||||
/// The `||` operator for boolean OR
|
|
||||||
BooleanOr,
|
|
||||||
/// The `&&` operator for boolean AND
|
|
||||||
BooleanAnd,
|
|
||||||
/// The `==` operator for equality testing
|
|
||||||
EqualityTest,
|
|
||||||
/// The `!=` operator for equality testing
|
|
||||||
NegatedEqualityTest,
|
|
||||||
/// The `<=` operator for lesser-equal testing
|
|
||||||
LesserEqualTest,
|
|
||||||
/// The `>=` operator for greater-equal testing
|
|
||||||
GreaterEqualTest,
|
|
||||||
/// The `<` operator for comparison
|
|
||||||
LesserTest,
|
|
||||||
/// The `>` operator for comparison
|
|
||||||
GreaterTest,
|
|
||||||
/// The `+` operator for addition
|
|
||||||
Addition,
|
|
||||||
/// The `*` operator for multiplication
|
|
||||||
Multiplication,
|
|
||||||
/// The `-` operator for subtraction
|
|
||||||
Subtraction,
|
|
||||||
/// The `/` operator for division
|
|
||||||
Division,
|
|
||||||
/// The `%` operator for remainder after division
|
|
||||||
Remainder,
|
|
||||||
/// The `<<` operator for left shift
|
|
||||||
LeftShift,
|
|
||||||
/// The `>>` operator for right shift
|
|
||||||
RightShift,
|
|
||||||
/// The `^` operator for bitwise XOR
|
|
||||||
BitwiseXor,
|
|
||||||
/// The `|` operator for bitwise OR
|
|
||||||
BitwiseOr,
|
|
||||||
/// The `&` operator for bitwise AND
|
|
||||||
BitwiseAnd,
|
|
||||||
/// The `=` operator for assignment
|
|
||||||
Assignment,
|
|
||||||
/// The `+=` operator for assignment after addition
|
|
||||||
AddAssign,
|
|
||||||
/// The `/=` operator for assignment after division
|
|
||||||
DivAssign,
|
|
||||||
/// The `*=` operator for assignment after multiplication
|
|
||||||
MulAssign,
|
|
||||||
/// The `%=` operator for assignment after remainders
|
|
||||||
RemAssign,
|
|
||||||
/// The `>>=` operator for assignment after shifting right
|
|
||||||
ShrAssign,
|
|
||||||
/// The `<<=` operator for assignment after shifting left
|
|
||||||
ShlAssign,
|
|
||||||
/// The `-=` operator for assignment after subtraction
|
|
||||||
SubAssign,
|
|
||||||
/// The `|=` operator for assignment after bitwise OR
|
|
||||||
BitOrAssign,
|
|
||||||
/// The `&=` operator for assignment after bitwise AND
|
|
||||||
BitAndAssign,
|
|
||||||
/// The `^=` operator for assignment after bitwise XOR
|
|
||||||
BitXorAssign,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BinOp {
|
|
||||||
pub fn is_assignment(self) -> bool {
|
|
||||||
matches!(
|
|
||||||
self,
|
|
||||||
BinOp::Assignment
|
|
||||||
| BinOp::AddAssign
|
|
||||||
| BinOp::DivAssign
|
|
||||||
| BinOp::MulAssign
|
|
||||||
| BinOp::RemAssign
|
|
||||||
| BinOp::ShrAssign
|
|
||||||
| BinOp::ShlAssign
|
|
||||||
| BinOp::SubAssign
|
|
||||||
| BinOp::BitOrAssign
|
|
||||||
| BinOp::BitAndAssign
|
|
||||||
| BinOp::BitXorAssign
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ast::BinExpr {
|
impl ast::BinExpr {
|
||||||
pub fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
|
pub fn op_details(&self) -> Option<(SyntaxToken, BinaryOp)> {
|
||||||
self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| {
|
self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| {
|
||||||
|
#[rustfmt::skip]
|
||||||
let bin_op = match c.kind() {
|
let bin_op = match c.kind() {
|
||||||
T![||] => BinOp::BooleanOr,
|
T![||] => BinaryOp::LogicOp(LogicOp::Or),
|
||||||
T![&&] => BinOp::BooleanAnd,
|
T![&&] => BinaryOp::LogicOp(LogicOp::And),
|
||||||
T![==] => BinOp::EqualityTest,
|
|
||||||
T![!=] => BinOp::NegatedEqualityTest,
|
T![==] => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
|
||||||
T![<=] => BinOp::LesserEqualTest,
|
T![!=] => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
|
||||||
T![>=] => BinOp::GreaterEqualTest,
|
T![<=] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false }),
|
||||||
T![<] => BinOp::LesserTest,
|
T![>=] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false }),
|
||||||
T![>] => BinOp::GreaterTest,
|
T![<] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true }),
|
||||||
T![+] => BinOp::Addition,
|
T![>] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true }),
|
||||||
T![*] => BinOp::Multiplication,
|
|
||||||
T![-] => BinOp::Subtraction,
|
T![+] => BinaryOp::ArithOp(ArithOp::Add),
|
||||||
T![/] => BinOp::Division,
|
T![*] => BinaryOp::ArithOp(ArithOp::Mul),
|
||||||
T![%] => BinOp::Remainder,
|
T![-] => BinaryOp::ArithOp(ArithOp::Sub),
|
||||||
T![<<] => BinOp::LeftShift,
|
T![/] => BinaryOp::ArithOp(ArithOp::Div),
|
||||||
T![>>] => BinOp::RightShift,
|
T![%] => BinaryOp::ArithOp(ArithOp::Rem),
|
||||||
T![^] => BinOp::BitwiseXor,
|
T![<<] => BinaryOp::ArithOp(ArithOp::Shl),
|
||||||
T![|] => BinOp::BitwiseOr,
|
T![>>] => BinaryOp::ArithOp(ArithOp::Shr),
|
||||||
T![&] => BinOp::BitwiseAnd,
|
T![^] => BinaryOp::ArithOp(ArithOp::BitXor),
|
||||||
T![=] => BinOp::Assignment,
|
T![|] => BinaryOp::ArithOp(ArithOp::BitOr),
|
||||||
T![+=] => BinOp::AddAssign,
|
T![&] => BinaryOp::ArithOp(ArithOp::BitAnd),
|
||||||
T![/=] => BinOp::DivAssign,
|
|
||||||
T![*=] => BinOp::MulAssign,
|
T![=] => BinaryOp::Assignment { op: None },
|
||||||
T![%=] => BinOp::RemAssign,
|
T![+=] => BinaryOp::Assignment { op: Some(ArithOp::Add) },
|
||||||
T![>>=] => BinOp::ShrAssign,
|
T![*=] => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
|
||||||
T![<<=] => BinOp::ShlAssign,
|
T![-=] => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
|
||||||
T![-=] => BinOp::SubAssign,
|
T![/=] => BinaryOp::Assignment { op: Some(ArithOp::Div) },
|
||||||
T![|=] => BinOp::BitOrAssign,
|
T![%=] => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
|
||||||
T![&=] => BinOp::BitAndAssign,
|
T![<<=] => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
|
||||||
T![^=] => BinOp::BitXorAssign,
|
T![>>=] => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
|
||||||
|
T![^=] => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
|
||||||
|
T![|=] => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
|
||||||
|
T![&=] => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some((c, bin_op))
|
Some((c, bin_op))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn op_kind(&self) -> Option<BinOp> {
|
pub fn op_kind(&self) -> Option<BinaryOp> {
|
||||||
self.op_details().map(|t| t.1)
|
self.op_details().map(|t| t.1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,42 +281,6 @@ impl ast::BinExpr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for BinOp {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
BinOp::BooleanOr => write!(f, "||"),
|
|
||||||
BinOp::BooleanAnd => write!(f, "&&"),
|
|
||||||
BinOp::EqualityTest => write!(f, "=="),
|
|
||||||
BinOp::NegatedEqualityTest => write!(f, "!="),
|
|
||||||
BinOp::LesserEqualTest => write!(f, "<="),
|
|
||||||
BinOp::GreaterEqualTest => write!(f, ">="),
|
|
||||||
BinOp::LesserTest => write!(f, "<"),
|
|
||||||
BinOp::GreaterTest => write!(f, ">"),
|
|
||||||
BinOp::Addition => write!(f, "+"),
|
|
||||||
BinOp::Multiplication => write!(f, "*"),
|
|
||||||
BinOp::Subtraction => write!(f, "-"),
|
|
||||||
BinOp::Division => write!(f, "/"),
|
|
||||||
BinOp::Remainder => write!(f, "%"),
|
|
||||||
BinOp::LeftShift => write!(f, "<<"),
|
|
||||||
BinOp::RightShift => write!(f, ">>"),
|
|
||||||
BinOp::BitwiseXor => write!(f, "^"),
|
|
||||||
BinOp::BitwiseOr => write!(f, "|"),
|
|
||||||
BinOp::BitwiseAnd => write!(f, "&"),
|
|
||||||
BinOp::Assignment => write!(f, "="),
|
|
||||||
BinOp::AddAssign => write!(f, "+="),
|
|
||||||
BinOp::DivAssign => write!(f, "/="),
|
|
||||||
BinOp::MulAssign => write!(f, "*="),
|
|
||||||
BinOp::RemAssign => write!(f, "%="),
|
|
||||||
BinOp::ShrAssign => write!(f, ">>="),
|
|
||||||
BinOp::ShlAssign => write!(f, "<<="),
|
|
||||||
BinOp::SubAssign => write!(f, "-"),
|
|
||||||
BinOp::BitOrAssign => write!(f, "|="),
|
|
||||||
BinOp::BitAndAssign => write!(f, "&="),
|
|
||||||
BinOp::BitXorAssign => write!(f, "^="),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ast::RangeExpr {
|
impl ast::RangeExpr {
|
||||||
fn op_details(&self) -> Option<(usize, SyntaxToken, RangeOp)> {
|
fn op_details(&self) -> Option<(usize, SyntaxToken, RangeOp)> {
|
||||||
self.syntax().children_with_tokens().enumerate().find_map(|(ix, child)| {
|
self.syntax().children_with_tokens().enumerate().find_map(|(ix, child)| {
|
||||||
|
|
|
@ -276,7 +276,8 @@ pub fn expr_path(path: ast::Path) -> ast::Expr {
|
||||||
pub fn expr_continue() -> ast::Expr {
|
pub fn expr_continue() -> ast::Expr {
|
||||||
expr_from_text("continue")
|
expr_from_text("continue")
|
||||||
}
|
}
|
||||||
pub fn expr_op(op: ast::BinOp, lhs: ast::Expr, rhs: ast::Expr) -> ast::Expr {
|
// Consider `op: SyntaxKind` instead for nicer syntax at the call-site?
|
||||||
|
pub fn expr_bin_op(lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::Expr {
|
||||||
expr_from_text(&format!("{} {} {}", lhs, op, rhs))
|
expr_from_text(&format!("{} {} {}", lhs, op, rhs))
|
||||||
}
|
}
|
||||||
pub fn expr_break(expr: Option<ast::Expr>) -> ast::Expr {
|
pub fn expr_break(expr: Option<ast::Expr>) -> ast::Expr {
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
//! Defines a bunch of data-less enums for unary and binary operators.
|
||||||
|
//!
|
||||||
|
//! Types here don't know about AST, this allows re-using them for both AST and
|
||||||
|
//! HIR.
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum RangeOp {
|
pub enum RangeOp {
|
||||||
/// `..`
|
/// `..`
|
||||||
|
@ -8,11 +14,11 @@ pub enum RangeOp {
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum UnaryOp {
|
pub enum UnaryOp {
|
||||||
/// The `*` operator for dereferencing
|
/// `*`
|
||||||
Deref,
|
Deref,
|
||||||
/// The `!` operator for logical inversion
|
/// `!`
|
||||||
Not,
|
Not,
|
||||||
/// The `-` operator for negation
|
/// `-`
|
||||||
Neg,
|
Neg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,47 +62,61 @@ pub enum ArithOp {
|
||||||
BitAnd,
|
BitAnd,
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::ast;
|
impl fmt::Display for LogicOp {
|
||||||
impl From<ast::BinOp> for BinaryOp {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
fn from(ast_op: ast::BinOp) -> Self {
|
let res = match self {
|
||||||
match ast_op {
|
LogicOp::And => "&&",
|
||||||
ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or),
|
LogicOp::Or => "||",
|
||||||
ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And),
|
};
|
||||||
ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
|
f.write_str(res)
|
||||||
ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
|
|
||||||
ast::BinOp::LesserEqualTest => {
|
|
||||||
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false })
|
|
||||||
}
|
}
|
||||||
ast::BinOp::GreaterEqualTest => {
|
|
||||||
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
|
|
||||||
}
|
}
|
||||||
ast::BinOp::LesserTest => {
|
|
||||||
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
|
impl fmt::Display for ArithOp {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let res = match self {
|
||||||
|
ArithOp::Add => "+",
|
||||||
|
ArithOp::Mul => "*",
|
||||||
|
ArithOp::Sub => "-",
|
||||||
|
ArithOp::Div => "/",
|
||||||
|
ArithOp::Rem => "%",
|
||||||
|
ArithOp::Shl => "<<",
|
||||||
|
ArithOp::Shr => ">>",
|
||||||
|
ArithOp::BitXor => "^",
|
||||||
|
ArithOp::BitOr => "|",
|
||||||
|
ArithOp::BitAnd => "&",
|
||||||
|
};
|
||||||
|
f.write_str(res)
|
||||||
}
|
}
|
||||||
ast::BinOp::GreaterTest => {
|
|
||||||
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true })
|
|
||||||
}
|
}
|
||||||
ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add),
|
|
||||||
ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul),
|
impl fmt::Display for CmpOp {
|
||||||
ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub),
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div),
|
let res = match self {
|
||||||
ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem),
|
CmpOp::Eq { negated: false } => "==",
|
||||||
ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl),
|
CmpOp::Eq { negated: true } => "!=",
|
||||||
ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr),
|
CmpOp::Ord { ordering: Ordering::Less, strict: false } => "<=",
|
||||||
ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor),
|
CmpOp::Ord { ordering: Ordering::Less, strict: true } => "<",
|
||||||
ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr),
|
CmpOp::Ord { ordering: Ordering::Greater, strict: false } => ">=",
|
||||||
ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd),
|
CmpOp::Ord { ordering: Ordering::Greater, strict: true } => ">",
|
||||||
ast::BinOp::Assignment => BinaryOp::Assignment { op: None },
|
};
|
||||||
ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) },
|
f.write_str(res)
|
||||||
ast::BinOp::DivAssign => BinaryOp::Assignment { op: Some(ArithOp::Div) },
|
}
|
||||||
ast::BinOp::MulAssign => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
|
}
|
||||||
ast::BinOp::RemAssign => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
|
|
||||||
ast::BinOp::ShlAssign => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
|
impl fmt::Display for BinaryOp {
|
||||||
ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
|
match self {
|
||||||
ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
|
BinaryOp::LogicOp(op) => fmt::Display::fmt(op, f),
|
||||||
ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
|
BinaryOp::ArithOp(op) => fmt::Display::fmt(op, f),
|
||||||
ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
|
BinaryOp::CmpOp(op) => fmt::Display::fmt(op, f),
|
||||||
|
BinaryOp::Assignment { op } => {
|
||||||
|
f.write_str("=")?;
|
||||||
|
if let Some(op) = op {
|
||||||
|
fmt::Display::fmt(op, f)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue