Add support for if-filters in list comprehensions.

This commit is contained in:
Windel Bouwman committed 2018-10-27 11:35:46 +02:00
1 parent b03dd623c7
commit 29ce0cf2e7
4 files changed
+45 -43

No files matched your search

+21 -2
View File
@@ -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
View File
@@ -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>> => {
+3 -4
View File
@@ -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]
+10
View File
@@ -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 {