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

@@ -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)
}
}
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)
}
}
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)
}
}
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::GreaterEqualTest => {
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Greater, strict: false })
}
ast::BinOp::LesserTest => {
BinaryOp::CmpOp(CmpOp::Ord { ordering: Ordering::Less, strict: true })
}
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),
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) },
}
}
}