|
27 | 27 |
|
28 | 28 | import static com.oracle.graal.python.runtime.PythonOptions.CatchAllExceptions;
|
29 | 29 |
|
| 30 | +import java.util.ArrayList; |
| 31 | +import java.util.List; |
| 32 | + |
30 | 33 | import com.oracle.graal.python.builtins.objects.PNone;
|
31 | 34 | import com.oracle.graal.python.builtins.objects.exception.PBaseException;
|
| 35 | +import com.oracle.graal.python.builtins.objects.module.PythonModule; |
32 | 36 | import com.oracle.graal.python.nodes.PNode;
|
| 37 | +import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode; |
| 38 | +import com.oracle.graal.python.nodes.frame.ReadGlobalOrBuiltinNode; |
| 39 | +import com.oracle.graal.python.nodes.literal.TupleLiteralNode; |
33 | 40 | import com.oracle.graal.python.runtime.PythonOptions;
|
34 | 41 | import com.oracle.graal.python.runtime.exception.ExceptionHandledException;
|
35 | 42 | import com.oracle.graal.python.runtime.exception.PException;
|
36 | 43 | import com.oracle.graal.python.runtime.exception.PythonErrorType;
|
37 |
| -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; |
38 |
| -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; |
39 | 44 | import com.oracle.truffle.api.CompilerDirectives;
|
| 45 | +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; |
| 46 | +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; |
40 | 47 | import com.oracle.truffle.api.frame.VirtualFrame;
|
| 48 | +import com.oracle.truffle.api.instrumentation.StandardTags; |
| 49 | +import com.oracle.truffle.api.instrumentation.Tag; |
| 50 | +import com.oracle.truffle.api.interop.ArityException; |
| 51 | +import com.oracle.truffle.api.interop.CanResolve; |
| 52 | +import com.oracle.truffle.api.interop.ForeignAccess; |
| 53 | +import com.oracle.truffle.api.interop.MessageResolution; |
| 54 | +import com.oracle.truffle.api.interop.Resolve; |
| 55 | +import com.oracle.truffle.api.interop.TruffleObject; |
| 56 | +import com.oracle.truffle.api.interop.UnknownIdentifierException; |
41 | 57 | import com.oracle.truffle.api.nodes.ControlFlowException;
|
42 | 58 | import com.oracle.truffle.api.nodes.ExplodeLoop;
|
| 59 | +import com.oracle.truffle.api.nodes.Node; |
43 | 60 |
|
44 |
| -public class TryExceptNode extends StatementNode { |
| 61 | +public class TryExceptNode extends StatementNode implements TruffleObject { |
45 | 62 |
|
46 | 63 | @Child private PNode body;
|
47 |
| - @Children final ExceptNode[] exceptNodes; |
| 64 | + @Children private final ExceptNode[] exceptNodes; |
48 | 65 | @Child private PNode orelse;
|
49 | 66 |
|
50 | 67 | @CompilationFinal boolean seenException;
|
@@ -125,4 +142,118 @@ public ExceptNode[] getExceptNodes() {
|
125 | 142 | public PNode getOrelse() {
|
126 | 143 | return orelse;
|
127 | 144 | }
|
| 145 | + |
| 146 | + @Override |
| 147 | + public boolean hasTag(Class<? extends Tag> tag) { |
| 148 | + return super.hasTag(tag) || StandardTags.TryBlockTag.class == tag; |
| 149 | + } |
| 150 | + |
| 151 | + public Object getNodeObject() { |
| 152 | + return this; |
| 153 | + } |
| 154 | + |
| 155 | + public ForeignAccess getForeignAccess() { |
| 156 | + return ExceptBlockMRForeign.ACCESS; |
| 157 | + } |
| 158 | + |
| 159 | + @MessageResolution(receiverType = TryExceptNode.class) |
| 160 | + static class ExceptBlockMR { |
| 161 | + @Resolve(message = "HAS_KEYS") |
| 162 | + abstract static class HasKeysNode extends Node { |
| 163 | + Object access(@SuppressWarnings("unused") TryExceptNode object) { |
| 164 | + return true; |
| 165 | + } |
| 166 | + } |
| 167 | + |
| 168 | + @Resolve(message = "KEYS") |
| 169 | + abstract static class KeysNode extends Node { |
| 170 | + Object access(TryExceptNode object) { |
| 171 | + return object.getContext().getEnv().asGuestValue(new String[]{StandardTags.TryBlockTag.CATCHES}); |
| 172 | + } |
| 173 | + } |
| 174 | + |
| 175 | + @Resolve(message = "READ") |
| 176 | + abstract static class ReadNode extends Node { |
| 177 | + Object access(TryExceptNode object, String name) { |
| 178 | + if (name.equals(StandardTags.TryBlockTag.CATCHES)) { |
| 179 | + ExceptNode[] exceptNodes = object.getExceptNodes(); |
| 180 | + List<String> literalCatches = new ArrayList<>(); |
| 181 | + for (ExceptNode node : exceptNodes) { |
| 182 | + PNode exceptType = node.getExceptType(); |
| 183 | + if (exceptType instanceof ReadGlobalOrBuiltinNode) { |
| 184 | + literalCatches.add(((ReadGlobalOrBuiltinNode) exceptType).getAttributeId()); |
| 185 | + } else if (exceptType instanceof TupleLiteralNode) { |
| 186 | + for (PNode tupleValue : ((TupleLiteralNode) exceptType).getValues()) { |
| 187 | + if (tupleValue instanceof ReadGlobalOrBuiltinNode) { |
| 188 | + literalCatches.add(((ReadGlobalOrBuiltinNode) tupleValue).getAttributeId()); |
| 189 | + } |
| 190 | + } |
| 191 | + } |
| 192 | + } |
| 193 | + return new CatchesFunction(object.getContext().getBuiltins(), literalCatches.toArray(new String[0])); |
| 194 | + } else { |
| 195 | + throw UnknownIdentifierException.raise(name); |
| 196 | + } |
| 197 | + } |
| 198 | + } |
| 199 | + |
| 200 | + @CanResolve |
| 201 | + abstract static class CheckFunction extends Node { |
| 202 | + protected static boolean test(TruffleObject receiver) { |
| 203 | + return receiver instanceof TryExceptNode; |
| 204 | + } |
| 205 | + } |
| 206 | + |
| 207 | + protected static class CatchesFunction implements TruffleObject { |
| 208 | + private final PythonModule builtins; |
| 209 | + @CompilationFinal(dimensions = 1) private final String[] attributes; |
| 210 | + private final ReadAttributeFromObjectNode getAttribute = ReadAttributeFromObjectNode.create(); |
| 211 | + |
| 212 | + CatchesFunction(PythonModule builtins, String[] array) { |
| 213 | + this.builtins = builtins; |
| 214 | + this.attributes = array; |
| 215 | + } |
| 216 | + |
| 217 | + boolean catches(Object exception) { |
| 218 | + for (String name : attributes) { |
| 219 | + Object execute = getAttribute.execute(builtins, name); |
| 220 | + if (execute == exception) { |
| 221 | + return true; |
| 222 | + } |
| 223 | + } |
| 224 | + return false; |
| 225 | + } |
| 226 | + |
| 227 | + public ForeignAccess getForeignAccess() { |
| 228 | + return ExceptListMRForeign.ACCESS; |
| 229 | + } |
| 230 | + |
| 231 | + @MessageResolution(receiverType = CatchesFunction.class) |
| 232 | + static class ExceptListMR { |
| 233 | + @Resolve(message = "IS_EXECUTABLE") |
| 234 | + abstract static class IsExecutableNode extends Node { |
| 235 | + Object access(@SuppressWarnings("unused") CatchesFunction object) { |
| 236 | + return true; |
| 237 | + } |
| 238 | + } |
| 239 | + |
| 240 | + @Resolve(message = "EXECUTE") |
| 241 | + abstract static class ExecuteNode extends Node { |
| 242 | + Object access(CatchesFunction object, Object[] arguments) { |
| 243 | + if (arguments.length != 1) { |
| 244 | + throw ArityException.raise(1, arguments.length); |
| 245 | + } |
| 246 | + return object.catches(arguments[0]); |
| 247 | + } |
| 248 | + } |
| 249 | + |
| 250 | + @CanResolve |
| 251 | + abstract static class CheckFunction extends Node { |
| 252 | + protected static boolean test(TruffleObject receiver) { |
| 253 | + return receiver instanceof TryExceptNode; |
| 254 | + } |
| 255 | + } |
| 256 | + } |
| 257 | + } |
| 258 | + } |
128 | 259 | }
|
0 commit comments