@@ -29,6 +29,12 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
29
29
bool else_pop = false ;
30
30
31
31
while (!source.atEof ()) {
32
+ #ifdef BLOCK_DEBUG
33
+ fprintf (stderr, " %02d" , pos);
34
+ for (unsigned int i = 0 ; i < blocks.size (); i++) fprintf (stderr, " " );
35
+ fprintf (stderr, " %s\n " , curblock->type_str ());
36
+ #endif
37
+
32
38
bc_next (source, mod, opcode, operand, pos);
33
39
34
40
if (else_pop && opcode != Pyc::JUMP_FORWARD_A) {
@@ -439,6 +445,43 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
439
445
break ;
440
446
case Pyc::END_FINALLY:
441
447
{
448
+ bool isFinally = false ;
449
+ if (curblock->blktype () == ASTBlock::BLK_FINALLY) {
450
+ PycRef<ASTBlock> final = curblock;
451
+ blocks.pop ();
452
+
453
+ curblock = blocks.top ();
454
+ curblock->append (final .cast <ASTNode>());
455
+ isFinally = true ;
456
+ } else if (curblock->blktype () == ASTBlock::BLK_ELSE) {
457
+ /* All except statements have an else block that
458
+ * bubbles the exception up.
459
+ * If it's empty, we'll ignore it.
460
+ */
461
+ if (curblock->size () == 0 ) {
462
+ blocks.pop ();
463
+ }
464
+
465
+ curblock = blocks.top ();
466
+ }
467
+
468
+ if (curblock->blktype () == ASTBlock::BLK_CONTAINER) {
469
+ /* This marks the end of the except block(s). */
470
+ PycRef<ASTContainerBlock> cont = curblock.cast <ASTContainerBlock>();
471
+ if (!cont->hasFinally () || isFinally) {
472
+ /* If there's no finally block, pop the container. */
473
+ blocks.pop ();
474
+ curblock = blocks.top ();
475
+ curblock->append (cont.cast <ASTNode>());
476
+ } else {
477
+ /* If we need a finally block, add it here */
478
+ PycRef<ASTBlock> final = new ASTBlock (ASTBlock::BLK_FINALLY);
479
+ blocks.push (final );
480
+ curblock = blocks.top ();
481
+ }
482
+ } else {
483
+ fprintf (stderr, " Something TERRIBLE happened.\n " );
484
+ }
442
485
}
443
486
break ;
444
487
case Pyc::EXEC_STMT:
@@ -757,6 +800,10 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
757
800
stack = stack_hist.top ();
758
801
stack_hist.pop ();
759
802
803
+ if (curblock->blktype () == ASTBlock::BLK_CONTAINER) {
804
+ break ;
805
+ }
806
+
760
807
PycRef<ASTBlock> prev = curblock;
761
808
PycRef<ASTBlock> nil;
762
809
@@ -839,6 +886,12 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
839
886
break ;
840
887
case Pyc::POP_BLOCK:
841
888
{
889
+ if (curblock->blktype () == ASTBlock::BLK_CONTAINER ||
890
+ curblock->blktype () == ASTBlock::BLK_FINALLY) {
891
+ /* These should only be popped by an END_FINALLY */
892
+ break ;
893
+ }
894
+
842
895
PycRef<ASTBlock> tmp;
843
896
844
897
if (curblock->nodes ().back ()->type () == ASTNode::NODE_KEYWORD) {
@@ -965,10 +1018,25 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
965
1018
break ;
966
1019
case Pyc::SETUP_EXCEPT_A:
967
1020
{
1021
+ if (curblock->blktype () == ASTBlock::BLK_CONTAINER) {
1022
+ curblock.cast <ASTContainerBlock>()->setHasExcept (true );
1023
+ } else {
1024
+ PycRef<ASTBlock> next = new ASTContainerBlock (false , true );
1025
+ blocks.push (next.cast <ASTBlock>());
1026
+ }
1027
+
1028
+ /* Store the current stack for the except/finally statement(s) */
1029
+ stack_hist.push (stack);
1030
+ PycRef<ASTBlock> tryblock = new ASTBlock (ASTBlock::BLK_TRY, pos+operand);
1031
+ blocks.push (tryblock.cast <ASTBlock>());
1032
+ curblock = blocks.top ();
968
1033
}
969
1034
break ;
970
1035
case Pyc::SETUP_FINALLY_A:
971
1036
{
1037
+ PycRef<ASTBlock> next = new ASTContainerBlock (true );
1038
+ blocks.push (next.cast <ASTBlock>());
1039
+ curblock = blocks.top ();
972
1040
}
973
1041
break ;
974
1042
case Pyc::SETUP_LOOP_A:
@@ -1525,6 +1593,22 @@ void print_src(PycRef<ASTNode> node, PycModule* mod)
1525
1593
&& node.cast <ASTBlock>()->size () == 0 )
1526
1594
break ;
1527
1595
1596
+ if (node.cast <ASTBlock>()->blktype () == ASTBlock::BLK_CONTAINER) {
1597
+ end_line ();
1598
+ PycRef<ASTBlock> blk = node.cast <ASTBlock>();
1599
+ ASTBlock::list_t lines = blk->nodes ();
1600
+ for (ASTBlock::list_t ::const_iterator ln = lines.begin (); ln != lines.end ();) {
1601
+ if ((*ln).cast <ASTNode>()->type () != ASTNode::NODE_NODELIST) {
1602
+ start_line (cur_indent);
1603
+ }
1604
+ print_src (*ln, mod);
1605
+ if (++ln != lines.end ()) {
1606
+ end_line ();
1607
+ }
1608
+ }
1609
+ end_line ();
1610
+ break ;
1611
+ }
1528
1612
inPrint = false ;
1529
1613
1530
1614
printf (" %s" , node.cast <ASTBlock>()->type_str ());
0 commit comments