mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 10:26:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			791 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			791 lines
		
	
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
 | 
						|
#include "generator.hpp"
 | 
						|
 | 
						|
#include <cassert>
 | 
						|
#include <algorithm>
 | 
						|
#include <iterator>
 | 
						|
#include <stdexcept>
 | 
						|
 | 
						|
#include "literals.hpp"
 | 
						|
 | 
						|
namespace
 | 
						|
{
 | 
						|
    void opPushInt (Compiler::Generator::CodeContainer& code, int value)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment0 (0, value));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFetchIntLiteral (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (4));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFetchFloatLiteral (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (5));
 | 
						|
    }
 | 
						|
 | 
						|
    void opIntToFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (3));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFloatToInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (6));
 | 
						|
    }
 | 
						|
 | 
						|
    void opStoreLocalShort (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (0));
 | 
						|
    }
 | 
						|
 | 
						|
    void opStoreLocalLong (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (1));
 | 
						|
    }
 | 
						|
 | 
						|
    void opStoreLocalFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (2));
 | 
						|
    }
 | 
						|
 | 
						|
    void opNegateInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (7));
 | 
						|
    }
 | 
						|
 | 
						|
    void opNegateFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (8));
 | 
						|
    }
 | 
						|
 | 
						|
    void opAddInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (9));
 | 
						|
    }
 | 
						|
 | 
						|
    void opAddFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (10));
 | 
						|
    }
 | 
						|
 | 
						|
    void opSubInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (11));
 | 
						|
    }
 | 
						|
 | 
						|
    void opSubFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (12));
 | 
						|
    }
 | 
						|
 | 
						|
    void opMulInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (13));
 | 
						|
    }
 | 
						|
 | 
						|
    void opMulFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (14));
 | 
						|
    }
 | 
						|
 | 
						|
    void opDivInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (15));
 | 
						|
    }
 | 
						|
 | 
						|
    void opDivFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (16));
 | 
						|
    }
 | 
						|
 | 
						|
    void opIntToFloat1 (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (17));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFloatToInt1 (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (18));
 | 
						|
    }
 | 
						|
 | 
						|
    void opSquareRoot (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (19));
 | 
						|
    }
 | 
						|
 | 
						|
    void opReturn (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (20));
 | 
						|
    }
 | 
						|
 | 
						|
    void opMessageBox (Compiler::Generator::CodeContainer& code, int buttons)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment3 (0, buttons));
 | 
						|
    }
 | 
						|
 | 
						|
    void opReport (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (58));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFetchLocalShort (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (21));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFetchLocalLong (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (22));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFetchLocalFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (23));
 | 
						|
    }
 | 
						|
 | 
						|
    void opJumpForward (Compiler::Generator::CodeContainer& code, int offset)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment0 (1, offset));
 | 
						|
    }
 | 
						|
 | 
						|
    void opJumpBackward (Compiler::Generator::CodeContainer& code, int offset)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment0 (2, offset));
 | 
						|
    }
 | 
						|
 | 
						|
    void opSkipOnZero (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (24));
 | 
						|
    }
 | 
						|
 | 
						|
    void opSkipOnNonZero (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (25));
 | 
						|
    }
 | 
						|
 | 
						|
    void opEqualInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (26));
 | 
						|
    }
 | 
						|
 | 
						|
    void opNonEqualInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (27));
 | 
						|
    }
 | 
						|
 | 
						|
    void opLessThanInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (28));
 | 
						|
    }
 | 
						|
 | 
						|
    void opLessOrEqualInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (29));
 | 
						|
    }
 | 
						|
 | 
						|
    void opGreaterThanInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (30));
 | 
						|
    }
 | 
						|
 | 
						|
    void opGreaterOrEqualInt (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (31));
 | 
						|
    }
 | 
						|
 | 
						|
    void opEqualFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (32));
 | 
						|
    }
 | 
						|
 | 
						|
    void opNonEqualFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (33));
 | 
						|
    }
 | 
						|
 | 
						|
    void opLessThanFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (34));
 | 
						|
    }
 | 
						|
 | 
						|
    void opLessOrEqualFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (35));
 | 
						|
    }
 | 
						|
 | 
						|
    void opGreaterThanFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (36));
 | 
						|
    }
 | 
						|
 | 
						|
    void opGreaterOrEqualFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (37));
 | 
						|
    }
 | 
						|
 | 
						|
    void opMenuMode (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (38));
 | 
						|
    }
 | 
						|
 | 
						|
    void opStoreGlobalShort (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (39));
 | 
						|
    }
 | 
						|
 | 
						|
    void opStoreGlobalLong (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (40));
 | 
						|
    }
 | 
						|
 | 
						|
    void opStoreGlobalFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (41));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFetchGlobalShort (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (42));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFetchGlobalLong (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (43));
 | 
						|
    }
 | 
						|
 | 
						|
    void opFetchGlobalFloat (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (44));
 | 
						|
    }
 | 
						|
 | 
						|
    void opRandom (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (45));
 | 
						|
    }
 | 
						|
 | 
						|
    void opScriptRunning (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (46));
 | 
						|
    }
 | 
						|
 | 
						|
    void opStartScript (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (47));
 | 
						|
    }
 | 
						|
 | 
						|
    void opStopScript (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (48));
 | 
						|
    }
 | 
						|
 | 
						|
    void opGetDistance (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (49));
 | 
						|
    }
 | 
						|
 | 
						|
    void opGetSecondsPassed (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (50));
 | 
						|
    }
 | 
						|
 | 
						|
    void opEnable (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (51));
 | 
						|
    }
 | 
						|
 | 
						|
    void opDisable (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (52));
 | 
						|
    }
 | 
						|
 | 
						|
    void opGetDisabled (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (53));
 | 
						|
    }
 | 
						|
 | 
						|
    void opEnableExplicit (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (54));
 | 
						|
    }
 | 
						|
 | 
						|
    void opDisableExplicit (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (55));
 | 
						|
    }
 | 
						|
 | 
						|
    void opGetDisabledExplicit (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (56));
 | 
						|
    }
 | 
						|
 | 
						|
    void opGetDistanceExplicit (Compiler::Generator::CodeContainer& code)
 | 
						|
    {
 | 
						|
        code.push_back (Compiler::Generator::segment5 (57));
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
namespace Compiler
 | 
						|
{
 | 
						|
    namespace Generator
 | 
						|
    {
 | 
						|
        void pushInt (CodeContainer& code, Literals& literals, int value)
 | 
						|
        {
 | 
						|
            int index = literals.addInteger (value);
 | 
						|
            opPushInt (code, index);
 | 
						|
            opFetchIntLiteral (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void pushFloat (CodeContainer& code, Literals& literals, float value)
 | 
						|
        {
 | 
						|
            int index = literals.addFloat (value);
 | 
						|
            opPushInt (code, index);
 | 
						|
            opFetchFloatLiteral (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void pushString (CodeContainer& code, Literals& literals, const std::string& value)
 | 
						|
        {
 | 
						|
            int index = literals.addString (value);
 | 
						|
            opPushInt (code, index);
 | 
						|
        }
 | 
						|
 | 
						|
        void assignToLocal (CodeContainer& code, char localType,
 | 
						|
            int localIndex, const CodeContainer& value, char valueType)
 | 
						|
        {
 | 
						|
            opPushInt (code, localIndex);
 | 
						|
 | 
						|
            std::copy (value.begin(), value.end(), std::back_inserter (code));
 | 
						|
 | 
						|
            if (localType!=valueType)
 | 
						|
            {
 | 
						|
                if (localType=='f' && valueType=='l')
 | 
						|
                {
 | 
						|
                    opIntToFloat (code);
 | 
						|
                }
 | 
						|
                else if ((localType=='l' || localType=='s') && valueType=='f')
 | 
						|
                {
 | 
						|
                    opFloatToInt (code);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            switch (localType)
 | 
						|
            {
 | 
						|
                case 'f':
 | 
						|
 | 
						|
                    opStoreLocalFloat (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 's':
 | 
						|
 | 
						|
                    opStoreLocalShort (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 'l':
 | 
						|
 | 
						|
                    opStoreLocalLong (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                default:
 | 
						|
 | 
						|
                    assert (0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void negate (CodeContainer& code, char valueType)
 | 
						|
        {
 | 
						|
            switch (valueType)
 | 
						|
            {
 | 
						|
                case 'l':
 | 
						|
 | 
						|
                    opNegateInt (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 'f':
 | 
						|
 | 
						|
                    opNegateFloat (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                default:
 | 
						|
 | 
						|
                    assert (0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void add (CodeContainer& code, char valueType1, char valueType2)
 | 
						|
        {
 | 
						|
            if (valueType1=='l' && valueType2=='l')
 | 
						|
            {
 | 
						|
                opAddInt (code);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (valueType1=='l')
 | 
						|
                    opIntToFloat1 (code);
 | 
						|
 | 
						|
                if (valueType2=='l')
 | 
						|
                    opIntToFloat (code);
 | 
						|
 | 
						|
                opAddFloat (code);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void sub (CodeContainer& code, char valueType1, char valueType2)
 | 
						|
        {
 | 
						|
            if (valueType1=='l' && valueType2=='l')
 | 
						|
            {
 | 
						|
                opSubInt (code);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (valueType1=='l')
 | 
						|
                    opIntToFloat1 (code);
 | 
						|
 | 
						|
                if (valueType2=='l')
 | 
						|
                    opIntToFloat (code);
 | 
						|
 | 
						|
                opSubFloat (code);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void mul (CodeContainer& code, char valueType1, char valueType2)
 | 
						|
        {
 | 
						|
            if (valueType1=='l' && valueType2=='l')
 | 
						|
            {
 | 
						|
                opMulInt (code);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (valueType1=='l')
 | 
						|
                    opIntToFloat1 (code);
 | 
						|
 | 
						|
                if (valueType2=='l')
 | 
						|
                    opIntToFloat (code);
 | 
						|
 | 
						|
                opMulFloat (code);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void div (CodeContainer& code, char valueType1, char valueType2)
 | 
						|
        {
 | 
						|
            if (valueType1=='l' && valueType2=='l')
 | 
						|
            {
 | 
						|
                opDivInt (code);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (valueType1=='l')
 | 
						|
                    opIntToFloat1 (code);
 | 
						|
 | 
						|
                if (valueType2=='l')
 | 
						|
                    opIntToFloat (code);
 | 
						|
 | 
						|
                opDivFloat (code);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void convert (CodeContainer& code, char fromType, char toType)
 | 
						|
        {
 | 
						|
            if (fromType!=toType)
 | 
						|
            {
 | 
						|
                if (fromType=='f' && toType=='l')
 | 
						|
                    opFloatToInt (code);
 | 
						|
                else if (fromType=='l' && toType=='f')
 | 
						|
                    opIntToFloat (code);
 | 
						|
                else
 | 
						|
                    throw std::logic_error ("illegal type conversion");
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void squareRoot (CodeContainer& code)
 | 
						|
        {
 | 
						|
            opSquareRoot (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void exit (CodeContainer& code)
 | 
						|
        {
 | 
						|
            opReturn (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void message (CodeContainer& code, Literals& literals, const std::string& message,
 | 
						|
            int buttons)
 | 
						|
        {
 | 
						|
            assert (buttons>=0);
 | 
						|
 | 
						|
            if (buttons>=256)
 | 
						|
                throw std::runtime_error ("A message box can't have more than 255 buttons");
 | 
						|
 | 
						|
            int index = literals.addString (message);
 | 
						|
 | 
						|
            opPushInt (code, index);
 | 
						|
            opMessageBox (code, buttons);
 | 
						|
        }
 | 
						|
 | 
						|
        void report (CodeContainer& code, Literals& literals, const std::string& message)
 | 
						|
        {
 | 
						|
            int index = literals.addString (message);
 | 
						|
 | 
						|
            opPushInt (code, index);
 | 
						|
            opReport (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void fetchLocal (CodeContainer& code, char localType, int localIndex)
 | 
						|
        {
 | 
						|
            opPushInt (code, localIndex);
 | 
						|
 | 
						|
            switch (localType)
 | 
						|
            {
 | 
						|
                case 'f':
 | 
						|
 | 
						|
                    opFetchLocalFloat (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 's':
 | 
						|
 | 
						|
                    opFetchLocalShort (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 'l':
 | 
						|
 | 
						|
                    opFetchLocalLong (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                default:
 | 
						|
 | 
						|
                    assert (0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void jump (CodeContainer& code, int offset)
 | 
						|
        {
 | 
						|
            if (offset>0)
 | 
						|
                opJumpForward (code, offset);
 | 
						|
            else if (offset<0)
 | 
						|
                opJumpBackward (code, -offset);
 | 
						|
            else
 | 
						|
                throw std::logic_error ("inifite loop");
 | 
						|
        }
 | 
						|
 | 
						|
        void jumpOnZero (CodeContainer& code, int offset)
 | 
						|
        {
 | 
						|
            opSkipOnNonZero (code);
 | 
						|
 | 
						|
            if (offset<0)
 | 
						|
                --offset; // compensate for skip instruction
 | 
						|
 | 
						|
            jump (code, offset);
 | 
						|
        }
 | 
						|
 | 
						|
        void jumpOnNonZero (CodeContainer& code, int offset)
 | 
						|
        {
 | 
						|
            opSkipOnZero (code);
 | 
						|
 | 
						|
            if (offset<0)
 | 
						|
                --offset; // compensate for skip instruction
 | 
						|
 | 
						|
            jump (code, offset);
 | 
						|
        }
 | 
						|
 | 
						|
        void compare (CodeContainer& code, char op, char valueType1, char valueType2)
 | 
						|
        {
 | 
						|
            if (valueType1=='l' && valueType2=='l')
 | 
						|
            {
 | 
						|
                switch (op)
 | 
						|
                {
 | 
						|
                    case 'e': opEqualInt (code); break;
 | 
						|
                    case 'n': opNonEqualInt (code); break;
 | 
						|
                    case 'l': opLessThanInt (code); break;
 | 
						|
                    case 'L': opLessOrEqualInt (code); break;
 | 
						|
                    case 'g': opGreaterThanInt (code); break;
 | 
						|
                    case 'G': opGreaterOrEqualInt (code); break;
 | 
						|
 | 
						|
                    default:
 | 
						|
 | 
						|
                        assert (0);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if (valueType1=='l')
 | 
						|
                    opIntToFloat1 (code);
 | 
						|
 | 
						|
                if (valueType2=='l')
 | 
						|
                    opIntToFloat (code);
 | 
						|
 | 
						|
                switch (op)
 | 
						|
                {
 | 
						|
                    case 'e': opEqualFloat (code); break;
 | 
						|
                    case 'n': opNonEqualFloat (code); break;
 | 
						|
                    case 'l': opLessThanFloat (code); break;
 | 
						|
                    case 'L': opLessOrEqualFloat (code); break;
 | 
						|
                    case 'g': opGreaterThanFloat (code); break;
 | 
						|
                    case 'G': opGreaterOrEqualFloat (code); break;
 | 
						|
 | 
						|
                    default:
 | 
						|
 | 
						|
                        assert (0);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void menuMode (CodeContainer& code)
 | 
						|
        {
 | 
						|
            opMenuMode (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void assignToGlobal (CodeContainer& code, Literals& literals, char localType,
 | 
						|
            const std::string& name, const CodeContainer& value, char valueType)
 | 
						|
        {
 | 
						|
            int index = literals.addString (name);
 | 
						|
 | 
						|
            opPushInt (code, index);
 | 
						|
 | 
						|
            std::copy (value.begin(), value.end(), std::back_inserter (code));
 | 
						|
 | 
						|
            if (localType!=valueType)
 | 
						|
            {
 | 
						|
                if (localType=='f' && valueType=='l')
 | 
						|
                {
 | 
						|
                    opIntToFloat (code);
 | 
						|
                }
 | 
						|
                else if ((localType=='l' || localType=='s') && valueType=='f')
 | 
						|
                {
 | 
						|
                    opFloatToInt (code);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            switch (localType)
 | 
						|
            {
 | 
						|
                case 'f':
 | 
						|
 | 
						|
                    opStoreGlobalFloat (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 's':
 | 
						|
 | 
						|
                    opStoreGlobalShort (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 'l':
 | 
						|
 | 
						|
                    opStoreGlobalLong (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                default:
 | 
						|
 | 
						|
                    assert (0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void fetchGlobal (CodeContainer& code, Literals& literals, char localType,
 | 
						|
            const std::string& name)
 | 
						|
        {
 | 
						|
            int index = literals.addString (name);
 | 
						|
 | 
						|
            opPushInt (code, index);
 | 
						|
 | 
						|
            switch (localType)
 | 
						|
            {
 | 
						|
                case 'f':
 | 
						|
 | 
						|
                    opFetchGlobalFloat (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 's':
 | 
						|
 | 
						|
                    opFetchGlobalShort (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                case 'l':
 | 
						|
 | 
						|
                    opFetchGlobalLong (code);
 | 
						|
                    break;
 | 
						|
 | 
						|
                default:
 | 
						|
 | 
						|
                    assert (0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void random (CodeContainer& code)
 | 
						|
        {
 | 
						|
            opRandom (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void scriptRunning (CodeContainer& code)
 | 
						|
        {
 | 
						|
            opScriptRunning (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void startScript (CodeContainer& code)
 | 
						|
        {
 | 
						|
            opStartScript (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void stopScript (CodeContainer& code)
 | 
						|
        {
 | 
						|
            opStopScript (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void getDistance (CodeContainer& code, Literals& literals, const std::string id)
 | 
						|
        {
 | 
						|
            if (id.empty())
 | 
						|
            {
 | 
						|
                opGetDistance (code);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                int index = literals.addString (id);
 | 
						|
                opPushInt (code, index);
 | 
						|
                opGetDistanceExplicit (code);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void getSecondsPassed (CodeContainer& code)
 | 
						|
        {
 | 
						|
            opGetSecondsPassed (code);
 | 
						|
        }
 | 
						|
 | 
						|
        void getDisabled (CodeContainer& code, Literals& literals, const std::string id)
 | 
						|
        {
 | 
						|
            if (id.empty())
 | 
						|
            {
 | 
						|
                opGetDisabled (code);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                int index = literals.addString (id);
 | 
						|
                opPushInt (code, index);
 | 
						|
                opGetDisabledExplicit (code);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void enable (CodeContainer& code, Literals& literals, const std::string id)
 | 
						|
        {
 | 
						|
            if (id.empty())
 | 
						|
            {
 | 
						|
                opEnable (code);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                int index = literals.addString (id);
 | 
						|
                opPushInt (code, index);
 | 
						|
                opEnableExplicit (code);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        void disable (CodeContainer& code, Literals& literals, const std::string id)
 | 
						|
        {
 | 
						|
            if (id.empty())
 | 
						|
            {
 | 
						|
                opDisable (code);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                int index = literals.addString (id);
 | 
						|
                opPushInt (code, index);
 | 
						|
                opDisableExplicit (code);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |