Skip to content

Commit 0158bfd

Browse files
committed
[GR-13199] Fix a more complex case for the scope translator
PullRequest: graalpython/342
2 parents 5581e5d + c1e0a98 commit 0158bfd

File tree

7 files changed

+135
-116
lines changed

7 files changed

+135
-116
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_generators.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates.
1+
# Copyright (c) 2018, 2019, Oracle and/or its affiliates.
22
# Copyright (C) 1996-2017 Python Software Foundation
33
#
44
# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -178,3 +178,46 @@ def func(*args):
178178
gen = (x for x in range(10))
179179
assert func(*lst) == set(lst)
180180
assert func(*gen) == set(lst)
181+
182+
183+
def test_generator_cell_confusion():
184+
# tfel: this demonstrates various errors we can get when we get confused
185+
# about the generator scopes and their parents for eager iterator
186+
# evaluation. In fact, all of these should work
187+
def unbound_local_l2():
188+
l1 = []
189+
l2 = []
190+
return [
191+
link for link in (
192+
(url for url in l1),
193+
(url for url in l2)
194+
)
195+
]
196+
197+
assert len(unbound_local_l2()) == 2
198+
199+
def assertion_error_getting_closure_from_locals():
200+
l1 = []
201+
l2 = []
202+
l3 = []
203+
return [
204+
link for link in (
205+
(url for url in l1),
206+
(url for url in l2),
207+
(url for url in l3),
208+
)
209+
]
210+
211+
assert len(assertion_error_getting_closure_from_locals()) == 3
212+
213+
def illegal_state_expected_cell_got_list():
214+
l11, l1 = [], []
215+
l22, l2 = [], []
216+
return [
217+
link for link in (
218+
(url for url in l1),
219+
(url for url in l2),
220+
)
221+
]
222+
223+
assert len(illegal_state_expected_cell_got_list()) == 2

graalpython/com.oracle.graal.python.test/src/tests/test_parser.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -88,3 +88,13 @@ def test_lambda_no_args_with_nested_lambdas():
8888

8989
def test_byte_numeric_escapes():
9090
assert eval('b"PK\\005\\006\\00\\11\\22\\08"') == b'PK\x05\x06\x00\t\x12\x008'
91+
92+
93+
def test_decorator_cell():
94+
foo = lambda x: "just a string, not %s" % x.__name__
95+
def run_me():
96+
@foo
97+
def func():
98+
pass
99+
return func
100+
assert run_me() == "just a string, not func", run_me()

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/generator/GeneratorBuiltins.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
33
* Copyright (c) 2014, Regents of the University of California
44
*
55
* All rights reserved.
@@ -27,6 +27,7 @@
2727

2828
import static com.oracle.graal.python.nodes.SpecialMethodNames.__ITER__;
2929
import static com.oracle.graal.python.nodes.SpecialMethodNames.__NEXT__;
30+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__REPR__;
3031
import static com.oracle.graal.python.runtime.exception.PythonErrorType.StopIteration;
3132
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
3233

