internal: merge hir::BinaryOp and ast::BinOp

This commit is contained in:
Aleksey Kladov 2021-08-14 18:08:31 +03:00
parent fe4f059450
commit 90357a9090
12 changed files with 160 additions and 233 deletions

View file

@ -27,8 +27,8 @@ use crate::{
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
db::DefDatabase,
expr::{
dummy_expr_id, Array, BinaryOp, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal,
MatchArm, MatchGuard, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, Label, LabelId, Literal, MatchArm,
MatchGuard, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
},
intern::Interned,
item_scope::BuiltinShadowMode,
@ -508,7 +508,7 @@ impl ExprCollector<'_> {
ast::Expr::BinExpr(e) => {
let lhs = self.collect_expr_opt(e.lhs());
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)
}
ast::Expr::TupleExpr(e) => {

View file

@ -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 op = expr.op_kind()?;
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);
if !cursor_in_range {
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)]
mod tests {
use crate::tests::{check_assist, check_assist_not_applicable};

View file

@ -892,7 +892,7 @@ fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Optio
let parent = expr.syntax().parent()?;
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(false);

View file

@ -1,4 +1,4 @@
use syntax::ast::{AstNode, BinExpr, BinOp};
use syntax::ast::{self, AstNode, BinExpr};
use crate::{AssistContext, AssistId, AssistKind, Assists};
@ -56,14 +56,19 @@ enum FlipAction {
DontFlip,
}
impl From<BinOp> for FlipAction {
fn from(op_kind: BinOp) -> Self {
impl From<ast::BinaryOp> for FlipAction {
fn from(op_kind: ast::BinaryOp) -> Self {
match op_kind {
kind if kind.is_assignment() => FlipAction::DontFlip,
BinOp::GreaterTest => FlipAction::FlipAndReplaceOp("<"),
BinOp::GreaterEqualTest => FlipAction::FlipAndReplaceOp("<="),
BinOp::LesserTest => FlipAction::FlipAndReplaceOp(">"),
BinOp::LesserEqualTest => FlipAction::FlipAndReplaceOp(">="),
ast::BinaryOp::Assignment { .. } => FlipAction::DontFlip,
ast::BinaryOp::CmpOp(ast::CmpOp::Ord { ordering, strict }) => {
let rev_op = match (ordering, strict) {
(ast::Ordering::Less, true) => ">",
(ast::Ordering::Less, false) => ">=",
(ast::Ordering::Greater, true) => "<",
(ast::Ordering::Greater, false) => "<=",
};
FlipAction::FlipAndReplaceOp(rev_op)
}
_ => FlipAction::Flip,
}
}

View file

@ -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 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);
return None;
}
@ -143,7 +143,7 @@ impl<'a> AssignmentsCollector<'a> {
}
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)
{
self.assignments.push((expr.clone(), expr.rhs()?));

View file

@ -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> {
match expr {
ast::Expr::BinExpr(bin) => match bin.op_kind()? {
ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()),
ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()),
ast::BinOp::LesserTest => bin.replace_op(T![>=]).map(|it| it.into()),
ast::BinOp::LesserEqualTest => bin.replace_op(T![>]).map(|it| it.into()),
ast::BinOp::GreaterTest => bin.replace_op(T![<=]).map(|it| it.into()),
ast::BinOp::GreaterEqualTest => bin.replace_op(T![<]).map(|it| it.into()),
ast::BinaryOp::CmpOp(op) => {
let rev_op = match op {
ast::CmpOp::Eq { negated: false } => T![!=],
ast::CmpOp::Eq { negated: true } => T![==],
ast::CmpOp::Ord { ordering: ast::Ordering::Less, strict: true } => T![>=],
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 `!`
_ => Some(make::expr_prefix(T![!], make::expr_paren(expr.clone()))),
},

View file

@ -1,7 +1,7 @@
//! This module contains functions to generate default trait impl function bodies where possible.
use syntax::{
ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner},
ast::{self, edit::AstNodeEdit, make, AstNode, BinaryOp, CmpOp, LogicOp, NameOwner},
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_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::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),
}
}
@ -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 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 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 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 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);
}
@ -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 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);
}
@ -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 rhs = make::expr_path(make::ext::ident_path("other"));
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);
}
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 rhs = make::expr_path(make::ext::ident_path("other"));
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);
}
make::block_expr(None, expr).indent(ast::edit::IndentLevel(1))

