| OLD | NEW |
| 1 import imp | 1 import imp |
| 2 import os | 2 import os |
| 3 import marshal | 3 import marshal |
| 4 import struct | 4 import struct |
| 5 import sys | 5 import sys |
| 6 from cStringIO import StringIO | 6 from cStringIO import StringIO |
| 7 | 7 |
| 8 from compiler import ast, parse, walk, syntax | 8 from compiler import ast, parse, walk, syntax |
| 9 from compiler import pyassem, misc, future, symbols | 9 from compiler import pyassem, misc, future, symbols |
| 10 from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICT, \ | 10 from compiler.consts import SC_LOCAL, SC_GLOBAL_IMPLICIT, SC_GLOBAL_EXPLICT, \ |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 self.emit('BUILD_CLASS') | 406 self.emit('BUILD_CLASS') |
| 407 self.storeName(node.name) | 407 self.storeName(node.name) |
| 408 | 408 |
| 409 # The rest are standard visitor methods | 409 # The rest are standard visitor methods |
| 410 | 410 |
| 411 # The next few implement control-flow statements | 411 # The next few implement control-flow statements |
| 412 | 412 |
| 413 def visitIf(self, node): | 413 def visitIf(self, node): |
| 414 end = self.newBlock() | 414 end = self.newBlock() |
| 415 numtests = len(node.tests) | 415 numtests = len(node.tests) |
| 416 for i in range(numtests): | 416 for i in range(numtests - 1): |
| 417 test, suite = node.tests[i] | 417 test, suite = node.tests[i] |
| 418 if is_constant_false(test): | 418 if is_constant_false(test): |
| 419 # XXX will need to check generator stuff here | 419 # XXX will need to check generator stuff here |
| 420 continue | 420 continue |
| 421 self.set_lineno(test) | 421 self.set_lineno(test) |
| 422 self.visit(test) | 422 self.visit(test) |
| 423 nextTest = self.newBlock() | 423 nextTest = self.newBlock() |
| 424 self.emit('POP_JUMP_IF_FALSE', nextTest) | 424 self.emit('POP_JUMP_IF_FALSE', nextTest) |
| 425 self.nextBlock() | 425 self.nextBlock() |
| 426 self.visit(suite) | 426 self.visit(suite) |
| 427 self.emit('JUMP_FORWARD', end) | 427 self.emit('JUMP_FORWARD', end) |
| 428 self.startBlock(nextTest) | 428 self.startBlock(nextTest) |
| 429 if node.else_: | 429 # The last test can optimize a few things |
| 430 self.visit(node.else_) | 430 test, suite = node.tests[numtests - 1] |
| 431 if is_constant_false(test): |
| 432 if node.else_: |
| 433 self.visit(node.else_) |
| 434 else: |
| 435 self.set_lineno(test) |
| 436 self.visit(test) |
| 437 else_block = self.newBlock() if node.else_ else end |
| 438 self.emit('POP_JUMP_IF_FALSE', else_block) |
| 439 self.nextBlock() |
| 440 self.visit(suite) |
| 441 if node.else_: |
| 442 self.emit('JUMP_FORWARD', end) |
| 443 self.startBlock(else_block) |
| 444 self.visit(node.else_) |
| 431 self.nextBlock(end) | 445 self.nextBlock(end) |
| 432 | 446 |
| 433 def visitWhile(self, node): | 447 def visitWhile(self, node): |
| 434 self.set_lineno(node) | 448 self.set_lineno(node) |
| 435 | 449 |
| 436 loop = self.newBlock() | 450 loop = self.newBlock() |
| 437 else_ = self.newBlock() | 451 else_ = self.newBlock() |
| 452 body = self.newBlock() |
| 453 tail = self.newBlock() |
| 454 after = self.newBlock() |
| 438 | 455 |
| 439 after = self.newBlock() | |
| 440 self.emit('SETUP_LOOP', after) | 456 self.emit('SETUP_LOOP', after) |
| 441 | 457 |
| 442 self.nextBlock(loop) | 458 self.nextBlock(loop) |
| 443 self.setups.push((LOOP, loop)) | 459 self.setups.push((LOOP, loop)) |
| 460 self.emit('JUMP_FORWARD', tail) |
| 461 self.startBlock(body) |
| 444 | 462 |
| 445 self.set_lineno(node, force=True) | 463 self.set_lineno(node, force=True) |
| 464 |
| 465 self.visit(node.body) |
| 466 |
| 467 self.nextBlock(tail) |
| 446 self.visit(node.test) | 468 self.visit(node.test) |
| 447 self.emit('POP_JUMP_IF_FALSE', else_ or after) | 469 self.emit('POP_JUMP_IF_TRUE', body) |
| 448 | 470 |
| 449 self.nextBlock() | 471 self.nextBlock(else_) # or just the POPs if not else clause |
| 450 self.visit(node.body) | |
| 451 self.emit('JUMP_ABSOLUTE', loop) | |
| 452 | |
| 453 self.startBlock(else_) # or just the POPs if not else clause | |
| 454 self.emit('POP_BLOCK') | 472 self.emit('POP_BLOCK') |
| 455 self.setups.pop() | 473 self.setups.pop() |
| 456 if node.else_: | 474 if node.else_: |
| 457 self.visit(node.else_) | 475 self.visit(node.else_) |
| 458 self.nextBlock(after) | 476 self.nextBlock(after) |
| 459 | 477 |
| 460 def visitFor(self, node): | 478 def visitFor(self, node): |
| 461 start = self.newBlock() | 479 start = self.newBlock() |
| 480 body = self.newBlock() |
| 481 tail = self.newBlock() |
| 462 anchor = self.newBlock() | 482 anchor = self.newBlock() |
| 463 after = self.newBlock() | 483 after = self.newBlock() |
| 464 self.setups.push((LOOP, start)) | 484 self.setups.push((LOOP, start)) |
| 465 | 485 |
| 466 self.set_lineno(node) | 486 self.set_lineno(node) |
| 467 self.emit('SETUP_LOOP', after) | 487 self.emit('SETUP_LOOP', after) |
| 468 self.visit(node.list) | 488 self.visit(node.list) |
| 469 self.emit('GET_ITER') | 489 self.emit('GET_ITER') |
| 470 | 490 |
| 471 self.nextBlock(start) | 491 self.nextBlock(start) |
| 472 self.set_lineno(node, force=1) | 492 self.set_lineno(node, force=1) |
| 473 self.emit('FOR_ITER', anchor) | 493 self.emit('JUMP_FORWARD', tail) |
| 494 self.startBlock(body) |
| 474 self.visit(node.assign) | 495 self.visit(node.assign) |
| 475 self.visit(node.body) | 496 self.visit(node.body) |
| 476 self.emit('JUMP_ABSOLUTE', start) | 497 self.nextBlock(tail) |
| 498 self.emit('FOR_ITER', body) |
| 477 self.nextBlock(anchor) | 499 self.nextBlock(anchor) |
| 478 self.emit('POP_BLOCK') | 500 self.emit('POP_BLOCK') |
| 479 self.setups.pop() | 501 self.setups.pop() |
| 480 if node.else_: | 502 if node.else_: |
| 481 self.visit(node.else_) | 503 self.visit(node.else_) |
| 482 self.nextBlock(after) | 504 self.nextBlock(after) |
| 483 | 505 |
| 484 def visitBreak(self, node): | 506 def visitBreak(self, node): |
| 485 if not self.setups: | 507 if not self.setups: |
| 486 raise SyntaxError, "'break' outside loop (%s, %d)" % \ | 508 raise SyntaxError, "'break' outside loop (%s, %d)" % \ |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 self.emit('POP_TOP') | 586 self.emit('POP_TOP') |
| 565 self.nextBlock(end) | 587 self.nextBlock(end) |
| 566 | 588 |
| 567 # list comprehensions | 589 # list comprehensions |
| 568 def visitListComp(self, node): | 590 def visitListComp(self, node): |
| 569 self.set_lineno(node) | 591 self.set_lineno(node) |
| 570 # setup list | 592 # setup list |
| 571 self.emit('BUILD_LIST', 0) | 593 self.emit('BUILD_LIST', 0) |
| 572 | 594 |
| 573 stack = [] | 595 stack = [] |
| 574 for i, for_ in zip(range(len(node.quals)), node.quals): | 596 for for_ in node.quals: |
| 575 start, anchor = self.visit(for_) | 597 body, tail = self.visit(for_) |
| 576 cont = None | |
| 577 for if_ in for_.ifs: | 598 for if_ in for_.ifs: |
| 578 if cont is None: | 599 self.visit(if_, tail) |
| 579 cont = self.newBlock() | 600 stack.insert(0, (for_, body, tail)) |
| 580 self.visit(if_, cont) | |
| 581 stack.insert(0, (start, cont, anchor)) | |
| 582 | 601 |
| 583 self.visit(node.expr) | 602 self.visit(node.expr) |
| 584 self.emit('LIST_APPEND', len(node.quals) + 1) | 603 self.emit('LIST_APPEND', len(node.quals) + 1) |
| 585 | 604 |
| 586 for start, cont, anchor in stack: | 605 for for_, body, tail in stack: |
| 587 if cont: | 606 self.nextBlock(tail) |
| 588 self.nextBlock(cont) | 607 self.set_lineno(for_, force=True) |
| 589 self.emit('JUMP_ABSOLUTE', start) | 608 self.emit('FOR_ITER', body) |
| 590 self.startBlock(anchor) | 609 self.nextBlock() |
| 591 | 610 |
| 592 def visitListCompFor(self, node): | 611 def visitListCompFor(self, node): |
| 593 start = self.newBlock() | 612 body = self.newBlock() |
| 594 anchor = self.newBlock() | 613 tail = self.newBlock() |
| 595 | 614 |
| 596 self.visit(node.list) | 615 self.visit(node.list) |
| 597 self.emit('GET_ITER') | 616 self.emit('GET_ITER') |
| 598 self.nextBlock(start) | |
| 599 self.set_lineno(node, force=True) | |
| 600 self.emit('FOR_ITER', anchor) | |
| 601 self.nextBlock() | 617 self.nextBlock() |
| 618 self.emit('JUMP_FORWARD', tail) |
| 619 self.nextBlock(body) |
| 602 self.visit(node.assign) | 620 self.visit(node.assign) |
| 603 return start, anchor | 621 return body, tail |
| 604 | 622 |
| 605 def visitListCompIf(self, node, branch): | 623 def visitListCompIf(self, node, branch): |
| 606 self.set_lineno(node, force=True) | 624 self.set_lineno(node, force=True) |
| 607 self.visit(node.test) | 625 self.visit(node.test) |
| 608 self.emit('POP_JUMP_IF_FALSE', branch) | 626 self.emit('POP_JUMP_IF_FALSE', branch) |
| 609 self.newBlock() | |
| 610 | 627 |
| 611 def _makeClosure(self, gen, args): | 628 def _makeClosure(self, gen, args): |
| 612 frees = gen.scope.get_free_vars() | 629 frees = gen.scope.get_free_vars() |
| 613 if frees: | 630 if frees: |
| 614 for name in frees: | 631 for name in frees: |
| 615 self.emit('LOAD_CLOSURE', name) | 632 self.emit('LOAD_CLOSURE', name) |
| 616 self.emit('BUILD_TUPLE', len(frees)) | 633 self.emit('BUILD_TUPLE', len(frees)) |
| 617 self.emit('LOAD_CONST', gen) | 634 self.emit('LOAD_CONST', gen) |
| 618 self.emit('MAKE_CLOSURE', args) | 635 self.emit('MAKE_CLOSURE', args) |
| 619 else: | 636 else: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 630 # precomputation of outmost iterable | 647 # precomputation of outmost iterable |
| 631 self.visit(node.code.quals[0].iter) | 648 self.visit(node.code.quals[0].iter) |
| 632 self.emit('GET_ITER') | 649 self.emit('GET_ITER') |
| 633 self.emit('CALL_FUNCTION', 1) | 650 self.emit('CALL_FUNCTION', 1) |
| 634 | 651 |
| 635 def visitGenExprInner(self, node): | 652 def visitGenExprInner(self, node): |
| 636 self.set_lineno(node) | 653 self.set_lineno(node) |
| 637 # setup list | 654 # setup list |
| 638 | 655 |
| 639 stack = [] | 656 stack = [] |
| 640 for i, for_ in zip(range(len(node.quals)), node.quals): | 657 for for_ in node.quals: |
| 641 start, anchor, end = self.visit(for_) | 658 body, tail, end = self.visit(for_) |
| 642 cont = None | |
| 643 for if_ in for_.ifs: | 659 for if_ in for_.ifs: |
| 644 if cont is None: | 660 self.visit(if_, tail) |
| 645 cont = self.newBlock() | 661 stack.insert(0, (for_, body, tail, end)) |
| 646 self.visit(if_, cont) | |
| 647 stack.insert(0, (start, cont, anchor, end)) | |
| 648 | 662 |
| 649 self.visit(node.expr) | 663 self.visit(node.expr) |
| 650 self.emit('YIELD_VALUE') | 664 self.emit('YIELD_VALUE') |
| 651 self.emit('POP_TOP') | 665 self.emit('POP_TOP') |
| 652 | 666 |
| 653 for start, cont, anchor, end in stack: | 667 for for_, body, tail, end in stack: |
| 654 if cont: | 668 self.nextBlock(tail) |
| 655 self.nextBlock(cont) | 669 self.set_lineno(for_, force=True) |
| 656 self.emit('JUMP_ABSOLUTE', start) | 670 self.emit('FOR_ITER', body) |
| 657 self.startBlock(anchor) | 671 self.nextBlock() |
| 658 self.emit('POP_BLOCK') | 672 self.emit('POP_BLOCK') |
| 659 self.setups.pop() | 673 self.setups.pop() |
| 660 self.nextBlock(end) | 674 self.nextBlock(end) |
| 661 | 675 |
| 662 self.emit('LOAD_CONST', None) | 676 self.emit('LOAD_CONST', None) |
| 663 | 677 |
| 664 def visitGenExprFor(self, node): | 678 def visitGenExprFor(self, node): |
| 665 start = self.newBlock() | 679 start = self.newBlock() |
| 666 anchor = self.newBlock() | 680 body = self.newBlock() |
| 681 tail = self.newBlock() |
| 667 end = self.newBlock() | 682 end = self.newBlock() |
| 668 | 683 |
| 669 self.setups.push((LOOP, start)) | 684 self.setups.push((LOOP, start)) |
| 670 self.emit('SETUP_LOOP', end) | 685 self.emit('SETUP_LOOP', end) |
| 671 | 686 |
| 672 if node.is_outmost: | 687 if node.is_outmost: |
| 673 self.loadName('.0') | 688 self.loadName('.0') |
| 674 else: | 689 else: |
| 675 self.visit(node.iter) | 690 self.visit(node.iter) |
| 676 self.emit('GET_ITER') | 691 self.emit('GET_ITER') |
| 677 | 692 |
| 678 self.nextBlock(start) | 693 self.nextBlock(start) |
| 679 self.set_lineno(node, force=True) | 694 self.emit('JUMP_FORWARD', tail) |
| 680 self.emit('FOR_ITER', anchor) | 695 self.nextBlock(body) |
| 681 self.nextBlock() | |
| 682 self.visit(node.assign) | 696 self.visit(node.assign) |
| 683 return start, anchor, end | 697 return body, tail, end |
| 684 | 698 |
| 685 def visitGenExprIf(self, node, branch): | 699 def visitGenExprIf(self, node, branch): |
| 686 self.set_lineno(node, force=True) | 700 self.set_lineno(node, force=True) |
| 687 self.visit(node.test) | 701 self.visit(node.test) |
| 688 self.emit('POP_JUMP_IF_FALSE', branch) | 702 self.emit('POP_JUMP_IF_FALSE', branch) |
| 689 self.newBlock() | 703 self.newBlock() |
| 690 | 704 |
| 691 # exception related | 705 # exception related |
| 692 | 706 |
| 693 def visitAssert(self, node): | 707 def visitAssert(self, node): |
| (...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1491 ast.Slice: AugSlice, | 1505 ast.Slice: AugSlice, |
| 1492 ast.Subscript: AugSubscript, | 1506 ast.Subscript: AugSubscript, |
| 1493 } | 1507 } |
| 1494 | 1508 |
| 1495 def wrap_aug(node): | 1509 def wrap_aug(node): |
| 1496 return wrapper[node.__class__](node) | 1510 return wrapper[node.__class__](node) |
| 1497 | 1511 |
| 1498 if __name__ == "__main__": | 1512 if __name__ == "__main__": |
| 1499 for file in sys.argv[1:]: | 1513 for file in sys.argv[1:]: |
| 1500 compileFile(file) | 1514 compileFile(file) |
| OLD | NEW |