diff --git a/ast/asdl_rs.py b/ast/asdl_rs.py index a8ca11a..e819193 100755 --- a/ast/asdl_rs.py +++ b/ast/asdl_rs.py @@ -496,15 +496,29 @@ class FoldTraitDefVisitor(EmitVisitor): self.emit("pub trait Fold {", depth) self.emit("type TargetU;", depth + 1) self.emit("type Error;", depth + 1) + self.emit("type UserContext;", depth + 1) self.emit( """ - fn map_user(&mut self, user: U) -> Result; + fn will_map_user(&mut self, user: &U) -> Self::UserContext; #[cfg(feature = "all-nodes-with-ranges")] - fn map_user_cfg(&mut self, user: U) -> Result { - self.map_user(user) + fn will_map_user_cfg(&mut self, user: &U) -> Self::UserContext { + self.will_map_user(user) } #[cfg(not(feature = "all-nodes-with-ranges"))] - fn map_user_cfg(&mut self, _user: crate::EmptyRange) -> Result, Self::Error> { + fn will_map_user_cfg(&mut self, user: &crate::EmptyRange) -> crate::EmptyRange { + crate::EmptyRange::default() + } + fn map_user(&mut self, user: U, context: Self::UserContext) -> Result; + #[cfg(feature = "all-nodes-with-ranges")] + fn map_user_cfg(&mut self, user: U, context: Self::UserContext) -> Result { + self.map_user(user, context) + } + #[cfg(not(feature = "all-nodes-with-ranges"))] + fn map_user_cfg( + &mut self, + _user: crate::EmptyRange, + _context: crate::EmptyRange, + ) -> Result, Self::Error> { Ok(crate::EmptyRange::default()) } """, @@ -578,10 +592,17 @@ class FoldImplVisitor(EmitVisitor): map_user_suffix = "" if type_info.has_attributes else "_cfg" self.emit( - f"let range = folder.map_user{map_user_suffix}(range)?;", depth + 3 + f"let context = folder.will_map_user{map_user_suffix}(&range);", + depth + 3, ) - - self.gen_construction( + self.fold_fields( + fields_pattern[0], cons.fields, fields_pattern[2], depth + 3 + ) + self.emit( + f"let range = folder.map_user{map_user_suffix}(range, context)?;", + depth + 3, + ) + self.composite_fields( fields_pattern[0], cons.fields, fields_pattern[2], depth + 3 ) self.emit("}", depth + 2) @@ -614,9 +635,15 @@ class FoldImplVisitor(EmitVisitor): self.emit(f"let {struct_name} {{ {fields_pattern[1]} }} = node;", depth + 1) map_user_suffix = "" if has_attributes else "_cfg" - self.emit(f"let range = folder.map_user{map_user_suffix}(range)?;", depth + 3) - self.gen_construction(struct_name, product.fields, "", depth + 1) + self.emit( + f"let context = folder.will_map_user{map_user_suffix}(&range);", depth + 3 + ) + self.fold_fields(struct_name, product.fields, "", depth + 1) + self.emit( + f"let range = folder.map_user{map_user_suffix}(range, context)?;", depth + 3 + ) + self.composite_fields(struct_name, product.fields, "", depth + 1) self.emit("}", depth) @@ -631,13 +658,17 @@ class FoldImplVisitor(EmitVisitor): return header, body, footer - def gen_construction(self, header, fields, footer, depth): + def fold_fields(self, header, fields, footer, depth): + for field in fields: + name = rust_field(field.name) + self.emit(f"let {name} = Foldable::fold({name}, folder)?;", depth + 1) + + def composite_fields(self, header, fields, footer, depth): self.emit(f"Ok({header} {{", depth) for field in fields: name = rust_field(field.name) - self.emit(f"{name}: Foldable::fold({name}, folder)?,", depth + 1) + self.emit(f"{name},", depth + 1) self.emit("range,", depth + 1) - self.emit(f"}}{footer})", depth) diff --git a/ast/src/gen/fold.rs b/ast/src/gen/fold.rs index 6d4342d..09f3bd9 100644 --- a/ast/src/gen/fold.rs +++ b/ast/src/gen/fold.rs @@ -1,19 +1,40 @@ // File automatically generated by ast/asdl_rs.py. -use crate::fold_helpers::Foldable; pub trait Fold { type TargetU; type Error; + type UserContext; - fn map_user(&mut self, user: U) -> Result; + fn will_map_user(&mut self, user: &U) -> Self::UserContext; #[cfg(feature = "all-nodes-with-ranges")] - fn map_user_cfg(&mut self, user: U) -> Result { - self.map_user(user) + fn will_map_user_cfg(&mut self, user: &U) -> Self::UserContext { + self.will_map_user(user) + } + #[cfg(not(feature = "all-nodes-with-ranges"))] + fn will_map_user_cfg( + &mut self, + _user: &crate::EmptyRange, + ) -> crate::EmptyRange { + crate::EmptyRange::default() + } + fn map_user( + &mut self, + user: U, + context: Self::UserContext, + ) -> Result; + #[cfg(feature = "all-nodes-with-ranges")] + fn map_user_cfg( + &mut self, + user: U, + context: Self::UserContext, + ) -> Result { + self.map_user(user, context) } #[cfg(not(feature = "all-nodes-with-ranges"))] fn map_user_cfg( &mut self, _user: crate::EmptyRange, + _context: crate::EmptyRange, ) -> Result, Self::Error> { Ok(crate::EmptyRange::default()) } @@ -110,36 +131,40 @@ pub fn fold_mod + ?Sized>( type_ignores, range, }) => { - let range = folder.map_user_cfg(range)?; + let context = folder.will_map_user_cfg(&range); + let body = Foldable::fold(body, folder)?; + let type_ignores = Foldable::fold(type_ignores, folder)?; + let range = folder.map_user_cfg(range, context)?; Ok(Mod::Module(ModModule { - body: Foldable::fold(body, folder)?, - type_ignores: Foldable::fold(type_ignores, folder)?, + body, + type_ignores, range, })) } Mod::Interactive(ModInteractive { body, range }) => { - let range = folder.map_user_cfg(range)?; - Ok(Mod::Interactive(ModInteractive { - body: Foldable::fold(body, folder)?, - range, - })) + let context = folder.will_map_user_cfg(&range); + let body = Foldable::fold(body, folder)?; + let range = folder.map_user_cfg(range, context)?; + Ok(Mod::Interactive(ModInteractive { body, range })) } Mod::Expression(ModExpression { body, range }) => { - let range = folder.map_user_cfg(range)?; - Ok(Mod::Expression(ModExpression { - body: Foldable::fold(body, folder)?, - range, - })) + let context = folder.will_map_user_cfg(&range); + let body = Foldable::fold(body, folder)?; + let range = folder.map_user_cfg(range, context)?; + Ok(Mod::Expression(ModExpression { body, range })) } Mod::FunctionType(ModFunctionType { argtypes, returns, range, }) => { - let range = folder.map_user_cfg(range)?; + let context = folder.will_map_user_cfg(&range); + let argtypes = Foldable::fold(argtypes, folder)?; + let returns = Foldable::fold(returns, folder)?; + let range = folder.map_user_cfg(range, context)?; Ok(Mod::FunctionType(ModFunctionType { - argtypes: Foldable::fold(argtypes, folder)?, - returns: Foldable::fold(returns, folder)?, + argtypes, + returns, range, })) } @@ -168,14 +193,21 @@ pub fn fold_stmt + ?Sized>( type_comment, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let name = Foldable::fold(name, folder)?; + let args = Foldable::fold(args, folder)?; + let body = Foldable::fold(body, folder)?; + let decorator_list = Foldable::fold(decorator_list, folder)?; + let returns = Foldable::fold(returns, folder)?; + let type_comment = Foldable::fold(type_comment, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::FunctionDef(StmtFunctionDef { - name: Foldable::fold(name, folder)?, - args: Foldable::fold(args, folder)?, - body: Foldable::fold(body, folder)?, - decorator_list: Foldable::fold(decorator_list, folder)?, - returns: Foldable::fold(returns, folder)?, - type_comment: Foldable::fold(type_comment, folder)?, + name, + args, + body, + decorator_list, + returns, + type_comment, range, })) } @@ -188,14 +220,21 @@ pub fn fold_stmt + ?Sized>( type_comment, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let name = Foldable::fold(name, folder)?; + let args = Foldable::fold(args, folder)?; + let body = Foldable::fold(body, folder)?; + let decorator_list = Foldable::fold(decorator_list, folder)?; + let returns = Foldable::fold(returns, folder)?; + let type_comment = Foldable::fold(type_comment, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::AsyncFunctionDef(StmtAsyncFunctionDef { - name: Foldable::fold(name, folder)?, - args: Foldable::fold(args, folder)?, - body: Foldable::fold(body, folder)?, - decorator_list: Foldable::fold(decorator_list, folder)?, - returns: Foldable::fold(returns, folder)?, - type_comment: Foldable::fold(type_comment, folder)?, + name, + args, + body, + decorator_list, + returns, + type_comment, range, })) } @@ -207,29 +246,33 @@ pub fn fold_stmt + ?Sized>( decorator_list, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let name = Foldable::fold(name, folder)?; + let bases = Foldable::fold(bases, folder)?; + let keywords = Foldable::fold(keywords, folder)?; + let body = Foldable::fold(body, folder)?; + let decorator_list = Foldable::fold(decorator_list, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::ClassDef(StmtClassDef { - name: Foldable::fold(name, folder)?, - bases: Foldable::fold(bases, folder)?, - keywords: Foldable::fold(keywords, folder)?, - body: Foldable::fold(body, folder)?, - decorator_list: Foldable::fold(decorator_list, folder)?, + name, + bases, + keywords, + body, + decorator_list, range, })) } Stmt::Return(StmtReturn { value, range }) => { - let range = folder.map_user(range)?; - Ok(Stmt::Return(StmtReturn { - value: Foldable::fold(value, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; + Ok(Stmt::Return(StmtReturn { value, range })) } Stmt::Delete(StmtDelete { targets, range }) => { - let range = folder.map_user(range)?; - Ok(Stmt::Delete(StmtDelete { - targets: Foldable::fold(targets, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let targets = Foldable::fold(targets, folder)?; + let range = folder.map_user(range, context)?; + Ok(Stmt::Delete(StmtDelete { targets, range })) } Stmt::Assign(StmtAssign { targets, @@ -237,11 +280,15 @@ pub fn fold_stmt + ?Sized>( type_comment, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let targets = Foldable::fold(targets, folder)?; + let value = Foldable::fold(value, folder)?; + let type_comment = Foldable::fold(type_comment, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::Assign(StmtAssign { - targets: Foldable::fold(targets, folder)?, - value: Foldable::fold(value, folder)?, - type_comment: Foldable::fold(type_comment, folder)?, + targets, + value, + type_comment, range, })) } @@ -251,11 +298,15 @@ pub fn fold_stmt + ?Sized>( value, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let target = Foldable::fold(target, folder)?; + let op = Foldable::fold(op, folder)?; + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::AugAssign(StmtAugAssign { - target: Foldable::fold(target, folder)?, - op: Foldable::fold(op, folder)?, - value: Foldable::fold(value, folder)?, + target, + op, + value, range, })) } @@ -266,12 +317,17 @@ pub fn fold_stmt + ?Sized>( simple, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let target = Foldable::fold(target, folder)?; + let annotation = Foldable::fold(annotation, folder)?; + let value = Foldable::fold(value, folder)?; + let simple = Foldable::fold(simple, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::AnnAssign(StmtAnnAssign { - target: Foldable::fold(target, folder)?, - annotation: Foldable::fold(annotation, folder)?, - value: Foldable::fold(value, folder)?, - simple: Foldable::fold(simple, folder)?, + target, + annotation, + value, + simple, range, })) } @@ -283,13 +339,19 @@ pub fn fold_stmt + ?Sized>( type_comment, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let target = Foldable::fold(target, folder)?; + let iter = Foldable::fold(iter, folder)?; + let body = Foldable::fold(body, folder)?; + let orelse = Foldable::fold(orelse, folder)?; + let type_comment = Foldable::fold(type_comment, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::For(StmtFor { - target: Foldable::fold(target, folder)?, - iter: Foldable::fold(iter, folder)?, - body: Foldable::fold(body, folder)?, - orelse: Foldable::fold(orelse, folder)?, - type_comment: Foldable::fold(type_comment, folder)?, + target, + iter, + body, + orelse, + type_comment, range, })) } @@ -301,13 +363,19 @@ pub fn fold_stmt + ?Sized>( type_comment, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let target = Foldable::fold(target, folder)?; + let iter = Foldable::fold(iter, folder)?; + let body = Foldable::fold(body, folder)?; + let orelse = Foldable::fold(orelse, folder)?; + let type_comment = Foldable::fold(type_comment, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::AsyncFor(StmtAsyncFor { - target: Foldable::fold(target, folder)?, - iter: Foldable::fold(iter, folder)?, - body: Foldable::fold(body, folder)?, - orelse: Foldable::fold(orelse, folder)?, - type_comment: Foldable::fold(type_comment, folder)?, + target, + iter, + body, + orelse, + type_comment, range, })) } @@ -317,11 +385,15 @@ pub fn fold_stmt + ?Sized>( orelse, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let test = Foldable::fold(test, folder)?; + let body = Foldable::fold(body, folder)?; + let orelse = Foldable::fold(orelse, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::While(StmtWhile { - test: Foldable::fold(test, folder)?, - body: Foldable::fold(body, folder)?, - orelse: Foldable::fold(orelse, folder)?, + test, + body, + orelse, range, })) } @@ -331,11 +403,15 @@ pub fn fold_stmt + ?Sized>( orelse, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let test = Foldable::fold(test, folder)?; + let body = Foldable::fold(body, folder)?; + let orelse = Foldable::fold(orelse, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::If(StmtIf { - test: Foldable::fold(test, folder)?, - body: Foldable::fold(body, folder)?, - orelse: Foldable::fold(orelse, folder)?, + test, + body, + orelse, range, })) } @@ -345,11 +421,15 @@ pub fn fold_stmt + ?Sized>( type_comment, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let items = Foldable::fold(items, folder)?; + let body = Foldable::fold(body, folder)?; + let type_comment = Foldable::fold(type_comment, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::With(StmtWith { - items: Foldable::fold(items, folder)?, - body: Foldable::fold(body, folder)?, - type_comment: Foldable::fold(type_comment, folder)?, + items, + body, + type_comment, range, })) } @@ -359,11 +439,15 @@ pub fn fold_stmt + ?Sized>( type_comment, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let items = Foldable::fold(items, folder)?; + let body = Foldable::fold(body, folder)?; + let type_comment = Foldable::fold(type_comment, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::AsyncWith(StmtAsyncWith { - items: Foldable::fold(items, folder)?, - body: Foldable::fold(body, folder)?, - type_comment: Foldable::fold(type_comment, folder)?, + items, + body, + type_comment, range, })) } @@ -372,20 +456,22 @@ pub fn fold_stmt + ?Sized>( cases, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let subject = Foldable::fold(subject, folder)?; + let cases = Foldable::fold(cases, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::Match(StmtMatch { - subject: Foldable::fold(subject, folder)?, - cases: Foldable::fold(cases, folder)?, + subject, + cases, range, })) } Stmt::Raise(StmtRaise { exc, cause, range }) => { - let range = folder.map_user(range)?; - Ok(Stmt::Raise(StmtRaise { - exc: Foldable::fold(exc, folder)?, - cause: Foldable::fold(cause, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let exc = Foldable::fold(exc, folder)?; + let cause = Foldable::fold(cause, folder)?; + let range = folder.map_user(range, context)?; + Ok(Stmt::Raise(StmtRaise { exc, cause, range })) } Stmt::Try(StmtTry { body, @@ -394,12 +480,17 @@ pub fn fold_stmt + ?Sized>( finalbody, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let body = Foldable::fold(body, folder)?; + let handlers = Foldable::fold(handlers, folder)?; + let orelse = Foldable::fold(orelse, folder)?; + let finalbody = Foldable::fold(finalbody, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::Try(StmtTry { - body: Foldable::fold(body, folder)?, - handlers: Foldable::fold(handlers, folder)?, - orelse: Foldable::fold(orelse, folder)?, - finalbody: Foldable::fold(finalbody, folder)?, + body, + handlers, + orelse, + finalbody, range, })) } @@ -410,29 +501,32 @@ pub fn fold_stmt + ?Sized>( finalbody, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let body = Foldable::fold(body, folder)?; + let handlers = Foldable::fold(handlers, folder)?; + let orelse = Foldable::fold(orelse, folder)?; + let finalbody = Foldable::fold(finalbody, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::TryStar(StmtTryStar { - body: Foldable::fold(body, folder)?, - handlers: Foldable::fold(handlers, folder)?, - orelse: Foldable::fold(orelse, folder)?, - finalbody: Foldable::fold(finalbody, folder)?, + body, + handlers, + orelse, + finalbody, range, })) } Stmt::Assert(StmtAssert { test, msg, range }) => { - let range = folder.map_user(range)?; - Ok(Stmt::Assert(StmtAssert { - test: Foldable::fold(test, folder)?, - msg: Foldable::fold(msg, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let test = Foldable::fold(test, folder)?; + let msg = Foldable::fold(msg, folder)?; + let range = folder.map_user(range, context)?; + Ok(Stmt::Assert(StmtAssert { test, msg, range })) } Stmt::Import(StmtImport { names, range }) => { - let range = folder.map_user(range)?; - Ok(Stmt::Import(StmtImport { - names: Foldable::fold(names, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let names = Foldable::fold(names, folder)?; + let range = folder.map_user(range, context)?; + Ok(Stmt::Import(StmtImport { names, range })) } Stmt::ImportFrom(StmtImportFrom { module, @@ -440,45 +534,49 @@ pub fn fold_stmt + ?Sized>( level, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let module = Foldable::fold(module, folder)?; + let names = Foldable::fold(names, folder)?; + let level = Foldable::fold(level, folder)?; + let range = folder.map_user(range, context)?; Ok(Stmt::ImportFrom(StmtImportFrom { - module: Foldable::fold(module, folder)?, - names: Foldable::fold(names, folder)?, - level: Foldable::fold(level, folder)?, + module, + names, + level, range, })) } Stmt::Global(StmtGlobal { names, range }) => { - let range = folder.map_user(range)?; - Ok(Stmt::Global(StmtGlobal { - names: Foldable::fold(names, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let names = Foldable::fold(names, folder)?; + let range = folder.map_user(range, context)?; + Ok(Stmt::Global(StmtGlobal { names, range })) } Stmt::Nonlocal(StmtNonlocal { names, range }) => { - let range = folder.map_user(range)?; - Ok(Stmt::Nonlocal(StmtNonlocal { - names: Foldable::fold(names, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let names = Foldable::fold(names, folder)?; + let range = folder.map_user(range, context)?; + Ok(Stmt::Nonlocal(StmtNonlocal { names, range })) } Stmt::Expr(StmtExpr { value, range }) => { - let range = folder.map_user(range)?; - Ok(Stmt::Expr(StmtExpr { - value: Foldable::fold(value, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; + Ok(Stmt::Expr(StmtExpr { value, range })) } Stmt::Pass(StmtPass { range }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let range = folder.map_user(range, context)?; Ok(Stmt::Pass(StmtPass { range })) } Stmt::Break(StmtBreak { range }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let range = folder.map_user(range, context)?; Ok(Stmt::Break(StmtBreak { range })) } Stmt::Continue(StmtContinue { range }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let range = folder.map_user(range, context)?; Ok(Stmt::Continue(StmtContinue { range })) } } @@ -498,22 +596,24 @@ pub fn fold_expr + ?Sized>( ) -> Result, F::Error> { match node { Expr::BoolOp(ExprBoolOp { op, values, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::BoolOp(ExprBoolOp { - op: Foldable::fold(op, folder)?, - values: Foldable::fold(values, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let op = Foldable::fold(op, folder)?; + let values = Foldable::fold(values, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::BoolOp(ExprBoolOp { op, values, range })) } Expr::NamedExpr(ExprNamedExpr { target, value, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let target = Foldable::fold(target, folder)?; + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::NamedExpr(ExprNamedExpr { - target: Foldable::fold(target, folder)?, - value: Foldable::fold(value, folder)?, + target, + value, range, })) } @@ -523,29 +623,31 @@ pub fn fold_expr + ?Sized>( right, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let left = Foldable::fold(left, folder)?; + let op = Foldable::fold(op, folder)?; + let right = Foldable::fold(right, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::BinOp(ExprBinOp { - left: Foldable::fold(left, folder)?, - op: Foldable::fold(op, folder)?, - right: Foldable::fold(right, folder)?, + left, + op, + right, range, })) } Expr::UnaryOp(ExprUnaryOp { op, operand, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::UnaryOp(ExprUnaryOp { - op: Foldable::fold(op, folder)?, - operand: Foldable::fold(operand, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let op = Foldable::fold(op, folder)?; + let operand = Foldable::fold(operand, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::UnaryOp(ExprUnaryOp { op, operand, range })) } Expr::Lambda(ExprLambda { args, body, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::Lambda(ExprLambda { - args: Foldable::fold(args, folder)?, - body: Foldable::fold(body, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let args = Foldable::fold(args, folder)?; + let body = Foldable::fold(body, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::Lambda(ExprLambda { args, body, range })) } Expr::IfExp(ExprIfExp { test, @@ -553,11 +655,15 @@ pub fn fold_expr + ?Sized>( orelse, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let test = Foldable::fold(test, folder)?; + let body = Foldable::fold(body, folder)?; + let orelse = Foldable::fold(orelse, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::IfExp(ExprIfExp { - test: Foldable::fold(test, folder)?, - body: Foldable::fold(body, folder)?, - orelse: Foldable::fold(orelse, folder)?, + test, + body, + orelse, range, })) } @@ -566,29 +672,34 @@ pub fn fold_expr + ?Sized>( values, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let keys = Foldable::fold(keys, folder)?; + let values = Foldable::fold(values, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::Dict(ExprDict { - keys: Foldable::fold(keys, folder)?, - values: Foldable::fold(values, folder)?, + keys, + values, range, })) } Expr::Set(ExprSet { elts, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::Set(ExprSet { - elts: Foldable::fold(elts, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let elts = Foldable::fold(elts, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::Set(ExprSet { elts, range })) } Expr::ListComp(ExprListComp { elt, generators, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let elt = Foldable::fold(elt, folder)?; + let generators = Foldable::fold(generators, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::ListComp(ExprListComp { - elt: Foldable::fold(elt, folder)?, - generators: Foldable::fold(generators, folder)?, + elt, + generators, range, })) } @@ -597,10 +708,13 @@ pub fn fold_expr + ?Sized>( generators, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let elt = Foldable::fold(elt, folder)?; + let generators = Foldable::fold(generators, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::SetComp(ExprSetComp { - elt: Foldable::fold(elt, folder)?, - generators: Foldable::fold(generators, folder)?, + elt, + generators, range, })) } @@ -610,11 +724,15 @@ pub fn fold_expr + ?Sized>( generators, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let key = Foldable::fold(key, folder)?; + let value = Foldable::fold(value, folder)?; + let generators = Foldable::fold(generators, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::DictComp(ExprDictComp { - key: Foldable::fold(key, folder)?, - value: Foldable::fold(value, folder)?, - generators: Foldable::fold(generators, folder)?, + key, + value, + generators, range, })) } @@ -623,33 +741,33 @@ pub fn fold_expr + ?Sized>( generators, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let elt = Foldable::fold(elt, folder)?; + let generators = Foldable::fold(generators, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::GeneratorExp(ExprGeneratorExp { - elt: Foldable::fold(elt, folder)?, - generators: Foldable::fold(generators, folder)?, + elt, + generators, range, })) } Expr::Await(ExprAwait { value, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::Await(ExprAwait { - value: Foldable::fold(value, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::Await(ExprAwait { value, range })) } Expr::Yield(ExprYield { value, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::Yield(ExprYield { - value: Foldable::fold(value, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::Yield(ExprYield { value, range })) } Expr::YieldFrom(ExprYieldFrom { value, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::YieldFrom(ExprYieldFrom { - value: Foldable::fold(value, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::YieldFrom(ExprYieldFrom { value, range })) } Expr::Compare(ExprCompare { left, @@ -657,11 +775,15 @@ pub fn fold_expr + ?Sized>( comparators, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let left = Foldable::fold(left, folder)?; + let ops = Foldable::fold(ops, folder)?; + let comparators = Foldable::fold(comparators, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::Compare(ExprCompare { - left: Foldable::fold(left, folder)?, - ops: Foldable::fold(ops, folder)?, - comparators: Foldable::fold(comparators, folder)?, + left, + ops, + comparators, range, })) } @@ -671,11 +793,15 @@ pub fn fold_expr + ?Sized>( keywords, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let func = Foldable::fold(func, folder)?; + let args = Foldable::fold(args, folder)?; + let keywords = Foldable::fold(keywords, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::Call(ExprCall { - func: Foldable::fold(func, folder)?, - args: Foldable::fold(args, folder)?, - keywords: Foldable::fold(keywords, folder)?, + func, + args, + keywords, range, })) } @@ -685,28 +811,30 @@ pub fn fold_expr + ?Sized>( format_spec, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let conversion = Foldable::fold(conversion, folder)?; + let format_spec = Foldable::fold(format_spec, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::FormattedValue(ExprFormattedValue { - value: Foldable::fold(value, folder)?, - conversion: Foldable::fold(conversion, folder)?, - format_spec: Foldable::fold(format_spec, folder)?, + value, + conversion, + format_spec, range, })) } Expr::JoinedStr(ExprJoinedStr { values, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::JoinedStr(ExprJoinedStr { - values: Foldable::fold(values, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let values = Foldable::fold(values, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::JoinedStr(ExprJoinedStr { values, range })) } Expr::Constant(ExprConstant { value, kind, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::Constant(ExprConstant { - value: Foldable::fold(value, folder)?, - kind: Foldable::fold(kind, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let kind = Foldable::fold(kind, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::Constant(ExprConstant { value, kind, range })) } Expr::Attribute(ExprAttribute { value, @@ -714,11 +842,15 @@ pub fn fold_expr + ?Sized>( ctx, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let attr = Foldable::fold(attr, folder)?; + let ctx = Foldable::fold(ctx, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::Attribute(ExprAttribute { - value: Foldable::fold(value, folder)?, - attr: Foldable::fold(attr, folder)?, - ctx: Foldable::fold(ctx, folder)?, + value, + attr, + ctx, range, })) } @@ -728,45 +860,45 @@ pub fn fold_expr + ?Sized>( ctx, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let slice = Foldable::fold(slice, folder)?; + let ctx = Foldable::fold(ctx, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::Subscript(ExprSubscript { - value: Foldable::fold(value, folder)?, - slice: Foldable::fold(slice, folder)?, - ctx: Foldable::fold(ctx, folder)?, + value, + slice, + ctx, range, })) } Expr::Starred(ExprStarred { value, ctx, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::Starred(ExprStarred { - value: Foldable::fold(value, folder)?, - ctx: Foldable::fold(ctx, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let ctx = Foldable::fold(ctx, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::Starred(ExprStarred { value, ctx, range })) } Expr::Name(ExprName { id, ctx, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::Name(ExprName { - id: Foldable::fold(id, folder)?, - ctx: Foldable::fold(ctx, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let id = Foldable::fold(id, folder)?; + let ctx = Foldable::fold(ctx, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::Name(ExprName { id, ctx, range })) } Expr::List(ExprList { elts, ctx, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::List(ExprList { - elts: Foldable::fold(elts, folder)?, - ctx: Foldable::fold(ctx, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let elts = Foldable::fold(elts, folder)?; + let ctx = Foldable::fold(ctx, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::List(ExprList { elts, ctx, range })) } Expr::Tuple(ExprTuple { elts, ctx, range }) => { - let range = folder.map_user(range)?; - Ok(Expr::Tuple(ExprTuple { - elts: Foldable::fold(elts, folder)?, - ctx: Foldable::fold(ctx, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let elts = Foldable::fold(elts, folder)?; + let ctx = Foldable::fold(ctx, folder)?; + let range = folder.map_user(range, context)?; + Ok(Expr::Tuple(ExprTuple { elts, ctx, range })) } Expr::Slice(ExprSlice { lower, @@ -774,11 +906,15 @@ pub fn fold_expr + ?Sized>( step, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let lower = Foldable::fold(lower, folder)?; + let upper = Foldable::fold(upper, folder)?; + let step = Foldable::fold(step, folder)?; + let range = folder.map_user(range, context)?; Ok(Expr::Slice(ExprSlice { - lower: Foldable::fold(lower, folder)?, - upper: Foldable::fold(upper, folder)?, - step: Foldable::fold(step, folder)?, + lower, + upper, + step, range, })) } @@ -879,12 +1015,17 @@ pub fn fold_comprehension + ?Sized>( is_async, range, } = node; - let range = folder.map_user_cfg(range)?; + let context = folder.will_map_user_cfg(&range); + let target = Foldable::fold(target, folder)?; + let iter = Foldable::fold(iter, folder)?; + let ifs = Foldable::fold(ifs, folder)?; + let is_async = Foldable::fold(is_async, folder)?; + let range = folder.map_user_cfg(range, context)?; Ok(Comprehension { - target: Foldable::fold(target, folder)?, - iter: Foldable::fold(iter, folder)?, - ifs: Foldable::fold(ifs, folder)?, - is_async: Foldable::fold(is_async, folder)?, + target, + iter, + ifs, + is_async, range, }) } @@ -908,11 +1049,15 @@ pub fn fold_excepthandler + ?Sized>( body, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let type_ = Foldable::fold(type_, folder)?; + let name = Foldable::fold(name, folder)?; + let body = Foldable::fold(body, folder)?; + let range = folder.map_user(range, context)?; Ok(Excepthandler::ExceptHandler(ExcepthandlerExceptHandler { - type_: Foldable::fold(type_, folder)?, - name: Foldable::fold(name, folder)?, - body: Foldable::fold(body, folder)?, + type_, + name, + body, range, })) } @@ -941,15 +1086,23 @@ pub fn fold_arguments + ?Sized>( defaults, range, } = node; - let range = folder.map_user_cfg(range)?; + let context = folder.will_map_user_cfg(&range); + let posonlyargs = Foldable::fold(posonlyargs, folder)?; + let args = Foldable::fold(args, folder)?; + let vararg = Foldable::fold(vararg, folder)?; + let kwonlyargs = Foldable::fold(kwonlyargs, folder)?; + let kw_defaults = Foldable::fold(kw_defaults, folder)?; + let kwarg = Foldable::fold(kwarg, folder)?; + let defaults = Foldable::fold(defaults, folder)?; + let range = folder.map_user_cfg(range, context)?; Ok(Arguments { - posonlyargs: Foldable::fold(posonlyargs, folder)?, - args: Foldable::fold(args, folder)?, - vararg: Foldable::fold(vararg, folder)?, - kwonlyargs: Foldable::fold(kwonlyargs, folder)?, - kw_defaults: Foldable::fold(kw_defaults, folder)?, - kwarg: Foldable::fold(kwarg, folder)?, - defaults: Foldable::fold(defaults, folder)?, + posonlyargs, + args, + vararg, + kwonlyargs, + kw_defaults, + kwarg, + defaults, range, }) } @@ -972,11 +1125,15 @@ pub fn fold_arg + ?Sized>( type_comment, range, } = node; - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let arg = Foldable::fold(arg, folder)?; + let annotation = Foldable::fold(annotation, folder)?; + let type_comment = Foldable::fold(type_comment, folder)?; + let range = folder.map_user(range, context)?; Ok(Arg { - arg: Foldable::fold(arg, folder)?, - annotation: Foldable::fold(annotation, folder)?, - type_comment: Foldable::fold(type_comment, folder)?, + arg, + annotation, + type_comment, range, }) } @@ -994,12 +1151,11 @@ pub fn fold_keyword + ?Sized>( node: Keyword, ) -> Result, F::Error> { let Keyword { arg, value, range } = node; - let range = folder.map_user(range)?; - Ok(Keyword { - arg: Foldable::fold(arg, folder)?, - value: Foldable::fold(value, folder)?, - range, - }) + let context = folder.will_map_user(&range); + let arg = Foldable::fold(arg, folder)?; + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; + Ok(Keyword { arg, value, range }) } impl Foldable for Alias { type Mapped = Alias; @@ -1019,10 +1175,13 @@ pub fn fold_alias + ?Sized>( asname, range, } = node; - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let name = Foldable::fold(name, folder)?; + let asname = Foldable::fold(asname, folder)?; + let range = folder.map_user(range, context)?; Ok(Alias { - name: Foldable::fold(name, folder)?, - asname: Foldable::fold(asname, folder)?, + name, + asname, range, }) } @@ -1044,10 +1203,13 @@ pub fn fold_withitem + ?Sized>( optional_vars, range, } = node; - let range = folder.map_user_cfg(range)?; + let context = folder.will_map_user_cfg(&range); + let context_expr = Foldable::fold(context_expr, folder)?; + let optional_vars = Foldable::fold(optional_vars, folder)?; + let range = folder.map_user_cfg(range, context)?; Ok(Withitem { - context_expr: Foldable::fold(context_expr, folder)?, - optional_vars: Foldable::fold(optional_vars, folder)?, + context_expr, + optional_vars, range, }) } @@ -1070,11 +1232,15 @@ pub fn fold_match_case + ?Sized>( body, range, } = node; - let range = folder.map_user_cfg(range)?; + let context = folder.will_map_user_cfg(&range); + let pattern = Foldable::fold(pattern, folder)?; + let guard = Foldable::fold(guard, folder)?; + let body = Foldable::fold(body, folder)?; + let range = folder.map_user_cfg(range, context)?; Ok(MatchCase { - pattern: Foldable::fold(pattern, folder)?, - guard: Foldable::fold(guard, folder)?, - body: Foldable::fold(body, folder)?, + pattern, + guard, + body, range, }) } @@ -1093,23 +1259,26 @@ pub fn fold_pattern + ?Sized>( ) -> Result, F::Error> { match node { Pattern::MatchValue(PatternMatchValue { value, range }) => { - let range = folder.map_user(range)?; - Ok(Pattern::MatchValue(PatternMatchValue { - value: Foldable::fold(value, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; + Ok(Pattern::MatchValue(PatternMatchValue { value, range })) } Pattern::MatchSingleton(PatternMatchSingleton { value, range }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let value = Foldable::fold(value, folder)?; + let range = folder.map_user(range, context)?; Ok(Pattern::MatchSingleton(PatternMatchSingleton { - value: Foldable::fold(value, folder)?, + value, range, })) } Pattern::MatchSequence(PatternMatchSequence { patterns, range }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let patterns = Foldable::fold(patterns, folder)?; + let range = folder.map_user(range, context)?; Ok(Pattern::MatchSequence(PatternMatchSequence { - patterns: Foldable::fold(patterns, folder)?, + patterns, range, })) } @@ -1119,11 +1288,15 @@ pub fn fold_pattern + ?Sized>( rest, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let keys = Foldable::fold(keys, folder)?; + let patterns = Foldable::fold(patterns, folder)?; + let rest = Foldable::fold(rest, folder)?; + let range = folder.map_user(range, context)?; Ok(Pattern::MatchMapping(PatternMatchMapping { - keys: Foldable::fold(keys, folder)?, - patterns: Foldable::fold(patterns, folder)?, - rest: Foldable::fold(rest, folder)?, + keys, + patterns, + rest, range, })) } @@ -1134,40 +1307,46 @@ pub fn fold_pattern + ?Sized>( kwd_patterns, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let cls = Foldable::fold(cls, folder)?; + let patterns = Foldable::fold(patterns, folder)?; + let kwd_attrs = Foldable::fold(kwd_attrs, folder)?; + let kwd_patterns = Foldable::fold(kwd_patterns, folder)?; + let range = folder.map_user(range, context)?; Ok(Pattern::MatchClass(PatternMatchClass { - cls: Foldable::fold(cls, folder)?, - patterns: Foldable::fold(patterns, folder)?, - kwd_attrs: Foldable::fold(kwd_attrs, folder)?, - kwd_patterns: Foldable::fold(kwd_patterns, folder)?, + cls, + patterns, + kwd_attrs, + kwd_patterns, range, })) } Pattern::MatchStar(PatternMatchStar { name, range }) => { - let range = folder.map_user(range)?; - Ok(Pattern::MatchStar(PatternMatchStar { - name: Foldable::fold(name, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let name = Foldable::fold(name, folder)?; + let range = folder.map_user(range, context)?; + Ok(Pattern::MatchStar(PatternMatchStar { name, range })) } Pattern::MatchAs(PatternMatchAs { pattern, name, range, }) => { - let range = folder.map_user(range)?; + let context = folder.will_map_user(&range); + let pattern = Foldable::fold(pattern, folder)?; + let name = Foldable::fold(name, folder)?; + let range = folder.map_user(range, context)?; Ok(Pattern::MatchAs(PatternMatchAs { - pattern: Foldable::fold(pattern, folder)?, - name: Foldable::fold(name, folder)?, + pattern, + name, range, })) } Pattern::MatchOr(PatternMatchOr { patterns, range }) => { - let range = folder.map_user(range)?; - Ok(Pattern::MatchOr(PatternMatchOr { - patterns: Foldable::fold(patterns, folder)?, - range, - })) + let context = folder.will_map_user(&range); + let patterns = Foldable::fold(patterns, folder)?; + let range = folder.map_user(range, context)?; + Ok(Pattern::MatchOr(PatternMatchOr { patterns, range })) } } } @@ -1186,10 +1365,13 @@ pub fn fold_type_ignore + ?Sized>( ) -> Result, F::Error> { match node { TypeIgnore::TypeIgnore(TypeIgnoreTypeIgnore { lineno, tag, range }) => { - let range = folder.map_user_cfg(range)?; + let context = folder.will_map_user_cfg(&range); + let lineno = Foldable::fold(lineno, folder)?; + let tag = Foldable::fold(tag, folder)?; + let range = folder.map_user_cfg(range, context)?; Ok(TypeIgnore::TypeIgnore(TypeIgnoreTypeIgnore { - lineno: Foldable::fold(lineno, folder)?, - tag: Foldable::fold(tag, folder)?, + lineno, + tag, range, })) } diff --git a/ast/src/optimizer.rs b/ast/src/optimizer.rs index f871734..9689163 100644 --- a/ast/src/optimizer.rs +++ b/ast/src/optimizer.rs @@ -15,8 +15,12 @@ impl ConstantOptimizer { impl crate::fold::Fold for ConstantOptimizer { type TargetU = U; type Error = std::convert::Infallible; + type UserContext = (); + + #[inline(always)] + fn will_map_user(&mut self, _user: &U) -> Self::UserContext {} #[inline] - fn map_user(&mut self, user: U) -> Result { + fn map_user(&mut self, user: U, _context: ()) -> Result { Ok(user) } fn fold_expr(&mut self, node: crate::Expr) -> Result, Self::Error> { diff --git a/ast/src/source_locator.rs b/ast/src/source_locator.rs index ebacd89..ef7e43e 100644 --- a/ast/src/source_locator.rs +++ b/ast/src/source_locator.rs @@ -1,14 +1,22 @@ use rustpython_parser_core::{ - source_code::{SourceLocator, SourceRange}, + source_code::{SourceLocation, SourceLocator, SourceRange}, text_size::TextRange, }; impl crate::fold::Fold for SourceLocator<'_> { type TargetU = SourceRange; type Error = std::convert::Infallible; + type UserContext = SourceLocation; - fn map_user(&mut self, user: TextRange) -> Result { - let start = self.locate(user.start()); + fn will_map_user(&mut self, user: &TextRange) -> Self::UserContext { + self.locate(user.start()) + } + + fn map_user( + &mut self, + user: TextRange, + start: Self::UserContext, + ) -> Result { let end = self.locate(user.end()); Ok((start..end).into()) }