mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Add support for if-filters in list comprehensions.
This commit is contained in:
1 parent
b03dd623c7
commit
29ce0cf2e7
4 files changed
+45
-43
No files matched your search
+21
-2
@@ -381,7 +381,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_double_list_comprehension() {
|
||||
let source = String::from("[x for y, y2 in z for a in b]");
|
||||
let source = String::from("[x for y, y2 in z for a in b if a < 5 if a > 10]");
|
||||
let parse_ast = parse_expression(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
@@ -415,7 +415,26 @@ mod tests {
|
||||
iter: ast::Expression::Identifier {
|
||||
name: "b".to_string()
|
||||
},
|
||||
ifs: vec![],
|
||||
ifs: vec![
|
||||
ast::Expression::Compare {
|
||||
a: Box::new(ast::Expression::Identifier {
|
||||
name: "a".to_string()
|
||||
}),
|
||||
op: ast::Comparison::Less,
|
||||
b: Box::new(ast::Expression::Number {
|
||||
value: ast::Number::Integer { value: 5 }
|
||||
}),
|
||||
},
|
||||
ast::Expression::Compare {
|
||||
a: Box::new(ast::Expression::Identifier {
|
||||
name: "a".to_string()
|
||||
}),
|
||||
op: ast::Comparison::Greater,
|
||||
b: Box::new(ast::Expression::Number {
|
||||
value: ast::Number::Integer { value: 10 }
|
||||
}),
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
+11
-37
@@ -904,34 +904,16 @@ StarExpr: ast::Expression = {
|
||||
};
|
||||
|
||||
// Comprehensions:
|
||||
CompIter: (Option<Vec<ast::Comprehension>>, Option<ast::Expression>) = {
|
||||
// <e:CompIf> => (None, Some(e)),
|
||||
<c:CompFor> => (Some(c), None),
|
||||
CompFor: Vec<ast::Comprehension> = {
|
||||
<c:SingleForComprehension+> => c,
|
||||
};
|
||||
|
||||
CompFor: Vec<ast::Comprehension> = {
|
||||
"for" <e:ExpressionList> "in" <i:OrTest> <c2:CompIter?> => {
|
||||
match c2 {
|
||||
None => {
|
||||
vec![ast::Comprehension {
|
||||
target: e,
|
||||
iter: i,
|
||||
ifs: vec![],
|
||||
}]
|
||||
},
|
||||
Some((Some(mut cphs), None)) => {
|
||||
let mut res = vec![];
|
||||
res.push(ast::Comprehension {
|
||||
target: e,
|
||||
iter: i,
|
||||
ifs: vec![],
|
||||
});
|
||||
res.append(&mut cphs);
|
||||
res
|
||||
},
|
||||
_ => {
|
||||
panic!("TODO");
|
||||
},
|
||||
SingleForComprehension: ast::Comprehension = {
|
||||
"for" <e:ExpressionList> "in" <i:OrTest> <c2:ComprehensionIf*> => {
|
||||
ast::Comprehension {
|
||||
target: e,
|
||||
iter: i,
|
||||
ifs: c2,
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -940,17 +922,9 @@ ExpressionNoCond: ast::Expression = {
|
||||
OrTest,
|
||||
};
|
||||
|
||||
//CompIf: ast::Expression = {
|
||||
// "if" <c:ExpressionNoCond> <c2:CompIter?> => {
|
||||
// match c2 {
|
||||
// None => {
|
||||
// vec![]
|
||||
// },
|
||||
// Some() => {
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
//};
|
||||
ComprehensionIf: ast::Expression = {
|
||||
"if" <c:ExpressionNoCond> => c,
|
||||
};
|
||||
|
||||
ArgumentList: (Vec<ast::Expression>, Vec<ast::Keyword>) = {
|
||||
<e: Comma<FunctionArgument>> => {
|
||||
|
||||
@@ -18,7 +18,6 @@ v = {b * 2 for b in x}
|
||||
# TODO:
|
||||
#u = {str(b): b-2 for b in x}
|
||||
|
||||
# TODO: With if filtering:
|
||||
#y = [a+2 for a in x if a % 2]
|
||||
#print(y)
|
||||
#assert y == [3, 5]
|
||||
y = [a+2 for a in x if a % 2]
|
||||
print(y)
|
||||
assert y == [3, 5]
|
||||
@@ -1050,6 +1050,16 @@ impl Compiler {
|
||||
self.emit(Instruction::ForIter);
|
||||
|
||||
self.compile_store(&generator.target)?;
|
||||
|
||||
// Now evaluate the ifs:
|
||||
for if_condition in &generator.ifs {
|
||||
self.compile_test(
|
||||
if_condition,
|
||||
None,
|
||||
Some(start_label),
|
||||
EvalContext::Statement,
|
||||
)?
|
||||
}
|
||||
}
|
||||
|
||||
match kind {
|
||||
|
||||
Reference in new issue
Block a user