Skip to content

Commit de97662

Browse files
committed
[GR-9228] Support TryBlockTag
PullRequest: graalpython-open/15
2 parents 9d1f837 + 18e5f02 commit de97662

File tree

7 files changed

+245
-13
lines changed

7 files changed

+245
-13
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
import com.oracle.truffle.api.source.Source;
7171

7272
@TruffleLanguage.Registration(id = PythonLanguage.ID, name = PythonLanguage.NAME, version = PythonLanguage.VERSION, mimeType = PythonLanguage.MIME_TYPE, interactive = true, internal = false)
73-
@ProvidedTags({StandardTags.CallTag.class, StandardTags.StatementTag.class, StandardTags.RootTag.class, DebuggerTags.AlwaysHalt.class})
73+
@ProvidedTags({StandardTags.CallTag.class, StandardTags.StatementTag.class, StandardTags.RootTag.class, StandardTags.TryBlockTag.class, DebuggerTags.AlwaysHalt.class})
7474
public final class PythonLanguage extends TruffleLanguage<PythonContext> {
7575

7676
public static final String ID = "python";

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/iterator/PZipBuiltins.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import com.oracle.graal.python.nodes.control.GetNextNode;
3737
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
3838
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
39-
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
4039
import com.oracle.truffle.api.dsl.Cached;
4140
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
4241
import com.oracle.truffle.api.dsl.NodeFactory;
@@ -62,7 +61,7 @@ public Object __next__(PZip self,
6261
for (int i = 0; i < iterators.length; i++) {
6362
tupleElements[i] = next.execute(iterators[i]);
6463
}
65-
return PythonObjectFactory.get().createTuple(tupleElements);
64+
return factory().createTuple(tupleElements);
6665
}
6766
}
6867

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/PNode.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
*/
2626
package com.oracle.graal.python.nodes;
2727

