Skip to content

Commit c9aa103

Browse files
committed
Change target of for loops into single expression.
1 parent 6105a83 commit c9aa103

File tree

5 files changed

+67
-31
lines changed

5 files changed

+67
-31
lines changed

parser/src/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub enum Statement {
7878
body: Vec<LocatedStatement>,
7979
},
8080
For {
81-
target: Vec<Expression>,
81+
target: Expression,
8282
iter: Vec<Expression>,
8383
body: Vec<LocatedStatement>,
8484
orelse: Option<Vec<LocatedStatement>>,
@@ -200,7 +200,7 @@ pub enum Expression {
200200

201201
#[derive(Debug, PartialEq, Clone)]
202202
pub struct Comprehension {
203-
pub target: Vec<Expression>, // TODO: should this be a non-vector?
203+
pub target: Expression,
204204
pub iter: Expression,
205205
pub ifs: Vec<Expression>,
206206
}

parser/src/parser.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,9 @@ mod tests {
337337
name: "x".to_string()
338338
}),
339339
generators: vec![ast::Comprehension {
340-
target: vec![ast::Expression::Identifier {
340+
target: ast::Expression::Identifier {
341341
name: "y".to_string()
342-
},],
342+
},
343343
iter: ast::Expression::Identifier {
344344
name: "z".to_string()
345345
},
@@ -348,4 +348,45 @@ mod tests {
348348
}
349349
);
350350
}
351+
352+
#[test]
353+
fn test_parse_double_list_comprehension() {
354+
let source = String::from("[x for y, y2 in z for a in b]");
355+
let parse_ast = parse_expression(&source).unwrap();
356+
assert_eq!(
357+
parse_ast,
358+
ast::Expression::ListComprehension {
359+
element: Box::new(ast::Expression::Identifier {
360+
name: "x".to_string()
361+
}),
362+
generators: vec![
363+
ast::Comprehension {
364+
target: ast::Expression::Tuple {
365+
elements: vec![
366+
ast::Expression::Identifier {
367+
name: "y".to_string()
368+
},
369+
ast::Expression::Identifier {
370+
name: "y2".to_string()
371+
},
372+
],
373+
},
374+
iter: ast::Expression::Identifier {
375+
name: "z".to_string()
376+
},
377+
ifs: vec![],
378+
},
379+
ast::Comprehension {
380+
target: ast::Expression::Identifier {
381+
name: "a".to_string()
382+
},
383+
iter: ast::Expression::Identifier {
384+
name: "b".to_string()
385+
},
386+
ifs: vec![],
387+
}
388+
],
389+
}
390+
);
391+
}
351392
}

parser/src/python.lalrpop

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,11 @@ ForStatement: ast::LocatedStatement = {
298298
None => None,
299299
};
300300
ast::LocatedStatement {
301-
location: loc,
302-
node: ast::Statement::For { target: e, iter: t, body: s, orelse: or_else },
301+
location: loc,
302+
node: ast::Statement::For {
303+
target: e,
304+
iter: t, body: s, orelse: or_else
305+
},
303306
}
304307
},
305308
};
@@ -622,8 +625,14 @@ DictEntry: (ast::Expression, ast::Expression) = {
622625
<e1: Test> ":" <e2: Test> => (e1, e2),
623626
};
624627

625-
ExpressionList: Vec<ast::Expression> = {
626-
<e: Comma<Expression>> => e,
628+
ExpressionList: ast::Expression = {
629+
<e: Comma<Expression>> => {
630+
if e.len() == 1 {
631+
e.into_iter().next().unwrap()
632+
} else {
633+
ast::Expression::Tuple { elements: e }
634+
}
635+
},
627636
};
628637

629638
#[inline]
@@ -653,12 +662,12 @@ CompFor: Vec<ast::Comprehension> = {
653662
},
654663
Some((Some(mut cphs), None)) => {
655664
let mut res = vec![];
656-
res.append(&mut cphs);
657665
res.push(ast::Comprehension {
658666
target: e,
659667
iter: i,
660668
ifs: vec![],
661669
});
670+
res.append(&mut cphs);
662671
res
663672
},
664673
_ => {

tests/snippets/comprehensions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,9 @@
44
y = [a*a+1 for a in x]
55
assert y == [2, 5, 10]
66

7+
z = [(b, c) for b in x for c in y]
8+
# print(z)
9+
assert z == [
10+
(1, 2), (1, 5), (1, 10),
11+
(2, 2), (2, 5), (2, 10),
12+
(3, 2), (3, 5), (3, 10)]

vm/src/compile.rs

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,7 @@ impl Compiler {
250250
self.emit(Instruction::ForIter);
251251

252252
// Start of loop iteration, set targets:
253-
// TODO: can we use compile_store here?
254-
for t in target {
255-
match t {
256-
ast::Expression::Identifier { name } => {
257-
self.emit(Instruction::StoreName {
258-
name: name.to_string(),
259-
});
260-
}
261-
_ => panic!("Not impl"),
262-
}
263-
}
253+
self.compile_store(target);
264254

265255
// Body of loop:
266256
self.compile_statements(body);
@@ -921,17 +911,7 @@ impl Compiler {
921911
self.set_label(start_label);
922912
self.emit(Instruction::ForIter);
923913

924-
// TODO: can we use compile_store here?
925-
for t in &generator.target {
926-
match t {
927-
ast::Expression::Identifier { name } => {
928-
self.emit(Instruction::StoreName {
929-
name: name.to_string(),
930-
});
931-
}
932-
_ => panic!("Not impl"),
933-
}
934-
}
914+
self.compile_store(&generator.target);
935915

936916
// Evaluate element:
937917
self.compile_expression(element);

0 commit comments

Comments
 (0)