Skip to content

Commit c7d2200

Browse files
committed
[GR-13750] Cells in the class scope should still end up in the namespace
PullRequest: graalpython/397
2 parents 97929f2 + 9ca6c81 commit c7d2200

File tree

5 files changed

+72
-13
lines changed

5 files changed

+72
-13
lines changed

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

Lines changed: 27 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
@@ -906,3 +906,29 @@ def my_obj():
906906

907907
assert set(my_obj.__code__.co_cellvars) == set()
908908
assert set(my_obj.__code__.co_freevars) == {'my_obj', 'y'}
909+
910+
911+
def test_classbody_scope():
912+
class A():
913+
ranges = [(1, 10)]
914+
915+
class B():
916+
ranges = [(2, 12)]
917+
918+
class C():
919+
ranges = [ ]
920+
921+
class CA():
922+
ranges = [(3, 13)]
923+
924+
locs = locals()
925+
926+
class D(B, C):
927+
pass
928+
929+
930+
A.C.ranges = (A.C.CA.ranges)
931+
assert A.C.ranges == A.C.CA.ranges == [(3, 13)]
932+
locs = list(A.locs.keys())
933+
for k in ["__module__", "__qualname__", "ranges", "B", "C", "locs", "D"]:
934+
assert k in locs, locs

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory.DictNodeFactory;
4242
import com.oracle.graal.python.builtins.objects.object.PythonObject;
4343
import com.oracle.graal.python.builtins.objects.traceback.PTraceback;
44+
import com.oracle.graal.python.nodes.function.ClassBodyRootNode;
4445
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
4546
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
4647
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
@@ -171,7 +172,13 @@ Object getFromFrame(Frame owner,
171172
@Cached("create()") BranchProfile noFrameOnPFrame) {
172173
PFrame pFrame = PArguments.getPFrame(owner);
173174
if (noPFrame.profile(pFrame == null)) {
174-
pFrame = factory().createPFrame(owner);
175+
Object specialArgument = PArguments.getSpecialArgument(owner);
176+
if (specialArgument instanceof ClassBodyRootNode) {
177+
// the namespace argument stores the locals
178+
pFrame = factory().createPFrame(owner, PArguments.getArgument(owner, 0));
179+
} else {
180+
pFrame = factory().createPFrame(owner);
181+
}
175182
PArguments.setPFrame(owner, pFrame);
176183
} else if (!pFrame.hasFrame()) {
177184
noFrameOnPFrame.enter();
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -50,18 +50,18 @@
5050
import com.oracle.graal.python.nodes.subscript.SetItemIfNotPresentNode;
5151
import com.oracle.truffle.api.frame.VirtualFrame;
5252

53-
public class ClassDefinitionEpilogNode extends StatementNode {
53+
public class ClassDefinitionPrologueNode extends StatementNode {
5454
@Child private ReadGlobalOrBuiltinNode readGlobalNameNode = ReadGlobalOrBuiltinNode.create(__NAME__);
5555
@Child private ReadIndexedArgumentNode readPrimaryArgNode = ReadIndexedArgumentNode.create(0);
5656
@Child private SetItemIfNotPresentNode setItemIfNotPresentNode = SetItemIfNotPresentNode.create();
5757

5858
private final String qualName;
5959

60-
public ClassDefinitionEpilogNode() {
60+
public ClassDefinitionPrologueNode() {
6161
this(null);
6262
}
6363

64-
public ClassDefinitionEpilogNode(String qualName) {
64+
public ClassDefinitionPrologueNode(String qualName) {
6565
this.qualName = qualName;
6666
}
6767

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/classes/ReadClassAttributeNode.java

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -47,6 +47,7 @@
4747
import com.oracle.graal.python.nodes.expression.ExpressionNode;
4848
import com.oracle.graal.python.nodes.frame.ReadLocalNode;
4949
import com.oracle.graal.python.nodes.frame.ReadNode;
50+
import com.oracle.graal.python.nodes.frame.WriteNode;
5051
import com.oracle.graal.python.nodes.statement.StatementNode;
5152
import com.oracle.graal.python.nodes.subscript.GetItemNode;
5253
import com.oracle.graal.python.runtime.exception.PException;
@@ -94,14 +95,12 @@ public StatementNode makeDeleteNode() {
9495

9596
@Override
9697
public StatementNode makeWriteNode(ExpressionNode rhs) {
97-
ExpressionNode right = rhs;
9898
// freevars pass through the special Class scope
9999
if (readCellLocal != null && !isFreeVar) {
100-
// TODO (tfel): Is this what's intended?
101-
return ((ReadNode) readCellLocal).makeWriteNode(rhs);
100+
return new WriteClassAttributeCellNode((ReadNode) readCellLocal, (ReadNode) getNsItem, rhs);
102101
} else {
103102
// assignments always got to the innermost scope
104-
return ((ReadNode) getNsItem).makeWriteNode(right);
103+
return ((ReadNode) getNsItem).makeWriteNode(rhs);
105104
}
106105
}
107106

@@ -132,4 +131,31 @@ Object read(VirtualFrame frame,
132131
return readGlobal.execute(frame);
133132
}
134133
}
134+
135+
private static class WriteClassAttributeCellNode extends StatementNode implements WriteNode {
136+
@Child private WriteNode writeCellLocal;
137+
@Child private WriteNode writeNsItem;
138+
@Child private ExpressionNode right;
139+
140+
WriteClassAttributeCellNode(ReadNode readCellLocal, ReadNode getNsItem, ExpressionNode rhs) {
141+
writeCellLocal = (WriteNode) readCellLocal.makeWriteNode(null);
142+
writeNsItem = (WriteNode) getNsItem.makeWriteNode(null);
143+
right = rhs;
144+
}
145+
146+
public ExpressionNode getRhs() {
147+
return right;
148+
}
149+
150+
public void doWrite(VirtualFrame frame, Object value) {
151+
writeCellLocal.doWrite(frame, value);
152+
writeNsItem.doWrite(frame, value);
153+
}
154+
155+
@Override
156+
public void executeVoid(VirtualFrame frame) {
157+
Object value = right.execute(frame);
158+
doWrite(frame, value);
159+
}
160+
}
135161
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
import com.oracle.graal.python.nodes.argument.ReadDefaultArgumentNode;
6060
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
6161
import com.oracle.graal.python.nodes.call.PythonCallNode;
62-
import com.oracle.graal.python.nodes.classes.ClassDefinitionEpilogNode;
62+
import com.oracle.graal.python.nodes.classes.ClassDefinitionPrologueNode;
6363
import com.oracle.graal.python.nodes.control.BlockNode;
6464
import com.oracle.graal.python.nodes.control.ForNode;
6565
import com.oracle.graal.python.nodes.control.GetIteratorNode;
@@ -1855,7 +1855,7 @@ protected ExpressionNode asClassBody(Object accept, String qualName) {
18551855
environment.createLocal(__DOC__);
18561856
body.set(0, environment.findVariable(__DOC__).makeWriteNode((ExpressionNode) body.get(0)));
18571857
}
1858-
body.add(new ClassDefinitionEpilogNode(qualName));
1858+
body.add(0, new ClassDefinitionPrologueNode(qualName));
18591859
return new ReturnTargetNode(asBlock(body), factory.createNullLiteral());
18601860
}
18611861

0 commit comments

Comments
 (0)