Skip to content

Commit 98dac2d

Browse files
committed
[GR-18309] UnboundLocalError: nested for loops with if block in comprehension.
PullRequest: graalpython/657
2 parents 151c746 + f356558 commit 98dac2d

File tree

4 files changed

+107
-4
lines changed

4 files changed

+107
-4
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/parser/GeneratorAndCompForTests.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,4 +305,9 @@ public void genFromPip() throws Exception {
305305
public void issueGR18174() throws Exception {
306306
checkScopeAndTree("[b for b in [a for a in (1,2)]]");
307307
}
308+
309+
@Test
310+
public void issueGR18309() throws Exception {
311+
checkScopeAndTree("[ b for a in d1 if d1 for b in d2]");
312+
}
308313
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Scope: []
2+
Kind: Module
3+
FrameDescriptor: Empty
4+
CellVars: Empty
5+
FreeVars: Empty
6+
Scope: generator2
7+
Kind: Generator
8+
FrameDescriptor: [a, b, <return_val>]
9+
CellVars: Empty
10+
FreeVars: Empty
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
ModuleRootNode Name: <module 'issueGR18309'> SourceSection: [0,34]`[ b for a in d1 if d...`
2+
Signature: varArgs=False, varKeywordArgs=False, noArguments=True, positionalOnly=True, requiresKeywordArgs=False
3+
FreeVars: None
4+
NeedsCellFrame: False
5+
FrameDescriptor: Empty
6+
Documentation: None
7+
InnerRootNode SourceSection: [0,34]`[ b for a in d1 if d...`
8+
PythonCallNodeGen SourceSection: [0,34]`[ b for a in d1 if d...`
9+
CachedCallNodeGen SourceSection: None
10+
CreateArgumentsNodeGen SourceSection: None
11+
CallDispatchNodeGen SourceSection: None
12+
GeneratorExpressionNode SourceSection: [4,33]`for a in d1 if d1 fo...`
13+
Name: [].<locals>.<genexp>:issueGR18309:1
14+
FrameDescriptor: 3 slots [b, a, <return_val>]
15+
Enclosing
16+
FrameDescriptor: Empty
17+
Active Flags: 4
18+
For Nodes: 2
19+
Block Nodes: 0
20+
Is Enclosing Frame Generator: false
21+
FunctionRootNode SourceSection: [4,33]`for a in d1 if d1 fo...`
22+
Name: [].<locals>.<genexp>:issueGR18309:1
23+
Signature: varArgs=False, varKeywordArgs=False, noArguments=True, positionalOnly=True, requiresKeywordArgs=False
24+
CelVars: None
25+
FreeVars: None
26+
NeedsCellFrame: False
27+
FrameDescriptor: 3 slots [b, a, <return_val>]
28+
ExecutionSlots:
29+
FreeVarsSlots: None
30+
CellVarsSlots: None
31+
InnerRootNode SourceSection: [4,33]`for a in d1 if d1 fo...`
32+
GeneratorReturnTargetNode SourceSection: [4,33]`for a in d1 if d1 fo...`
33+
flagSlot: 3
34+
GeneratorForNode SourceSection: [4,33]`for a in d1 if d1 fo...`
35+
GeneratorIfNode SourceSection: None
36+
GeneratorAccessNode SourceSection: None
37+
YesNodeGen SourceSection: None
38+
ReadGlobalOrBuiltinNodeGen SourceSection: [19,21]`d1`
39+
Identifier: d1
40+
ReadAttributeFromObjectNotTypeNodeGen SourceSection: None
41+
GeneratorForNode SourceSection: [22,33]`for b in d2`
42+
ExpressionStatementNode SourceSection: [2,3]`b`
43+
YieldNode SourceSection: [2,3]`b`
44+
flagSlot: 0
45+
ReadGeneratorFrameVariableNode SourceSection: [2,3]`b`
46+
Frame: [0,b,Illegal]
47+
ReadVariableFromFrameNodeGen SourceSection: None
48+
GeneratorAccessNode SourceSection: None
49+
WriteGeneratorFrameVariableNodeGen SourceSection: None
50+
Identifier: b
51+
WriteGeneraterFrameSlotNodeGen SourceSection: None
52+
Frame: [0,b,Illegal]
53+
GetIteratorExpressionNodeGen SourceSection: [31,33]`d2`
54+
GetIteratorNodeGen SourceSection: None
55+
ReadGlobalOrBuiltinNodeGen SourceSection: [31,33]`d2`
56+
Identifier: d2
57+
ReadAttributeFromObjectNotTypeNodeGen SourceSection: None
58+
GetNextNode SourceSection: None
59+
LookupAndCallUnaryNodeGen SourceSection: None
60+
Op: __next__
61+
GeneratorAccessNode SourceSection: None
62+
BlockNode SourceSection: None
63+
WriteGeneratorFrameVariableNodeGen SourceSection: None
64+
Identifier: a
65+
WriteGeneraterFrameSlotNodeGen SourceSection: None
66+
Frame: [1,a,Illegal]
67+
ArgumentExpressionNode SourceSection: None
68+
ReadIndexedArgumentNodeGen SourceSection: None
69+
Index: 0
70+
GetNextNode SourceSection: None
71+
LookupAndCallUnaryNodeGen SourceSection: None
72+
Op: __next__
73+
GeneratorAccessNode SourceSection: None
74+
ReadGeneratorFrameVariableNode SourceSection: None
75+
Frame: [2,<return_val>,Illegal]
76+
ReadVariableFromFrameNodeGen SourceSection: None
77+
BlockNode SourceSection: None
78+
GeneratorAccessNode SourceSection: None
79+
PRaiseNodeGen SourceSection: None
80+
GetIteratorExpressionNodeGen SourceSection: [13,15]`d1`
81+
GetIteratorNodeGen SourceSection: None
82+
ReadNameNodeGen SourceSection: [13,15]`d1`
83+
Identifier: d1
84+
PythonObjectFactoryNodeGen SourceSection: None
85+
ReadGlobalOrBuiltinNodeGen SourceSection: None
86+
Identifier: list
87+
ReadAttributeFromObjectNotTypeNodeGen SourceSection: None

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/sst/GeneratorFactorySSTVisitor.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,18 @@ private StatementNode createGeneratorExpressionBody(ForComprehensionSSTNode node
250250
}
251251
}
252252
StatementNode body = yield;
253-
if (condition != null) {
254-
// TODO: Do we have to create empty block in the else branch?
255-
body = GeneratorIfNode.create(nodeFactory.createYesNode(condition), body, nodeFactory.createBlock(), numOfActiveFlags++, numOfActiveFlags++);
256-
} else if (node.iterator instanceof ForComprehensionSSTNode && ((ForComprehensionSSTNode) node.iterator).resultType == PythonBuiltinClassType.PGenerator) {
253+
if (node.iterator instanceof ForComprehensionSSTNode && ((ForComprehensionSSTNode) node.iterator).resultType == PythonBuiltinClassType.PGenerator) {
257254
ForComprehensionSSTNode forComp = (ForComprehensionSSTNode) node.iterator;
258255
SSTNode sstIterator = forComp.iterator instanceof ForComprehensionSSTNode ? ((ForComprehensionSSTNode) forComp.iterator).target : forComp.iterator;
259256
ExpressionNode exprIterator = (ExpressionNode) sstIterator.accept(this);
260257
GetIteratorExpressionNode getIterator = nodeFactory.createGetIterator(exprIterator);
261258
getIterator.assignSourceSection(exprIterator.getSourceSection());
262259
body = createGeneratorExpressionBody(forComp, getIterator, yield);
263260
}
261+
if (condition != null) {
262+
// TODO: Do we have to create empty block in the else branch?
263+
body = GeneratorIfNode.create(nodeFactory.createYesNode(condition), body, nodeFactory.createBlock(), numOfActiveFlags++, numOfActiveFlags++);
264+
}
264265

265266
StatementNode variable;
266267
if (node.variables.length == 1) {

0 commit comments

Comments
 (0)