@@ -52,6 +53,7 @@
5253
import com.oracle.truffle.api.CallTarget;
5354
import com.oracle.truffle.api.RootCallTarget;
5455
import com.oracle.truffle.api.Truffle;
56+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
5557
import com.oracle.truffle.api.dsl.Cached;
5658
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
5759
import com.oracle.truffle.api.dsl.NodeFactory;
@@ -220,4 +222,14 @@ Object getCode(PGenerator self,
220222
return code;
221223
}
222224
}
225+
226+
@Builtin(name = __REPR__, fixedNumOfPositionalArgs = 1)
227+
@GenerateNodeFactory
228+
abstract static class ReprNode extends PythonUnaryBuiltinNode {
229+
@Specialization
230+
@TruffleBoundary
231+
String repr(PGenerator self) {
232+
return self.toString();
233+
}
234+
}
223235
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -228,31 +228,31 @@ private SourceSection deriveSourceSection(RuleNode node) {
228228

229229
@Override
230230
public Object visitFile_input(Python3Parser.File_inputContext ctx) {
231-
environment.enterScope(ctx.scope);
231+
environment.pushScope(ctx.scope);
232232
ExpressionNode file = asExpression(super.visitFile_input(ctx));
233233
deriveSourceSection(ctx, file);
234-
environment.leaveScope();
234+
environment.popScope();
235235
return factory.createModuleRoot(name, file, ctx.scope.getFrameDescriptor());
236236
}
237237

238238
@Override
239239
public Object visitEval_input(Python3Parser.Eval_inputContext ctx) {
240-
environment.enterScope(ctx.scope);
240+
environment.pushScope(ctx.scope);
241241
ExpressionNode node = (ExpressionNode) super.visitEval_input(ctx);
242242
deriveSourceSection(ctx, node);
243243
StatementNode evalReturn = factory.createFrameReturn(factory.createWriteLocal(node, environment.getReturnSlot()));
244244
ReturnTargetNode returnTarget = new ReturnTargetNode(evalReturn, factory.createReadLocal(environment.getReturnSlot()));
245245
FunctionRootNode functionRoot = factory.createFunctionRoot(node.getSourceSection(), name, false, ctx.scope.getFrameDescriptor(), returnTarget, environment.getExecutionCellSlots());
246-
environment.leaveScope();
246+
environment.popScope();
247247
return functionRoot;
248248
}
249249

250250
@Override
251251
public Object visitSingle_input(Python3Parser.Single_inputContext ctx) {
252-
environment.enterScope(ctx.scope);
252+
environment.pushScope(ctx.scope);
253253
ExpressionNode body = asExpression(super.visitSingle_input(ctx));
254254
deriveSourceSection(ctx, body);
255-
environment.leaveScope();
255+
environment.popScope();
256256
if (isInlineMode) {
257257
return body;
258258
} else {
@@ -468,7 +468,7 @@ private ExpressionNode createComprehensionExpression(ParserRuleContext ctx, Pyth
468468

469469
private ExpressionNode createComprehensionExpression(ParserRuleContext ctx, Python3Parser.Comp_forContext compctx, Function<ParserRuleContext, ExpressionNode> getBlock) {
470470
try {
471-
environment.enterScope(compctx.scope);
471+
environment.pushScope(compctx.scope);
472472
ExpressionNode block = getBlock.apply(ctx);
473473
ExpressionNode yield = factory.createYield(block, environment.getReturnSlot());
474474
yield.assignSourceSection(block.getSourceSection());
@@ -482,13 +482,13 @@ private ExpressionNode createComprehensionExpression(ParserRuleContext ctx, Pyth
482482
genExprDef.assignSourceSection(srcSection);
483483
return genExprDef;
484484
} finally {
485-
environment.leaveScope();
485+
environment.popScope();
486486
}
487487
}
488488

489489
private GeneratorExpressionNode createGeneratorExpressionDefinition(ExpressionNode body, int lineNum) {
490490
FrameDescriptor fd = environment.getCurrentFrame();
491-
String generatorName = source.getName() + ":generator_exp:" + lineNum;
491+
String generatorName = environment.getCurrentScope().getParent().getScopeId() + ".<locals>.<genexp>:" + source.getName() + ":" + lineNum;
492492
FunctionRootNode funcRoot = factory.createFunctionRoot(body.getSourceSection(), generatorName, true, fd, body, environment.getExecutionCellSlots());
493493
GeneratorTranslator gtran = new GeneratorTranslator(funcRoot, true);
494494
RootCallTarget callTarget = gtran.translate();
@@ -1440,7 +1440,7 @@ public Object visitFuncdef(Python3Parser.FuncdefContext ctx) {
14401440
}
14411441
}
14421442

1443-
environment.enterScope(ctx.scope);
1443+
environment.pushScope(ctx.scope);
14441444
environment.setDefaultArgumentNodes(defaultArgs);
14451445

14461446
/**
@@ -1491,7 +1491,7 @@ public Object visitFuncdef(Python3Parser.FuncdefContext ctx) {
14911491
} else {
14921492
funcDef = new FunctionDefinitionNode(funcName, enclosingClassName, doc, arity, defaults, ct, environment.getDefinitionCellSlots(), environment.getExecutionCellSlots());
14931493
}
1494-
environment.leaveScope();
1494+
environment.popScope();
14951495

14961496
ReadNode funcVar = environment.findVariable(funcName);
14971497
return funcVar.makeWriteNode(funcDef);
@@ -1624,7 +1624,7 @@ private PNode createLambda(ParserRuleContext ctx, VarargslistContext varargslist
16241624
}
16251625

16261626
String funcname = "anonymous";
1627-
environment.enterScope(scope);
1627+
environment.pushScope(scope);
16281628
environment.setDefaultArgumentNodes(defaultArgs);
16291629

16301630
/**
@@ -1667,7 +1667,7 @@ private PNode createLambda(ParserRuleContext ctx, VarargslistContext varargslist
16671667
} else {
16681668
funcDef = new FunctionDefinitionNode(funcname, null, null, arity, defaults, ct, environment.getDefinitionCellSlots(), environment.getExecutionCellSlots());
16691669
}
1670-
environment.leaveScope();
1670+
environment.popScope();
16711671

16721672
return funcDef;
16731673
}
@@ -1730,14 +1730,14 @@ public Object visitClassdef(Python3Parser.ClassdefContext ctx) {
17301730
ExpressionNode[] splatArguments = new ExpressionNode[2];
17311731
visitCallArglist(ctx.arglist(), argumentNodes, keywords, splatArguments);
17321732

1733-
environment.enterScope(ctx.scope);
1733+
environment.pushScope(ctx.scope);
17341734

17351735
ExpressionNode body = asClassBody(ctx.suite().accept(this), qualName);
17361736
ClassBodyRootNode classBodyRoot = factory.createClassBodyRoot(deriveSourceSection(ctx), className, environment.getCurrentFrame(), body, environment.getExecutionCellSlots());
17371737
RootCallTarget ct = Truffle.getRuntime().createCallTarget(classBodyRoot);
17381738
FunctionDefinitionNode funcDef = new FunctionDefinitionNode(className, null, null, Arity.createOneArgumentWithVarKwArgs(className),
17391739
factory.createBlock(), ct, environment.getDefinitionCellSlots(), environment.getExecutionCellSlots());
1740-
environment.leaveScope();
1740+
environment.popScope();
17411741

17421742
argumentNodes.add(0, factory.createStringLiteral(className));
17431743
argumentNodes.add(0, funcDef);
@@ -1855,11 +1855,11 @@ private StatementNode createGeneratorExpression(Python3Parser.Comp_forContext co
18551855
// TODO: async
18561856
ScopeInfo old = null;
18571857
if (iteratorInParentScope) {
1858-
old = environment.pushCurentScope();
1858+
old = environment.popScope();
18591859
}
18601860
ExpressionNode iterator = (ExpressionNode) comp_for.or_test().accept(this);
18611861
if (iteratorInParentScope) {
1862-
environment.popCurrentScope(old);
1862+
environment.pushScope(old);
18631863
}
18641864

18651865
StatementNode targets = assigns.translate(comp_for.exprlist());

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/ScopeInfo.java

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates.
2+
* Copyright (c) 2017, 2019, Oracle and/or its affiliates.
33
* Copyright (c) 2013, Regents of the University of California
44
*
55
* All rights reserved.
@@ -81,8 +81,6 @@ public enum ScopeKind {
8181
private List<ExpressionNode> defaultArgumentNodes;
8282
private ReadDefaultArgumentNode[] defaultArgumentReads;
8383

84-
private int loopCount = 0;
85-
8684
public ScopeInfo(String scopeId, ScopeKind kind, FrameDescriptor frameDescriptor, ScopeInfo parent) {
8785
this.scopeId = scopeId;
8886
this.scopeKind = kind;
@@ -96,18 +94,6 @@ public ScopeInfo(String scopeId, ScopeKind kind, FrameDescriptor frameDescriptor
9694
}
9795
}
9896

99-
public void incLoopCount() {
100-
loopCount++;
101-
}
102-
103-
public int getLoopCount() {
104-
return loopCount;
105-
}
106-
107-
public void resetLoopCount() {
108-
this.loopCount = 0;
109-
}
110-
11197
public ScopeInfo getFirstChildScope() {
11298
return firstChildScope;
11399
}

0 commit comments

Comments
 (0)