summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gamestate.cpp658
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();