ruff/crates/ruff_python_ast/src/comparable.rs
Charlie Marsh 8a0f844642
Box type params and arguments fields on the class definition node (#6275)
## Summary

This PR boxes the `TypeParams` and `Arguments` fields on the class
definition node. These fields are optional and often emitted, and given
that class definition is our largest enum variant, we pay the cost of
including them for every statement in the AST. Boxing these types
reduces the statement size by 40 bytes, which seems like a good tradeoff
given how infrequently these are accessed.

## Test Plan

Need to benchmark, but no behavior changes.
2023-08-02 16:47:06 +00:00

1498 lines
44 KiB
Rust

//! An equivalent object hierarchy to the `RustPython` AST hierarchy, but with the
//! ability to compare expressions for equality (via [`Eq`] and [`Hash`]).
use crate as ast;
use num_bigint::BigInt;
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableExprContext {
Load,
Store,
Del,
}
impl From<&ast::ExprContext> for ComparableExprContext {
fn from(ctx: &ast::ExprContext) -> Self {
match ctx {
ast::ExprContext::Load => Self::Load,
ast::ExprContext::Store => Self::Store,
ast::ExprContext::Del => Self::Del,
}
}
}
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableBoolOp {
And,
Or,
}
impl From<ast::BoolOp> for ComparableBoolOp {
fn from(op: ast::BoolOp) -> Self {
match op {
ast::BoolOp::And => Self::And,
ast::BoolOp::Or => Self::Or,
}
}
}
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableOperator {
Add,
Sub,
Mult,
MatMult,
Div,
Mod,
Pow,
LShift,
RShift,
BitOr,
BitXor,
BitAnd,
FloorDiv,
}
impl From<ast::Operator> for ComparableOperator {
fn from(op: ast::Operator) -> Self {
match op {
ast::Operator::Add => Self::Add,
ast::Operator::Sub => Self::Sub,
ast::Operator::Mult => Self::Mult,
ast::Operator::MatMult => Self::MatMult,
ast::Operator::Div => Self::Div,
ast::Operator::Mod => Self::Mod,
ast::Operator::Pow => Self::Pow,
ast::Operator::LShift => Self::LShift,
ast::Operator::RShift => Self::RShift,
ast::Operator::BitOr => Self::BitOr,
ast::Operator::BitXor => Self::BitXor,
ast::Operator::BitAnd => Self::BitAnd,
ast::Operator::FloorDiv => Self::FloorDiv,
}
}
}
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableUnaryOp {
Invert,
Not,
UAdd,
USub,
}
impl From<ast::UnaryOp> for ComparableUnaryOp {
fn from(op: ast::UnaryOp) -> Self {
match op {
ast::UnaryOp::Invert => Self::Invert,
ast::UnaryOp::Not => Self::Not,
ast::UnaryOp::UAdd => Self::UAdd,
ast::UnaryOp::USub => Self::USub,
}
}
}
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
pub enum ComparableCmpOp {
Eq,
NotEq,
Lt,
LtE,
Gt,
GtE,
Is,
IsNot,
In,
NotIn,
}
impl From<ast::CmpOp> for ComparableCmpOp {
fn from(op: ast::CmpOp) -> Self {
match op {
ast::CmpOp::Eq => Self::Eq,
ast::CmpOp::NotEq => Self::NotEq,
ast::CmpOp::Lt => Self::Lt,
ast::CmpOp::LtE => Self::LtE,
ast::CmpOp::Gt => Self::Gt,
ast::CmpOp::GtE => Self::GtE,
ast::CmpOp::Is => Self::Is,
ast::CmpOp::IsNot => Self::IsNot,
ast::CmpOp::In => Self::In,
ast::CmpOp::NotIn => Self::NotIn,
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableAlias<'a> {
name: &'a str,
asname: Option<&'a str>,
}
impl<'a> From<&'a ast::Alias> for ComparableAlias<'a> {
fn from(alias: &'a ast::Alias) -> Self {
Self {
name: alias.name.as_str(),
asname: alias.asname.as_deref(),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableWithItem<'a> {
context_expr: ComparableExpr<'a>,
optional_vars: Option<ComparableExpr<'a>>,
}
impl<'a> From<&'a ast::WithItem> for ComparableWithItem<'a> {
fn from(with_item: &'a ast::WithItem) -> Self {
Self {
context_expr: (&with_item.context_expr).into(),
optional_vars: with_item.optional_vars.as_ref().map(Into::into),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchValue<'a> {
value: ComparableExpr<'a>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchSingleton<'a> {
value: ComparableConstant<'a>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchSequence<'a> {
patterns: Vec<ComparablePattern<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchMapping<'a> {
keys: Vec<ComparableExpr<'a>>,
patterns: Vec<ComparablePattern<'a>>,
rest: Option<&'a str>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchClass<'a> {
cls: ComparableExpr<'a>,
patterns: Vec<ComparablePattern<'a>>,
kwd_attrs: Vec<&'a str>,
kwd_patterns: Vec<ComparablePattern<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchStar<'a> {
name: Option<&'a str>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchAs<'a> {
pattern: Option<Box<ComparablePattern<'a>>>,
name: Option<&'a str>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct PatternMatchOr<'a> {
patterns: Vec<ComparablePattern<'a>>,
}
#[allow(clippy::enum_variant_names)]
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum ComparablePattern<'a> {
MatchValue(PatternMatchValue<'a>),
MatchSingleton(PatternMatchSingleton<'a>),
MatchSequence(PatternMatchSequence<'a>),
MatchMapping(PatternMatchMapping<'a>),
MatchClass(PatternMatchClass<'a>),
MatchStar(PatternMatchStar<'a>),
MatchAs(PatternMatchAs<'a>),
MatchOr(PatternMatchOr<'a>),
}
impl<'a> From<&'a ast::Pattern> for ComparablePattern<'a> {
fn from(pattern: &'a ast::Pattern) -> Self {
match pattern {
ast::Pattern::MatchValue(ast::PatternMatchValue { value, .. }) => {
Self::MatchValue(PatternMatchValue {
value: value.into(),
})
}
ast::Pattern::MatchSingleton(ast::PatternMatchSingleton { value, .. }) => {
Self::MatchSingleton(PatternMatchSingleton {
value: value.into(),
})
}
ast::Pattern::MatchSequence(ast::PatternMatchSequence { patterns, .. }) => {
Self::MatchSequence(PatternMatchSequence {
patterns: patterns.iter().map(Into::into).collect(),
})
}
ast::Pattern::MatchMapping(ast::PatternMatchMapping {
keys,
patterns,
rest,
..
}) => Self::MatchMapping(PatternMatchMapping {
keys: keys.iter().map(Into::into).collect(),
patterns: patterns.iter().map(Into::into).collect(),
rest: rest.as_deref(),
}),
ast::Pattern::MatchClass(ast::PatternMatchClass {
cls,
patterns,
kwd_attrs,
kwd_patterns,
..
}) => Self::MatchClass(PatternMatchClass {
cls: cls.into(),
patterns: patterns.iter().map(Into::into).collect(),
kwd_attrs: kwd_attrs.iter().map(ast::Identifier::as_str).collect(),
kwd_patterns: kwd_patterns.iter().map(Into::into).collect(),
}),
ast::Pattern::MatchStar(ast::PatternMatchStar { name, .. }) => {
Self::MatchStar(PatternMatchStar {
name: name.as_deref(),
})
}
ast::Pattern::MatchAs(ast::PatternMatchAs { pattern, name, .. }) => {
Self::MatchAs(PatternMatchAs {
pattern: pattern.as_ref().map(Into::into),
name: name.as_deref(),
})
}
ast::Pattern::MatchOr(ast::PatternMatchOr { patterns, .. }) => {
Self::MatchOr(PatternMatchOr {
patterns: patterns.iter().map(Into::into).collect(),
})
}
}
}
}
impl<'a> From<&'a Box<ast::Pattern>> for Box<ComparablePattern<'a>> {
fn from(pattern: &'a Box<ast::Pattern>) -> Self {
Box::new((pattern.as_ref()).into())
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableMatchCase<'a> {
pattern: ComparablePattern<'a>,
guard: Option<ComparableExpr<'a>>,
body: Vec<ComparableStmt<'a>>,
}
impl<'a> From<&'a ast::MatchCase> for ComparableMatchCase<'a> {
fn from(match_case: &'a ast::MatchCase) -> Self {
Self {
pattern: (&match_case.pattern).into(),
guard: match_case.guard.as_ref().map(Into::into),
body: match_case.body.iter().map(Into::into).collect(),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableDecorator<'a> {
expression: ComparableExpr<'a>,
}
impl<'a> From<&'a ast::Decorator> for ComparableDecorator<'a> {
fn from(decorator: &'a ast::Decorator) -> Self {
Self {
expression: (&decorator.expression).into(),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum ComparableConstant<'a> {
None,
Bool(&'a bool),
Str(&'a str),
Bytes(&'a [u8]),
Int(&'a BigInt),
Tuple(Vec<ComparableConstant<'a>>),
Float(u64),
Complex { real: u64, imag: u64 },
Ellipsis,
}
impl<'a> From<&'a ast::Constant> for ComparableConstant<'a> {
fn from(constant: &'a ast::Constant) -> Self {
match constant {
ast::Constant::None => Self::None,
ast::Constant::Bool(value) => Self::Bool(value),
ast::Constant::Str(value) => Self::Str(value),
ast::Constant::Bytes(value) => Self::Bytes(value),
ast::Constant::Int(value) => Self::Int(value),
ast::Constant::Float(value) => Self::Float(value.to_bits()),
ast::Constant::Complex { real, imag } => Self::Complex {
real: real.to_bits(),
imag: imag.to_bits(),
},
ast::Constant::Ellipsis => Self::Ellipsis,
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableArguments<'a> {
args: Vec<ComparableExpr<'a>>,
keywords: Vec<ComparableKeyword<'a>>,
}
impl<'a> From<&'a ast::Arguments> for ComparableArguments<'a> {
fn from(arguments: &'a ast::Arguments) -> Self {
Self {
args: arguments.args.iter().map(Into::into).collect(),
keywords: arguments.keywords.iter().map(Into::into).collect(),
}
}
}
impl<'a> From<&'a Box<ast::Arguments>> for ComparableArguments<'a> {
fn from(arguments: &'a Box<ast::Arguments>) -> Self {
(arguments.as_ref()).into()
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableParameters<'a> {
posonlyargs: Vec<ComparableParameterWithDefault<'a>>,
args: Vec<ComparableParameterWithDefault<'a>>,
vararg: Option<ComparableParameter<'a>>,
kwonlyargs: Vec<ComparableParameterWithDefault<'a>>,
kwarg: Option<ComparableParameter<'a>>,
}
impl<'a> From<&'a ast::Parameters> for ComparableParameters<'a> {
fn from(parameters: &'a ast::Parameters) -> Self {
Self {
posonlyargs: parameters.posonlyargs.iter().map(Into::into).collect(),
args: parameters.args.iter().map(Into::into).collect(),
vararg: parameters.vararg.as_ref().map(Into::into),
kwonlyargs: parameters.kwonlyargs.iter().map(Into::into).collect(),
kwarg: parameters.kwarg.as_ref().map(Into::into),
}
}
}
impl<'a> From<&'a Box<ast::Parameters>> for ComparableParameters<'a> {
fn from(parameters: &'a Box<ast::Parameters>) -> Self {
(parameters.as_ref()).into()
}
}
impl<'a> From<&'a Box<ast::Parameter>> for ComparableParameter<'a> {
fn from(arg: &'a Box<ast::Parameter>) -> Self {
(arg.as_ref()).into()
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableParameter<'a> {
arg: &'a str,
annotation: Option<Box<ComparableExpr<'a>>>,
}
impl<'a> From<&'a ast::Parameter> for ComparableParameter<'a> {
fn from(arg: &'a ast::Parameter) -> Self {
Self {
arg: arg.name.as_str(),
annotation: arg.annotation.as_ref().map(Into::into),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableParameterWithDefault<'a> {
def: ComparableParameter<'a>,
default: Option<ComparableExpr<'a>>,
}
impl<'a> From<&'a ast::ParameterWithDefault> for ComparableParameterWithDefault<'a> {
fn from(arg: &'a ast::ParameterWithDefault) -> Self {
Self {
def: (&arg.parameter).into(),
default: arg.default.as_ref().map(Into::into),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableKeyword<'a> {
arg: Option<&'a str>,
value: ComparableExpr<'a>,
}
impl<'a> From<&'a ast::Keyword> for ComparableKeyword<'a> {
fn from(keyword: &'a ast::Keyword) -> Self {
Self {
arg: keyword.arg.as_ref().map(ast::Identifier::as_str),
value: (&keyword.value).into(),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableComprehension<'a> {
target: ComparableExpr<'a>,
iter: ComparableExpr<'a>,
ifs: Vec<ComparableExpr<'a>>,
is_async: bool,
}
impl<'a> From<&'a ast::Comprehension> for ComparableComprehension<'a> {
fn from(comprehension: &'a ast::Comprehension) -> Self {
Self {
target: (&comprehension.target).into(),
iter: (&comprehension.iter).into(),
ifs: comprehension.ifs.iter().map(Into::into).collect(),
is_async: comprehension.is_async,
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExceptHandlerExceptHandler<'a> {
type_: Option<Box<ComparableExpr<'a>>>,
name: Option<&'a str>,
body: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum ComparableExceptHandler<'a> {
ExceptHandler(ExceptHandlerExceptHandler<'a>),
}
impl<'a> From<&'a ast::ExceptHandler> for ComparableExceptHandler<'a> {
fn from(except_handler: &'a ast::ExceptHandler) -> Self {
let ast::ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
type_,
name,
body,
..
}) = except_handler;
Self::ExceptHandler(ExceptHandlerExceptHandler {
type_: type_.as_ref().map(Into::into),
name: name.as_deref(),
body: body.iter().map(Into::into).collect(),
})
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableElifElseClause<'a> {
test: Option<ComparableExpr<'a>>,
body: Vec<ComparableStmt<'a>>,
}
impl<'a> From<&'a ast::ElifElseClause> for ComparableElifElseClause<'a> {
fn from(elif_else_clause: &'a ast::ElifElseClause) -> Self {
let ast::ElifElseClause {
range: _,
test,
body,
} = elif_else_clause;
Self {
test: test.as_ref().map(Into::into),
body: body.iter().map(Into::into).collect(),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprBoolOp<'a> {
op: ComparableBoolOp,
values: Vec<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprNamedExpr<'a> {
target: Box<ComparableExpr<'a>>,
value: Box<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprBinOp<'a> {
left: Box<ComparableExpr<'a>>,
op: ComparableOperator,
right: Box<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprUnaryOp<'a> {
op: ComparableUnaryOp,
operand: Box<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprLambda<'a> {
parameters: ComparableParameters<'a>,
body: Box<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprIfExp<'a> {
test: Box<ComparableExpr<'a>>,
body: Box<ComparableExpr<'a>>,
orelse: Box<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprDict<'a> {
keys: Vec<Option<ComparableExpr<'a>>>,
values: Vec<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprSet<'a> {
elts: Vec<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprListComp<'a> {
elt: Box<ComparableExpr<'a>>,
generators: Vec<ComparableComprehension<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprSetComp<'a> {
elt: Box<ComparableExpr<'a>>,
generators: Vec<ComparableComprehension<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprDictComp<'a> {
key: Box<ComparableExpr<'a>>,
value: Box<ComparableExpr<'a>>,
generators: Vec<ComparableComprehension<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprGeneratorExp<'a> {
elt: Box<ComparableExpr<'a>>,
generators: Vec<ComparableComprehension<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprAwait<'a> {
value: Box<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprYield<'a> {
value: Option<Box<ComparableExpr<'a>>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprYieldFrom<'a> {
value: Box<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprCompare<'a> {
left: Box<ComparableExpr<'a>>,
ops: Vec<ComparableCmpOp>,
comparators: Vec<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprCall<'a> {
func: Box<ComparableExpr<'a>>,
arguments: ComparableArguments<'a>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprFormattedValue<'a> {
value: Box<ComparableExpr<'a>>,
debug_text: Option<&'a ast::DebugText>,
conversion: ast::ConversionFlag,
format_spec: Option<Box<ComparableExpr<'a>>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprJoinedStr<'a> {
values: Vec<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprConstant<'a> {
value: ComparableConstant<'a>,
kind: Option<&'a str>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprAttribute<'a> {
value: Box<ComparableExpr<'a>>,
attr: &'a str,
ctx: ComparableExprContext,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprSubscript<'a> {
value: Box<ComparableExpr<'a>>,
slice: Box<ComparableExpr<'a>>,
ctx: ComparableExprContext,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprStarred<'a> {
value: Box<ComparableExpr<'a>>,
ctx: ComparableExprContext,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprName<'a> {
id: &'a str,
ctx: ComparableExprContext,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprList<'a> {
elts: Vec<ComparableExpr<'a>>,
ctx: ComparableExprContext,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprTuple<'a> {
elts: Vec<ComparableExpr<'a>>,
ctx: ComparableExprContext,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprSlice<'a> {
lower: Option<Box<ComparableExpr<'a>>>,
upper: Option<Box<ComparableExpr<'a>>>,
step: Option<Box<ComparableExpr<'a>>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ExprLineMagic<'a> {
kind: ast::MagicKind,
value: &'a str,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum ComparableExpr<'a> {
BoolOp(ExprBoolOp<'a>),
NamedExpr(ExprNamedExpr<'a>),
BinOp(ExprBinOp<'a>),
UnaryOp(ExprUnaryOp<'a>),
Lambda(ExprLambda<'a>),
IfExp(ExprIfExp<'a>),
Dict(ExprDict<'a>),
Set(ExprSet<'a>),
ListComp(ExprListComp<'a>),
SetComp(ExprSetComp<'a>),
DictComp(ExprDictComp<'a>),
GeneratorExp(ExprGeneratorExp<'a>),
Await(ExprAwait<'a>),
Yield(ExprYield<'a>),
YieldFrom(ExprYieldFrom<'a>),
Compare(ExprCompare<'a>),
Call(ExprCall<'a>),
FormattedValue(ExprFormattedValue<'a>),
JoinedStr(ExprJoinedStr<'a>),
Constant(ExprConstant<'a>),
Attribute(ExprAttribute<'a>),
Subscript(ExprSubscript<'a>),
Starred(ExprStarred<'a>),
Name(ExprName<'a>),
List(ExprList<'a>),
Tuple(ExprTuple<'a>),
Slice(ExprSlice<'a>),
LineMagic(ExprLineMagic<'a>),
}
impl<'a> From<&'a Box<ast::Expr>> for Box<ComparableExpr<'a>> {
fn from(expr: &'a Box<ast::Expr>) -> Self {
Box::new((expr.as_ref()).into())
}
}
impl<'a> From<&'a Box<ast::Expr>> for ComparableExpr<'a> {
fn from(expr: &'a Box<ast::Expr>) -> Self {
(expr.as_ref()).into()
}
}
impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> {
fn from(expr: &'a ast::Expr) -> Self {
match expr {
ast::Expr::BoolOp(ast::ExprBoolOp {
op,
values,
range: _range,
}) => Self::BoolOp(ExprBoolOp {
op: (*op).into(),
values: values.iter().map(Into::into).collect(),
}),
ast::Expr::NamedExpr(ast::ExprNamedExpr {
target,
value,
range: _range,
}) => Self::NamedExpr(ExprNamedExpr {
target: target.into(),
value: value.into(),
}),
ast::Expr::BinOp(ast::ExprBinOp {
left,
op,
right,
range: _range,
}) => Self::BinOp(ExprBinOp {
left: left.into(),
op: (*op).into(),
right: right.into(),
}),
ast::Expr::UnaryOp(ast::ExprUnaryOp {
op,
operand,
range: _range,
}) => Self::UnaryOp(ExprUnaryOp {
op: (*op).into(),
operand: operand.into(),
}),
ast::Expr::Lambda(ast::ExprLambda {
parameters,
body,
range: _range,
}) => Self::Lambda(ExprLambda {
parameters: (parameters.as_ref()).into(),
body: body.into(),
}),
ast::Expr::IfExp(ast::ExprIfExp {
test,
body,
orelse,
range: _range,
}) => Self::IfExp(ExprIfExp {
test: test.into(),
body: body.into(),
orelse: orelse.into(),
}),
ast::Expr::Dict(ast::ExprDict {
keys,
values,
range: _range,
}) => Self::Dict(ExprDict {
keys: keys
.iter()
.map(|expr| expr.as_ref().map(Into::into))
.collect(),
values: values.iter().map(Into::into).collect(),
}),
ast::Expr::Set(ast::ExprSet {
elts,
range: _range,
}) => Self::Set(ExprSet {
elts: elts.iter().map(Into::into).collect(),
}),
ast::Expr::ListComp(ast::ExprListComp {
elt,
generators,
range: _range,
}) => Self::ListComp(ExprListComp {
elt: elt.into(),
generators: generators.iter().map(Into::into).collect(),
}),
ast::Expr::SetComp(ast::ExprSetComp {
elt,
generators,
range: _range,
}) => Self::SetComp(ExprSetComp {
elt: elt.into(),
generators: generators.iter().map(Into::into).collect(),
}),
ast::Expr::DictComp(ast::ExprDictComp {
key,
value,
generators,
range: _range,
}) => Self::DictComp(ExprDictComp {
key: key.into(),
value: value.into(),
generators: generators.iter().map(Into::into).collect(),
}),
ast::Expr::GeneratorExp(ast::ExprGeneratorExp {
elt,
generators,
range: _range,
}) => Self::GeneratorExp(ExprGeneratorExp {
elt: elt.into(),
generators: generators.iter().map(Into::into).collect(),
}),
ast::Expr::Await(ast::ExprAwait {
value,
range: _range,
}) => Self::Await(ExprAwait {
value: value.into(),
}),
ast::Expr::Yield(ast::ExprYield {
value,
range: _range,
}) => Self::Yield(ExprYield {
value: value.as_ref().map(Into::into),
}),
ast::Expr::YieldFrom(ast::ExprYieldFrom {
value,
range: _range,
}) => Self::YieldFrom(ExprYieldFrom {
value: value.into(),
}),
ast::Expr::Compare(ast::ExprCompare {
left,
ops,
comparators,
range: _range,
}) => Self::Compare(ExprCompare {
left: left.into(),
ops: ops.iter().copied().map(Into::into).collect(),
comparators: comparators.iter().map(Into::into).collect(),
}),
ast::Expr::Call(ast::ExprCall {
func,
arguments,
range: _range,
}) => Self::Call(ExprCall {
func: func.into(),
arguments: arguments.into(),
}),
ast::Expr::FormattedValue(ast::ExprFormattedValue {
value,
conversion,
debug_text,
format_spec,
range: _range,
}) => Self::FormattedValue(ExprFormattedValue {
value: value.into(),
conversion: *conversion,
debug_text: debug_text.as_ref(),
format_spec: format_spec.as_ref().map(Into::into),
}),
ast::Expr::JoinedStr(ast::ExprJoinedStr {
values,
range: _range,
}) => Self::JoinedStr(ExprJoinedStr {
values: values.iter().map(Into::into).collect(),
}),
ast::Expr::Constant(ast::ExprConstant {
value,
kind,
range: _range,
}) => Self::Constant(ExprConstant {
value: value.into(),
kind: kind.as_ref().map(String::as_str),
}),
ast::Expr::Attribute(ast::ExprAttribute {
value,
attr,
ctx,
range: _range,
}) => Self::Attribute(ExprAttribute {
value: value.into(),
attr: attr.as_str(),
ctx: ctx.into(),
}),
ast::Expr::Subscript(ast::ExprSubscript {
value,
slice,
ctx,
range: _range,
}) => Self::Subscript(ExprSubscript {
value: value.into(),
slice: slice.into(),
ctx: ctx.into(),
}),
ast::Expr::Starred(ast::ExprStarred {
value,
ctx,
range: _range,
}) => Self::Starred(ExprStarred {
value: value.into(),
ctx: ctx.into(),
}),
ast::Expr::Name(ast::ExprName {
id,
ctx,
range: _range,
}) => Self::Name(ExprName {
id: id.as_str(),
ctx: ctx.into(),
}),
ast::Expr::List(ast::ExprList {
elts,
ctx,
range: _range,
}) => Self::List(ExprList {
elts: elts.iter().map(Into::into).collect(),
ctx: ctx.into(),
}),
ast::Expr::Tuple(ast::ExprTuple {
elts,
ctx,
range: _range,
}) => Self::Tuple(ExprTuple {
elts: elts.iter().map(Into::into).collect(),
ctx: ctx.into(),
}),
ast::Expr::Slice(ast::ExprSlice {
lower,
upper,
step,
range: _range,
}) => Self::Slice(ExprSlice {
lower: lower.as_ref().map(Into::into),
upper: upper.as_ref().map(Into::into),
step: step.as_ref().map(Into::into),
}),
ast::Expr::LineMagic(ast::ExprLineMagic {
kind,
value,
range: _range,
}) => Self::LineMagic(ExprLineMagic {
kind: *kind,
value: value.as_str(),
}),
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtFunctionDef<'a> {
decorator_list: Vec<ComparableDecorator<'a>>,
name: &'a str,
type_params: Option<ComparableTypeParams<'a>>,
parameters: ComparableParameters<'a>,
returns: Option<ComparableExpr<'a>>,
body: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtAsyncFunctionDef<'a> {
decorator_list: Vec<ComparableDecorator<'a>>,
name: &'a str,
type_params: Option<ComparableTypeParams<'a>>,
parameters: ComparableParameters<'a>,
returns: Option<ComparableExpr<'a>>,
body: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtClassDef<'a> {
decorator_list: Vec<ComparableDecorator<'a>>,
name: &'a str,
type_params: Option<ComparableTypeParams<'a>>,
arguments: Option<ComparableArguments<'a>>,
body: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtReturn<'a> {
value: Option<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtDelete<'a> {
targets: Vec<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtTypeAlias<'a> {
pub name: Box<ComparableExpr<'a>>,
pub type_params: Option<ComparableTypeParams<'a>>,
pub value: Box<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ComparableTypeParams<'a> {
pub type_params: Vec<ComparableTypeParam<'a>>,
}
impl<'a> From<&'a ast::TypeParams> for ComparableTypeParams<'a> {
fn from(type_params: &'a ast::TypeParams) -> Self {
Self {
type_params: type_params.iter().map(Into::into).collect(),
}
}
}
impl<'a> From<&'a Box<ast::TypeParams>> for ComparableTypeParams<'a> {
fn from(type_params: &'a Box<ast::TypeParams>) -> Self {
type_params.as_ref().into()
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum ComparableTypeParam<'a> {
TypeVar(TypeParamTypeVar<'a>),
ParamSpec(TypeParamParamSpec<'a>),
TypeVarTuple(TypeParamTypeVarTuple<'a>),
}
impl<'a> From<&'a ast::TypeParam> for ComparableTypeParam<'a> {
fn from(type_param: &'a ast::TypeParam) -> Self {
match type_param {
ast::TypeParam::TypeVar(ast::TypeParamTypeVar {
name,
bound,
range: _,
}) => Self::TypeVar(TypeParamTypeVar {
name: name.as_str(),
bound: bound.as_ref().map(Into::into),
}),
ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { name, range: _ }) => {
Self::TypeVarTuple(TypeParamTypeVarTuple {
name: name.as_str(),
})
}
ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { name, range: _ }) => {
Self::ParamSpec(TypeParamParamSpec {
name: name.as_str(),
})
}
}
}
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TypeParamTypeVar<'a> {
pub name: &'a str,
pub bound: Option<Box<ComparableExpr<'a>>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TypeParamParamSpec<'a> {
pub name: &'a str,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct TypeParamTypeVarTuple<'a> {
pub name: &'a str,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtAssign<'a> {
targets: Vec<ComparableExpr<'a>>,
value: ComparableExpr<'a>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtAugAssign<'a> {
target: ComparableExpr<'a>,
op: ComparableOperator,
value: ComparableExpr<'a>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtAnnAssign<'a> {
target: ComparableExpr<'a>,
annotation: ComparableExpr<'a>,
value: Option<ComparableExpr<'a>>,
simple: bool,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtFor<'a> {
target: ComparableExpr<'a>,
iter: ComparableExpr<'a>,
body: Vec<ComparableStmt<'a>>,
orelse: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtAsyncFor<'a> {
target: ComparableExpr<'a>,
iter: ComparableExpr<'a>,
body: Vec<ComparableStmt<'a>>,
orelse: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtWhile<'a> {
test: ComparableExpr<'a>,
body: Vec<ComparableStmt<'a>>,
orelse: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtIf<'a> {
test: ComparableExpr<'a>,
body: Vec<ComparableStmt<'a>>,
elif_else_clauses: Vec<ComparableElifElseClause<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtWith<'a> {
items: Vec<ComparableWithItem<'a>>,
body: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtAsyncWith<'a> {
items: Vec<ComparableWithItem<'a>>,
body: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtMatch<'a> {
subject: ComparableExpr<'a>,
cases: Vec<ComparableMatchCase<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtRaise<'a> {
exc: Option<ComparableExpr<'a>>,
cause: Option<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtTry<'a> {
body: Vec<ComparableStmt<'a>>,
handlers: Vec<ComparableExceptHandler<'a>>,
orelse: Vec<ComparableStmt<'a>>,
finalbody: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtTryStar<'a> {
body: Vec<ComparableStmt<'a>>,
handlers: Vec<ComparableExceptHandler<'a>>,
orelse: Vec<ComparableStmt<'a>>,
finalbody: Vec<ComparableStmt<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtAssert<'a> {
test: ComparableExpr<'a>,
msg: Option<ComparableExpr<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtImport<'a> {
names: Vec<ComparableAlias<'a>>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtImportFrom<'a> {
module: Option<&'a str>,
names: Vec<ComparableAlias<'a>>,
level: Option<ast::Int>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtGlobal<'a> {
names: Vec<&'a str>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtNonlocal<'a> {
names: Vec<&'a str>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtExpr<'a> {
value: ComparableExpr<'a>,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct StmtLineMagic<'a> {
kind: ast::MagicKind,
value: &'a str,
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum ComparableStmt<'a> {
FunctionDef(StmtFunctionDef<'a>),
AsyncFunctionDef(StmtAsyncFunctionDef<'a>),
ClassDef(StmtClassDef<'a>),
Return(StmtReturn<'a>),
Delete(StmtDelete<'a>),
Assign(StmtAssign<'a>),
AugAssign(StmtAugAssign<'a>),
AnnAssign(StmtAnnAssign<'a>),
For(StmtFor<'a>),
AsyncFor(StmtAsyncFor<'a>),
While(StmtWhile<'a>),
If(StmtIf<'a>),
With(StmtWith<'a>),
AsyncWith(StmtAsyncWith<'a>),
Match(StmtMatch<'a>),
Raise(StmtRaise<'a>),
Try(StmtTry<'a>),
TryStar(StmtTryStar<'a>),
TypeAlias(StmtTypeAlias<'a>),
Assert(StmtAssert<'a>),
Import(StmtImport<'a>),
ImportFrom(StmtImportFrom<'a>),
Global(StmtGlobal<'a>),
Nonlocal(StmtNonlocal<'a>),
LineMagic(StmtLineMagic<'a>),
Expr(StmtExpr<'a>),
Pass,
Break,
Continue,
}
impl<'a> From<&'a ast::Stmt> for ComparableStmt<'a> {
fn from(stmt: &'a ast::Stmt) -> Self {
match stmt {
ast::Stmt::FunctionDef(ast::StmtFunctionDef {
name,
parameters,
body,
decorator_list,
returns,
type_params,
range: _range,
}) => Self::FunctionDef(StmtFunctionDef {
name: name.as_str(),
parameters: parameters.into(),
body: body.iter().map(Into::into).collect(),
decorator_list: decorator_list.iter().map(Into::into).collect(),
returns: returns.as_ref().map(Into::into),
type_params: type_params.as_ref().map(Into::into),
}),
ast::Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
name,
parameters,
body,
decorator_list,
returns,
type_params,
range: _range,
}) => Self::AsyncFunctionDef(StmtAsyncFunctionDef {
name: name.as_str(),
parameters: parameters.into(),
body: body.iter().map(Into::into).collect(),
decorator_list: decorator_list.iter().map(Into::into).collect(),
returns: returns.as_ref().map(Into::into),
type_params: type_params.as_ref().map(Into::into),
}),
ast::Stmt::ClassDef(ast::StmtClassDef {
name,
arguments,
body,
decorator_list,
type_params,
range: _range,
}) => Self::ClassDef(StmtClassDef {
name: name.as_str(),
arguments: arguments.as_ref().map(Into::into),
body: body.iter().map(Into::into).collect(),
decorator_list: decorator_list.iter().map(Into::into).collect(),
type_params: type_params.as_ref().map(Into::into),
}),
ast::Stmt::Return(ast::StmtReturn {
value,
range: _range,
}) => Self::Return(StmtReturn {
value: value.as_ref().map(Into::into),
}),
ast::Stmt::Delete(ast::StmtDelete {
targets,
range: _range,
}) => Self::Delete(StmtDelete {
targets: targets.iter().map(Into::into).collect(),
}),
ast::Stmt::TypeAlias(ast::StmtTypeAlias {
range: _range,
name,
type_params,
value,
}) => Self::TypeAlias(StmtTypeAlias {
name: name.into(),
type_params: type_params.as_ref().map(Into::into),
value: value.into(),
}),
ast::Stmt::Assign(ast::StmtAssign {
targets,
value,
range: _range,
}) => Self::Assign(StmtAssign {
targets: targets.iter().map(Into::into).collect(),
value: value.into(),
}),
ast::Stmt::AugAssign(ast::StmtAugAssign {
target,
op,
value,
range: _range,
}) => Self::AugAssign(StmtAugAssign {
target: target.into(),
op: (*op).into(),
value: value.into(),
}),
ast::Stmt::AnnAssign(ast::StmtAnnAssign {
target,
annotation,
value,
simple,
range: _range,
}) => Self::AnnAssign(StmtAnnAssign {
target: target.into(),
annotation: annotation.into(),
value: value.as_ref().map(Into::into),
simple: *simple,
}),
ast::Stmt::For(ast::StmtFor {
target,
iter,
body,
orelse,
range: _range,
}) => Self::For(StmtFor {
target: target.into(),
iter: iter.into(),
body: body.iter().map(Into::into).collect(),
orelse: orelse.iter().map(Into::into).collect(),
}),
ast::Stmt::AsyncFor(ast::StmtAsyncFor {
target,
iter,
body,
orelse,
range: _range,
}) => Self::AsyncFor(StmtAsyncFor {
target: target.into(),
iter: iter.into(),
body: body.iter().map(Into::into).collect(),
orelse: orelse.iter().map(Into::into).collect(),
}),
ast::Stmt::While(ast::StmtWhile {
test,
body,
orelse,
range: _range,
}) => Self::While(StmtWhile {
test: test.into(),
body: body.iter().map(Into::into).collect(),
orelse: orelse.iter().map(Into::into).collect(),
}),
ast::Stmt::If(ast::StmtIf {
test,
body,
elif_else_clauses,
range: _range,
}) => Self::If(StmtIf {
test: test.into(),
body: body.iter().map(Into::into).collect(),
elif_else_clauses: elif_else_clauses.iter().map(Into::into).collect(),
}),
ast::Stmt::With(ast::StmtWith {
items,
body,
range: _range,
}) => Self::With(StmtWith {
items: items.iter().map(Into::into).collect(),
body: body.iter().map(Into::into).collect(),
}),
ast::Stmt::AsyncWith(ast::StmtAsyncWith {
items,
body,
range: _range,
}) => Self::AsyncWith(StmtAsyncWith {
items: items.iter().map(Into::into).collect(),
body: body.iter().map(Into::into).collect(),
}),
ast::Stmt::Match(ast::StmtMatch {
subject,
cases,
range: _range,
}) => Self::Match(StmtMatch {
subject: subject.into(),
cases: cases.iter().map(Into::into).collect(),
}),
ast::Stmt::Raise(ast::StmtRaise {
exc,
cause,
range: _range,
}) => Self::Raise(StmtRaise {
exc: exc.as_ref().map(Into::into),
cause: cause.as_ref().map(Into::into),
}),
ast::Stmt::Try(ast::StmtTry {
body,
handlers,
orelse,
finalbody,
range: _range,
}) => Self::Try(StmtTry {
body: body.iter().map(Into::into).collect(),
handlers: handlers.iter().map(Into::into).collect(),
orelse: orelse.iter().map(Into::into).collect(),
finalbody: finalbody.iter().map(Into::into).collect(),
}),
ast::Stmt::TryStar(ast::StmtTryStar {
body,
handlers,
orelse,
finalbody,
range: _range,
}) => Self::TryStar(StmtTryStar {
body: body.iter().map(Into::into).collect(),
handlers: handlers.iter().map(Into::into).collect(),
orelse: orelse.iter().map(Into::into).collect(),
finalbody: finalbody.iter().map(Into::into).collect(),
}),
ast::Stmt::Assert(ast::StmtAssert {
test,
msg,
range: _range,
}) => Self::Assert(StmtAssert {
test: test.into(),
msg: msg.as_ref().map(Into::into),
}),
ast::Stmt::Import(ast::StmtImport {
names,
range: _range,
}) => Self::Import(StmtImport {
names: names.iter().map(Into::into).collect(),
}),
ast::Stmt::ImportFrom(ast::StmtImportFrom {
module,
names,
level,
range: _range,
}) => Self::ImportFrom(StmtImportFrom {
module: module.as_deref(),
names: names.iter().map(Into::into).collect(),
level: *level,
}),
ast::Stmt::Global(ast::StmtGlobal {
names,
range: _range,
}) => Self::Global(StmtGlobal {
names: names.iter().map(ast::Identifier::as_str).collect(),
}),
ast::Stmt::Nonlocal(ast::StmtNonlocal {
names,
range: _range,
}) => Self::Nonlocal(StmtNonlocal {
names: names.iter().map(ast::Identifier::as_str).collect(),
}),
ast::Stmt::LineMagic(ast::StmtLineMagic {
kind,
value,
range: _range,
}) => Self::LineMagic(StmtLineMagic {
kind: *kind,
value: value.as_str(),
}),
ast::Stmt::Expr(ast::StmtExpr {
value,
range: _range,
}) => Self::Expr(StmtExpr {
value: value.into(),
}),
ast::Stmt::Pass(_) => Self::Pass,
ast::Stmt::Break(_) => Self::Break,
ast::Stmt::Continue(_) => Self::Continue,
}
}
}