28+
import com.oracle.graal.python.nodes.statement.TryExceptNode;
2829
import com.oracle.graal.python.nodes.truffle.PythonTypes;
2930
import com.oracle.graal.python.runtime.PythonOptions;
3031
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -46,6 +47,7 @@ public abstract class PNode extends PBaseNode implements InstrumentableNode {
4647
@CompilationFinal private SourceSection sourceSection;
4748
@CompilationFinal private boolean isStmt = false;
4849
@CompilationFinal private boolean isRoot = false;
50+
@CompilationFinal private boolean isTryBlock = false;
4951

5052
public NodeFactory getNodeFactory() {
5153
return getCore().getLanguage().getNodeFactory();
@@ -115,7 +117,7 @@ public void assignSourceSection(SourceSection source) {
115117
}
116118

117119
public boolean hasTag(Class<? extends Tag> tag) {
118-
return (isStmt && tag == StandardTags.StatementTag.class) || (isRoot && tag == StandardTags.RootTag.class);
120+
return (isStmt && tag == StandardTags.StatementTag.class) || (isRoot && tag == StandardTags.RootTag.class) || (isTryBlock && tag == StandardTags.TryBlockTag.class);
119121
}
120122

121123
public WrapperNode createWrapper(ProbeNode probeNode) {
@@ -141,4 +143,24 @@ public void markAsRoot() {
141143
public boolean isRoot() {
142144
return isRoot;
143145
}
146+
147+
public void markAsTryBlock() {
148+
isTryBlock = true;
149+
}
150+
151+
public boolean isTryBlock() {
152+
return isTryBlock;
153+
}
154+
155+
public Object getNodeObject() {
156+
if (isTryBlock) {
157+
if (this.getParent() instanceof TryExceptNode) {
158+
return this.getParent();
159+
} else if (this.getParent() instanceof PNodeWrapper) {
160+
assert this.getParent().getParent() instanceof TryExceptNode;
161+
return this.getParent().getParent();
162+
}
163+
}
164+
return null;
165+
}
144166
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/literal/PIntLiteralNode.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,14 @@
2828
import java.math.BigInteger;
2929

3030
import com.oracle.graal.python.builtins.objects.ints.PInt;
31-
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
3231
import com.oracle.truffle.api.frame.VirtualFrame;
3332

3433
public final class PIntLiteralNode extends LiteralNode {
3534

3635
private final PInt value;
3736

3837
public PIntLiteralNode(BigInteger value) {
39-
this.value = PythonObjectFactory.get().createInt(value);
38+
this.value = factory().createInt(value);
4039
}
4140

4241
public PInt getValue() {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/statement/TryExceptNode.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,26 @@
3434
import com.oracle.graal.python.runtime.exception.ExceptionHandledException;
3535
import com.oracle.graal.python.runtime.exception.PException;
3636
import com.oracle.graal.python.runtime.exception.PythonErrorType;
37-
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
38-
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
3937
import com.oracle.truffle.api.CompilerDirectives;
38+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
39+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
4040
import com.oracle.truffle.api.frame.VirtualFrame;
41+
import com.oracle.truffle.api.interop.ForeignAccess;
42+
import com.oracle.truffle.api.interop.TruffleObject;
4143
import com.oracle.truffle.api.nodes.ControlFlowException;
4244
import com.oracle.truffle.api.nodes.ExplodeLoop;
4345

44-
public class TryExceptNode extends StatementNode {
45-
46+
public class TryExceptNode extends StatementNode implements TruffleObject {
4647
@Child private PNode body;
47-
@Children final ExceptNode[] exceptNodes;
48+
@Children private final ExceptNode[] exceptNodes;
4849
@Child private PNode orelse;
50+
@CompilationFinal private TryExceptNodeMessageResolution.CatchesFunction catchesFunction;
4951

5052
@CompilationFinal boolean seenException;
5153

5254
public TryExceptNode(PNode body, ExceptNode[] exceptNodes, PNode orelse) {
5355
this.body = body;
56+
body.markAsTryBlock();
5457
this.exceptNodes = exceptNodes;
5558
this.orelse = orelse;
5659
}
@@ -125,4 +128,18 @@ public ExceptNode[] getExceptNodes() {
125128
public PNode getOrelse() {
126129
return orelse;
127130
}
131+
132+
@Override
133+
public ForeignAccess getForeignAccess() {
134+
return TryExceptNodeMessageResolutionForeign.ACCESS;
135+
}
136+
137+
public TryExceptNodeMessageResolution.CatchesFunction getCatchesFunction() {
138+
return this.catchesFunction;
139+
}
140+
141+
public void setCatchesFunction(TryExceptNodeMessageResolution.CatchesFunction catchesFunction) {
142+
CompilerDirectives.transferToInterpreterAndInvalidate();
143+
this.catchesFunction = catchesFunction;
144+
}
128145
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates.
3+
*
4+
* The Universal Permissive License (UPL), Version 1.0
5+
*
6+
* Subject to the condition set forth below, permission is hereby granted to any
7+
* person obtaining a copy of this software, associated documentation and/or data
8+
* (collectively the "Software"), free of charge and under any and all copyright
9+
* rights in the Software, and any and all patent rights owned or freely
10+
* licensable by each licensor hereunder covering either (i) the unmodified
11+
* Software as contributed to or provided by such licensor, or (ii) the Larger
12+
* Works (as defined below), to deal in both
13+
*
14+
* (a) the Software, and
15+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
16+
* one is included with the Software (each a "Larger Work" to which the
17+
* Software is contributed by such licensors),
18+
*
19+
* without restriction, including without limitation the rights to copy, create
20+
* derivative works of, display, perform, and distribute the Software and make,
21+
* use, sell, offer for sale, import, export, have made, and have sold the
22+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
23+
* either these or other terms.
24+
*
25+
* This license is subject to the following condition:
26+
*
27+
* The above copyright notice and either this complete permission notice or at a
28+
* minimum a reference to the UPL must be included in all copies or substantial
29+
* portions of the Software.
30+
*
31+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37+
* SOFTWARE.
38+
*/
39+
package com.oracle.graal.python.nodes.statement;
40+
41+
import java.util.ArrayList;
42+
43+
import com.oracle.graal.python.builtins.objects.exception.PBaseException;
44+
import com.oracle.graal.python.builtins.objects.function.PArguments;
45+
import com.oracle.graal.python.builtins.objects.function.PBuiltinFunction;
46+
import com.oracle.graal.python.builtins.objects.module.PythonModule;
47+
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
48+
import com.oracle.graal.python.nodes.BuiltinNames;
49+
import com.oracle.graal.python.nodes.PNode;
50+
import com.oracle.graal.python.nodes.attributes.GetAttributeNode;
51+
import com.oracle.graal.python.nodes.frame.ReadGlobalOrBuiltinNode;
52+
import com.oracle.graal.python.nodes.literal.TupleLiteralNode;
53+
import com.oracle.graal.python.runtime.exception.PException;
54+
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
55+
import com.oracle.truffle.api.CompilerDirectives;
56+
import com.oracle.truffle.api.RootCallTarget;
57+
import com.oracle.truffle.api.instrumentation.StandardTags;
58+
import com.oracle.truffle.api.interop.ArityException;
59+
import com.oracle.truffle.api.interop.CanResolve;
60+
import com.oracle.truffle.api.interop.ForeignAccess;
61+
import com.oracle.truffle.api.interop.KeyInfo;
62+
import com.oracle.truffle.api.interop.MessageResolution;
63+
import com.oracle.truffle.api.interop.Resolve;
64+
import com.oracle.truffle.api.interop.TruffleObject;
65+
import com.oracle.truffle.api.interop.UnknownIdentifierException;
66+
import com.oracle.truffle.api.nodes.ExplodeLoop;
67+
import com.oracle.truffle.api.nodes.Node;
68+
69+
@MessageResolution(receiverType = TryExceptNode.class)
70+
class TryExceptNodeMessageResolution {
71+
@Resolve(message = "HAS_KEYS")
72+
abstract static class HasKeysNode extends Node {
73+
Object access(@SuppressWarnings("unused") TryExceptNode object) {
74+
return true;
75+
}
76+
}
77+
78+
@Resolve(message = "KEYS")
79+
abstract static class KeysNode extends Node {
80+
Object access(TryExceptNode object) {
81+
return object.getContext().getEnv().asGuestValue(new String[]{StandardTags.TryBlockTag.CATCHES});
82+
}
83+
}
84+
85+
@Resolve(message = "KEY_INFO")
86+
abstract static class KeyInfoNode extends Node {
87+
Object access(@SuppressWarnings("unused") TryExceptNode object, String name) {
88+
if (name.equals(StandardTags.TryBlockTag.CATCHES)) {
89+
return KeyInfo.INVOCABLE | KeyInfo.READABLE;
90+
} else {
91+
return KeyInfo.NONE;
92+
}
93+
}
94+
}
95+
96+
@Resolve(message = "READ")
97+
abstract static class ReadNode extends Node {
98+
@Child GetAttributeNode getAttr = GetAttributeNode.create();
99+
@Child PythonObjectFactory factory = PythonObjectFactory.create();
100+
101+
CatchesFunction access(TryExceptNode object, String name) {
102+
return doit(object, name, getAttr, factory);
103+
}
104+
105+
static CatchesFunction doit(TryExceptNode object, String name, GetAttributeNode getAttr, PythonObjectFactory factory) {
106+
if (name.equals(StandardTags.TryBlockTag.CATCHES)) {
107+
if (object.getCatchesFunction() == null) {
108+
CompilerDirectives.transferToInterpreterAndInvalidate();
109+
ArrayList<Object> literalCatches = new ArrayList<>();
110+
ExceptNode[] exceptNodes = object.getExceptNodes();
111+
PythonModule builtins = object.getContext().getBuiltins();
112+
113+
for (ExceptNode node : exceptNodes) {
114+
PNode exceptType = node.getExceptType();
115+
if (exceptType instanceof ReadGlobalOrBuiltinNode) {
116+
try {
117+
literalCatches.add(getAttr.execute(builtins, ((ReadGlobalOrBuiltinNode) exceptType).getAttributeId()));
118+
} catch (PException e) {
119+
}
120+
} else if (exceptType instanceof TupleLiteralNode) {
121+
for (PNode tupleValue : ((TupleLiteralNode) exceptType).getValues()) {
122+
if (tupleValue instanceof ReadGlobalOrBuiltinNode) {
123+
try {
124+
literalCatches.add(getAttr.execute(builtins, ((ReadGlobalOrBuiltinNode) tupleValue).getAttributeId()));
125+
} catch (PException e) {
126+
}
127+
}
128+
}
129+
}
130+
}
131+
132+
Object isinstanceFunc = getAttr.execute(builtins, BuiltinNames.ISINSTANCE);
133+
PTuple caughtClasses = factory.createTuple(literalCatches.toArray());
134+
135+
if (isinstanceFunc instanceof PBuiltinFunction) {
136+
RootCallTarget callTarget = ((PBuiltinFunction) isinstanceFunc).getCallTarget();
137+
object.setCatchesFunction(new CatchesFunction(callTarget, caughtClasses));
138+
} else {
139+
throw new IllegalStateException("isinstance was redefined, cannot check exceptions");
140+
}
141+
}
142+
return object.getCatchesFunction();
143+
} else {
144+
throw UnknownIdentifierException.raise(name);
145+
}
146+
}
147+
}
148+
149+
@Resolve(message = "INVOKE")
150+
abstract static class InvokeNode extends Node {
151+
@Child GetAttributeNode getAttr = GetAttributeNode.create();
152+
@Child PythonObjectFactory factory = PythonObjectFactory.create();
153+
154+
Object access(TryExceptNode object, String name, Object[] arguments) {
155+
CatchesFunction catchesFunction = ReadNode.doit(object, name, getAttr, factory);
156+
if (arguments.length != 1) {
157+
throw ArityException.raise(1, arguments.length);
158+
}
159+
return catchesFunction.catches(arguments[0]);
160+
}
161+
}
162+
163+
@CanResolve
164+
abstract static class CheckFunction extends Node {
165+
protected static boolean test(TruffleObject receiver) {
166+
return receiver instanceof TryExceptNode;
167+
}
168+
}
169+
170+
static class CatchesFunction implements TruffleObject {
171+
private final RootCallTarget isInstance;
172+
private final Object[] args = PArguments.create(2);
173+
174+
CatchesFunction(RootCallTarget callTarget, PTuple caughtClasses) {
175+
this.isInstance = callTarget;
176+
PArguments.setArgument(args, 1, caughtClasses);
177+
}
178+
179+
@ExplodeLoop
180+
boolean catches(Object exception) {
181+
if (exception instanceof PBaseException) {
182+
PArguments.setArgument(args, 0, exception);
183+
try {
184+
return isInstance.call(args) == Boolean.TRUE;
185+
} catch (PException e) {
186+
}
187+
}
188+
return false;
189+
}
190+
191+
public ForeignAccess getForeignAccess() {
192+
return null;
193+
}
194+
}
195+
}

mx.graalpython/suite.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@
2525
},
2626
{
2727
"name": "sulong",
28-
"version": "a8ec4a7e8cb4488c7f8b774bbc7b1342efd92c71",
28+
"version": "1ea7ec556932ffd2177a41054aebb06ab48a8307",
2929
"urls": [
3030
{"url": "https://github.com/graalvm/sulong", "kind": "git"},
3131
]
3232
},
3333
{
3434
"name": "regex",
35-
"version": "5dc95abd42795d871c937d5be205ef01ae7300ff",
35+
"version": "a8fb89610ab91373ae9c6ed42ab184b2d7ba93d5",
3636
"subdir": True,
3737
"urls": [
3838
{"url": "https://github.com/oracle/graal", "kind": "git"},

0 commit comments

Comments
 (0)