forked from teamnwah/openmw-tes3coop
added menumode script function; added global variable handling in compiler and interpreter (openmw context still ignores global variables)
This commit is contained in:
parent
cdcc244fc5
commit
f9c1548f80
20 changed files with 418 additions and 11 deletions
|
@ -7,5 +7,10 @@ namespace SACompiler
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
char Context::getGlobalType (const std::string& name) const
|
||||
{
|
||||
return ' ';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ namespace SACompiler
|
|||
|
||||
virtual bool canDeclareLocals() const;
|
||||
///< Is the compiler allowed to declare local variables?
|
||||
|
||||
virtual char getGlobalType (const std::string& name) const;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,32 @@ namespace SAInterpreter
|
|||
for (std::size_t i=0; i<buttons.size(); ++i)
|
||||
std::cout << " button " << i << ": " << buttons[i] << std::endl;
|
||||
}
|
||||
|
||||
bool Context::menuMode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Context::getGlobalShort (const std::string& name) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Context::getGlobalLong (const std::string& name) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Context::getGlobalFloat (const std::string& name) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Context::setGlobalShort (const std::string& name, int value) {}
|
||||
|
||||
void Context::setGlobalLong (const std::string& name, int value) {}
|
||||
|
||||
void Context::setGlobalFloat (const std::string& name, float value) {}
|
||||
|
||||
void Context::report()
|
||||
{
|
||||
|
|
|
@ -38,6 +38,20 @@ namespace SAInterpreter
|
|||
virtual void messageBox (const std::string& message,
|
||||
const std::vector<std::string>& buttons);
|
||||
|
||||
virtual bool menuMode();
|
||||
|
||||
virtual int getGlobalShort (const std::string& name) const;
|
||||
|
||||
virtual int getGlobalLong (const std::string& name) const;
|
||||
|
||||
virtual float getGlobalFloat (const std::string& name) const;
|
||||
|
||||
virtual void setGlobalShort (const std::string& name, int value);
|
||||
|
||||
virtual void setGlobalLong (const std::string& name, int value);
|
||||
|
||||
virtual void setGlobalFloat (const std::string& name, float value);
|
||||
|
||||
void report();
|
||||
///< Write state to std::cout
|
||||
};
|
||||
|
|
|
@ -29,6 +29,9 @@ namespace MWScript
|
|||
{
|
||||
return mType==Type_Full;
|
||||
}
|
||||
|
||||
virtual char getGlobalType (const std::string& name) const { return ' '; }
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,41 @@ namespace MWScript
|
|||
std::cerr << "error: message box buttons not supported" << std::endl;
|
||||
}
|
||||
|
||||
bool InterpreterContext::menuMode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int InterpreterContext::getGlobalShort (const std::string& name) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int InterpreterContext::getGlobalLong (const std::string& name) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float InterpreterContext::getGlobalFloat (const std::string& name) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InterpreterContext::setGlobalShort (const std::string& name, int value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InterpreterContext::setGlobalLong (const std::string& name, int value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void InterpreterContext::setGlobalFloat (const std::string& name, float value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MWWorld::World& InterpreterContext::getWorld()
|
||||
{
|
||||
return *mEnvironment.mWorld;
|
||||
|
|
|
@ -47,6 +47,20 @@ namespace MWScript
|
|||
virtual void messageBox (const std::string& message,
|
||||
const std::vector<std::string>& buttons);
|
||||
|
||||
virtual bool menuMode();
|
||||
|
||||
virtual int getGlobalShort (const std::string& name) const;
|
||||
|
||||
virtual int getGlobalLong (const std::string& name) const;
|
||||
|
||||
virtual float getGlobalFloat (const std::string& name) const;
|
||||
|
||||
virtual void setGlobalShort (const std::string& name, int value);
|
||||
|
||||
virtual void setGlobalLong (const std::string& name, int value);
|
||||
|
||||
virtual void setGlobalFloat (const std::string& name, float value);
|
||||
|
||||
MWWorld::World& getWorld();
|
||||
|
||||
MWSound::SoundManager& getSoundManager();
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef COMPILER_CONTEXT_H_INCLUDED
|
||||
#define COMPILER_CONTEXT_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
class Extensions;
|
||||
|
@ -27,6 +29,9 @@ namespace Compiler
|
|||
{
|
||||
return mExtensions;
|
||||
}
|
||||
|
||||
virtual char getGlobalType (const std::string& name) const = 0;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -243,16 +243,29 @@ namespace Compiler
|
|||
mFirst = false;
|
||||
|
||||
if (mNextOperand)
|
||||
{
|
||||
char type = mLocals.getType (name);
|
||||
{
|
||||
std::string name2 = toLower (name);
|
||||
|
||||
char type = mLocals.getType (name2);
|
||||
|
||||
if (type!=' ')
|
||||
{
|
||||
Generator::fetchLocal (mCode, type, mLocals.getIndex (name));
|
||||
Generator::fetchLocal (mCode, type, mLocals.getIndex (name2));
|
||||
mNextOperand = false;
|
||||
mOperands.push_back (type=='f' ? 'f' : 'l');
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
type = getContext().getGlobalType (name2);
|
||||
|
||||
if (type!=' ')
|
||||
{
|
||||
Generator::fetchGlobal (mCode, mLiterals, type, name2);
|
||||
mNextOperand = false;
|
||||
mOperands.push_back (type=='f' ? 'f' : 'l');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -281,6 +294,16 @@ namespace Compiler
|
|||
mNextOperand = false;
|
||||
return true;
|
||||
}
|
||||
else if (keyword==Scanner::K_menumode)
|
||||
{
|
||||
mTokenLoc = loc;
|
||||
|
||||
Generator::menuMode (mCode);
|
||||
mOperands.push_back ('l');
|
||||
|
||||
mNextOperand = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// check for custom extensions
|
||||
|
|
|
@ -219,6 +219,41 @@ namespace
|
|||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
namespace Compiler
|
||||
|
@ -511,6 +546,85 @@ namespace Compiler
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,14 @@ namespace Compiler
|
|||
void jumpOnNonZero (CodeContainer& code, int offset);
|
||||
|
||||
void compare (CodeContainer& code, char op, char valueType1, char valueType2);
|
||||
|
||||
void menuMode (CodeContainer& code);
|
||||
|
||||
void assignToGlobal (CodeContainer& code, Literals& literals, char localType,
|
||||
const std::string& name, const CodeContainer& value, char valueType);
|
||||
|
||||
void fetchGlobal (CodeContainer& code, Literals& literals, char localType,
|
||||
const std::string& name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,8 +61,9 @@ namespace Compiler
|
|||
|
||||
if (mState==SetState)
|
||||
{
|
||||
// local variable?
|
||||
std::string name2 = toLower (name);
|
||||
|
||||
// local variable?
|
||||
char type = mLocals.getType (name2);
|
||||
if (type!=' ')
|
||||
{
|
||||
|
@ -71,6 +72,15 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
|
||||
type = getContext().getGlobalType (name2);
|
||||
if (type!=' ')
|
||||
{
|
||||
mName = name2;
|
||||
mType = type;
|
||||
mState = SetGlobalVarState;
|
||||
return true;
|
||||
}
|
||||
|
||||
getErrorHandler().error ("unknown variable", loc);
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
|
@ -166,7 +176,20 @@ namespace Compiler
|
|||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (mState==SetGlobalVarState && keyword==Scanner::K_to)
|
||||
{
|
||||
mExprParser.reset();
|
||||
scanner.scan (mExprParser);
|
||||
|
||||
std::vector<Interpreter::Type_Code> code;
|
||||
char type = mExprParser.append (code);
|
||||
|
||||
Generator::assignToGlobal (mCode, mLiterals, mType, mName, code, type);
|
||||
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parser::parseKeyword (keyword, loc, scanner);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Compiler
|
|||
{
|
||||
BeginState,
|
||||
ShortState, LongState, FloatState,
|
||||
SetState, SetLocalVarState,
|
||||
SetState, SetLocalVarState, SetGlobalVarState,
|
||||
MessageState, MessageCommaState,
|
||||
EndState
|
||||
};
|
||||
|
@ -31,6 +31,7 @@ namespace Compiler
|
|||
std::vector<Interpreter::Type_Code>& mCode;
|
||||
State mState;
|
||||
std::string mName;
|
||||
char mType;
|
||||
ExprParser mExprParser;
|
||||
|
||||
public:
|
||||
|
|
|
@ -242,6 +242,7 @@ namespace Compiler
|
|||
"messagebox",
|
||||
"set", "to",
|
||||
"getsquareroot",
|
||||
"menumode",
|
||||
0
|
||||
};
|
||||
|
||||
|
|
|
@ -48,7 +48,8 @@ namespace Compiler
|
|||
K_return,
|
||||
K_messagebox,
|
||||
K_set, K_to,
|
||||
K_getsquareroot
|
||||
K_getsquareroot,
|
||||
K_menumode
|
||||
};
|
||||
|
||||
enum special
|
||||
|
|
|
@ -32,6 +32,20 @@ namespace Interpreter
|
|||
std::vector<std::string> empty;
|
||||
messageBox (message, empty);
|
||||
}
|
||||
|
||||
virtual bool menuMode() = 0;
|
||||
|
||||
virtual int getGlobalShort (const std::string& name) const = 0;
|
||||
|
||||
virtual int getGlobalLong (const std::string& name) const = 0;
|
||||
|
||||
virtual float getGlobalFloat (const std::string& name) const = 0;
|
||||
|
||||
virtual void setGlobalShort (const std::string& name, int value) = 0;
|
||||
|
||||
virtual void setGlobalLong (const std::string& name, int value) = 0;
|
||||
|
||||
virtual void setGlobalFloat (const std::string& name, float value) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,13 @@ op 34: compare (float) stack[1] with stack[0]; pop twice; push 1 if lesser than
|
|||
op 35: compare (float) stack[1] with stack[0]; pop twice; push 1 if lesser or equal, 0 else
|
||||
op 36: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater than, 0 else
|
||||
op 37: compare (float) stack[1] with stack[0]; pop twice; push 1 if greater or equal, 0 else
|
||||
opcodes 38-33554431 unused
|
||||
op 38: push 1 if game is in menu mode, 0 else
|
||||
op 39: store stack[0] in global short stack[1] and pop twice
|
||||
op 40: store stack[0] in global long stack[1] and pop twice
|
||||
op 41: store stack[0] in global float stack[1] and pop twice
|
||||
op 42: replace stack[0] with global short stack[0]
|
||||
op 43: replace stack[0] with global long stack[0]
|
||||
op 44: replace stack[0] with global float stack[0]
|
||||
opcodes 45-33554431 unused
|
||||
opcodes 33554432-67108863 reserved for extensions
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Interpreter
|
|||
interpreter.installSegment5 (17, new OpIntToFloat1);
|
||||
interpreter.installSegment5 (18, new OpFloatToInt1);
|
||||
|
||||
// local variables & literals
|
||||
// local variables, global variables & literals
|
||||
interpreter.installSegment5 (0, new OpStoreLocalShort);
|
||||
interpreter.installSegment5 (1, new OpStoreLocalLong);
|
||||
interpreter.installSegment5 (2, new OpStoreLocalFloat);
|
||||
|
@ -32,6 +32,12 @@ namespace Interpreter
|
|||
interpreter.installSegment5 (21, new OpFetchLocalShort);
|
||||
interpreter.installSegment5 (22, new OpFetchLocalLong);
|
||||
interpreter.installSegment5 (23, new OpFetchLocalFloat);
|
||||
interpreter.installSegment5 (39, new OpStoreGlobalShort);
|
||||
interpreter.installSegment5 (40, new OpStoreGlobalLong);
|
||||
interpreter.installSegment5 (41, new OpStoreGlobalFloat);
|
||||
interpreter.installSegment5 (42, new OpFetchGlobalShort);
|
||||
interpreter.installSegment5 (43, new OpFetchGlobalLong);
|
||||
interpreter.installSegment5 (44, new OpFetchGlobalFloat);
|
||||
|
||||
// math
|
||||
interpreter.installSegment5 (9, new OpAddInt<Type_Integer>);
|
||||
|
@ -77,7 +83,8 @@ namespace Interpreter
|
|||
interpreter.installSegment0 (2, new OpJumpBackward);
|
||||
|
||||
// misc
|
||||
interpreter.installSegment3 (0, new OpMessageBox);
|
||||
interpreter.installSegment3 (0, new OpMessageBox);
|
||||
interpreter.installSegment5 (38, new OpMenuMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -112,6 +112,99 @@ namespace Interpreter
|
|||
runtime[0] = *reinterpret_cast<Type_Data *> (&value);
|
||||
}
|
||||
};
|
||||
|
||||
class OpStoreGlobalShort : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Data data = runtime[0];
|
||||
int index = runtime[1];
|
||||
|
||||
std::string name = runtime.getStringLiteral (index);
|
||||
|
||||
runtime.getContext().setGlobalShort (name, *reinterpret_cast<int *> (&data));
|
||||
|
||||
runtime.pop();
|
||||
runtime.pop();
|
||||
}
|
||||
};
|
||||
|
||||
class OpStoreGlobalLong : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Data data = runtime[0];
|
||||
int index = runtime[1];
|
||||
|
||||
std::string name = runtime.getStringLiteral (index);
|
||||
|
||||
runtime.getContext().setGlobalLong (name, *reinterpret_cast<int *> (&data));
|
||||
|
||||
runtime.pop();
|
||||
runtime.pop();
|
||||
}
|
||||
};
|
||||
|
||||
class OpStoreGlobalFloat : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Data data = runtime[0];
|
||||
int index = runtime[1];
|
||||
|
||||
std::string name = runtime.getStringLiteral (index);
|
||||
|
||||
runtime.getContext().setGlobalFloat (name, *reinterpret_cast<float *> (&data));
|
||||
|
||||
runtime.pop();
|
||||
runtime.pop();
|
||||
}
|
||||
};
|
||||
|
||||
class OpFetchGlobalShort : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
int index = runtime[0];
|
||||
std::string name = runtime.getStringLiteral (index);
|
||||
int value = runtime.getContext().getGlobalShort (name);
|
||||
runtime[0] = *reinterpret_cast<Type_Data *> (&value);
|
||||
}
|
||||
};
|
||||
|
||||
class OpFetchGlobalLong : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
int index = runtime[0];
|
||||
std::string name = runtime.getStringLiteral (index);
|
||||
int value = runtime.getContext().getGlobalLong (name);
|
||||
runtime[0] = *reinterpret_cast<Type_Data *> (&value);
|
||||
}
|
||||
};
|
||||
|
||||
class OpFetchGlobalFloat : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
int index = runtime[0];
|
||||
std::string name = runtime.getStringLiteral (index);
|
||||
float value = runtime.getContext().getGlobalFloat (name);
|
||||
runtime[0] = *reinterpret_cast<Type_Data *> (&value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -85,7 +85,17 @@ namespace Interpreter
|
|||
std::vector<std::string> buttons;
|
||||
|
||||
runtime.getContext().messageBox (formattedMessage, buttons);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class OpMenuMode : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
runtime.push (runtime.getContext().menuMode());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue