Lichen

internal_tests/branches.py

90:c7ddfc4525da
2016-10-08 Paul Boddie Added some support for eliminating accessor class types where the provided attributes are invoked and are unbound methods. This uses a more sophisticated method involving usage observations that incorporate invocation information, permitting classes as accessors if paths through the code support them, even if other paths require instances as accessors to invoke methods.
     1 #!/usr/bin/env python     2      3 import branching     4      5 names = []     6      7 # Equivalent to...     8 #     9 # a = ...    10 # a.p    11 # if ...:    12 #   a = ...    13 #   a.x    14 # else:    15 #   ...    16 # a.q    17     18 bt = branching.BranchTracker()    19 a1 = bt.assign_names(["a"])    20 bt.use_attribute("a", "p")    21 bt.new_branchpoint()                # begin    22 bt.new_branch()                     # if ...    23 a2 = bt.assign_names(["a"])         # a = ...    24 ax = bt.use_attribute("a", "x")    25 bt.shelve_branch()    26 bt.new_branch()                     # else    27 bt.shelve_branch()    28 bt.merge_branches()                 # end    29 aq = bt.use_attribute("a", "q")    30     31 print a1.get_usage() == \    32     {'a' : set([('p',), ('p', 'q')])}, \    33     a1.get_usage()    34 print a2.get_usage() == \    35     {'a' : set([('q', 'x')])}, \    36     a2.get_usage()    37 print bt.get_assignment_positions_for_branches("a", ax) == [1], \    38     bt.get_assignment_positions_for_branches("a", ax)    39 print bt.get_assignment_positions_for_branches("a", aq) == [0, 1], \    40     bt.get_assignment_positions_for_branches("a", aq)    41 names.append(bt.assignments["a"])    42     43 # Equivalent to...    44 #    45 # a = ...    46 # a.p    47 # if ...:    48 #   a.x    49 # elif ...:    50 #   a.y; a.z    51 # else:    52 #   ...    53 # a.q    54     55 bt = branching.BranchTracker()    56 a = bt.assign_names(["a"])    57 bt.use_attribute("a", "p")    58 bt.new_branchpoint()                # begin    59 bt.new_branch()                     # if ...    60 ax = bt.use_attribute("a", "x")    61 bt.shelve_branch()    62 bt.new_branch()                     # elif ...    63 ay = bt.use_attribute("a", "y")    64 az = bt.use_attribute("a", "z")    65 bt.shelve_branch()    66 bt.new_branch()                     # else    67 bt.shelve_branch()    68 bt.merge_branches()                 # end    69 bt.use_attribute("a", "q")    70     71 print a.get_usage() == \    72     {'a' : set([('p', 'q'), ('p', 'q', 'x'), ('p', 'q', 'y', 'z')])}, \    73     a.get_usage()    74 print bt.get_assignment_positions_for_branches("a", ax) == [0], \    75     bt.get_assignment_positions_for_branches("a", ax)    76 print bt.get_assignment_positions_for_branches("a", ay) == [0], \    77     bt.get_assignment_positions_for_branches("a", ay)    78 print bt.get_assignment_positions_for_branches("a", az) == [0], \    79     bt.get_assignment_positions_for_branches("a", az)    80 names.append(bt.assignments["a"])    81     82 # Equivalent to...    83 #    84 # a = ...    85 # a.p    86 # while ...:    87 #   a.x    88 # a.q    89     90 bt = branching.BranchTracker()    91 a = bt.assign_names(["a"])    92 bt.use_attribute("a", "p")    93 bt.new_branchpoint(True)            # begin    94 bt.new_branch(True)                 # while ...    95 ax = bt.use_attribute("a", "x")    96 bt.resume_continuing_branches()    97 bt.shelve_branch(True)    98 bt.new_branch()                     # (null)    99 bt.shelve_branch()   100 bt.merge_branches()                 # end   101 bt.resume_broken_branches()   102 bt.use_attribute("a", "q")   103    104 print a.get_usage() == \   105     {'a' : set([('p', 'q'), ('p', 'q', 'x')])}, a.get_usage()   106 print bt.get_assignment_positions_for_branches("a", ax) == [0], \   107     bt.get_assignment_positions_for_branches("a", ax)   108 names.append(bt.assignments["a"])   109    110 # Equivalent to...   111 #   112 # a = ...   113 # a.p   114 # while ...:   115 #   if ...:   116 #     a.x   117 #   else ...:   118 #     a.y   119 # a.q   120    121 bt = branching.BranchTracker()   122 a = bt.assign_names(["a"])   123 bt.use_attribute("a", "p")   124 bt.new_branchpoint(True)            # begin   125 bt.new_branch(True)                 # while ...   126 bt.new_branchpoint()                # begin   127 bt.new_branch()                     # if ...   128 ax = bt.use_attribute("a", "x")   129 bt.shelve_branch()   130 bt.new_branch()   131 ay = bt.use_attribute("a", "y")   132 bt.shelve_branch()   133 bt.merge_branches()                 # end   134 bt.resume_continuing_branches()   135 bt.shelve_branch(True)   136 bt.new_branch()                     # (null)   137 bt.shelve_branch()   138 bt.merge_branches()                 # end   139 bt.resume_broken_branches()   140 bt.use_attribute("a", "q")   141    142 print a.get_usage() == \   143     {'a' : set([('p', 'q'), ('p', 'q', 'x'), ('p', 'q', 'y')])}, \   144     a.get_usage()   145 print bt.get_assignment_positions_for_branches("a", ax) == [0], \   146     bt.get_assignment_positions_for_branches("a", ax)   147 print bt.get_assignment_positions_for_branches("a", ay) == [0], \   148     bt.get_assignment_positions_for_branches("a", ay)   149 names.append(bt.assignments["a"])   150    151 # Equivalent to...   152 #   153 # a = ...   154 # a.p   155 # while ...:   156 #   if ...:   157 #     a = ...   158 #     a.x   159 #   else ...:   160 #     a.y   161 # a.q   162    163 bt = branching.BranchTracker()   164 a1 = bt.assign_names(["a"])   165 bt.use_attribute("a", "p")   166 bt.new_branchpoint(True)            # begin   167 bt.new_branch(True)                 # while ...   168 bt.new_branchpoint()                # begin   169 bt.new_branch()                     # if ...   170 a2 = bt.assign_names(["a"])         # a = ...   171 ax = bt.use_attribute("a", "x")   172 bt.shelve_branch()   173 bt.new_branch()   174 ay = bt.use_attribute("a", "y")   175 bt.shelve_branch()   176 bt.merge_branches()                 # end   177 bt.resume_continuing_branches()   178 bt.shelve_branch(True)   179 bt.new_branch()                     # (null)   180 bt.shelve_branch()   181 bt.merge_branches()                 # end   182 bt.resume_broken_branches()   183 bt.use_attribute("a", "q")   184    185 print a1.get_usage() == \   186     {'a' : set([('p', 'q'), ('p', 'q', 'y'), ('p',)])}, a1.get_usage()   187 print a2.get_usage() == \   188     {'a' : set([('q', 'x')])}, a2.get_usage()   189 print bt.get_assignment_positions_for_branches("a", ax) == [1], \   190     bt.get_assignment_positions_for_branches("a", ax)   191 print bt.get_assignment_positions_for_branches("a", ay) == [0, 1], \   192     bt.get_assignment_positions_for_branches("a", ay)   193 names.append(bt.assignments["a"])   194    195 # Equivalent to...   196 #   197 # a = ...   198 # a.p   199 # while ...:   200 #   if ...:   201 #     a.y   202 #   else ...:   203 #     a = ...   204 #     a.x   205 # a.q   206    207 bt = branching.BranchTracker()   208 a1 = bt.assign_names(["a"])   209 bt.use_attribute("a", "p")   210 bt.new_branchpoint(True)            # begin   211 bt.new_branch(True)                 # while ...   212 bt.new_branchpoint()                # begin   213 bt.new_branch()                     # if ...   214 ay = bt.use_attribute("a", "y")   215 bt.shelve_branch()   216 bt.new_branch()   217 a2 = bt.assign_names(["a"])         # a = ...   218 ax = bt.use_attribute("a", "x")   219 bt.shelve_branch()   220 bt.merge_branches()                 # end   221 bt.resume_continuing_branches()   222 bt.shelve_branch(True)   223 bt.new_branch()                     # (null)   224 bt.shelve_branch()   225 bt.merge_branches()                 # end   226 bt.resume_broken_branches()   227 bt.use_attribute("a", "q")   228    229 print a1.get_usage() == \   230     {'a' : set([('p', 'q'), ('p', 'q', 'y'), ('p',)])}, a1.get_usage()   231 print a2.get_usage() == \   232     {'a' : set([('q', 'x')])}, a2.get_usage()   233 print bt.get_assignment_positions_for_branches("a", ax) == [1], \   234     bt.get_assignment_positions_for_branches("a", ax)   235 print bt.get_assignment_positions_for_branches("a", ay) == [0, 1], \   236     bt.get_assignment_positions_for_branches("a", ay)   237 names.append(bt.assignments["a"])   238    239 # Equivalent to...   240 #   241 # a = ...   242 # a.p   243 # while ...:   244 #   a = ...   245 #   a.x   246 # a.q   247    248 bt = branching.BranchTracker()   249 a1 = bt.assign_names(["a"])   250 ap = bt.use_attribute("a", "p")   251 bt.new_branchpoint(True)            # begin   252 bt.new_branch(True)                 # while ...   253 a2 = bt.assign_names(["a"])         # a = ...   254 ax = bt.use_attribute("a", "x")   255 bt.resume_continuing_branches()   256 bt.shelve_branch(True)   257 bt.new_branch()                     # (null)   258 bt.shelve_branch()   259 bt.merge_branches()                 # end   260 bt.resume_broken_branches()   261 aq = bt.use_attribute("a", "q")   262    263 print a1.get_usage() == \   264     {'a' : set([('p', 'q'), ('p',)])}, a1.get_usage()   265 print a2.get_usage() == \   266     {'a' : set([('q', 'x')])}, a2.get_usage()   267 print bt.get_assignment_positions_for_branches("a", ax) == [1], \   268     bt.get_assignment_positions_for_branches("a", ax)   269 print bt.get_assignment_positions_for_branches("a", ap) == [0], \   270     bt.get_assignment_positions_for_branches("a", ap)   271 print bt.get_assignment_positions_for_branches("a", aq) == [0, 1], \   272     bt.get_assignment_positions_for_branches("a", aq)   273 names.append(bt.assignments["a"])   274    275 # Equivalent to...   276 #   277 # a = ...   278 # a.p   279 # while ...:   280 #   if ...:   281 #     break   282 #   a.q   283 # a.r   284    285 bt = branching.BranchTracker()   286 a1 = bt.assign_names(["a"])   287 bt.use_attribute("a", "p")   288 bt.new_branchpoint(True)            # begin   289 bt.new_branch(True)                 # while ...   290 bt.new_branchpoint()                # begin   291 bt.new_branch()                     # if ...   292 bt.suspend_broken_branch()          # break   293 bt.shelve_branch()   294 bt.new_branch()                     # (null)   295 bt.shelve_branch()   296 bt.merge_branches()                 # end   297 bt.use_attribute("a", "q")   298 bt.resume_continuing_branches()   299 bt.shelve_branch(True)   300 bt.merge_branches()                 # end   301 bt.resume_broken_branches()   302 bt.use_attribute("a", "r")   303    304 print a1.get_usage() == \   305     {'a' : set([('p', 'q', 'r'), ('p', 'r')])}, a1.get_usage()   306 names.append(bt.assignments["a"])   307    308 # Equivalent to...   309 #   310 # a = ...   311 # a.p and a.q and a.r   312    313 bt = branching.BranchTracker()   314 a1 = bt.assign_names(["a"])   315 bt.new_branchpoint()                # begin   316 bt.new_branch()   317 bt.use_attribute("a", "p")   318 bt.new_branchpoint()                # begin   319 bt.new_branch()   320 bt.use_attribute("a", "q")   321 bt.new_branchpoint()                # begin   322 bt.new_branch()   323 bt.use_attribute("a", "r")   324 bt.shelve_branch()   325 bt.new_branch()                     # (null)   326 bt.shelve_branch()   327 bt.merge_branches()                 # end   328 bt.shelve_branch()   329 bt.new_branch()                     # (null)   330 bt.shelve_branch()   331 bt.merge_branches()                 # end   332 bt.shelve_branch()   333 bt.merge_branches()                 # end   334    335 print a1.get_usage() == \   336     {'a' : set([('p', 'q', 'r'), ('p', 'q'), ('p',)])}, a1.get_usage()   337 names.append(bt.assignments["a"])   338    339 # Equivalent to...   340 #   341 # a = ...   342 # if ...:   343 #   a.p   344 #   return   345 # a.q   346    347 bt = branching.BranchTracker()   348 a1 = bt.assign_names(["a"])   349 bt.new_branchpoint()                # begin   350 bt.new_branch()                     # if ...   351 bt.use_attribute("a", "p")   352 bt.abandon_returning_branch()   353 bt.shelve_branch()   354 bt.new_branch()                     # (null)   355 bt.shelve_branch()   356 bt.merge_branches()                 # end   357 bt.use_attribute("a", "q")   358    359 print a1.get_usage() == \   360     {'a' : set([('p',), ('q',)])}, a1.get_usage()   361 names.append(bt.assignments["a"])   362    363 # Equivalent to...   364 #   365 # a = ...   366 # try:   367 #   if ...:   368 #     a.p   369 #     return   370 #   a.q   371 # except:   372 #   a.r   373    374 bt = branching.BranchTracker()   375 a1 = bt.assign_names(["a"])   376 bt.new_branchpoint()                # begin (try)   377 bt.new_branchpoint()                # begin   378 bt.new_branch()                     # if ...   379 bt.use_attribute("a", "p")   380 bt.abandon_returning_branch()   381 bt.shelve_branch()                  # ... if   382 bt.new_branch()                     # (null)   383 bt.shelve_branch()   384 bt.merge_branches()                 # end   385 bt.use_attribute("a", "q")   386 bt.resume_abandoned_branches()      # except   387 bt.use_attribute("a", "r")   388 bt.shelve_branch()   389 bt.merge_branches()                 # end   390    391 print a1.get_usage() == \   392     {'a' : set([('p',), ('q', 'r')])}, a1.get_usage()   393 names.append(bt.assignments["a"])   394    395 # Equivalent to...   396 #   397 # a = ...   398 # if ...:   399 #   a.p   400 # a = ...   401 # if ...:   402 #   a.q   403    404 bt = branching.BranchTracker()   405 a1 = bt.assign_names(["a"])   406 bt.new_branchpoint()                # begin   407 bt.new_branch()                     # if ...   408 ap = bt.use_attribute("a", "p")   409 bt.abandon_branch()   410 bt.shelve_branch()                  # ... if   411 bt.new_branch()                     # (null)   412 bt.shelve_branch()   413 bt.merge_branches()                 # end   414 a2 = bt.assign_names(["a"])   415 bt.new_branchpoint()                # begin   416 bt.new_branch()                     # if ...   417 aq = bt.use_attribute("a", "q")   418 bt.abandon_branch()   419 bt.shelve_branch()                  # ... if   420 bt.new_branch()                     # (null)   421 bt.shelve_branch()   422 bt.merge_branches()                 # end   423    424 print a1.get_usage() == \   425     {'a' : set([('p',), ()])}, a1.get_usage()   426 print a2.get_usage() == \   427     {'a' : set([('q',), ()])}, a2.get_usage()   428 print bt.get_assignment_positions_for_branches("a", ap) == [0], \   429     bt.get_assignment_positions_for_branches("a", ap)   430 print bt.get_assignment_positions_for_branches("a", aq) == [1], \   431     bt.get_assignment_positions_for_branches("a", aq)   432 names.append(bt.assignments["a"])   433    434 # Equivalent to...   435 #   436 # a = {}   437 # a.p   438 # if ...:   439 #   a = ...   440 #   a.x   441 # else:   442 #   ...   443 # a.q   444    445 bt = branching.BranchTracker()   446 a1 = bt.assign_names(["a"], ["<instance>:__builtins__.dict.dict"])   447 ap = bt.use_attribute("a", "p")   448 bt.new_branchpoint()                # begin   449 bt.new_branch()                     # if ...   450 a2 = bt.assign_names(["a"])         # a = ...   451 ax = bt.use_attribute("a", "x")   452 bt.shelve_branch()   453 bt.new_branch()                     # else   454 bt.shelve_branch()   455 bt.merge_branches()                 # end   456 aq = bt.use_attribute("a", "q")   457    458 print a1.get_usage() == \   459     {'a' : set([('p',), ('p', 'q')])}, \   460     a1.get_usage()   461 print a2.get_usage() == \   462     {'a' : set([('q', 'x')])}, \   463     a2.get_usage()   464 print bt.get_assignment_positions_for_branches("a", ap) == [0], \   465     bt.get_assignment_positions_for_branches("a", ap)   466 print bt.get_assignment_positions_for_branches("a", ax) == [1], \   467     bt.get_assignment_positions_for_branches("a", ax)   468 print bt.get_assignment_positions_for_branches("a", aq) == [0, 1], \   469     bt.get_assignment_positions_for_branches("a", aq)   470 names.append(bt.assignments["a"])   471    472 # Equivalent to...   473 #   474 # if ...:   475 #   a = ...   476 #   a.x   477 # else:   478 #   ...   479 # a.q   480    481 bt = branching.BranchTracker()   482 bt.new_branchpoint()                # begin   483 bt.new_branch()                     # if ...   484 a1 = bt.assign_names(["a"])         # a = ...   485 ax = bt.use_attribute("a", "x")   486 bt.shelve_branch()   487 bt.new_branch()                     # else   488 bt.shelve_branch()   489 bt.merge_branches()                 # end   490 aq = bt.use_attribute("a", "q")   491    492 print a1.get_usage() == \   493     {'a' : set([('q', 'x')])}, \   494     a1.get_usage()   495 print bt.get_assignment_positions_for_branches("a", aq) == [None, 0], \   496     bt.get_assignment_positions_for_branches("a", aq)   497 names.append(bt.assignments["a"])   498    499 # Equivalent to...   500 #   501 # if ...:   502 #   a = ...   503 #   return   504 # a.q   505    506 bt = branching.BranchTracker()   507 bt.new_branchpoint()                # begin   508 bt.new_branch()                     # if ...   509 a1 = bt.assign_names(["a"])   510 bt.abandon_returning_branch()   511 bt.shelve_branch()   512 bt.new_branch()                     # (null)   513 bt.shelve_branch()   514 bt.merge_branches()                 # end   515 aq = bt.use_attribute("a", "q")   516    517 print a1.get_usage() == \   518     {'a' : set([()])}, a1.get_usage()   519 print bt.get_assignment_positions_for_branches("a", aq) == [None], \   520     bt.get_assignment_positions_for_branches("a", aq)   521 names.append(bt.assignments["a"])   522    523 # Equivalent to...   524 #   525 # a = ...   526 # try:   527 #   if ...:   528 #     a.p   529 #     return   530 #   a.q   531 # finally:   532 #   a.r   533    534 bt = branching.BranchTracker()   535 a1 = bt.assign_names(["a"])   536 bt.new_branchpoint()                # begin   537 bt.new_branch()                     # if ...   538 bt.use_attribute("a", "p")   539 bt.abandon_returning_branch()   540 bt.shelve_branch()                  # ... if   541 bt.new_branch()                     # (null)   542 bt.shelve_branch()   543 bt.merge_branches()                 # end   544 bt.use_attribute("a", "q")   545 branches = bt.resume_all_abandoned_branches()   546 bt.use_attribute("a", "r")   547 bt.restore_active_branches(branches)   548    549 print a1.get_usage() == \   550     {'a' : set([('p', 'r'), ('q', 'r')])}, a1.get_usage()   551 names.append(bt.assignments["a"])   552    553 # Equivalent to...   554 #   555 # a = ...   556 # try:   557 #   if ...:   558 #     a = ...   559 #     a.p   560 #     return   561 #   a.q   562 # finally:   563 #   a.r   564    565 bt = branching.BranchTracker()   566 a1 = bt.assign_names(["a"])   567 bt.new_branchpoint()                # begin   568 bt.new_branch()                     # if ...   569 a2 = bt.assign_names(["a"])   570 bt.use_attribute("a", "p")   571 bt.abandon_returning_branch()   572 bt.shelve_branch()                  # ... if   573 bt.new_branch()                     # (null)   574 bt.shelve_branch()   575 bt.merge_branches()                 # end   576 aq = bt.use_attribute("a", "q")   577 branches = bt.resume_all_abandoned_branches()   578 ar = bt.use_attribute("a", "r")   579 bt.restore_active_branches(branches)   580    581 print a1.get_usage() == \   582     {'a' : set([(), ('q', 'r')])}, a1.get_usage()   583 print a2.get_usage() == \   584     {'a' : set([('p', 'r')])}, a2.get_usage()   585 print bt.get_assignment_positions_for_branches("a", ar) == [0, 1], \   586     bt.get_assignment_positions_for_branches("a", ar)   587 names.append(bt.assignments["a"])   588    589 # Equivalent to...   590 #   591 # a = ...   592 # try:   593 #   if ...:   594 #     a = ...   595 #     a.p   596 #     return   597 #   a.q   598 # except:   599 #   a.r   600    601 bt = branching.BranchTracker()   602 a1 = bt.assign_names(["a"])   603 bt.new_branchpoint()                # begin (try)   604 bt.new_branchpoint()                # begin   605 bt.new_branch()                     # if ...   606 a2 = bt.assign_names(["a"])   607 bt.use_attribute("a", "p")   608 bt.abandon_returning_branch()   609 bt.shelve_branch()                  # ... if   610 bt.new_branch()                     # (null)   611 bt.shelve_branch()   612 bt.merge_branches()                 # end   613 bt.use_attribute("a", "q")   614 bt.resume_abandoned_branches()      # except   615 ar = bt.use_attribute("a", "r")   616 bt.shelve_branch()   617 bt.merge_branches()                 # end   618    619 print a1.get_usage() == \   620     {'a' : set([(), ('q', 'r')])}, a1.get_usage()   621 print a2.get_usage() == \   622     {'a' : set([('p',)])}, a2.get_usage()   623 print bt.get_assignment_positions_for_branches("a", ar) == [0, 1], \   624     bt.get_assignment_positions_for_branches("a", ar)   625 names.append(bt.assignments["a"])   626    627 # vim: tabstop=4 expandtab shiftwidth=4