diff options
| author | Mike Buland <eichlan@xagasoft.com> | 2012-02-08 09:29:15 -0700 |
|---|---|---|
| committer | Mike Buland <eichlan@xagasoft.com> | 2012-02-08 09:29:15 -0700 |
| commit | 98c5559c40c17d6dbf402f88fc8274b31657a1df (patch) | |
| tree | 0d26fe56023b63fe55c1e4bf71d36219515a923d | |
| parent | a859a39f3455fcbf0575bd7acd25915c40922f92 (diff) | |
| download | stage-98c5559c40c17d6dbf402f88fc8274b31657a1df.tar.gz stage-98c5559c40c17d6dbf402f88fc8274b31657a1df.tar.bz2 stage-98c5559c40c17d6dbf402f88fc8274b31657a1df.tar.xz stage-98c5559c40c17d6dbf402f88fc8274b31657a1df.zip | |
Fixed crash in empty functions.
| -rw-r--r-- | src/gamestate.cpp | 658 |
1 files changed, 331 insertions, 327 deletions
diff --git a/src/gamestate.cpp b/src/gamestate.cpp index 0434e6d..b009e4c 100644 --- a/src/gamestate.cpp +++ b/src/gamestate.cpp | |||
| @@ -553,397 +553,401 @@ void GameState::run( const AstBranch::NodeList &lNode, bool bNewScope ) | |||
| 553 | while( !sProg.isEmpty() ) | 553 | while( !sProg.isEmpty() ) |
| 554 | { | 554 | { |
| 555 | ProgramCounter &i = sProg.peek(); | 555 | ProgramCounter &i = sProg.peek(); |
| 556 | if( i ) | ||
| 557 | { | ||
| 556 | // sio << "Stack: " << lStack << sio.nl; | 558 | // sio << "Stack: " << lStack << sio.nl; |
| 557 | // sio << "exec: " << (*i)->getType() << sio.nl; | 559 | // sio << "exec: " << (*i)->getType() << sio.nl; |
| 558 | switch( (*i)->getType() ) | 560 | switch( (*i)->getType() ) |
| 559 | { | ||
| 560 | // tLeaf | ||
| 561 | case AstNode::tNot: | ||
| 562 | { | 561 | { |
| 563 | Variable x = popDeref(); | 562 | // tLeaf |
| 564 | if( x.getType() != Variable::tBool ) | 563 | case AstNode::tNot: |
| 565 | throw Bu::ExceptionBase("Non-bool used with logical not operator."); | 564 | { |
| 566 | push( Variable( !x.getBool() ) ); | 565 | Variable x = popDeref(); |
| 567 | } | 566 | if( x.getType() != Variable::tBool ) |
| 568 | break; | 567 | throw Bu::ExceptionBase("Non-bool used with logical not operator."); |
| 568 | push( Variable( !x.getBool() ) ); | ||
| 569 | } | ||
| 570 | break; | ||
| 569 | 571 | ||
| 570 | case AstNode::tComp: | 572 | case AstNode::tComp: |
| 571 | { | 573 | { |
| 572 | push( popDeref() == popDeref() ); | 574 | push( popDeref() == popDeref() ); |
| 573 | } | 575 | } |
| 574 | break; | 576 | break; |
| 575 | 577 | ||
| 576 | case AstNode::tCompGt: | 578 | case AstNode::tCompGt: |
| 577 | { | 579 | { |
| 578 | Variable y = popDeref(); | 580 | Variable y = popDeref(); |
| 579 | Variable x = popDeref(); | 581 | Variable x = popDeref(); |
| 580 | push( x > y ); | 582 | push( x > y ); |
| 581 | } | 583 | } |
| 582 | break; | 584 | break; |
| 583 | 585 | ||
| 584 | case AstNode::tCompLt: | 586 | case AstNode::tCompLt: |
| 585 | { | 587 | { |
| 586 | Variable y = popDeref(); | 588 | Variable y = popDeref(); |
| 587 | Variable x = popDeref(); | 589 | Variable x = popDeref(); |
| 588 | push( x < y ); | 590 | push( x < y ); |
| 589 | } | 591 | } |
| 590 | break; | 592 | break; |
| 591 | 593 | ||
| 592 | case AstNode::tCompGtEq: | 594 | case AstNode::tCompGtEq: |
| 593 | { | 595 | { |
| 594 | Variable y = popDeref(); | 596 | Variable y = popDeref(); |
| 595 | Variable x = popDeref(); | 597 | Variable x = popDeref(); |
| 596 | push( x >= y ); | 598 | push( x >= y ); |
| 597 | } | 599 | } |
| 598 | break; | 600 | break; |
| 599 | 601 | ||
| 600 | case AstNode::tCompLtEq: | 602 | case AstNode::tCompLtEq: |
| 601 | { | 603 | { |
| 602 | Variable y = popDeref(); | 604 | Variable y = popDeref(); |
| 603 | Variable x = popDeref(); | 605 | Variable x = popDeref(); |
| 604 | push( x <= y ); | 606 | push( x <= y ); |
| 605 | } | 607 | } |
| 606 | break; | 608 | break; |
| 607 | 609 | ||
| 608 | case AstNode::tStore: | 610 | case AstNode::tStore: |
| 609 | { | 611 | { |
| 610 | Variable y = popDeref(); | 612 | Variable y = popDeref(); |
| 611 | deref( lStack.peek(), true ) = y; | 613 | deref( lStack.peek(), true ) = y; |
| 612 | /* Variable dst = pop(); | 614 | /* Variable dst = pop(); |
| 613 | 615 | ||
| 614 | VariableRef r = dst.getVariableRef(); | 616 | VariableRef r = dst.getVariableRef(); |
| 615 | setVariable( r.sName, y, r.sid ); */ | 617 | setVariable( r.sName, y, r.sid ); */ |
| 616 | } | 618 | } |
| 617 | break; | 619 | break; |
| 618 | 620 | ||
| 619 | case AstNode::tStoreRev: | 621 | case AstNode::tStoreRev: |
| 620 | { | 622 | { |
| 621 | Variable dst = pop(); | 623 | Variable dst = pop(); |
| 622 | Variable y = popDeref(); | 624 | Variable y = popDeref(); |
| 623 | VariableRef r = dst.getVariableRef(); | 625 | VariableRef r = dst.getVariableRef(); |
| 624 | setVariable( r.sName, y, r.sid ); | 626 | setVariable( r.sName, y, r.sid ); |
| 625 | } | 627 | } |
| 626 | break; | 628 | break; |
| 627 | 629 | ||
| 628 | case AstNode::tAnd: | 630 | case AstNode::tAnd: |
| 629 | { | ||
| 630 | Variable y = popDeref(); | ||
| 631 | Variable x = popDeref(); | ||
| 632 | if( x.getType() != Variable::tBool || | ||
| 633 | y.getType() != Variable::tBool ) | ||
| 634 | { | 631 | { |
| 635 | throw Bu::ExceptionBase("Non-bool used in logical AND operator."); | 632 | Variable y = popDeref(); |
| 633 | Variable x = popDeref(); | ||
| 634 | if( x.getType() != Variable::tBool || | ||
| 635 | y.getType() != Variable::tBool ) | ||
| 636 | { | ||
| 637 | throw Bu::ExceptionBase("Non-bool used in logical AND operator."); | ||
| 638 | } | ||
| 639 | lStack.push( Variable( x.getBool() && y.getBool() ) ); | ||
| 636 | } | 640 | } |
| 637 | lStack.push( Variable( x.getBool() && y.getBool() ) ); | 641 | break; |
| 638 | } | ||
| 639 | break; | ||
| 640 | 642 | ||
| 641 | case AstNode::tOr: | 643 | case AstNode::tOr: |
| 642 | { | ||
| 643 | Variable y = popDeref(); | ||
| 644 | Variable x = popDeref(); | ||
| 645 | if( x.getType() != Variable::tBool || | ||
| 646 | y.getType() != Variable::tBool ) | ||
| 647 | { | 644 | { |
| 648 | throw Bu::ExceptionBase("Non-bool used in logical OR operator."); | 645 | Variable y = popDeref(); |
| 646 | Variable x = popDeref(); | ||
| 647 | if( x.getType() != Variable::tBool || | ||
| 648 | y.getType() != Variable::tBool ) | ||
| 649 | { | ||
| 650 | throw Bu::ExceptionBase("Non-bool used in logical OR operator."); | ||
| 651 | } | ||
| 652 | lStack.push( Variable( x.getBool() || y.getBool() ) ); | ||
| 649 | } | 653 | } |
| 650 | lStack.push( Variable( x.getBool() || y.getBool() ) ); | 654 | break; |
| 651 | } | ||
| 652 | break; | ||
| 653 | 655 | ||
| 654 | case AstNode::tPlus: | 656 | case AstNode::tPlus: |
| 655 | { | 657 | { |
| 656 | Variable y = popDeref(); | 658 | Variable y = popDeref(); |
| 657 | Variable x = popDeref(); | 659 | Variable x = popDeref(); |
| 658 | lStack.push( x + y ); | 660 | lStack.push( x + y ); |
| 659 | } | 661 | } |
| 660 | break; | 662 | break; |
| 661 | 663 | ||
| 662 | case AstNode::tMinus: | 664 | case AstNode::tMinus: |
| 663 | { | 665 | { |
| 664 | Variable y = popDeref(); | 666 | Variable y = popDeref(); |
| 665 | Variable x = popDeref(); | 667 | Variable x = popDeref(); |
| 666 | lStack.push( x - y ); | 668 | lStack.push( x - y ); |
| 667 | } | 669 | } |
| 668 | break; | 670 | break; |
| 669 | 671 | ||
| 670 | case AstNode::tDivide: | 672 | case AstNode::tDivide: |
| 671 | { | 673 | { |
| 672 | Variable y = popDeref(); | 674 | Variable y = popDeref(); |
| 673 | Variable x = popDeref(); | 675 | Variable x = popDeref(); |
| 674 | lStack.push( x / y ); | 676 | lStack.push( x / y ); |
| 675 | } | 677 | } |
| 676 | break; | 678 | break; |
| 677 | 679 | ||
| 678 | case AstNode::tMultiply: | 680 | case AstNode::tMultiply: |
| 679 | { | 681 | { |
| 680 | Variable y = popDeref(); | 682 | Variable y = popDeref(); |
| 681 | Variable x = popDeref(); | 683 | Variable x = popDeref(); |
| 682 | lStack.push( x * y ); | 684 | lStack.push( x * y ); |
| 683 | } | 685 | } |
| 684 | break; | 686 | break; |
| 685 | 687 | ||
| 686 | case AstNode::tPlusStore: | 688 | case AstNode::tPlusStore: |
| 687 | { | 689 | { |
| 688 | Variable y = popDeref(); | 690 | Variable y = popDeref(); |
| 689 | deref( lStack.peek(), true ) += y; | 691 | deref( lStack.peek(), true ) += y; |
| 690 | } | 692 | } |
| 691 | break; | 693 | break; |
| 692 | 694 | ||
| 693 | case AstNode::tMinusStore: | 695 | case AstNode::tMinusStore: |
| 694 | { | 696 | { |
| 695 | Variable y = popDeref(); | 697 | Variable y = popDeref(); |
| 696 | deref( lStack.peek(), true ) -= y; | 698 | deref( lStack.peek(), true ) -= y; |
| 697 | } | 699 | } |
| 698 | break; | 700 | break; |
| 699 | 701 | ||
| 700 | case AstNode::tDivideStore: | 702 | case AstNode::tDivideStore: |
| 701 | { | 703 | { |
| 702 | Variable y = popDeref(); | 704 | Variable y = popDeref(); |
| 703 | deref( lStack.peek(), true ) /= y; | 705 | deref( lStack.peek(), true ) /= y; |
| 704 | } | 706 | } |
| 705 | break; | 707 | break; |
| 706 | 708 | ||
| 707 | case AstNode::tMultiplyStore: | 709 | case AstNode::tMultiplyStore: |
| 708 | { | 710 | { |
| 709 | Variable y = popDeref(); | 711 | Variable y = popDeref(); |
| 710 | deref( lStack.peek(), true ) *= y; | 712 | deref( lStack.peek(), true ) *= y; |
| 711 | } | 713 | } |
| 712 | break; | 714 | break; |
| 713 | 715 | ||
| 714 | case AstNode::tNegate: | 716 | case AstNode::tNegate: |
| 715 | push( -popDeref() ); | 717 | push( -popDeref() ); |
| 716 | break; | 718 | break; |
| 717 | 719 | ||
| 718 | case AstNode::tIn: | 720 | case AstNode::tIn: |
| 719 | { | ||
| 720 | Variable v = popDeref(); | ||
| 721 | Variable x = popDeref(); | ||
| 722 | if( v.getType() == Variable::tDictionary || | ||
| 723 | v.getType() == Variable::tList ) | ||
| 724 | { | 721 | { |
| 725 | push( Variable( v.has( x ) ) ); | 722 | Variable v = popDeref(); |
| 723 | Variable x = popDeref(); | ||
| 724 | if( v.getType() == Variable::tDictionary || | ||
| 725 | v.getType() == Variable::tList ) | ||
| 726 | { | ||
| 727 | push( Variable( v.has( x ) ) ); | ||
| 728 | } | ||
| 729 | else | ||
| 730 | { | ||
| 731 | throw Bu::ExceptionBase("Invalid type for operator in"); | ||
| 732 | } | ||
| 726 | } | 733 | } |
| 727 | else | 734 | break; |
| 735 | |||
| 736 | case AstNode::tGoto: | ||
| 728 | { | 737 | { |
| 729 | throw Bu::ExceptionBase("Invalid type for operator in"); | 738 | Variable x = popDeref(); |
| 739 | if( x.getType() != Variable::tSituation ) | ||
| 740 | throw Bu::ExceptionBase("You cannot goto anything but a situation."); | ||
| 741 | sGoto = x.getString(); | ||
| 742 | return; | ||
| 730 | } | 743 | } |
| 731 | } | 744 | break; |
| 732 | break; | ||
| 733 | |||
| 734 | case AstNode::tGoto: | ||
| 735 | { | ||
| 736 | Variable x = popDeref(); | ||
| 737 | if( x.getType() != Variable::tSituation ) | ||
| 738 | throw Bu::ExceptionBase("You cannot goto anything but a situation."); | ||
| 739 | sGoto = x.getString(); | ||
| 740 | return; | ||
| 741 | } | ||
| 742 | break; | ||
| 743 | 745 | ||
| 744 | case AstNode::tSwap: | 746 | case AstNode::tSwap: |
| 745 | { | 747 | { |
| 746 | Variable y = pop(); | 748 | Variable y = pop(); |
| 747 | Variable x = pop(); | 749 | Variable x = pop(); |
| 748 | push( y ); | 750 | push( y ); |
| 749 | push( x ); | 751 | push( x ); |
| 750 | } | 752 | } |
| 751 | break; | 753 | break; |
| 752 | 754 | ||
| 753 | case AstNode::tReturn: | 755 | case AstNode::tReturn: |
| 754 | if( bNewScope ) | 756 | if( bNewScope ) |
| 755 | lsLocal.pop(); | 757 | lsLocal.pop(); |
| 756 | return; | 758 | return; |
| 757 | 759 | ||
| 758 | case AstNode::tAppend: | 760 | case AstNode::tAppend: |
| 759 | { | 761 | { |
| 760 | Variable v = popDeref(); | 762 | Variable v = popDeref(); |
| 761 | deref( lStack.peek() ) += v; | 763 | deref( lStack.peek() ) += v; |
| 762 | } | 764 | } |
| 763 | break; | 765 | break; |
| 764 | 766 | ||
| 765 | case AstNode::tInsert: | 767 | case AstNode::tInsert: |
| 766 | { | 768 | { |
| 767 | Variable v = popDeref(); | 769 | Variable v = popDeref(); |
| 768 | Variable k = popDeref(); | 770 | Variable k = popDeref(); |
| 769 | deref( lStack.peek() ).insert( k, v ); | 771 | deref( lStack.peek() ).insert( k, v ); |
| 770 | } | 772 | } |
| 771 | break; | 773 | break; |
| 772 | 774 | ||
| 773 | case AstNode::tIndex: | 775 | case AstNode::tIndex: |
| 774 | { | 776 | { |
| 775 | Variable v = popDeref(); | 777 | Variable v = popDeref(); |
| 776 | Variable cx = pop(); | 778 | Variable cx = pop(); |
| 777 | Variable &c = deref( cx ); | 779 | Variable &c = deref( cx ); |
| 778 | push( Variable( &c.get( v ) ) ); | 780 | push( Variable( &c.get( v ) ) ); |
| 779 | } | 781 | } |
| 780 | break; | 782 | break; |
| 781 | 783 | ||
| 782 | case AstNode::tPop: | 784 | case AstNode::tPop: |
| 783 | pop(); | 785 | pop(); |
| 784 | break; | 786 | break; |
| 785 | 787 | ||
| 786 | case AstNode::tDeref: | 788 | case AstNode::tDeref: |
| 787 | push( popDeref() ); | 789 | push( popDeref() ); |
| 788 | break; | 790 | break; |
| 789 | 791 | ||
| 790 | case AstNode::tExists: | 792 | case AstNode::tExists: |
| 791 | { | 793 | { |
| 792 | Variable v = pop(); | 794 | Variable v = pop(); |
| 793 | VariableRef r = v.getVariableRef(); | 795 | VariableRef r = v.getVariableRef(); |
| 794 | push( Variable( hasVariable( r.sName, r.sid ) ) ); | 796 | push( Variable( hasVariable( r.sName, r.sid ) ) ); |
| 795 | } | 797 | } |
| 796 | break; | 798 | break; |
| 797 | 799 | ||
| 798 | case AstNode::tDelete: | 800 | case AstNode::tDelete: |
| 799 | { | 801 | { |
| 800 | Variable v = pop(); | 802 | Variable v = pop(); |
| 801 | VariableRef r = v.getVariableRef(); | 803 | VariableRef r = v.getVariableRef(); |
| 802 | delVariable( r.sName, r.sid ); | 804 | delVariable( r.sName, r.sid ); |
| 803 | push( Variable( Variable::tNull ) ); | 805 | push( Variable( Variable::tNull ) ); |
| 804 | } | 806 | } |
| 805 | break; | 807 | break; |
| 806 | 808 | ||
| 807 | // tLeafLiteral | 809 | // tLeafLiteral |
| 808 | case AstNode::tVarName: | 810 | case AstNode::tVarName: |
| 809 | case AstNode::tLiteral: | 811 | case AstNode::tLiteral: |
| 810 | lStack.push( dynamic_cast<const AstLeafLiteral *>(*i)->getValue() ); | 812 | lStack.push( dynamic_cast<const AstLeafLiteral *>(*i)->getValue() ); |
| 811 | break; | 813 | break; |
| 812 | 814 | ||
| 813 | case AstNode::tFuncCall: | 815 | case AstNode::tFuncCall: |
| 814 | callFunction( | 816 | callFunction( |
| 815 | dynamic_cast<const AstLeafLiteral *>(*i) | 817 | dynamic_cast<const AstLeafLiteral *>(*i) |
| 816 | ->getValue().getString() | 818 | ->getValue().getString() |
| 817 | ); | 819 | ); |
| 818 | break; | 820 | break; |
| 819 | 821 | ||
| 820 | // tBranch | 822 | // tBranch |
| 821 | case AstNode::tScope: | 823 | case AstNode::tScope: |
| 822 | throw Bu::ExceptionBase("Scope? that shouldn't be here..."); | 824 | throw Bu::ExceptionBase("Scope? that shouldn't be here..."); |
| 823 | break; | 825 | break; |
| 824 | 826 | ||
| 825 | case AstNode::tIf: | 827 | case AstNode::tIf: |
| 826 | { | 828 | { |
| 827 | AstBranch::NodeList lIf = | 829 | AstBranch::NodeList lIf = |
| 828 | dynamic_cast<const AstBranch *>(*i)->getNodeList(); | 830 | dynamic_cast<const AstBranch *>(*i)->getNodeList(); |
| 829 | Variable v = popDeref(); | 831 | Variable v = popDeref(); |
| 830 | if( v.getType() != Variable::tBool ) | 832 | if( v.getType() != Variable::tBool ) |
| 831 | throw Bu::ExceptionBase("conditional did not evaluate to boolean."); | 833 | throw Bu::ExceptionBase("conditional did not evaluate to boolean."); |
| 832 | AstBranch::NodeList::const_iterator iIf = lIf.begin(); | 834 | AstBranch::NodeList::const_iterator iIf = lIf.begin(); |
| 833 | if( v.getBool() ) | 835 | if( v.getBool() ) |
| 834 | { | ||
| 835 | i++; | ||
| 836 | sProg.push( dynamic_cast<const AstBranch *>(*iIf)-> | ||
| 837 | getNodeList().begin() ); | ||
| 838 | continue; | ||
| 839 | } | ||
| 840 | else | ||
| 841 | { | ||
| 842 | iIf++; | ||
| 843 | if( iIf ) | ||
| 844 | { | 836 | { |
| 845 | i++; | 837 | i++; |
| 846 | sProg.push( dynamic_cast<const AstBranch *>(*iIf)-> | 838 | sProg.push( dynamic_cast<const AstBranch *>(*iIf)-> |
| 847 | getNodeList().begin() ); | 839 | getNodeList().begin() ); |
| 848 | continue; | 840 | continue; |
| 849 | } | 841 | } |
| 850 | } | 842 | else |
| 851 | } | ||
| 852 | break; | ||
| 853 | |||
| 854 | case AstNode::tForEach: | ||
| 855 | { | ||
| 856 | AstBranch::NodeList lFe = | ||
| 857 | dynamic_cast<const AstBranch *>(*i)->getNodeList(); | ||
| 858 | AstBranch::NodeList::const_iterator iEach = lFe.begin(); | ||
| 859 | AstBranch::NodeList::const_iterator iIn = iEach+1; | ||
| 860 | AstBranch::NodeList::const_iterator iDo = iIn+1; | ||
| 861 | |||
| 862 | const AstBranch::NodeList &lEachVrs = | ||
| 863 | dynamic_cast<const AstBranch *>(*iEach)->getNodeList(); | ||
| 864 | AstBranch::NodeList::const_iterator iEachVrs = lEachVrs.begin(); | ||
| 865 | |||
| 866 | bool bUseKey = false; | ||
| 867 | VariableRef vrKey, vrValue; | ||
| 868 | if( lEachVrs.getSize() == 2 ) | ||
| 869 | { | ||
| 870 | vrKey = dynamic_cast<const AstLeafLiteral *>(*iEachVrs)-> | ||
| 871 | getValue().getVariableRef(); | ||
| 872 | iEachVrs++; | ||
| 873 | vrValue = dynamic_cast<const AstLeafLiteral *>(*iEachVrs)-> | ||
| 874 | getValue().getVariableRef(); | ||
| 875 | bUseKey = true; | ||
| 876 | } | ||
| 877 | else | ||
| 878 | { | ||
| 879 | vrValue = dynamic_cast<const AstLeafLiteral *>(*iEachVrs)-> | ||
| 880 | getValue().getVariableRef(); | ||
| 881 | } | ||
| 882 | |||
| 883 | run( dynamic_cast<const AstBranch *>(*iIn), | ||
| 884 | false ); | ||
| 885 | Variable vIn = popDeref(); | ||
| 886 | |||
| 887 | const AstBranch::NodeList &rDo = | ||
| 888 | dynamic_cast<const AstBranch *>(*iDo)->getNodeList(); | ||
| 889 | |||
| 890 | if( vIn.getType() == Variable::tDictionary ) | ||
| 891 | { | ||
| 892 | const Variable::VariableHash &rHash = vIn.getHash(); | ||
| 893 | for( Variable::VariableHash::const_iterator i = | ||
| 894 | rHash.begin(); i; i++ ) | ||
| 895 | { | 843 | { |
| 896 | if( bUseKey ) | 844 | iIf++; |
| 897 | setVariable( vrKey.sName, i.getKey(), vrKey.sid ); | 845 | if( iIf ) |
| 898 | setVariable( vrValue.sName, i.getValue(), vrValue.sid ); | 846 | { |
| 899 | run( rDo, false ); | 847 | i++; |
| 848 | sProg.push( dynamic_cast<const AstBranch *>(*iIf)-> | ||
| 849 | getNodeList().begin() ); | ||
| 850 | continue; | ||
| 851 | } | ||
| 900 | } | 852 | } |
| 901 | } | 853 | } |
| 902 | else if( vIn.getType() == Variable::tList ) | 854 | break; |
| 855 | |||
| 856 | case AstNode::tForEach: | ||
| 903 | { | 857 | { |
| 904 | if( bUseKey ) | 858 | AstBranch::NodeList lFe = |
| 859 | dynamic_cast<const AstBranch *>(*i)->getNodeList(); | ||
| 860 | AstBranch::NodeList::const_iterator iEach = lFe.begin(); | ||
| 861 | AstBranch::NodeList::const_iterator iIn = iEach+1; | ||
| 862 | AstBranch::NodeList::const_iterator iDo = iIn+1; | ||
| 863 | |||
| 864 | const AstBranch::NodeList &lEachVrs = | ||
| 865 | dynamic_cast<const AstBranch *>(*iEach)->getNodeList(); | ||
| 866 | AstBranch::NodeList::const_iterator iEachVrs = lEachVrs.begin(); | ||
| 867 | |||
| 868 | bool bUseKey = false; | ||
| 869 | VariableRef vrKey, vrValue; | ||
| 870 | if( lEachVrs.getSize() == 2 ) | ||
| 905 | { | 871 | { |
| 906 | throw Bu::ExceptionBase("You cannot use key:value pairs as iterators in a for each loop iterating over a list."); | 872 | vrKey = dynamic_cast<const AstLeafLiteral *>(*iEachVrs)-> |
| 873 | getValue().getVariableRef(); | ||
| 874 | iEachVrs++; | ||
| 875 | vrValue = dynamic_cast<const AstLeafLiteral *>(*iEachVrs)-> | ||
| 876 | getValue().getVariableRef(); | ||
| 877 | bUseKey = true; | ||
| 907 | } | 878 | } |
| 908 | const Variable::VariableArray &rList = vIn.getList(); | 879 | else |
| 909 | for( Variable::VariableArray::const_iterator i = | ||
| 910 | rList.begin(); i; i++ ) | ||
| 911 | { | 880 | { |
| 912 | setVariable( vrValue.sName, *i, vrValue.sid ); | 881 | vrValue = dynamic_cast<const AstLeafLiteral *>(*iEachVrs)-> |
| 913 | run( rDo, false ); | 882 | getValue().getVariableRef(); |
| 914 | } | 883 | } |
| 915 | } | ||
| 916 | } | ||
| 917 | break; | ||
| 918 | 884 | ||
| 919 | case AstNode::tWhile: | 885 | run( dynamic_cast<const AstBranch *>(*iIn), |
| 920 | { | 886 | false ); |
| 921 | AstBranch::NodeList lWhile = | 887 | Variable vIn = popDeref(); |
| 922 | dynamic_cast<const AstBranch *>(*i)->getNodeList(); | 888 | |
| 923 | AstBranch::NodeList::const_iterator iTest = lWhile.begin(); | 889 | const AstBranch::NodeList &rDo = |
| 924 | AstBranch::NodeList::const_iterator iDo = iTest+1; | 890 | dynamic_cast<const AstBranch *>(*iDo)->getNodeList(); |
| 925 | 891 | ||
| 926 | for(;;) | 892 | if( vIn.getType() == Variable::tDictionary ) |
| 893 | { | ||
| 894 | const Variable::VariableHash &rHash = vIn.getHash(); | ||
| 895 | for( Variable::VariableHash::const_iterator i = | ||
| 896 | rHash.begin(); i; i++ ) | ||
| 897 | { | ||
| 898 | if( bUseKey ) | ||
| 899 | setVariable( vrKey.sName, i.getKey(), vrKey.sid ); | ||
| 900 | setVariable( vrValue.sName, i.getValue(), vrValue.sid ); | ||
| 901 | run( rDo, false ); | ||
| 902 | } | ||
| 903 | } | ||
| 904 | else if( vIn.getType() == Variable::tList ) | ||
| 905 | { | ||
| 906 | if( bUseKey ) | ||
| 907 | { | ||
| 908 | throw Bu::ExceptionBase("You cannot use key:value pairs as iterators in a for each loop iterating over a list."); | ||
| 909 | } | ||
| 910 | const Variable::VariableArray &rList = vIn.getList(); | ||
| 911 | for( Variable::VariableArray::const_iterator i = | ||
| 912 | rList.begin(); i; i++ ) | ||
| 913 | { | ||
| 914 | setVariable( vrValue.sName, *i, vrValue.sid ); | ||
| 915 | run( rDo, false ); | ||
| 916 | } | ||
| 917 | } | ||
| 918 | } | ||
| 919 | break; | ||
| 920 | |||
| 921 | case AstNode::tWhile: | ||
| 927 | { | 922 | { |
| 928 | run( dynamic_cast<const AstBranch *>(*iTest)-> | 923 | AstBranch::NodeList lWhile = |
| 929 | getNodeList(), false ); | 924 | dynamic_cast<const AstBranch *>(*i)->getNodeList(); |
| 930 | Variable v = popDeref(); | 925 | AstBranch::NodeList::const_iterator iTest = lWhile.begin(); |
| 931 | if( v.getType() != Variable::tBool ) | 926 | AstBranch::NodeList::const_iterator iDo = iTest+1; |
| 932 | throw Bu::ExceptionBase("conditional did not evaluate to boolean."); | ||
| 933 | if( !v.getBool() ) | ||
| 934 | break; | ||
| 935 | 927 | ||
| 936 | run( dynamic_cast<const AstBranch *>(*iDo)-> | 928 | for(;;) |
| 937 | getNodeList(), false ); | 929 | { |
| 930 | run( dynamic_cast<const AstBranch *>(*iTest)-> | ||
| 931 | getNodeList(), false ); | ||
| 932 | Variable v = popDeref(); | ||
| 933 | if( v.getType() != Variable::tBool ) | ||
| 934 | throw Bu::ExceptionBase("conditional did not evaluate to boolean."); | ||
| 935 | if( !v.getBool() ) | ||
| 936 | break; | ||
| 937 | |||
| 938 | run( dynamic_cast<const AstBranch *>(*iDo)-> | ||
| 939 | getNodeList(), false ); | ||
| 940 | } | ||
| 938 | } | 941 | } |
| 942 | break; | ||
| 939 | } | 943 | } |
| 940 | break; | ||
| 941 | } | ||
| 942 | 944 | ||
| 943 | if( sGoto.isSet() ) | 945 | if( sGoto.isSet() ) |
| 944 | return; | 946 | return; |
| 947 | |||
| 948 | ++sProg.peek(); | ||
| 949 | } | ||
| 945 | 950 | ||
| 946 | ++sProg.peek(); | ||
| 947 | while( !sProg.isEmpty() && !sProg.peek() ) | 951 | while( !sProg.isEmpty() && !sProg.peek() ) |
| 948 | { | 952 | { |
| 949 | sProg.pop(); | 953 | sProg.pop(); |
