diff options
Diffstat (limited to 'src')
-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(); |