Skip to content

Commit aaf80e2

Browse files
committed
[GR-17036] Use the new RootBodyTag.
PullRequest: graalpython/774
2 parents 7b8393c + ad2ba2a commit aaf80e2

File tree

248 files changed

+72021
-70925
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

248 files changed

+72021
-70925
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/debug/PythonDebugTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2020, 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
@@ -370,7 +370,7 @@ public void testGettersSetters() throws Throwable {
370370
expectSuspended((SuspendedEvent event) -> {
371371
DebugStackFrame frame = event.getTopStackFrame();
372372
assertEquals(1, frame.getSourceSection().getStartLine());
373-
event.prepareStepOver(7);
373+
event.prepareStepOver(2);
374374
});
375375
expectSuspended((SuspendedEvent event) -> {
376376
DebugStackFrame frame = event.getTopStackFrame();
Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.test.interop;
42+
43+
import com.oracle.graal.python.nodes.PNode;
44+
import com.oracle.graal.python.nodes.function.InnerRootNode;
45+
import com.oracle.graal.python.test.PythonTests;
46+
import com.oracle.truffle.api.frame.VirtualFrame;
47+
import com.oracle.truffle.api.instrumentation.EventContext;
48+
import com.oracle.truffle.api.instrumentation.ExecutionEventListener;
49+
import com.oracle.truffle.api.instrumentation.InstrumentableNode;
50+
import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
51+
import com.oracle.truffle.api.instrumentation.StandardTags;
52+
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
53+
import com.oracle.truffle.api.interop.InteropLibrary;
54+
import com.oracle.truffle.api.library.LibraryFactory;
55+
import com.oracle.truffle.api.nodes.Node;
56+
import java.util.HashMap;
57+
import org.graalvm.polyglot.Context;
58+
import org.graalvm.polyglot.Engine;
59+
import org.graalvm.polyglot.Instrument;
60+
import org.graalvm.polyglot.Source;
61+
import org.junit.Assert;
62+
import static org.junit.Assert.assertTrue;
63+
import static org.junit.Assert.assertFalse;
64+
import org.junit.Test;
65+
66+
public class StandardTagsTests extends PythonTests {
67+
68+
static final InteropLibrary INTEROP = LibraryFactory.resolve(InteropLibrary.class).getUncached();
69+
70+
private static Context newContext(Engine engine) {
71+
return Context.newBuilder().allowExperimentalOptions(true).allowAllAccess(true).engine(engine).build();
72+
}
73+
74+
@Test
75+
public void testRootBodyTagModule() throws Exception {
76+
String code = "import time\n" +
77+
"time.gmtime()\n";
78+
checkRootTagAndRootBodyTag(code);
79+
}
80+
81+
@Test
82+
public void testRootBodyTagGenerator01() throws Exception {
83+
String code = "def test():\n" +
84+
" yield 22\n" +
85+
"for i in test():\n" +
86+
" i\n";
87+
checkRootTagAndRootBodyTag(code);
88+
}
89+
90+
@Test
91+
public void testRootBodyTagGenerator02() throws Exception {
92+
String code = "def test():\n" +
93+
" yield 22\n" +
94+
" yield 42\n" +
95+
" yield 62\n" +
96+
"for i in test():\n" +
97+
" i\n";
98+
checkRootTagAndRootBodyTag(code);
99+
}
100+
101+
@Test
102+
public void testRootBodyTagGenerator03() throws Exception {
103+
String code = "def fn(a, b):\n" +
104+
" yield a\n" +
105+
" yield b\n" +
106+
"for i in fn(3,4):\n" +
107+
" i\n";
108+
checkRootTagAndRootBodyTag(code);
109+
}
110+
111+
@Test
112+
public void testRootBodyTagFunction01() throws Exception {
113+
String code = "def test():\n" +
114+
" return 22\n" +
115+
"test()";
116+
checkRootTagAndRootBodyTag(code);
117+
}
118+
119+
@Test
120+
public void testRootBodyTagFunction02() throws Exception {
121+
String code = "def test(a,b):\n" +
122+
" return a + b\n" +
123+
"test(1, 2)";
124+
HashMap<InstrumentableNode, InstrumentableNode> rootsMap = checkRootTagAndRootBodyTag(code);
125+
InnerRootNode inner = findInnerRootNodeWithEndOffset(rootsMap, 30);
126+
checkBodyPosition(rootsMap, inner, 17, 29);
127+
}
128+
129+
@Test
130+
public void testRootBodyTagFunction03() throws Exception {
131+
String code = "def test(a,b):\n" +
132+
" '''This is a simple doc'''\n" +
133+
" return a + b\n" +
134+
"test(1, 2)";
135+
HashMap<InstrumentableNode, InstrumentableNode> rootsMap = checkRootTagAndRootBodyTag(code);
136+
InnerRootNode inner = findInnerRootNodeWithEndOffset(rootsMap, 59);
137+
checkBodyPosition(rootsMap, inner, 46, 58);
138+
}
139+
140+
@Test
141+
public void testRootBodyTagFunction04() throws Exception {
142+
String code = "def test():\n" +
143+
" '''Function without body'''\n" +
144+
"test()";
145+
HashMap<InstrumentableNode, InstrumentableNode> rootsMap = checkRootTagAndRootBodyTag(code);
146+
InnerRootNode inner = findInnerRootNodeWithEndOffset(rootsMap, 42);
147+
checkBodyPosition(rootsMap, inner, 41, 42);
148+
}
149+
150+
@Test
151+
public void testRootBodyTagFunction05() throws Exception {
152+
String code = "def fn():\n" +
153+
" try:\n" +
154+
" pass\n" +
155+
" except ValueError as va:\n" +
156+
" pass\n" +
157+
"fn()";
158+
HashMap<InstrumentableNode, InstrumentableNode> rootsMap = checkRootTagAndRootBodyTag(code);
159+
InnerRootNode inner = findInnerRootNodeWithEndOffset(rootsMap, 62);
160+
checkBodyPosition(rootsMap, inner, 12, 62);
161+
}
162+
163+
@Test
164+
public void testRootBodyTagLambda01() throws Exception {
165+
String code = "x = lambda a, b, c : a + b + c\n" +
166+
"x(5, 6, 2)";
167+
checkRootTagAndRootBodyTag(code);
168+
}
169+
170+
@Test
171+
public void testRootBodyTagClass01() throws Exception {
172+
String code = "class MyClass:\n" +
173+
" x = 5\n" +
174+
"m = MyClass()\n";
175+
HashMap<InstrumentableNode, InstrumentableNode> rootsMap = checkRootTagAndRootBodyTag(code);
176+
InnerRootNode inner = findInnerRootNodeWithEndOffset(rootsMap, 23);
177+
checkBodyPosition(rootsMap, inner, 17, 22);
178+
}
179+
180+
@Test
181+
public void testRootBodyTagClass02() throws Exception {
182+
String code = "class MyClass:\n" +
183+
" '''This is a simple test class'''\n" +
184+
" x = 5\n" + "m = MyClass()\n";
185+
HashMap<InstrumentableNode, InstrumentableNode> rootsMap = checkRootTagAndRootBodyTag(code);
186+
InnerRootNode inner = findInnerRootNodeWithEndOffset(rootsMap, 59);
187+
checkBodyPosition(rootsMap, inner, 53, 58);
188+
189+
}
190+
191+
private HashMap<InstrumentableNode, InstrumentableNode> checkRootTagAndRootBodyTag(String code) throws Exception {
192+
Engine engine = Engine.newBuilder().build();
193+
Context newContext = newContext(engine);
194+
newContext.initialize("python");
195+
Instrument envInstr = newContext.getEngine().getInstruments().get("TestPythonInstrument");
196+
197+
Source source = Source.newBuilder("python", code, "testing").build();
198+
TruffleInstrument.Env env = envInstr.lookup(TestEnvProvider.class).env;
199+
SourceSectionFilter filter = SourceSectionFilter.newBuilder().lineIn(1, source.getLineCount()).tagIs(StandardTags.RootTag.class, StandardTags.RootBodyTag.class).build();
200+
HashMap<InstrumentableNode, InstrumentableNode> rootsMap = new HashMap<>();
201+
env.getInstrumenter().attachExecutionEventListener(filter, new RootTagAndRoodBodyTagListener(rootsMap));
202+
203+
newContext.eval(source);
204+
205+
for (InstrumentableNode rootBodyTag : rootsMap.values()) {
206+
assertTrue("There is a RootTag node without RootBodyTag node", rootBodyTag != null);
207+
}
208+
return rootsMap;
209+
}
210+
211+
private InnerRootNode findInnerRootNodeWithEndOffset(HashMap<InstrumentableNode, InstrumentableNode> rootsMap, int end) {
212+
for (InstrumentableNode node : rootsMap.keySet()) {
213+
InnerRootNode inner = (InnerRootNode) node;
214+
if (inner.getSourceSection().getCharEndIndex() == end) {
215+
return inner;
216+
}
217+
}
218+
assertTrue("No InnerRootNode found with end offset " + end, false);
219+
return null;
220+
}
221+
222+
private void checkBodyPosition(HashMap<InstrumentableNode, InstrumentableNode> rootsMap, InnerRootNode inner, int start, int end) {
223+
InstrumentableNode body = rootsMap.get(inner);
224+
assertTrue(body != null);
225+
PNode pbody = (PNode) body;
226+
Assert.assertEquals(start, pbody.getSourceSection().getCharIndex());
227+
Assert.assertEquals(end, pbody.getSourceSection().getCharEndIndex());
228+
}
229+
230+
@TruffleInstrument.Registration(id = "TestPythonInstrument", services = TestEnvProvider.class)
231+
public static class TestPythonInstrument extends TruffleInstrument {
232+
233+
@Override
234+
protected void onCreate(final TruffleInstrument.Env env) {
235+
env.registerService(new TestEnvProvider(env));
236+
}
237+
}
238+
239+
private static class TestEnvProvider {
240+
241+
TruffleInstrument.Env env;
242+
243+
TestEnvProvider(TruffleInstrument.Env env) {
244+
this.env = env;
245+
}
246+
}
247+
248+
private static class RootTagAndRoodBodyTagListener implements ExecutionEventListener {
249+
250+
// map of the RootTag -> RootBodyTag
251+
private final HashMap<InstrumentableNode, InstrumentableNode> result;
252+
253+
public RootTagAndRoodBodyTagListener(HashMap<InstrumentableNode, InstrumentableNode> resultMap) {
254+
this.result = resultMap;
255+
}
256+
257+
@Override
258+
public void onEnter(EventContext context, VirtualFrame frame) {
259+
Node node = context.getInstrumentedNode();
260+
InstrumentableNode inode = (InstrumentableNode) node;
261+
262+
if (inode.hasTag(StandardTags.RootTag.class)) {
263+
result.put(inode, null);
264+
}
265+
if (inode.hasTag(StandardTags.RootBodyTag.class)) {
266+
Node parent = node;
267+
while (parent != null) {
268+
if (parent instanceof InstrumentableNode) {
269+
InstrumentableNode iparent = (InstrumentableNode) parent;
270+
if (iparent.hasTag(StandardTags.RootTag.class)) {
271+
assertTrue("RootBodyTag find sooner then RootTag", result.containsKey(iparent));
272+
assertTrue("Found RootTag that already has RootBodyTag", result.get(iparent) == null);
273+
result.put(iparent, inode);
274+
break;
275+
}
276+
if (iparent != inode) {
277+
assertFalse("RootBodyTag is innered in other RootBodyTag", iparent.hasTag(StandardTags.RootBodyTag.class));
278+
}
279+
}
280+
parent = parent.getParent();
281+
}
282+
assertFalse("Found RootBodyTag without RootTag", parent == null);
283+
}
284+
}
285+
286+
@Override
287+
public void onReturnValue(EventContext context, VirtualFrame frame, Object result) {
288+
}
289+
290+
@Override
291+
public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) {
292+
}
293+
}
294+
}

graalpython/com.oracle.graal.python.test/testData/goldenFiles/AssignmentTests/annotationType02.tast

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ ModuleRootNode Name: <module 'annotationType02'> SourceSection: [0,28]`def fn():
3333
ReturnTargetNode SourceSection: [0,28]`def fn():↵ index : ...`
3434
Body: BlockNode SourceSection: None
3535
BlockNode SourceSection: None
36-
WriteLocalVariableNodeGen SourceSection: [12,27]`index : int = 0`
37-
Identifier: index
38-
WriteLocalFrameSlotNodeGen SourceSection: None
39-
Frame: [0,index,Illegal]
40-
IntegerLiteralNode SourceSection: [26,27]`0`
41-
Value: 0
36+
FunctionBodyNode SourceSection: [12,27]`index : int = 0`
37+
WriteLocalVariableNodeGen SourceSection: [12,27]`index : int = 0`
38+
Identifier: index
39+
WriteLocalFrameSlotNodeGen SourceSection: None
40+
Frame: [0,index,Illegal]
41+
IntegerLiteralNode SourceSection: [26,27]`0`
42+
Value: 0
4243
Return Expresssion: ReadLocalVariableNode SourceSection: None
4344
Frame: [1,<return_val>,Illegal]
4445
ReadVariableFromFrameNodeGen SourceSection: None

graalpython/com.oracle.graal.python.test/testData/goldenFiles/AssignmentTests/assignment06.tast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ ModuleRootNode Name: <module 'assignment06'> SourceSection: [0,29]`def fn():↵
3333
ReturnTargetNode SourceSection: [0,29]`def fn():↵ a = b = ...`
3434
Body: BlockNode SourceSection: None
3535
BlockNode SourceSection: None
36-
BlockNode SourceSection: [12,29]`a = b = c = d = e`
36+
FunctionBodyNode SourceSection: [12,29]`a = b = c = d = e`
3737
WriteLocalVariableNodeGen SourceSection: None
3838
Identifier: <>temp4
3939
WriteLocalFrameSlotNodeGen SourceSection: None

0 commit comments

Comments
 (0)