View file

@ -655,7 +655,7 @@ fn reference_access(def: &Definition, name_ref: &ast::NameRef) -> Option<Referen
match_ast! {
match (node) {
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).
// FIXME: This is not terribly accurate.
if let Some(lhs) = expr.lhs() {

View file

@ -18,13 +18,13 @@ use crate::{
};
pub use self::{
expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind},
expr_ext::{ArrayExprKind, Effect, ElseBranch, LiteralKind},
generated::{nodes::*, tokens::*},
node_ext::{
AttrKind, AttrsOwnerNode, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind,
SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind,
},
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, RangeOp, UnaryOp, Ordering},
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp},
token_ext::{
CommentKind, CommentPlacement, CommentShape, FormatSpecifier, HasFormatSpecifier, IsString,
QuoteOffsets, Radix,

View file

@ -5,7 +5,7 @@ use rowan::WalkEvent;
use crate::{
ast::{
self,
operators::{RangeOp, UnaryOp},
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp},
support, AstChildren, AstNode,
},
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 {
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| {
#[rustfmt::skip]
let bin_op = match c.kind() {
T![||] => BinOp::BooleanOr,
T![&&] => BinOp::BooleanAnd,
T![==] => BinOp::EqualityTest,
T![!=] => BinOp::NegatedEqualityTest,
T![<=] => BinOp::LesserEqualTest,
T![>=] => BinOp::GreaterEqualTest,
T![<] => BinOp::LesserTest,
T![>] => BinOp::GreaterTest,
T![+] => BinOp::Addition,
T![*] => BinOp::Multiplication,
T![-] => BinOp::Subtraction,
T![/] => BinOp::Division,
T![%] => BinOp::Remainder,
T![<<] => BinOp::LeftShift,
T![>>] => BinOp::RightShift,
T![^] => BinOp::BitwiseXor,
T![|] => BinOp::BitwiseOr,
T![&] => BinOp::BitwiseAnd,
T![=] => BinOp::Assignment,
T![+=] => BinOp::AddAssign,
T![/=] => BinOp::DivAssign,
T![*=] => BinOp::MulAssign,
T![%=] => BinOp::RemAssign,
T![>>=] => BinOp::ShrAssign,
T![<<=] => BinOp::ShlAssign,
T![-=] => BinOp::SubAssign,
T![|=] => BinOp::BitOrAssign,
T![&=] => BinOp::BitAndAssign,
T![^=] => BinOp::BitXorAssign,
T![||] => BinaryOp::LogicOp(LogicOp::Or),
T![&&] => BinaryOp::LogicOp(LogicOp::And),
T![==] => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
T![!=] => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
T![<=] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false }),
T![>=] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false }),
T![<] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true }),
T![>] => BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true }),
T![+] => BinaryOp::ArithOp(ArithOp::Add),
T![*] => BinaryOp::ArithOp(ArithOp::Mul),
T![-] => BinaryOp::ArithOp(ArithOp::Sub),
T![/] => BinaryOp::ArithOp(ArithOp::Div),
T![%] => BinaryOp::ArithOp(ArithOp::Rem),
T![<<] => BinaryOp::ArithOp(ArithOp::Shl),
T![>>] => BinaryOp::ArithOp(ArithOp::Shr),
T![^] => BinaryOp::ArithOp(ArithOp::BitXor),
T![|] => BinaryOp::ArithOp(ArithOp::BitOr),
T![&] => BinaryOp::ArithOp(ArithOp::BitAnd),
T![=] => BinaryOp::Assignment { op: None },
T![+=] => BinaryOp::Assignment { op: Some(ArithOp::Add) },
T![*=] => BinaryOp::Assignment { op: Some(ArithOp::Mul) },
T![-=] => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
T![/=] => BinaryOp::Assignment { op: Some(ArithOp::Div) },
T![%=] => BinaryOp::Assignment { op: Some(ArithOp::Rem) },
T![<<=] => BinaryOp::Assignment { op: Some(ArithOp::Shl) },
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,
};
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)
}
@ -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 {
fn op_details(&self) -> Option<(usize, SyntaxToken, RangeOp)> {
self.syntax().children_with_tokens().enumerate().find_map(|(ix, child)| {

View file

@ -276,7 +276,8 @@ pub fn expr_path(path: ast::Path) -> ast::Expr {
pub fn expr_continue() -> ast::Expr {
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))
}
pub fn expr_break(expr: Option<ast::Expr>) -> ast::Expr {

View file

@ -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)]
pub enum RangeOp {
/// `..`
@ -8,11 +14,11 @@ pub enum RangeOp {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum UnaryOp {
/// The `*` operator for dereferencing
/// `*`
Deref,
/// The `!` operator for logical inversion
/// `!`
Not,
/// The `-` operator for negation
/// `-`
Neg,
}
@ -56,47 +62,61 @@ pub enum ArithOp {
BitAnd,
}
use crate::ast;
impl From<ast::BinOp> for BinaryOp {
fn from(ast_op: ast::BinOp) -> Self {
match ast_op {
ast::BinOp::BooleanOr => BinaryOp::LogicOp(LogicOp::Or),
ast::BinOp::BooleanAnd => BinaryOp::LogicOp(LogicOp::And),
ast::BinOp::EqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: false }),
ast::BinOp::NegatedEqualityTest => BinaryOp::CmpOp(CmpOp::Eq { negated: true }),
ast::BinOp::LesserEqualTest => {
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: false })
impl fmt::Display for LogicOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let res = match self {
LogicOp::And => "&&",
LogicOp::Or => "||",
};
f.write_str(res)
}
ast::BinOp::GreaterEqualTest => {
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
}
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::LesserTest => {
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
}
impl fmt::Display for CmpOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let res = match self {
CmpOp::Eq { negated: false } => "==",
CmpOp::Eq { negated: true } => "!=",
CmpOp::Ord { ordering: Ordering::Less, strict: false } => "<=",
CmpOp::Ord { ordering: Ordering::Less, strict: true } => "<",
CmpOp::Ord { ordering: Ordering::Greater, strict: false } => ">=",
CmpOp::Ord { ordering: Ordering::Greater, strict: true } => ">",
};
f.write_str(res)
}
ast::BinOp::GreaterTest => {
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: true })
}
impl fmt::Display for BinaryOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BinaryOp::LogicOp(op) => fmt::Display::fmt(op, f),
BinaryOp::ArithOp(op) => fmt::Display::fmt(op, f),
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(())
}
ast::BinOp::Addition => BinaryOp::ArithOp(ArithOp::Add),
ast::BinOp::Multiplication => BinaryOp::ArithOp(ArithOp::Mul),
ast::BinOp::Subtraction => BinaryOp::ArithOp(ArithOp::Sub),
ast::BinOp::Division => BinaryOp::ArithOp(ArithOp::Div),
ast::BinOp::Remainder => BinaryOp::ArithOp(ArithOp::Rem),
ast::BinOp::LeftShift => BinaryOp::ArithOp(ArithOp::Shl),
ast::BinOp::RightShift => BinaryOp::ArithOp(ArithOp::Shr),
ast::BinOp::BitwiseXor => BinaryOp::ArithOp(ArithOp::BitXor),
ast::BinOp::BitwiseOr => BinaryOp::ArithOp(ArithOp::BitOr),
ast::BinOp::BitwiseAnd => BinaryOp::ArithOp(ArithOp::BitAnd),
ast::BinOp::Assignment => BinaryOp::Assignment { op: None },
ast::BinOp::AddAssign => BinaryOp::Assignment { op: Some(ArithOp::Add) },
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) },
ast::BinOp::ShrAssign => BinaryOp::Assignment { op: Some(ArithOp::Shr) },
ast::BinOp::SubAssign => BinaryOp::Assignment { op: Some(ArithOp::Sub) },
ast::BinOp::BitOrAssign => BinaryOp::Assignment { op: Some(ArithOp::BitOr) },
ast::BinOp::BitAndAssign => BinaryOp::Assignment { op: Some(ArithOp::BitAnd) },
ast::BinOp::BitXorAssign => BinaryOp::Assignment { op: Some(ArithOp::BitXor) },
}
}
}