|
30 | 30 | import static com.oracle.graal.python.builtins.objects.PNone.NO_VALUE;
|
31 | 31 | import static com.oracle.graal.python.builtins.objects.PNotImplemented.NOT_IMPLEMENTED;
|
32 | 32 | import static com.oracle.graal.python.nodes.BuiltinNames.ABS;
|
| 33 | +import static com.oracle.graal.python.nodes.BuiltinNames.ALL; |
| 34 | +import static com.oracle.graal.python.nodes.BuiltinNames.ANY; |
33 | 35 | import static com.oracle.graal.python.nodes.BuiltinNames.ASCII;
|
34 | 36 | import static com.oracle.graal.python.nodes.BuiltinNames.BIN;
|
35 | 37 | import static com.oracle.graal.python.nodes.BuiltinNames.BREAKPOINT;
|
|
102 | 104 | import com.oracle.graal.python.builtins.objects.code.PCode;
|
103 | 105 | import com.oracle.graal.python.builtins.objects.common.DynamicObjectStorage;
|
104 | 106 | import com.oracle.graal.python.builtins.objects.common.HashingCollectionNodes;
|
| 107 | +import com.oracle.graal.python.builtins.objects.common.HashingStorage; |
105 | 108 | import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
|
| 109 | +import com.oracle.graal.python.builtins.objects.common.PHashingCollection; |
106 | 110 | import com.oracle.graal.python.builtins.objects.common.SequenceNodes.GetObjectArrayNode;
|
107 | 111 | import com.oracle.graal.python.builtins.objects.common.SequenceNodesFactory.GetObjectArrayNodeGen;
|
108 | 112 | import com.oracle.graal.python.builtins.objects.common.SequenceStorageNodes;
|
|
134 | 138 | import com.oracle.graal.python.lib.PyObjectGetAttr;
|
135 | 139 | import com.oracle.graal.python.lib.PyObjectGetIter;
|
136 | 140 | import com.oracle.graal.python.lib.PyObjectHashNode;
|
| 141 | +import com.oracle.graal.python.lib.PyObjectIsTrueNode; |
137 | 142 | import com.oracle.graal.python.lib.PyObjectLookupAttr;
|
138 | 143 | import com.oracle.graal.python.lib.PyObjectReprAsObjectNode;
|
139 | 144 | import com.oracle.graal.python.lib.PyObjectSizeNode;
|
|
144 | 149 | import com.oracle.graal.python.nodes.ErrorMessages;
|
145 | 150 | import com.oracle.graal.python.nodes.GraalPythonTranslationErrorNode;
|
146 | 151 | import com.oracle.graal.python.nodes.PGuards;
|
| 152 | +import com.oracle.graal.python.nodes.PNodeWithContext; |
147 | 153 | import com.oracle.graal.python.nodes.PNodeWithRaise;
|
148 | 154 | import com.oracle.graal.python.nodes.PRaiseNode;
|
149 | 155 | import com.oracle.graal.python.nodes.PRootNode;
|
|
204 | 210 | import com.oracle.graal.python.runtime.exception.PException;
|
205 | 211 | import com.oracle.graal.python.runtime.exception.PythonErrorType;
|
206 | 212 | import com.oracle.graal.python.runtime.object.PythonObjectFactory;
|
| 213 | +import com.oracle.graal.python.runtime.sequence.storage.BoolSequenceStorage; |
| 214 | +import com.oracle.graal.python.runtime.sequence.storage.IntSequenceStorage; |
207 | 215 | import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
|
208 | 216 | import com.oracle.graal.python.util.CharsetMapping;
|
209 | 217 | import com.oracle.graal.python.util.PythonUtils;
|
|
232 | 240 | import com.oracle.truffle.api.library.CachedLibrary;
|
233 | 241 | import com.oracle.truffle.api.nodes.ExplodeLoop;
|
234 | 242 | import com.oracle.truffle.api.nodes.ExplodeLoop.LoopExplosionKind;
|
| 243 | +import com.oracle.truffle.api.nodes.LoopNode; |
235 | 244 | import com.oracle.truffle.api.nodes.Node;
|
236 | 245 | import com.oracle.truffle.api.nodes.RootNode;
|
237 | 246 | import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
238 | 247 | import com.oracle.truffle.api.profiles.BranchProfile;
|
239 | 248 | import com.oracle.truffle.api.profiles.ConditionProfile;
|
| 249 | +import com.oracle.truffle.api.profiles.LoopConditionProfile; |
240 | 250 | import com.oracle.truffle.api.source.Source;
|
241 | 251 | import com.oracle.truffle.api.utilities.TriState;
|
242 | 252 |
|
@@ -286,6 +296,217 @@ public Object absObject(VirtualFrame frame, Object object,
|
286 | 296 | }
|
287 | 297 | }
|
288 | 298 |
|
| 299 | + /** |
| 300 | + * Common class for all() and any() operations, as their logic and behaviors are very similar. |
| 301 | + */ |
| 302 | + abstract static class AllOrAnyNode extends PNodeWithContext { |
| 303 | + enum NodeType { |
| 304 | + ALL, |
| 305 | + ANY |
| 306 | + } |
| 307 | + |
| 308 | + @Child private PyObjectIsTrueNode isTrueNode = PyObjectIsTrueNode.create(); |
| 309 | + |
| 310 | + private final LoopConditionProfile loopConditionProfile = LoopConditionProfile.create(); |
| 311 | + |
| 312 | + abstract boolean execute(Frame frame, Object storageObj, NodeType nodeType); |
| 313 | + |
| 314 | + @Specialization |
| 315 | + boolean doBoolSequence(VirtualFrame frame, |
| 316 | + BoolSequenceStorage sequenceStorage, |
| 317 | + NodeType nodeType) { |
| 318 | + boolean[] internalArray = sequenceStorage.getInternalBoolArray(); |
| 319 | + int seqLength = sequenceStorage.length(); |
| 320 | + |
| 321 | + loopConditionProfile.profileCounted(seqLength); |
| 322 | + for (int i = 0; loopConditionProfile.inject(i < seqLength); i++) { |
| 323 | + if (nodeType == NodeType.ALL && !isTrueNode.execute(frame, internalArray[i])) { |
| 324 | + return false; |
| 325 | + } else if (nodeType == NodeType.ANY && isTrueNode.execute(frame, internalArray[i])) { |
| 326 | + return true; |
| 327 | + } |
| 328 | + } |
| 329 | + |
| 330 | + return nodeType == NodeType.ALL; |
| 331 | + } |
| 332 | + |
| 333 | + @Specialization |
| 334 | + boolean doIntSequence(VirtualFrame frame, |
| 335 | + IntSequenceStorage sequenceStorage, |
| 336 | + NodeType nodeType) { |
| 337 | + int[] internalArray = sequenceStorage.getInternalIntArray(); |
| 338 | + int seqLength = sequenceStorage.length(); |
| 339 | + |
| 340 | + loopConditionProfile.profileCounted(seqLength); |
| 341 | + for (int i = 0; loopConditionProfile.inject(i < seqLength); i++) { |
| 342 | + if (nodeType == NodeType.ALL && !isTrueNode.execute(frame, internalArray[i])) { |
| 343 | + return false; |
| 344 | + } else if (nodeType == NodeType.ANY && isTrueNode.execute(frame, internalArray[i])) { |
| 345 | + return true; |
| 346 | + } |
| 347 | + } |
| 348 | + |
| 349 | + return nodeType == NodeType.ALL; |
| 350 | + } |
| 351 | + |
| 352 | + @Specialization |
| 353 | + boolean doGenericSequence(VirtualFrame frame, |
| 354 | + SequenceStorage sequenceStorage, |
| 355 | + NodeType nodeType, |
| 356 | + @Cached SequenceStorageNodes.LenNode lenNode) { |
| 357 | + Object[] internalArray = sequenceStorage.getInternalArray(); |
| 358 | + int seqLength = lenNode.execute(sequenceStorage); |
| 359 | + |
| 360 | + loopConditionProfile.profileCounted(seqLength); |
| 361 | + for (int i = 0; loopConditionProfile.inject(i < seqLength); i++) { |
| 362 | + if (nodeType == NodeType.ALL && !isTrueNode.execute(frame, internalArray[i])) { |
| 363 | + return false; |
| 364 | + } else if (nodeType == NodeType.ANY && isTrueNode.execute(frame, internalArray[i])) { |
| 365 | + return true; |
| 366 | + } |
| 367 | + } |
| 368 | + |
| 369 | + return nodeType == NodeType.ALL; |
| 370 | + } |
| 371 | + |
| 372 | + @Specialization(limit = "3") |
| 373 | + protected boolean doHashStorage(VirtualFrame frame, |
| 374 | + HashingStorage hashingStorage, |
| 375 | + NodeType nodeType, |
| 376 | + @CachedLibrary("hashingStorage") HashingStorageLibrary hlib) { |
| 377 | + HashingStorageLibrary.HashingStorageIterator<Object> keysIter = hlib.keys(hashingStorage).iterator(); |
| 378 | + int seqLength = hlib.length(hashingStorage); |
| 379 | + |
| 380 | + loopConditionProfile.profileCounted(seqLength); |
| 381 | + for (int i = 0; loopConditionProfile.inject(i < seqLength); i++) { |
| 382 | + Object key = keysIter.next(); |
| 383 | + if (nodeType == NodeType.ALL) { |
| 384 | + if (!isTrueNode.execute(frame, key)) { |
| 385 | + return false; |
| 386 | + } |
| 387 | + } else if (nodeType == NodeType.ANY && isTrueNode.execute(frame, key)) { |
| 388 | + return true; |
| 389 | + } |
| 390 | + } |
| 391 | + |
| 392 | + return nodeType == NodeType.ALL; |
| 393 | + } |
| 394 | + } |
| 395 | + |
| 396 | + @Builtin(name = ALL, minNumOfPositionalArgs = 1) |
| 397 | + @GenerateNodeFactory |
| 398 | + public abstract static class AllNode extends PythonUnaryBuiltinNode { |
| 399 | + |
| 400 | + @Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1") |
| 401 | + static boolean doList(VirtualFrame frame, |
| 402 | + PList object, |
| 403 | + @SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode, |
| 404 | + @Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) { |
| 405 | + return allOrAnyNode.execute(frame, object.getSequenceStorage(), AllOrAnyNode.NodeType.ALL); |
| 406 | + } |
| 407 | + |
| 408 | + @Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1") |
| 409 | + static boolean doTuple(VirtualFrame frame, |
| 410 | + PTuple object, |
| 411 | + @SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode, |
| 412 | + @Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) { |
| 413 | + return allOrAnyNode.execute(frame, object.getSequenceStorage(), AllOrAnyNode.NodeType.ALL); |
| 414 | + } |
| 415 | + |
| 416 | + @Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1") |
| 417 | + static boolean doHashColl(VirtualFrame frame, |
| 418 | + PHashingCollection object, |
| 419 | + @SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode, |
| 420 | + @Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) { |
| 421 | + return allOrAnyNode.execute(frame, object.getDictStorage(), AllOrAnyNode.NodeType.ALL); |
| 422 | + } |
| 423 | + |
| 424 | + @Specialization |
| 425 | + boolean doObject(VirtualFrame frame, |
| 426 | + Object object, |
| 427 | + @Cached PyObjectGetIter getIter, |
| 428 | + @Cached GetNextNode nextNode, |
| 429 | + @Cached IsBuiltinClassProfile errorProfile, |
| 430 | + @Cached PyObjectIsTrueNode isTrueNode) { |
| 431 | + Object iterator = getIter.execute(frame, object); |
| 432 | + int nbrIter = 0; |
| 433 | + |
| 434 | + while (true) { |
| 435 | + try { |
| 436 | + Object next = nextNode.execute(frame, iterator); |
| 437 | + nbrIter++; |
| 438 | + if (!isTrueNode.execute(frame, next)) { |
| 439 | + return false; |
| 440 | + } |
| 441 | + } catch (PException e) { |
| 442 | + e.expectStopIteration(errorProfile); |
| 443 | + break; |
| 444 | + } finally { |
| 445 | + LoopNode.reportLoopCount(this, nbrIter); |
| 446 | + } |
| 447 | + } |
| 448 | + |
| 449 | + return true; |
| 450 | + } |
| 451 | + } |
| 452 | + |
| 453 | + @Builtin(name = ANY, minNumOfPositionalArgs = 1) |
| 454 | + @GenerateNodeFactory |
| 455 | + public abstract static class AnyNode extends PythonUnaryBuiltinNode { |
| 456 | + |
| 457 | + @Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1") |
| 458 | + static boolean doList(VirtualFrame frame, |
| 459 | + PList object, |
| 460 | + @SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode, |
| 461 | + @Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) { |
| 462 | + return allOrAnyNode.execute(frame, object.getSequenceStorage(), AllOrAnyNode.NodeType.ANY); |
| 463 | + } |
| 464 | + |
| 465 | + @Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1") |
| 466 | + static boolean doTuple(VirtualFrame frame, |
| 467 | + PTuple object, |
| 468 | + @SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode, |
| 469 | + @Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) { |
| 470 | + return allOrAnyNode.execute(frame, object.getSequenceStorage(), AllOrAnyNode.NodeType.ANY); |
| 471 | + } |
| 472 | + |
| 473 | + @Specialization(guards = "cannotBeOverridden(object, getClassNode)", limit = "1") |
| 474 | + static boolean doHashColl(VirtualFrame frame, |
| 475 | + PHashingCollection object, |
| 476 | + @SuppressWarnings("unused") @Shared("getClassNode") @Cached GetClassNode getClassNode, |
| 477 | + @Shared("allOrAnyNode") @Cached AllOrAnyNode allOrAnyNode) { |
| 478 | + return allOrAnyNode.execute(frame, object.getDictStorage(), AllOrAnyNode.NodeType.ANY); |
| 479 | + } |
| 480 | + |
| 481 | + @Specialization |
| 482 | + boolean doObject(VirtualFrame frame, |
| 483 | + Object object, |
| 484 | + @Cached PyObjectGetIter getIter, |
| 485 | + @Cached GetNextNode nextNode, |
| 486 | + @Cached IsBuiltinClassProfile errorProfile, |
| 487 | + @Cached PyObjectIsTrueNode isTrueNode) { |
| 488 | + Object iterator = getIter.execute(frame, object); |
| 489 | + int nbrIter = 0; |
| 490 | + |
| 491 | + while (true) { |
| 492 | + try { |
| 493 | + Object next = nextNode.execute(frame, iterator); |
| 494 | + nbrIter++; |
| 495 | + if (isTrueNode.execute(frame, next)) { |
| 496 | + return true; |
| 497 | + } |
| 498 | + } catch (PException e) { |
| 499 | + e.expectStopIteration(errorProfile); |
| 500 | + break; |
| 501 | + } finally { |
| 502 | + LoopNode.reportLoopCount(this, nbrIter); |
| 503 | + } |
| 504 | + } |
| 505 | + |
| 506 | + return false; |
| 507 | + } |
| 508 | + } |
| 509 | + |
289 | 510 | // bin(object)
|
290 | 511 | @Builtin(name = BIN, minNumOfPositionalArgs = 1)
|
291 | 512 | @TypeSystemReference(PythonArithmeticTypes.class)
|
|
0 commit comments