|
40 | 40 | */
|
41 | 41 | package com.oracle.graal.python.builtins.modules;
|
42 | 42 |
|
| 43 | +import static com.oracle.graal.python.nodes.SpecialAttributeNames.__CLASS__; |
43 | 44 | import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
|
44 | 45 |
|
45 | 46 | import java.io.IOException;
|
|
53 | 54 | import com.oracle.graal.python.builtins.CoreFunctions;
|
54 | 55 | import com.oracle.graal.python.builtins.PythonBuiltins;
|
55 | 56 | import com.oracle.graal.python.builtins.objects.PNone;
|
| 57 | +import com.oracle.graal.python.builtins.objects.cell.PCell; |
56 | 58 | import com.oracle.graal.python.builtins.objects.exception.PBaseException;
|
| 59 | +import com.oracle.graal.python.builtins.objects.function.PArguments; |
| 60 | +import com.oracle.graal.python.builtins.objects.function.PKeyword; |
57 | 61 | import com.oracle.graal.python.builtins.objects.ints.PInt;
|
58 | 62 | import com.oracle.graal.python.builtins.objects.str.PString;
|
| 63 | +import com.oracle.graal.python.builtins.objects.type.PythonClass; |
| 64 | +import com.oracle.graal.python.nodes.argument.ReadIndexedArgumentNode; |
| 65 | +import com.oracle.graal.python.nodes.attributes.SetAttributeNode; |
| 66 | +import com.oracle.graal.python.nodes.frame.ReadCallerFrameNode; |
| 67 | +import com.oracle.graal.python.nodes.frame.ReadLocalVariableNode; |
| 68 | +import com.oracle.graal.python.nodes.function.BuiltinFunctionRootNode; |
59 | 69 | import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
|
60 | 70 | import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
|
| 71 | +import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode; |
61 | 72 | import com.oracle.graal.python.runtime.PythonContext;
|
62 | 73 | import com.oracle.graal.python.runtime.PythonCore;
|
63 | 74 | import com.oracle.graal.python.runtime.exception.PException;
|
|
67 | 78 | import com.oracle.truffle.api.Truffle;
|
68 | 79 | import com.oracle.truffle.api.TruffleLanguage.ContextReference;
|
69 | 80 | import com.oracle.truffle.api.TruffleOptions;
|
| 81 | +import com.oracle.truffle.api.dsl.Cached; |
| 82 | +import com.oracle.truffle.api.dsl.Fallback; |
70 | 83 | import com.oracle.truffle.api.dsl.GenerateNodeFactory;
|
71 | 84 | import com.oracle.truffle.api.dsl.NodeFactory;
|
72 | 85 | import com.oracle.truffle.api.dsl.Specialization;
|
| 86 | +import com.oracle.truffle.api.frame.Frame; |
| 87 | +import com.oracle.truffle.api.frame.FrameSlot; |
| 88 | +import com.oracle.truffle.api.frame.FrameSlotTypeException; |
73 | 89 | import com.oracle.truffle.api.frame.VirtualFrame;
|
74 | 90 | import com.oracle.truffle.api.nodes.DirectCallNode;
|
75 | 91 | import com.oracle.truffle.api.nodes.RootNode;
|
| 92 | +import com.oracle.truffle.api.profiles.ConditionProfile; |
76 | 93 |
|
77 | 94 | @CoreFunctions(defineModule = "sys")
|
78 | 95 | public class SysModuleBuiltins extends PythonBuiltins {
|
@@ -182,6 +199,143 @@ public void initialize(PythonCore core) {
|
182 | 199 | super.initialize(core);
|
183 | 200 | }
|
184 | 201 |
|
| 202 | + @Builtin(name = "__super__init__", minNumOfArguments = 1, takesVariableArguments = true, takesVariableKeywords = true) |
| 203 | + @GenerateNodeFactory |
| 204 | + public abstract static class SuperInitNode extends PythonVarargsBuiltinNode { |
| 205 | + |
| 206 | + @Child private SetAttributeNode setTypeAttribute = SetAttributeNode.create("__type__"); |
| 207 | + @Child private SetAttributeNode setObjAttribute = SetAttributeNode.create("__obj__"); |
| 208 | + |
| 209 | + @Override |
| 210 | + public Object varArgExecute(VirtualFrame frame, Object[] arguments, PKeyword[] keywords) throws VarargsBuiltinDirectInvocationNotSupported { |
| 211 | + if (keywords.length != 0) { |
| 212 | + throw raise(PythonErrorType.RuntimeError, "super(): unexpected keyword arguments"); |
| 213 | + } |
| 214 | + if (arguments.length == 1) { |
| 215 | + return execute(frame, arguments[0], PNone.NO_VALUE, PNone.NO_VALUE); |
| 216 | + } else if (arguments.length == 2) { |
| 217 | + return execute(frame, arguments[0], arguments[1], PNone.NO_VALUE); |
| 218 | + } else if (arguments.length == 3) { |
| 219 | + return execute(frame, arguments[0], arguments[1], arguments[2]); |
| 220 | + } else { |
| 221 | + throw raise(PythonErrorType.RuntimeError, "super(): invalid number of arguments"); |
| 222 | + } |
| 223 | + } |
| 224 | + |
| 225 | + @Override |
| 226 | + public final Object execute(VirtualFrame frame, Object self, Object[] arguments, PKeyword[] keywords) { |
| 227 | + if (keywords.length != 0) { |
| 228 | + throw raise(PythonErrorType.RuntimeError, "super(): unexpected keyword arguments"); |
| 229 | + } |
| 230 | + if (arguments.length == 0) { |
| 231 | + return execute(frame, self, PNone.NO_VALUE, PNone.NO_VALUE); |
| 232 | + } else if (arguments.length == 1) { |
| 233 | + return execute(frame, self, arguments[0], PNone.NO_VALUE); |
| 234 | + } else if (arguments.length == 2) { |
| 235 | + return execute(frame, self, arguments[0], arguments[1]); |
| 236 | + } else { |
| 237 | + throw raise(PythonErrorType.RuntimeError, "super(): too many arguments"); |
| 238 | + } |
| 239 | + } |
| 240 | + |
| 241 | + protected abstract Object execute(VirtualFrame frame, Object self, Object cls, Object obj); |
| 242 | + |
| 243 | + @Specialization(guards = {"!isNoValue(cls)", "!isNoValue(obj)"}) |
| 244 | + PNone init(Object self, Object cls, Object obj) { |
| 245 | + if (!(cls instanceof PythonClass)) { |
| 246 | + throw raise(PythonErrorType.RuntimeError, "super(): __class__ is not a type (%p)", cls); |
| 247 | + } |
| 248 | + setTypeAttribute.execute(self, cls); |
| 249 | + setObjAttribute.execute(self, obj); |
| 250 | + return PNone.NONE; |
| 251 | + } |
| 252 | + |
| 253 | + protected boolean isInBuiltinFunctionRoot() { |
| 254 | + return getRootNode() instanceof BuiltinFunctionRootNode; |
| 255 | + } |
| 256 | + |
| 257 | + protected ReadLocalVariableNode createRead(VirtualFrame frame) { |
| 258 | + FrameSlot slot = frame.getFrameDescriptor().findFrameSlot(__CLASS__); |
| 259 | + if (slot == null) { |
| 260 | + throw raise(PythonErrorType.RuntimeError, "super(): empty __class__ cell"); |
| 261 | + } |
| 262 | + return ReadLocalVariableNode.create(slot); |
| 263 | + } |
| 264 | + |
| 265 | + /** |
| 266 | + * Executed with the frame of the calling method - direct access to the frame. |
| 267 | + */ |
| 268 | + @Specialization(guards = {"!isInBuiltinFunctionRoot()", "isNoValue(clsArg)", "isNoValue(objArg)"}) |
| 269 | + PNone initInPlace(VirtualFrame frame, Object self, @SuppressWarnings("unused") PNone clsArg, @SuppressWarnings("unused") PNone objArg, |
| 270 | + @Cached("createRead(frame)") ReadLocalVariableNode readClass, |
| 271 | + @Cached("create(0)") ReadIndexedArgumentNode readArgument, |
| 272 | + @Cached("createBinaryProfile()") ConditionProfile isCellProfile) { |
| 273 | + Object obj = readArgument.execute(frame); |
| 274 | + if (obj == PNone.NONE) { |
| 275 | + throw raise(PythonErrorType.RuntimeError, "super(): no arguments"); |
| 276 | + } |
| 277 | + Object cls = readClass.execute(frame); |
| 278 | + if (isCellProfile.profile(cls instanceof PCell)) { |
| 279 | + cls = ((PCell) cls).getPythonRef(); |
| 280 | + } |
| 281 | + if (cls == PNone.NONE) { |
| 282 | + throw raise(PythonErrorType.RuntimeError, "super(): empty __class__ cell"); |
| 283 | + } |
| 284 | + return init(self, cls, obj); |
| 285 | + } |
| 286 | + |
| 287 | + /** |
| 288 | + * Executed within a {@link BuiltinFunctionRootNode} - indirect access to the frame. |
| 289 | + */ |
| 290 | + @Specialization(guards = {"isInBuiltinFunctionRoot()", "isNoValue(clsArg)", "isNoValue(objArg)"}) |
| 291 | + PNone init(VirtualFrame frame, Object self, @SuppressWarnings("unused") PNone clsArg, @SuppressWarnings("unused") PNone objArg, |
| 292 | + @Cached("create(0)") ReadCallerFrameNode readCaller) { |
| 293 | + Frame target = readCaller.executeWith(frame); |
| 294 | + if (target == null) { |
| 295 | + throw raise(PythonErrorType.RuntimeError, "super(): no current frame"); |
| 296 | + } |
| 297 | + Object[] arguments = target.getArguments(); |
| 298 | + if (arguments.length <= PArguments.USER_ARGUMENTS_OFFSET) { |
| 299 | + throw raise(PythonErrorType.RuntimeError, "super(): no arguments"); |
| 300 | + } |
| 301 | + Object obj = arguments[PArguments.USER_ARGUMENTS_OFFSET]; |
| 302 | + if (obj == PNone.NONE) { |
| 303 | + throw raise(PythonErrorType.RuntimeError, "super(): no arguments"); |
| 304 | + } |
| 305 | + |
| 306 | + return initFromFrame(self, target, obj); |
| 307 | + } |
| 308 | + |
| 309 | + @TruffleBoundary |
| 310 | + private PNone initFromFrame(Object self, Frame target, Object obj) { |
| 311 | + // TODO: remove me |
| 312 | + // TODO: do it properly via the python API in super.__init__ : |
| 313 | + // sys._getframe(1).f_code.co_closure? |
| 314 | + FrameSlot classSlot = target.getFrameDescriptor().findFrameSlot(__CLASS__); |
| 315 | + Object cls = PNone.NONE; |
| 316 | + if (classSlot != null) { |
| 317 | + try { |
| 318 | + cls = target.getObject(classSlot); |
| 319 | + if (cls instanceof PCell) { |
| 320 | + cls = ((PCell) cls).getPythonRef(); |
| 321 | + } |
| 322 | + } catch (FrameSlotTypeException e) { |
| 323 | + // fallthrough |
| 324 | + } |
| 325 | + } |
| 326 | + if (cls == PNone.NONE) { |
| 327 | + throw raise(PythonErrorType.RuntimeError, "super(): empty __class__ cell"); |
| 328 | + } |
| 329 | + return init(self, cls, obj); |
| 330 | + } |
| 331 | + |
| 332 | + @SuppressWarnings("unused") |
| 333 | + @Fallback |
| 334 | + PNone initFallback(Object self, Object cls, Object obj) { |
| 335 | + throw raise(PythonErrorType.RuntimeError, "super(): invalid arguments"); |
| 336 | + } |
| 337 | + } |
| 338 | + |
185 | 339 | @Builtin(name = "exc_info", fixedNumOfArguments = 0)
|
186 | 340 | @GenerateNodeFactory
|
187 | 341 | public static abstract class ExcInfoNode extends PythonBuiltinNode {
|
|
0 commit comments