1# Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com 2# 3# Part of "Nuitka", an optimizing Python compiler that is compatible and 4# integrates with CPython, but also works on its own. 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18""" Optimize calls to built-in references to specific built-in calls. 19 20For built-in name references, we check if it's one of the supported built-in 21types, and then specialize for the ones, where it makes sense. 22""" 23 24from nuitka.__past__ import xrange # pylint: disable=I0021,redefined-builtin 25from nuitka.Errors import NuitkaAssumptionError 26from nuitka.nodes.AssignNodes import ( 27 StatementAssignmentVariable, 28 StatementDelVariable, 29) 30from nuitka.nodes.AttributeNodes import ( 31 ExpressionAttributeLookup, 32 ExpressionBuiltinGetattr, 33 ExpressionBuiltinHasattr, 34 ExpressionBuiltinSetattr, 35) 36from nuitka.nodes.BuiltinAllNodes import ExpressionBuiltinAll 37from nuitka.nodes.BuiltinAnyNodes import ExpressionBuiltinAny 38from nuitka.nodes.BuiltinComplexNodes import ( 39 ExpressionBuiltinComplex1, 40 ExpressionBuiltinComplex2, 41) 42from nuitka.nodes.BuiltinDecodingNodes import ( 43 ExpressionBuiltinChr, 44 ExpressionBuiltinOrd, 45) 46from nuitka.nodes.BuiltinDecoratorNodes import ( 47 ExpressionBuiltinClassmethod, 48 ExpressionBuiltinStaticmethod, 49) 50from nuitka.nodes.BuiltinDictNodes import ExpressionBuiltinDict 51from nuitka.nodes.BuiltinFormatNodes import ( 52 ExpressionBuiltinAscii, 53 ExpressionBuiltinBin, 54 ExpressionBuiltinFormat, 55 ExpressionBuiltinHex, 56 ExpressionBuiltinId, 57 ExpressionBuiltinOct, 58) 59from nuitka.nodes.BuiltinHashNodes import ExpressionBuiltinHash 60from nuitka.nodes.BuiltinIntegerNodes import ( 61 ExpressionBuiltinInt1, 62 ExpressionBuiltinInt2, 63) 64from nuitka.nodes.BuiltinIteratorNodes import ( 65 ExpressionBuiltinIter1, 66 ExpressionBuiltinIter2, 67) 68from nuitka.nodes.BuiltinLenNodes import ExpressionBuiltinLen 69from nuitka.nodes.BuiltinNextNodes import ( 70 ExpressionBuiltinNext1, 71 ExpressionBuiltinNext2, 72) 73from nuitka.nodes.BuiltinOpenNodes import ExpressionBuiltinOpen 74from nuitka.nodes.BuiltinRangeNodes import ( 75 ExpressionBuiltinRange1, 76 ExpressionBuiltinRange2, 77 ExpressionBuiltinRange3, 78 ExpressionBuiltinXrange1, 79 ExpressionBuiltinXrange2, 80 ExpressionBuiltinXrange3, 81) 82from nuitka.nodes.BuiltinRefNodes import ( 83 ExpressionBuiltinAnonymousRef, 84 makeExpressionBuiltinTypeRef, 85) 86from nuitka.nodes.BuiltinSumNodes import ( 87 ExpressionBuiltinSum1, 88 ExpressionBuiltinSum2, 89) 90from nuitka.nodes.BuiltinTypeNodes import ( 91 ExpressionBuiltinBool, 92 ExpressionBuiltinBytearray1, 93 ExpressionBuiltinBytearray3, 94 ExpressionBuiltinFloat, 95 ExpressionBuiltinFrozenset, 96 ExpressionBuiltinList, 97 ExpressionBuiltinSet, 98 ExpressionBuiltinStrP2, 99 ExpressionBuiltinStrP3, 100 ExpressionBuiltinTuple, 101 ExpressionBuiltinUnicodeP2, 102) 103from nuitka.nodes.BuiltinVarsNodes import ExpressionBuiltinVars 104from nuitka.nodes.CallNodes import makeExpressionCall 105from nuitka.nodes.ClassNodes import ExpressionBuiltinType3 106from nuitka.nodes.ComparisonNodes import ExpressionComparisonIs 107from nuitka.nodes.ConditionalNodes import ( 108 ExpressionConditional, 109 makeStatementConditional, 110) 111from nuitka.nodes.ConstantRefNodes import makeConstantRefNode 112from nuitka.nodes.ContainerMakingNodes import makeExpressionMakeTupleOrConstant 113from nuitka.nodes.ExecEvalNodes import ( 114 ExpressionBuiltinCompile, 115 ExpressionBuiltinEval, 116) 117from nuitka.nodes.GlobalsLocalsNodes import ( 118 ExpressionBuiltinDir1, 119 ExpressionBuiltinGlobals, 120) 121from nuitka.nodes.ImportNodes import ExpressionBuiltinImport 122from nuitka.nodes.NodeMakingHelpers import ( 123 makeConstantReplacementNode, 124 makeExpressionBuiltinLocals, 125 makeRaiseExceptionReplacementExpression, 126 makeRaiseExceptionReplacementExpressionFromInstance, 127 wrapExpressionWithSideEffects, 128) 129from nuitka.nodes.OperatorNodes import ExpressionOperationBinaryDivmod 130from nuitka.nodes.OperatorNodesUnary import ( 131 ExpressionOperationNot, 132 ExpressionOperationUnaryAbs, 133 ExpressionOperationUnaryRepr, 134) 135from nuitka.nodes.OutlineNodes import ExpressionOutlineBody 136from nuitka.nodes.ReturnNodes import makeStatementReturn 137from nuitka.nodes.SliceNodes import makeExpressionBuiltinSlice 138from nuitka.nodes.TypeNodes import ( 139 ExpressionBuiltinIsinstance, 140 ExpressionBuiltinIssubclass, 141 ExpressionBuiltinSuper0, 142 ExpressionBuiltinSuper2, 143 ExpressionBuiltinType1, 144) 145from nuitka.nodes.VariableRefNodes import ( 146 ExpressionTempVariableRef, 147 ExpressionVariableRef, 148) 149from nuitka.PythonVersions import python_version 150from nuitka.specs import BuiltinParameterSpecs 151from nuitka.tree.ReformulationExecStatements import wrapEvalGlobalsAndLocals 152from nuitka.tree.ReformulationTryFinallyStatements import ( 153 makeTryFinallyStatement, 154) 155from nuitka.tree.TreeHelpers import ( 156 makeCallNode, 157 makeStatementsSequence, 158 makeStatementsSequenceFromStatement, 159) 160 161 162def dir_extractor(node): 163 locals_scope = node.subnode_called.getLocalsScope() 164 165 def buildDirEmptyCase(source_ref): 166 source = makeExpressionBuiltinLocals( 167 locals_scope=locals_scope, source_ref=source_ref 168 ) 169 170 result = makeCallNode( 171 ExpressionAttributeLookup( 172 expression=source, attribute_name="keys", source_ref=source_ref 173 ), 174 source_ref, 175 ) 176 177 # For Python3, keys doesn't really return values, but instead a handle 178 # only, but we want it to be a list. 179 if python_version >= 0x300: 180 result = ExpressionBuiltinList(value=result, source_ref=source_ref) 181 182 return result 183 184 return BuiltinParameterSpecs.extractBuiltinArgs( 185 node=node, 186 # TODO: Needs locals_scope attached. 187 builtin_class=ExpressionBuiltinDir1, 188 builtin_spec=BuiltinParameterSpecs.builtin_dir_spec, 189 empty_special_class=buildDirEmptyCase, 190 ) 191 192 193def vars_extractor(node): 194 locals_scope = node.subnode_called.getLocalsScope() 195 196 def selectVarsEmptyClass(source_ref): 197 return makeExpressionBuiltinLocals( 198 locals_scope=locals_scope, source_ref=source_ref 199 ) 200 201 return BuiltinParameterSpecs.extractBuiltinArgs( 202 node=node, 203 # TODO: Needs locals_cope attached 204 builtin_class=ExpressionBuiltinVars, 205 builtin_spec=BuiltinParameterSpecs.builtin_vars_spec, 206 empty_special_class=selectVarsEmptyClass, 207 ) 208 209 210def import_extractor(node): 211 return BuiltinParameterSpecs.extractBuiltinArgs( 212 node=node, 213 builtin_class=ExpressionBuiltinImport, 214 builtin_spec=BuiltinParameterSpecs.builtin_import_spec, 215 ) 216 217 218def type_extractor(node): 219 args = node.subnode_args 220 221 if args is None: 222 iter_length = 0 223 else: 224 iter_length = args.getIterationLength() 225 226 if iter_length == 1: 227 return BuiltinParameterSpecs.extractBuiltinArgs( 228 node=node, 229 builtin_class=ExpressionBuiltinType1, 230 builtin_spec=BuiltinParameterSpecs.builtin_type1_spec, 231 ) 232 elif iter_length == 3: 233 return BuiltinParameterSpecs.extractBuiltinArgs( 234 node=node, 235 builtin_class=ExpressionBuiltinType3, 236 builtin_spec=BuiltinParameterSpecs.builtin_type3_spec, 237 ) 238 else: 239 return makeRaiseExceptionReplacementExpressionFromInstance( 240 expression=node, exception=TypeError("type() takes 1 or 3 arguments") 241 ) 242 243 244def iter_extractor(node): 245 def wrapIterCreation(callable_arg, sentinel, source_ref): 246 if sentinel is None: 247 return ExpressionBuiltinIter1(value=callable_arg, source_ref=source_ref) 248 else: 249 return ExpressionBuiltinIter2( 250 callable_arg=callable_arg, sentinel=sentinel, source_ref=source_ref 251 ) 252 253 return BuiltinParameterSpecs.extractBuiltinArgs( 254 node=node, 255 builtin_class=wrapIterCreation, 256 builtin_spec=BuiltinParameterSpecs.builtin_iter_spec, 257 ) 258 259 260def next_extractor(node): 261 # Split up next with and without defaults, they are not going to behave 262 # really very similar. 263 def selectNextBuiltinClass(iterator, default, source_ref): 264 if default is None: 265 return ExpressionBuiltinNext1(value=iterator, source_ref=source_ref) 266 else: 267 return ExpressionBuiltinNext2( 268 iterator=iterator, default=default, source_ref=source_ref 269 ) 270 271 return BuiltinParameterSpecs.extractBuiltinArgs( 272 node=node, 273 builtin_class=selectNextBuiltinClass, 274 builtin_spec=BuiltinParameterSpecs.builtin_next_spec, 275 ) 276 277 278def sum_extractor(node): 279 # Split up sumwith and without start value, one is much easier. 280 def selectSumBuiltinClass(sequence, start, source_ref): 281 if start is None: 282 return ExpressionBuiltinSum1(sequence=sequence, source_ref=source_ref) 283 else: 284 return ExpressionBuiltinSum2( 285 sequence=sequence, start=start, source_ref=source_ref 286 ) 287 288 def makeSum0(source_ref): 289 # pylint: disable=unused-argument 290 291 return makeRaiseExceptionReplacementExpressionFromInstance( 292 expression=node, 293 exception=TypeError( 294 "sum expected at least 1 arguments, got 0" 295 if python_version < 0x380 296 else "sum() takes at least 1 positional argument (0 given)" 297 ), 298 ) 299 300 return BuiltinParameterSpecs.extractBuiltinArgs( 301 node=node, 302 builtin_class=selectSumBuiltinClass, 303 builtin_spec=BuiltinParameterSpecs.builtin_sum_spec, 304 empty_special_class=makeSum0, 305 ) 306 307 308def dict_extractor(node): 309 # The "dict" built-in is a bit strange in that it accepts a position 310 # parameter, or not, but won't have a default value. 311 def wrapExpressionBuiltinDictCreation(positional_args, dict_star_arg, source_ref): 312 if len(positional_args) > 1: 313 314 result = makeRaiseExceptionReplacementExpressionFromInstance( 315 expression=node, 316 exception=TypeError( 317 "dict expected at most 1 arguments, got %d" % (len(positional_args)) 318 ), 319 ) 320 321 result = wrapExpressionWithSideEffects( 322 side_effects=positional_args, old_node=node, new_node=result 323 ) 324 325 if dict_star_arg: 326 result = wrapExpressionWithSideEffects( 327 side_effects=dict_star_arg, old_node=node, new_node=result 328 ) 329 330 return result 331 332 return ExpressionBuiltinDict( 333 pos_arg=positional_args[0] if positional_args else None, 334 pairs=dict_star_arg, 335 source_ref=source_ref, 336 ) 337 338 return BuiltinParameterSpecs.extractBuiltinArgs( 339 node=node, 340 builtin_class=wrapExpressionBuiltinDictCreation, 341 builtin_spec=BuiltinParameterSpecs.builtin_dict_spec, 342 ) 343 344 345def chr_extractor(node): 346 return BuiltinParameterSpecs.extractBuiltinArgs( 347 node=node, 348 builtin_class=ExpressionBuiltinChr, 349 builtin_spec=BuiltinParameterSpecs.builtin_chr_spec, 350 ) 351 352 353def ord_extractor(node): 354 def makeOrd0(source_ref): 355 # pylint: disable=unused-argument 356 357 return makeRaiseExceptionReplacementExpressionFromInstance( 358 expression=node, 359 exception=TypeError("ord() takes exactly one argument (0 given)"), 360 ) 361 362 return BuiltinParameterSpecs.extractBuiltinArgs( 363 node=node, 364 builtin_class=ExpressionBuiltinOrd, 365 builtin_spec=BuiltinParameterSpecs.builtin_ord_spec, 366 empty_special_class=makeOrd0, 367 ) 368 369 370def bin_extractor(node): 371 return BuiltinParameterSpecs.extractBuiltinArgs( 372 node=node, 373 builtin_class=ExpressionBuiltinBin, 374 builtin_spec=BuiltinParameterSpecs.builtin_bin_spec, 375 ) 376 377 378def oct_extractor(node): 379 return BuiltinParameterSpecs.extractBuiltinArgs( 380 node=node, 381 builtin_class=ExpressionBuiltinOct, 382 builtin_spec=BuiltinParameterSpecs.builtin_oct_spec, 383 ) 384 385 386def hex_extractor(node): 387 return BuiltinParameterSpecs.extractBuiltinArgs( 388 node=node, 389 builtin_class=ExpressionBuiltinHex, 390 builtin_spec=BuiltinParameterSpecs.builtin_hex_spec, 391 ) 392 393 394def id_extractor(node): 395 return BuiltinParameterSpecs.extractBuiltinArgs( 396 node=node, 397 builtin_class=ExpressionBuiltinId, 398 builtin_spec=BuiltinParameterSpecs.builtin_id_spec, 399 ) 400 401 402def repr_extractor(node): 403 return BuiltinParameterSpecs.extractBuiltinArgs( 404 node=node, 405 builtin_class=ExpressionOperationUnaryRepr, 406 builtin_spec=BuiltinParameterSpecs.builtin_repr_spec, 407 ) 408 409 410if python_version >= 0x300: 411 412 def ascii_extractor(node): 413 return BuiltinParameterSpecs.extractBuiltinArgs( 414 node=node, 415 builtin_class=ExpressionBuiltinAscii, 416 builtin_spec=BuiltinParameterSpecs.builtin_repr_spec, 417 ) 418 419 420def range_extractor(node): 421 def selectRangeBuiltin(low, high, step, source_ref): 422 if high is None: 423 return ExpressionBuiltinRange1(low=low, source_ref=source_ref) 424 elif step is None: 425 return ExpressionBuiltinRange2(low=low, high=high, source_ref=source_ref) 426 else: 427 return ExpressionBuiltinRange3( 428 low=low, high=high, step=step, source_ref=source_ref 429 ) 430 431 def makeRange0(source_ref): 432 # pylint: disable=unused-argument 433 try: 434 range() 435 except Exception as e: # We want to broad here, pylint: disable=broad-except 436 return makeRaiseExceptionReplacementExpressionFromInstance( 437 expression=node, exception=e 438 ) 439 else: 440 raise NuitkaAssumptionError("range without argument is expected to raise") 441 442 return BuiltinParameterSpecs.extractBuiltinArgs( 443 node=node, 444 builtin_class=selectRangeBuiltin, 445 builtin_spec=BuiltinParameterSpecs.builtin_range_spec, 446 empty_special_class=makeRange0, 447 ) 448 449 450def xrange_extractor(node): 451 def selectXrangeBuiltin(low, high, step, source_ref): 452 if high is None: 453 return ExpressionBuiltinXrange1(low=low, source_ref=source_ref) 454 elif step is None: 455 return ExpressionBuiltinXrange2(low=low, high=high, source_ref=source_ref) 456 else: 457 return ExpressionBuiltinXrange3( 458 low=low, high=high, step=step, source_ref=source_ref 459 ) 460 461 def makeXrange0(source_ref): 462 # pylint: disable=unused-argument 463 try: 464 xrange() 465 except Exception as e: # We want to broad here, pylint: disable=broad-except 466 return makeRaiseExceptionReplacementExpressionFromInstance( 467 expression=node, exception=e 468 ) 469 else: 470 raise NuitkaAssumptionError("range without argument is expected to raise") 471 472 return BuiltinParameterSpecs.extractBuiltinArgs( 473 node=node, 474 builtin_class=selectXrangeBuiltin, 475 builtin_spec=BuiltinParameterSpecs.builtin_xrange_spec, 476 empty_special_class=makeXrange0, 477 ) 478 479 480def len_extractor(node): 481 return BuiltinParameterSpecs.extractBuiltinArgs( 482 node=node, 483 builtin_class=ExpressionBuiltinLen, 484 builtin_spec=BuiltinParameterSpecs.builtin_len_spec, 485 ) 486 487 488def all_extractor(node): 489 # pylint: disable=unused-argument 490 def makeAll0(source_ref): 491 exception_message = "all() takes exactly one argument (0 given)" 492 493 return makeRaiseExceptionReplacementExpressionFromInstance( 494 expression=node, exception=TypeError(exception_message) 495 ) 496 497 return BuiltinParameterSpecs.extractBuiltinArgs( 498 node=node, 499 builtin_class=ExpressionBuiltinAll, 500 builtin_spec=BuiltinParameterSpecs.builtin_all_spec, 501 empty_special_class=makeAll0, 502 ) 503 504 505def abs_extractor(node): 506 return BuiltinParameterSpecs.extractBuiltinArgs( 507 node=node, 508 builtin_class=ExpressionOperationUnaryAbs, 509 builtin_spec=BuiltinParameterSpecs.builtin_abs_spec, 510 ) 511 512 513def any_extractor(node): 514 # pylint: disable=unused-argument 515 def makeAny0(source_ref): 516 exception_message = "any() takes exactly one argument (0 given)" 517 518 return makeRaiseExceptionReplacementExpressionFromInstance( 519 expression=node, exception=TypeError(exception_message) 520 ) 521 522 return BuiltinParameterSpecs.extractBuiltinArgs( 523 node=node, 524 builtin_class=ExpressionBuiltinAny, 525 builtin_spec=BuiltinParameterSpecs.builtin_any_spec, 526 empty_special_class=makeAny0, 527 ) 528 529 530def tuple_extractor(node): 531 return BuiltinParameterSpecs.extractBuiltinArgs( 532 node=node, 533 builtin_class=ExpressionBuiltinTuple, 534 builtin_spec=BuiltinParameterSpecs.builtin_tuple_spec, 535 ) 536 537 538def list_extractor(node): 539 return BuiltinParameterSpecs.extractBuiltinArgs( 540 node=node, 541 builtin_class=ExpressionBuiltinList, 542 builtin_spec=BuiltinParameterSpecs.builtin_list_spec, 543 ) 544 545 546def set_extractor(node): 547 return BuiltinParameterSpecs.extractBuiltinArgs( 548 node=node, 549 builtin_class=ExpressionBuiltinSet, 550 builtin_spec=BuiltinParameterSpecs.builtin_set_spec, 551 ) 552 553 554def frozenset_extractor(node): 555 return BuiltinParameterSpecs.extractBuiltinArgs( 556 node=node, 557 builtin_class=ExpressionBuiltinFrozenset, 558 builtin_spec=BuiltinParameterSpecs.builtin_frozenset_spec, 559 ) 560 561 562def float_extractor(node): 563 def makeFloat0(source_ref): 564 # pylint: disable=unused-argument 565 566 return makeConstantReplacementNode( 567 constant=float(), node=node, user_provided=False 568 ) 569 570 return BuiltinParameterSpecs.extractBuiltinArgs( 571 node=node, 572 builtin_class=ExpressionBuiltinFloat, 573 builtin_spec=BuiltinParameterSpecs.builtin_float_spec, 574 empty_special_class=makeFloat0, 575 ) 576 577 578def complex_extractor(node): 579 def makeComplex0(source_ref): 580 # pylint: disable=unused-argument 581 582 return makeConstantReplacementNode( 583 constant=complex(), node=node, user_provided=False 584 ) 585 586 def selectComplexBuiltin(real, imag, source_ref): 587 if imag is None: 588 return ExpressionBuiltinComplex1(value=real, source_ref=source_ref) 589 else: 590 return ExpressionBuiltinComplex2( 591 real=real, imag=imag, source_ref=source_ref 592 ) 593 594 return BuiltinParameterSpecs.extractBuiltinArgs( 595 node=node, 596 builtin_class=selectComplexBuiltin, 597 builtin_spec=BuiltinParameterSpecs.builtin_complex_spec, 598 empty_special_class=makeComplex0, 599 ) 600 601 602def str_extractor(node): 603 builtin_class = ExpressionBuiltinStrP2 if str is bytes else ExpressionBuiltinStrP3 604 605 return BuiltinParameterSpecs.extractBuiltinArgs( 606 node=node, 607 builtin_class=builtin_class, 608 builtin_spec=builtin_class.builtin_spec, 609 ) 610 611 612if python_version < 0x300: 613 614 def unicode_extractor(node): 615 return BuiltinParameterSpecs.extractBuiltinArgs( 616 node=node, 617 builtin_class=ExpressionBuiltinUnicodeP2, 618 builtin_spec=ExpressionBuiltinUnicodeP2.builtin_spec, 619 ) 620 621 622else: 623 from nuitka.nodes.BuiltinTypeNodes import ( 624 ExpressionBuiltinBytes1, 625 ExpressionBuiltinBytes3, 626 ) 627 628 def bytes_extractor(node): 629 def makeBytes0(source_ref): 630 # pylint: disable=unused-argument 631 632 return makeConstantReplacementNode( 633 constant=bytes(), node=node, user_provided=False 634 ) 635 636 def selectBytesBuiltin(string, encoding, errors, source_ref): 637 if encoding is None and errors is None: 638 return ExpressionBuiltinBytes1(value=string, source_ref=source_ref) 639 else: 640 return ExpressionBuiltinBytes3( 641 value=string, 642 encoding=encoding, 643 errors=errors, 644 source_ref=source_ref, 645 ) 646 647 return BuiltinParameterSpecs.extractBuiltinArgs( 648 node=node, 649 builtin_class=selectBytesBuiltin, 650 builtin_spec=BuiltinParameterSpecs.builtin_bytes_p3_spec, 651 empty_special_class=makeBytes0, 652 ) 653 654 655def bool_extractor(node): 656 def makeBool0(source_ref): 657 # pylint: disable=unused-argument 658 659 return makeConstantReplacementNode( 660 constant=bool(), node=node, user_provided=False 661 ) 662 663 return BuiltinParameterSpecs.extractBuiltinArgs( 664 node=node, 665 builtin_class=ExpressionBuiltinBool, 666 builtin_spec=BuiltinParameterSpecs.builtin_bool_spec, 667 empty_special_class=makeBool0, 668 ) 669 670 671def int_extractor(node): 672 def makeInt0(source_ref): 673 # pylint: disable=unused-argument 674 675 return makeConstantReplacementNode( 676 constant=int(), node=node, user_provided=False 677 ) 678 679 def selectIntBuiltin(value, base, source_ref): 680 if base is None: 681 return ExpressionBuiltinInt1(value=value, source_ref=source_ref) 682 else: 683 return ExpressionBuiltinInt2(value=value, base=base, source_ref=source_ref) 684 685 return BuiltinParameterSpecs.extractBuiltinArgs( 686 node=node, 687 builtin_class=selectIntBuiltin, 688 builtin_spec=BuiltinParameterSpecs.builtin_int_spec, 689 empty_special_class=makeInt0, 690 ) 691 692 693if python_version < 0x300: 694 from nuitka.nodes.BuiltinIntegerNodes import ( 695 ExpressionBuiltinLong1, 696 ExpressionBuiltinLong2, 697 ) 698 699 def long_extractor(node): 700 def makeLong0(source_ref): 701 # pylint: disable=unused-argument 702 703 return makeConstantReplacementNode( 704 constant=int(), node=node, user_provided=False 705 ) 706 707 def selectIntBuiltin(value, base, source_ref): 708 if base is None: 709 return ExpressionBuiltinLong1(value=value, source_ref=source_ref) 710 else: 711 return ExpressionBuiltinLong2( 712 value=value, base=base, source_ref=source_ref 713 ) 714 715 return BuiltinParameterSpecs.extractBuiltinArgs( 716 node=node, 717 builtin_class=selectIntBuiltin, 718 builtin_spec=BuiltinParameterSpecs.builtin_int_spec, 719 empty_special_class=makeLong0, 720 ) 721 722 723def globals_extractor(node): 724 return BuiltinParameterSpecs.extractBuiltinArgs( 725 node=node, 726 builtin_class=ExpressionBuiltinGlobals, 727 builtin_spec=BuiltinParameterSpecs.builtin_globals_spec, 728 ) 729 730 731def locals_extractor(node): 732 locals_scope = node.subnode_called.getLocalsScope() 733 734 def makeLocalsNode(source_ref): 735 return makeExpressionBuiltinLocals( 736 locals_scope=locals_scope, source_ref=source_ref 737 ) 738 739 # Note: Locals on the module level is really globals. 740 return BuiltinParameterSpecs.extractBuiltinArgs( 741 node=node, 742 builtin_class=makeLocalsNode, 743 builtin_spec=BuiltinParameterSpecs.builtin_locals_spec, 744 ) 745 746 747if python_version < 0x300: 748 from nuitka.nodes.ExecEvalNodes import ExpressionBuiltinExecfile 749 750 def execfile_extractor(node): 751 def wrapExpressionBuiltinExecfileCreation( 752 filename, globals_arg, locals_arg, source_ref 753 ): 754 outline_body = ExpressionOutlineBody( 755 provider=node.getParentVariableProvider(), 756 name="execfile_call", 757 source_ref=source_ref, 758 ) 759 760 globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals( 761 provider=node.getParentVariableProvider(), 762 globals_node=globals_arg, 763 locals_node=locals_arg, 764 temp_scope=outline_body.getOutlineTempScope(), 765 source_ref=source_ref, 766 ) 767 768 tried = makeStatementsSequence( 769 statements=( 770 tried, 771 makeStatementReturn( 772 expression=ExpressionBuiltinExecfile( 773 source_code=makeCallNode( 774 ExpressionAttributeLookup( 775 expression=ExpressionBuiltinOpen( 776 filename=filename, 777 mode=makeConstantRefNode( 778 constant="rU", source_ref=source_ref 779 ), 780 buffering=None, 781 source_ref=source_ref, 782 ), 783 attribute_name="read", 784 source_ref=source_ref, 785 ), 786 source_ref, 787 ), 788 globals_arg=globals_ref, 789 locals_arg=locals_ref, 790 source_ref=source_ref, 791 ), 792 source_ref=source_ref, 793 ), 794 ), 795 allow_none=False, 796 source_ref=source_ref, 797 ) 798 799 outline_body.setChild( 800 "body", 801 makeStatementsSequenceFromStatement( 802 statement=makeTryFinallyStatement( 803 provider=outline_body, 804 tried=tried, 805 final=final, 806 source_ref=source_ref, 807 ) 808 ), 809 ) 810 811 return outline_body 812 813 return BuiltinParameterSpecs.extractBuiltinArgs( 814 node=node, 815 builtin_class=wrapExpressionBuiltinExecfileCreation, 816 builtin_spec=BuiltinParameterSpecs.builtin_execfile_spec, 817 ) 818 819 820def eval_extractor(node): 821 def wrapEvalBuiltin(source, globals_arg, locals_arg, source_ref): 822 provider = node.getParentVariableProvider() 823 824 outline_body = ExpressionOutlineBody( 825 provider=node.getParentVariableProvider(), 826 name="eval_call", 827 source_ref=source_ref, 828 ) 829 830 globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals( 831 provider=provider, 832 globals_node=globals_arg, 833 locals_node=locals_arg, 834 temp_scope=outline_body.getOutlineTempScope(), 835 source_ref=source_ref, 836 ) 837 838 # The wrapping should not relocate to the "source_ref". 839 assert ( 840 globals_arg is None 841 or globals_ref.getSourceReference() == globals_arg.getSourceReference() 842 ) 843 assert ( 844 locals_arg is None 845 or locals_ref.getSourceReference() == locals_arg.getSourceReference() 846 ) 847 848 source_variable = outline_body.allocateTempVariable( 849 temp_scope=None, name="source" 850 ) 851 852 final.setChild( 853 "statements", 854 final.subnode_statements 855 + ( 856 StatementDelVariable( 857 variable=source_variable, tolerant=True, source_ref=source_ref 858 ), 859 ), 860 ) 861 862 strip_choice = makeConstantRefNode(constant=(" \t",), source_ref=source_ref) 863 864 if python_version >= 0x300: 865 strip_choice = ExpressionConditional( 866 condition=ExpressionComparisonIs( 867 left=ExpressionBuiltinType1( 868 value=ExpressionTempVariableRef( 869 variable=source_variable, source_ref=source_ref 870 ), 871 source_ref=source_ref, 872 ), 873 right=makeExpressionBuiltinTypeRef( 874 builtin_name="bytes", source_ref=source_ref 875 ), 876 source_ref=source_ref, 877 ), 878 expression_yes=makeConstantRefNode( 879 constant=(b" \t",), source_ref=source_ref 880 ), 881 expression_no=strip_choice, 882 source_ref=source_ref, 883 ) 884 885 # Source needs some special treatment for eval, if it's a string, it 886 # must be stripped. 887 string_fixup = StatementAssignmentVariable( 888 variable=source_variable, 889 source=makeExpressionCall( 890 called=ExpressionAttributeLookup( 891 expression=ExpressionTempVariableRef( 892 variable=source_variable, source_ref=source_ref 893 ), 894 attribute_name="strip", 895 source_ref=source_ref, 896 ), 897 args=strip_choice, # This is a tuple 898 kw=None, 899 source_ref=source_ref, 900 ), 901 source_ref=source_ref, 902 ) 903 904 acceptable_builtin_types = [ 905 ExpressionBuiltinAnonymousRef(builtin_name="code", source_ref=source_ref) 906 ] 907 908 if python_version >= 0x270: 909 acceptable_builtin_types.append( 910 makeExpressionBuiltinTypeRef( 911 builtin_name="memoryview", source_ref=source_ref 912 ) 913 ) 914 915 statements = ( 916 StatementAssignmentVariable( 917 variable=source_variable, source=source, source_ref=source_ref 918 ), 919 makeStatementConditional( 920 condition=ExpressionOperationNot( 921 operand=ExpressionBuiltinIsinstance( 922 instance=ExpressionTempVariableRef( 923 variable=source_variable, source_ref=source_ref 924 ), 925 classes=makeExpressionMakeTupleOrConstant( 926 elements=acceptable_builtin_types, 927 user_provided=True, 928 source_ref=source_ref, 929 ), 930 source_ref=source_ref, 931 ), 932 source_ref=source_ref, 933 ), 934 yes_branch=string_fixup, 935 no_branch=None, 936 source_ref=source_ref, 937 ), 938 makeStatementReturn( 939 expression=ExpressionBuiltinEval( 940 source_code=ExpressionTempVariableRef( 941 variable=source_variable, source_ref=source_ref 942 ), 943 globals_arg=globals_ref, 944 locals_arg=locals_ref, 945 source_ref=source_ref, 946 ), 947 source_ref=source_ref, 948 ), 949 ) 950 951 tried = makeStatementsSequence( 952 statements=(tried,) + statements, allow_none=False, source_ref=source_ref 953 ) 954 955 outline_body.setChild( 956 "body", 957 makeStatementsSequenceFromStatement( 958 statement=makeTryFinallyStatement( 959 provider=outline_body, 960 tried=tried, 961 final=final, 962 source_ref=source_ref, 963 ) 964 ), 965 ) 966 967 return outline_body 968 969 return BuiltinParameterSpecs.extractBuiltinArgs( 970 node=node, 971 builtin_class=wrapEvalBuiltin, 972 builtin_spec=BuiltinParameterSpecs.builtin_eval_spec, 973 ) 974 975 976if python_version >= 0x300: 977 from nuitka.nodes.ExecEvalNodes import ExpressionBuiltinExec 978 979 def exec_extractor(node): 980 def wrapExpressionBuiltinExecCreation( 981 source, globals_arg, locals_arg, source_ref 982 ): 983 provider = node.getParentVariableProvider() 984 985 outline_body = ExpressionOutlineBody( 986 provider=provider, name="exec_call", source_ref=source_ref 987 ) 988 989 globals_ref, locals_ref, tried, final = wrapEvalGlobalsAndLocals( 990 provider=provider, 991 globals_node=globals_arg, 992 locals_node=locals_arg, 993 temp_scope=outline_body.getOutlineTempScope(), 994 source_ref=source_ref, 995 ) 996 997 tried = makeStatementsSequence( 998 statements=( 999 tried, 1000 makeStatementReturn( 1001 expression=ExpressionBuiltinExec( 1002 source_code=source, 1003 globals_arg=globals_ref, 1004 locals_arg=locals_ref, 1005 source_ref=source_ref, 1006 ), 1007 source_ref=source_ref, 1008 ), 1009 ), 1010 allow_none=False, 1011 source_ref=source_ref, 1012 ) 1013 1014 # Hack: Allow some APIs to work already 1015 tried.parent = outline_body 1016 1017 outline_body.setChild( 1018 "body", 1019 makeStatementsSequenceFromStatement( 1020 statement=makeTryFinallyStatement( 1021 provider=provider, 1022 tried=tried, 1023 final=final, 1024 source_ref=source_ref, 1025 ) 1026 ), 1027 ) 1028 1029 return outline_body 1030 1031 return BuiltinParameterSpecs.extractBuiltinArgs( 1032 node=node, 1033 builtin_class=wrapExpressionBuiltinExecCreation, 1034 builtin_spec=BuiltinParameterSpecs.builtin_eval_spec, 1035 ) 1036 1037 1038def compile_extractor(node): 1039 def wrapExpressionBuiltinCompileCreation( 1040 source_code, filename, mode, flags, dont_inherit, optimize=None, source_ref=None 1041 ): 1042 return ExpressionBuiltinCompile( 1043 source_code=source_code, 1044 filename=filename, 1045 mode=mode, 1046 flags=flags, 1047 dont_inherit=dont_inherit, 1048 optimize=optimize, 1049 source_ref=source_ref, 1050 ) 1051 1052 return BuiltinParameterSpecs.extractBuiltinArgs( 1053 node=node, 1054 builtin_class=wrapExpressionBuiltinCompileCreation, 1055 builtin_spec=BuiltinParameterSpecs.builtin_compile_spec, 1056 ) 1057 1058 1059def open_extractor(node): 1060 def makeOpen0(source_ref): 1061 # pylint: disable=unused-argument 1062 try: 1063 open() 1064 except Exception as e: # We want to broad here, pylint: disable=broad-except 1065 return makeRaiseExceptionReplacementExpressionFromInstance( 1066 expression=node, exception=e 1067 ) 1068 else: 1069 raise NuitkaAssumptionError("open without argument is expected to raise") 1070 1071 return BuiltinParameterSpecs.extractBuiltinArgs( 1072 node=node, 1073 builtin_class=ExpressionBuiltinOpen, 1074 builtin_spec=BuiltinParameterSpecs.builtin_open_spec, 1075 empty_special_class=makeOpen0, 1076 ) 1077 1078 1079def super_extractor(node): 1080 def wrapSuperBuiltin(type_arg, object_arg, source_ref): 1081 if type_arg is None and python_version >= 0x300: 1082 if provider.isCompiledPythonModule(): 1083 return makeRaiseExceptionReplacementExpression( 1084 expression=node, 1085 exception_type="RuntimeError", 1086 exception_value="super(): no arguments", 1087 ) 1088 1089 class_variable = provider.getVariableForReference(variable_name="__class__") 1090 1091 provider.trace_collection.getVariableCurrentTrace(class_variable).addUsage() 1092 1093 type_arg = ExpressionVariableRef( 1094 # Ought to be already closure taken due to "super" flag in 1095 # tree building. 1096 variable=class_variable, 1097 source_ref=source_ref, 1098 ) 1099 1100 # If we already have this as a local variable, then use that 1101 # instead. 1102 type_arg_owner = class_variable.getOwner() 1103 if type_arg_owner is provider or not ( 1104 type_arg_owner.isExpressionFunctionBody() 1105 or type_arg_owner.isExpressionClassBody() 1106 ): 1107 return makeRaiseExceptionReplacementExpression( 1108 expression=node, 1109 exception_type="SystemError" 1110 if python_version < 0x331 1111 else "RuntimeError", 1112 exception_value="super(): __class__ cell not found", 1113 ) 1114 1115 if object_arg is None: 1116 if ( 1117 provider.isExpressionGeneratorObjectBody() 1118 or provider.isExpressionCoroutineObjectBody() 1119 or provider.isExpressionAsyncgenObjectBody() 1120 ): 1121 parameter_provider = provider.getParentVariableProvider() 1122 else: 1123 parameter_provider = provider 1124 1125 if parameter_provider.getParameters().getArgumentCount() == 0: 1126 return makeRaiseExceptionReplacementExpression( 1127 expression=node, 1128 exception_type="RuntimeError", 1129 exception_value="super(): no arguments", 1130 ) 1131 else: 1132 par1_name = parameter_provider.getParameters().getArgumentNames()[0] 1133 1134 object_variable = provider.getVariableForReference( 1135 variable_name=par1_name 1136 ) 1137 1138 provider.trace_collection.getVariableCurrentTrace( 1139 object_variable 1140 ).addUsage() 1141 1142 object_arg = ExpressionVariableRef( 1143 variable=object_variable, source_ref=source_ref 1144 ) 1145 1146 if not object_arg.getVariable().isParameterVariable(): 1147 return makeRaiseExceptionReplacementExpression( 1148 expression=node, 1149 exception_type="SystemError" 1150 if python_version < 0x300 1151 else "RuntimeError", 1152 exception_value="super(): __class__ cell not found", 1153 ) 1154 1155 return ExpressionBuiltinSuper0( 1156 type_arg=type_arg, object_arg=object_arg, source_ref=source_ref 1157 ) 1158 1159 return ExpressionBuiltinSuper2( 1160 type_arg=type_arg, object_arg=object_arg, source_ref=source_ref 1161 ) 1162 1163 provider = node.getParentVariableProvider().getEntryPoint() 1164 1165 if not provider.isCompiledPythonModule(): 1166 provider.discardFlag("has_super") 1167 1168 return BuiltinParameterSpecs.extractBuiltinArgs( 1169 node=node, 1170 builtin_class=wrapSuperBuiltin, 1171 builtin_spec=BuiltinParameterSpecs.builtin_super_spec, 1172 ) 1173 1174 1175def hasattr_extractor(node): 1176 # We need to have to builtin arguments, pylint: disable=redefined-builtin 1177 def makeExpressionBuiltinHasattr(object, name, source_ref): 1178 return ExpressionBuiltinHasattr( 1179 expression=object, name=name, source_ref=source_ref 1180 ) 1181 1182 return BuiltinParameterSpecs.extractBuiltinArgs( 1183 node=node, 1184 builtin_class=makeExpressionBuiltinHasattr, 1185 builtin_spec=BuiltinParameterSpecs.builtin_hasattr_spec, 1186 ) 1187 1188 1189def getattr_extractor(node): 1190 # We need to have to builtin arguments, pylint: disable=redefined-builtin 1191 def makeExpressionBuiltinGetattr(object, name, default, source_ref): 1192 return ExpressionBuiltinGetattr( 1193 expression=object, name=name, default=default, source_ref=source_ref 1194 ) 1195 1196 return BuiltinParameterSpecs.extractBuiltinArgs( 1197 node=node, 1198 builtin_class=makeExpressionBuiltinGetattr, 1199 builtin_spec=BuiltinParameterSpecs.builtin_getattr_spec, 1200 ) 1201 1202 1203def setattr_extractor(node): 1204 # We need to have to builtin arguments, pylint: disable=redefined-builtin 1205 def makeExpressionBuiltinSetattr(object, name, value, source_ref): 1206 return ExpressionBuiltinSetattr( 1207 expression=object, name=name, value=value, source_ref=source_ref 1208 ) 1209 1210 return BuiltinParameterSpecs.extractBuiltinArgs( 1211 node=node, 1212 builtin_class=makeExpressionBuiltinSetattr, 1213 builtin_spec=BuiltinParameterSpecs.builtin_setattr_spec, 1214 ) 1215 1216 1217def isinstance_extractor(node): 1218 return BuiltinParameterSpecs.extractBuiltinArgs( 1219 node=node, 1220 builtin_class=ExpressionBuiltinIsinstance, 1221 builtin_spec=BuiltinParameterSpecs.builtin_isinstance_spec, 1222 ) 1223 1224 1225def issubclass_extractor(node): 1226 return BuiltinParameterSpecs.extractBuiltinArgs( 1227 node=node, 1228 builtin_class=ExpressionBuiltinIssubclass, 1229 builtin_spec=BuiltinParameterSpecs.builtin_isinstance_spec, 1230 ) 1231 1232 1233def bytearray_extractor(node): 1234 def makeBytearray0(source_ref): 1235 return makeConstantRefNode(constant=bytearray(), source_ref=source_ref) 1236 1237 def selectNextBuiltinClass(string, encoding, errors, source_ref): 1238 if encoding is None: 1239 return ExpressionBuiltinBytearray1(value=string, source_ref=source_ref) 1240 else: 1241 return ExpressionBuiltinBytearray3( 1242 string=string, encoding=encoding, errors=errors, source_ref=source_ref 1243 ) 1244 1245 return BuiltinParameterSpecs.extractBuiltinArgs( 1246 node=node, 1247 builtin_class=selectNextBuiltinClass, 1248 builtin_spec=BuiltinParameterSpecs.builtin_bytearray_spec, 1249 empty_special_class=makeBytearray0, 1250 ) 1251 1252 1253def slice_extractor(node): 1254 def wrapSlice(start, stop, step, source_ref): 1255 if start is not None and stop is None: 1256 # Default rules are strange. If one argument is given, it's the 1257 # second one then. 1258 stop = start 1259 start = None 1260 1261 return makeExpressionBuiltinSlice( 1262 start=start, stop=stop, step=step, source_ref=source_ref 1263 ) 1264 1265 return BuiltinParameterSpecs.extractBuiltinArgs( 1266 node=node, 1267 builtin_class=wrapSlice, 1268 builtin_spec=BuiltinParameterSpecs.builtin_slice_spec, 1269 ) 1270 1271 1272def hash_extractor(node): 1273 return BuiltinParameterSpecs.extractBuiltinArgs( 1274 node=node, 1275 builtin_class=ExpressionBuiltinHash, 1276 builtin_spec=BuiltinParameterSpecs.builtin_hash_spec, 1277 ) 1278 1279 1280def format_extractor(node): 1281 def makeFormat0(source_ref): 1282 # pylint: disable=unused-argument 1283 1284 return makeRaiseExceptionReplacementExpressionFromInstance( 1285 expression=node, 1286 exception=TypeError("format() takes at least 1 argument (0 given)"), 1287 ) 1288 1289 return BuiltinParameterSpecs.extractBuiltinArgs( 1290 node=node, 1291 builtin_class=ExpressionBuiltinFormat, 1292 builtin_spec=BuiltinParameterSpecs.builtin_format_spec, 1293 empty_special_class=makeFormat0, 1294 ) 1295 1296 1297def staticmethod_extractor(node): 1298 def makeStaticmethod0(source_ref): 1299 # pylint: disable=unused-argument 1300 1301 return makeRaiseExceptionReplacementExpressionFromInstance( 1302 expression=node, 1303 exception=TypeError("staticmethod expected 1 arguments, got 0"), 1304 ) 1305 1306 return BuiltinParameterSpecs.extractBuiltinArgs( 1307 node=node, 1308 builtin_class=ExpressionBuiltinStaticmethod, 1309 builtin_spec=BuiltinParameterSpecs.builtin_staticmethod_spec, 1310 empty_special_class=makeStaticmethod0, 1311 ) 1312 1313 1314def classmethod_extractor(node): 1315 def makeStaticmethod0(source_ref): 1316 # pylint: disable=unused-argument 1317 1318 return makeRaiseExceptionReplacementExpressionFromInstance( 1319 expression=node, 1320 exception=TypeError("classmethod expected 1 arguments, got 0"), 1321 ) 1322 1323 return BuiltinParameterSpecs.extractBuiltinArgs( 1324 node=node, 1325 builtin_class=ExpressionBuiltinClassmethod, 1326 builtin_spec=BuiltinParameterSpecs.builtin_classmethod_spec, 1327 empty_special_class=makeStaticmethod0, 1328 ) 1329 1330 1331def divmod_extractor(node): 1332 return BuiltinParameterSpecs.extractBuiltinArgs( 1333 node=node, 1334 builtin_class=ExpressionOperationBinaryDivmod, 1335 builtin_spec=BuiltinParameterSpecs.builtin_divmod_spec, 1336 ) 1337 1338 1339_dispatch_dict = { 1340 "compile": compile_extractor, 1341 "globals": globals_extractor, 1342 "locals": locals_extractor, 1343 "eval": eval_extractor, 1344 "dir": dir_extractor, 1345 "vars": vars_extractor, 1346 "__import__": import_extractor, 1347 "chr": chr_extractor, 1348 "ord": ord_extractor, 1349 "bin": bin_extractor, 1350 "oct": oct_extractor, 1351 "hex": hex_extractor, 1352 "id": id_extractor, 1353 "type": type_extractor, 1354 "iter": iter_extractor, 1355 "next": next_extractor, 1356 "sum": sum_extractor, 1357 "tuple": tuple_extractor, 1358 "list": list_extractor, 1359 "dict": dict_extractor, 1360 "set": set_extractor, 1361 "frozenset": frozenset_extractor, 1362 "float": float_extractor, 1363 "complex": complex_extractor, 1364 "str": str_extractor, 1365 "bool": bool_extractor, 1366 "int": int_extractor, 1367 "repr": repr_extractor, 1368 "len": len_extractor, 1369 "any": any_extractor, 1370 "abs": abs_extractor, 1371 "all": all_extractor, 1372 "super": super_extractor, 1373 "hasattr": hasattr_extractor, 1374 "getattr": getattr_extractor, 1375 "setattr": setattr_extractor, 1376 "isinstance": isinstance_extractor, 1377 "issubclass": issubclass_extractor, 1378 "bytearray": bytearray_extractor, 1379 "slice": slice_extractor, 1380 "hash": hash_extractor, 1381 "format": format_extractor, 1382 "open": open_extractor, 1383 "staticmethod": staticmethod_extractor, 1384 "classmethod": classmethod_extractor, 1385 "divmod": divmod_extractor, 1386} 1387 1388if python_version < 0x300: 1389 # These are not in Python3 1390 _dispatch_dict["long"] = long_extractor 1391 _dispatch_dict["unicode"] = unicode_extractor 1392 _dispatch_dict["execfile"] = execfile_extractor 1393 _dispatch_dict["xrange"] = xrange_extractor 1394 1395 _dispatch_dict["range"] = range_extractor 1396else: 1397 # This one is not in Python2: 1398 _dispatch_dict["bytes"] = bytes_extractor 1399 _dispatch_dict["ascii"] = ascii_extractor 1400 _dispatch_dict["exec"] = exec_extractor 1401 1402 # The Python3 range is really an xrange, use that. 1403 _dispatch_dict["range"] = xrange_extractor 1404 1405 1406def check(): 1407 from nuitka.Builtins import builtin_names 1408 1409 for builtin_name in _dispatch_dict: 1410 assert builtin_name in builtin_names, builtin_name 1411 1412 1413check() 1414 1415_builtin_ignore_list = ( 1416 # Not supporting 'print', because it could be replaced, and is not 1417 # worth the effort yet. 1418 "print", 1419 # TODO: This could, and should be supported, as we could e.g. lower 1420 # types easily for it. 1421 "sorted", 1422 # TODO: This would be very worthwhile, as it could easily optimize 1423 # its iteration away. 1424 "zip", 1425 # TODO: This would be most precious due to the type hint it gives 1426 "enumerate", 1427 # TODO: Also worthwhile for known values. 1428 "reversed", 1429 # TODO: Not sure what this really is about. 1430 "memoryview", 1431) 1432 1433 1434def _describeNewNode(builtin_name, inspect_node): 1435 """Describe the change for better understanding.""" 1436 1437 # Don't mention side effects, that's not what we care about. 1438 if inspect_node.isExpressionSideEffects(): 1439 inspect_node = inspect_node.subnode_expression 1440 1441 if inspect_node.isExpressionBuiltinImport(): 1442 tags = "new_import" 1443 message = """\ 1444Replaced dynamic "__import__" call with static built-in call.""" 1445 elif inspect_node.isExpressionBuiltin() or inspect_node.isStatementExec(): 1446 tags = "new_builtin" 1447 message = "Replaced call to built-in '%s' with built-in call '%s'." % ( 1448 builtin_name, 1449 inspect_node.kind, 1450 ) 1451 elif inspect_node.isExpressionRaiseException(): 1452 tags = "new_raise" 1453 message = """\ 1454Replaced call to built-in '%s' with exception raise.""" % ( 1455 builtin_name, 1456 ) 1457 elif inspect_node.isExpressionOperationBinary(): 1458 tags = "new_expression" 1459 message = """\ 1460Replaced call to built-in '%s' with binary operation '%s'.""" % ( 1461 builtin_name, 1462 inspect_node.getOperator(), 1463 ) 1464 elif inspect_node.isExpressionOperationUnary(): 1465 tags = "new_expression" 1466 message = """\ 1467Replaced call to built-in '%s' with unary operation '%s'.""" % ( 1468 builtin_name, 1469 inspect_node.getOperator(), 1470 ) 1471 elif inspect_node.isExpressionCall(): 1472 tags = "new_expression" 1473 message = """\ 1474Replaced call to built-in '%s' with call.""" % ( 1475 builtin_name, 1476 ) 1477 elif inspect_node.isExpressionOutlineBody(): 1478 tags = "new_expression" 1479 message = ( 1480 """\ 1481Replaced call to built-in '%s' with outlined call.""" 1482 % builtin_name 1483 ) 1484 elif inspect_node.isExpressionConstantRef(): 1485 tags = "new_expression" 1486 message = ( 1487 """\ 1488Replaced call to built-in '%s' with constant value.""" 1489 % builtin_name 1490 ) 1491 else: 1492 assert False, (builtin_name, "->", inspect_node) 1493 1494 return tags, message 1495 1496 1497def computeBuiltinCall(builtin_name, call_node): 1498 # There is some dispatching for how to output various types of changes, 1499 # with lots of cases. 1500 if builtin_name in _dispatch_dict: 1501 new_node = _dispatch_dict[builtin_name](call_node) 1502 1503 assert new_node is not call_node, builtin_name 1504 assert new_node is not None, builtin_name 1505 1506 # For traces, we are going to ignore side effects, and output traces 1507 # only based on the basis of it. 1508 tags, message = _describeNewNode(builtin_name, new_node) 1509 1510 return new_node, tags, message 1511 else: 1512 # TODO: Achieve coverage of all built-ins in at least the ignore list. 1513 # if False and builtin_name not in _builtin_ignore_list: 1514 # optimization_logger.warning( 1515 # "Not handling built-in %r, consider support." % builtin_name 1516 # ) 1517 1518 return call_node, None, None 1519