Skip to content

Clean up operator representations #134552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@


<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/rust-lang/www.rust-lang.org/master/static/images/rust-social-wide-dark.svg">
Expand Down
115 changes: 111 additions & 4 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub use crate::format::*;
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter};
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
use crate::util::parser::{AssocOp, ExprPrecedence};
use crate::util::parser::{ExprPrecedence, Fixity};

/// A "Label" is an identifier of some point in sources,
/// e.g. in the following code:
Expand Down Expand Up @@ -937,8 +937,37 @@ impl BinOpKind {
matches!(self, BinOpKind::And | BinOpKind::Or)
}

pub fn precedence(&self) -> ExprPrecedence {
use BinOpKind::*;
match *self {
Mul | Div | Rem => ExprPrecedence::Product,
Add | Sub => ExprPrecedence::Sum,
Shl | Shr => ExprPrecedence::Shift,
BitAnd => ExprPrecedence::BitAnd,
BitXor => ExprPrecedence::BitXor,
BitOr => ExprPrecedence::BitOr,
Lt | Gt | Le | Ge | Eq | Ne => ExprPrecedence::Compare,
And => ExprPrecedence::LAnd,
Or => ExprPrecedence::LOr,
}
}

pub fn fixity(&self) -> Fixity {
use BinOpKind::*;
match self {
Eq | Ne | Lt | Le | Gt | Ge => Fixity::None,
Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => {
Fixity::Left
}
}
}

pub fn is_comparison(self) -> bool {
crate::util::parser::AssocOp::from_ast_binop(self).is_comparison()
use BinOpKind::*;
match self {
Eq | Ne | Lt | Le | Gt | Ge => true,
Add | Sub | Mul | Div | Rem | And | Or | BitXor | BitAnd | BitOr | Shl | Shr => false,
}
}

/// Returns `true` if the binary operator takes its arguments by value.
Expand All @@ -949,6 +978,75 @@ impl BinOpKind {

pub type BinOp = Spanned<BinOpKind>;

// Sometimes `BinOpKind` and `AssignOpKind` need the same treatment. The
// operations covered by `AssignOpKind` are a subset of those covered by
// `BinOpKind`, so it makes sense to convert `AssignOpKind` to `BinOpKind`.
impl From<AssignOpKind> for BinOpKind {
fn from(op: AssignOpKind) -> BinOpKind {
match op {
AssignOpKind::AddAssign => BinOpKind::Add,
AssignOpKind::SubAssign => BinOpKind::Sub,
AssignOpKind::MulAssign => BinOpKind::Mul,
AssignOpKind::DivAssign => BinOpKind::Div,
AssignOpKind::RemAssign => BinOpKind::Rem,
AssignOpKind::BitXorAssign => BinOpKind::BitXor,
AssignOpKind::BitAndAssign => BinOpKind::BitAnd,
AssignOpKind::BitOrAssign => BinOpKind::BitOr,
AssignOpKind::ShlAssign => BinOpKind::Shl,
AssignOpKind::ShrAssign => BinOpKind::Shr,
}
}
}

#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum AssignOpKind {
/// The `+=` operator (addition)
AddAssign,
/// The `-=` operator (subtraction)
SubAssign,
/// The `*=` operator (multiplication)
MulAssign,
/// The `/=` operator (division)
DivAssign,
/// The `%=` operator (modulus)
RemAssign,
/// The `^=` operator (bitwise xor)
BitXorAssign,
/// The `&=` operator (bitwise and)
BitAndAssign,
/// The `|=` operator (bitwise or)
BitOrAssign,
/// The `<<=` operator (shift left)
ShlAssign,
/// The `>>=` operator (shift right)
ShrAssign,
}

impl AssignOpKind {
pub fn as_str(&self) -> &'static str {
use AssignOpKind::*;
match self {
AddAssign => "+=",
SubAssign => "-=",
MulAssign => "*=",
DivAssign => "/=",
RemAssign => "%=",
BitXorAssign => "^=",
BitAndAssign => "&=",
BitOrAssign => "|=",
ShlAssign => "<<=",
ShrAssign => ">>=",
}
}

/// AssignOps are always by value.
pub fn is_by_value(self) -> bool {
true
}
}

pub type AssignOp = Spanned<AssignOpKind>;

/// Unary operator.
///
/// Note that `&data` is not an operator, it's an `AddrOf` expression.
Expand Down Expand Up @@ -1332,7 +1430,7 @@ impl Expr {
ExprKind::Range(..) => ExprPrecedence::Range,

// Binop-like expr kinds, handled by `AssocOp`.
ExprKind::Binary(op, ..) => AssocOp::from_ast_binop(op.node).precedence(),
ExprKind::Binary(op, ..) => op.node.precedence(),
ExprKind::Cast(..) => ExprPrecedence::Cast,

ExprKind::Assign(..) |
Expand Down Expand Up @@ -1424,6 +1522,15 @@ pub enum RangeLimits {
Closed,
}

impl RangeLimits {
pub fn as_str(&self) -> &'static str {
match self {
RangeLimits::HalfOpen => "..",
RangeLimits::Closed => "..=",
}
}
}

/// A method call (e.g. `x.foo::<Bar, Baz>(a, b, c)`).
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct MethodCall {
Expand Down Expand Up @@ -1540,7 +1647,7 @@ pub enum ExprKind {
/// An assignment with an operator.
///
/// E.g., `a += 1`.
AssignOp(BinOp, P<Expr>, P<Expr>),
AssignOp(AssignOp, P<Expr>, P<Expr>),
/// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
Field(P<Expr>, Ident),
/// An indexing operation (e.g., `foo[2]`).
Expand Down
Loading
Loading