forked from mirror/openmw-tes3mp
Merge branch 'xdoty' into script
This commit is contained in:
commit
0795730a19
19 changed files with 578 additions and 72 deletions
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include "../mwworld/world.hpp"
|
||||
|
||||
#include "scriptmanager.hpp"
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
CompilerContext::CompilerContext (Type type)
|
||||
|
@ -21,6 +23,18 @@ namespace MWScript
|
|||
return MWBase::Environment::get().getWorld()->getGlobalVariableType (name);
|
||||
}
|
||||
|
||||
char CompilerContext::getMemberType (const std::string& name, const std::string& id) const
|
||||
{
|
||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPtr (id, false);
|
||||
|
||||
std::string script = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
if (script.empty())
|
||||
return ' ';
|
||||
|
||||
return MWBase::Environment::get().getScriptManager()->getLocals (script).getType (name);
|
||||
}
|
||||
|
||||
bool CompilerContext::isId (const std::string& name) const
|
||||
{
|
||||
return
|
||||
|
|
|
@ -30,6 +30,9 @@ namespace MWScript
|
|||
/// 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
virtual char getGlobalType (const std::string& name) const;
|
||||
|
||||
virtual char getMemberType (const std::string& name, const std::string& id) const;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
|
||||
virtual bool isId (const std::string& name) const;
|
||||
///< Does \a name match an ID, that can be referenced?
|
||||
};
|
||||
|
|
|
@ -270,6 +270,84 @@ namespace MWScript
|
|||
MWBase::Environment::get().getWorld()->disable (ref);
|
||||
}
|
||||
|
||||
int InterpreterContext::getMemberShort (const std::string& id, const std::string& name) const
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId));
|
||||
return ptr.getRefData().getLocals().mShorts[index];
|
||||
}
|
||||
|
||||
int InterpreterContext::getMemberLong (const std::string& id, const std::string& name) const
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId));
|
||||
return ptr.getRefData().getLocals().mLongs[index];
|
||||
}
|
||||
|
||||
float InterpreterContext::getMemberFloat (const std::string& id, const std::string& name) const
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId));
|
||||
return ptr.getRefData().getLocals().mFloats[index];
|
||||
}
|
||||
|
||||
void InterpreterContext::setMemberShort (const std::string& id, const std::string& name, int value)
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 's');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId));
|
||||
ptr.getRefData().getLocals().mShorts[index] = value;
|
||||
}
|
||||
|
||||
void InterpreterContext::setMemberLong (const std::string& id, const std::string& name, int value)
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'l');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId));
|
||||
ptr.getRefData().getLocals().mLongs[index] = value;
|
||||
}
|
||||
|
||||
void InterpreterContext::setMemberFloat (const std::string& id, const std::string& name, float value)
|
||||
{
|
||||
const MWWorld::Ptr ptr = getReference (id, false);
|
||||
|
||||
std::string scriptId = MWWorld::Class::get (ptr).getScript (ptr);
|
||||
|
||||
int index = MWBase::Environment::get().getScriptManager()->getLocalIndex (scriptId, name, 'f');
|
||||
|
||||
ptr.getRefData().setLocals (
|
||||
*MWBase::Environment::get().getWorld()->getStore().scripts.find (scriptId));
|
||||
ptr.getRefData().getLocals().mFloats[index] = value;
|
||||
}
|
||||
|
||||
MWWorld::Ptr InterpreterContext::getReference()
|
||||
{
|
||||
return getReference ("", true);
|
||||
|
|
|
@ -107,6 +107,18 @@ namespace MWScript
|
|||
|
||||
virtual void disable (const std::string& id = "");
|
||||
|
||||
virtual int getMemberShort (const std::string& id, const std::string& name) const;
|
||||
|
||||
virtual int getMemberLong (const std::string& id, const std::string& name) const;
|
||||
|
||||
virtual float getMemberFloat (const std::string& id, const std::string& name) const;
|
||||
|
||||
virtual void setMemberShort (const std::string& id, const std::string& name, int value);
|
||||
|
||||
virtual void setMemberLong (const std::string& id, const std::string& name, int value);
|
||||
|
||||
virtual void setMemberFloat (const std::string& id, const std::string& name, float value);
|
||||
|
||||
MWWorld::Ptr getReference();
|
||||
///< Reference, that the script is running from (can be empty)
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <components/compiler/scanner.hpp>
|
||||
#include <components/compiler/context.hpp>
|
||||
#include <components/compiler/exception.hpp>
|
||||
|
||||
#include "extensions.hpp"
|
||||
|
||||
|
@ -46,8 +47,14 @@ namespace MWScript
|
|||
if (!mErrorHandler.isGood())
|
||||
Success = false;
|
||||
}
|
||||
catch (...)
|
||||
catch (const Compiler::SourceException&)
|
||||
{
|
||||
// error has already been reported via error handler
|
||||
Success = false;
|
||||
}
|
||||
catch (const std::exception& error)
|
||||
{
|
||||
std::cerr << "An exception has been thrown: " << error.what() << std::endl;
|
||||
Success = false;
|
||||
}
|
||||
|
||||
|
@ -140,6 +147,9 @@ namespace MWScript
|
|||
{
|
||||
if (!compile (name))
|
||||
{
|
||||
/// \todo Handle case of cyclic member variable access. Currently this could look up
|
||||
/// the whole application in an endless recursion.
|
||||
|
||||
// failed -> ignore script from now on.
|
||||
std::vector<Interpreter::Type_Code> empty;
|
||||
mScripts.insert (std::make_pair (name, std::make_pair (empty, Compiler::Locals())));
|
||||
|
@ -156,4 +166,43 @@ namespace MWScript
|
|||
{
|
||||
return mGlobalScripts;
|
||||
}
|
||||
|
||||
int ScriptManager::getLocalIndex (const std::string& scriptId, const std::string& variable,
|
||||
char type)
|
||||
{
|
||||
const ESM::Script *script = mStore.scripts.find (scriptId);
|
||||
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 's':
|
||||
|
||||
offset = 0;
|
||||
size = script->data.numShorts;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
|
||||
offset = script->data.numShorts;
|
||||
size = script->data.numLongs;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
|
||||
offset = script->data.numShorts+script->data.numLongs;
|
||||
size = script->data.numFloats;
|
||||
|
||||
default:
|
||||
|
||||
throw std::runtime_error ("invalid variable type");
|
||||
}
|
||||
|
||||
for (int i=0; i<size; ++i)
|
||||
if (script->varNames.at (i+offset)==variable)
|
||||
return i;
|
||||
|
||||
throw std::runtime_error ("unable to access local variable " + variable + " of " + scriptId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,10 @@ namespace MWScript
|
|||
///< Return locals for script \a name.
|
||||
|
||||
GlobalScripts& getGlobalScripts();
|
||||
|
||||
int getLocalIndex (const std::string& scriptId, const std::string& variable, char type);
|
||||
///< Return index of the variable of the given name and type in the given script. Will
|
||||
/// throw an exception, if there is no such script or variable or the type does not match.
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -33,10 +33,12 @@ namespace Compiler
|
|||
virtual char getGlobalType (const std::string& name) const = 0;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
|
||||
virtual char getMemberType (const std::string& name, const std::string& id) const = 0;
|
||||
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
|
||||
|
||||
virtual bool isId (const std::string& name) const = 0;
|
||||
///< Does \a name match an ID, that can be referenced?
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -195,10 +195,31 @@ namespace Compiler
|
|||
return parseArguments (arguments, scanner, mCode);
|
||||
}
|
||||
|
||||
bool ExprParser::handleMemberAccess (const std::string& name)
|
||||
{
|
||||
mMemberOp = false;
|
||||
|
||||
std::string name2 = toLower (name);
|
||||
std::string id = toLower (mExplicit);
|
||||
|
||||
char type = getContext().getMemberType (name2, id);
|
||||
|
||||
if (type!=' ')
|
||||
{
|
||||
Generator::fetchMember (mCode, mLiterals, type, name2, id);
|
||||
mNextOperand = false;
|
||||
mExplicit.clear();
|
||||
mOperands.push_back (type=='f' ? 'f' : 'l');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ExprParser::ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
Literals& literals, bool argument)
|
||||
: Parser (errorHandler, context), mLocals (locals), mLiterals (literals),
|
||||
mNextOperand (true), mFirst (true), mArgument (argument)
|
||||
mNextOperand (true), mFirst (true), mArgument (argument), mRefOp (false), mMemberOp (false)
|
||||
{}
|
||||
|
||||
bool ExprParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner)
|
||||
|
@ -251,7 +272,12 @@ namespace Compiler
|
|||
Scanner& scanner)
|
||||
{
|
||||
if (!mExplicit.empty())
|
||||
{
|
||||
if (mMemberOp && handleMemberAccess (name))
|
||||
return true;
|
||||
|
||||
return Parser::parseName (name, loc, scanner);
|
||||
}
|
||||
|
||||
mFirst = false;
|
||||
|
||||
|
@ -281,7 +307,7 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
|
||||
if (mExplicit.empty() && getContext().isId (name))
|
||||
if (mExplicit.empty() && getContext().isId (name2))
|
||||
{
|
||||
mExplicit = name;
|
||||
return true;
|
||||
|
@ -497,6 +523,12 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!mMemberOp && code==Scanner::S_member)
|
||||
{
|
||||
mMemberOp = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parser::parseSpecial (code, loc, scanner);
|
||||
}
|
||||
|
||||
|
@ -609,6 +641,7 @@ namespace Compiler
|
|||
mFirst = true;
|
||||
mExplicit.clear();
|
||||
mRefOp = false;
|
||||
mMemberOp = false;
|
||||
Parser::reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace Compiler
|
|||
bool mArgument;
|
||||
std::string mExplicit;
|
||||
bool mRefOp;
|
||||
bool mMemberOp;
|
||||
|
||||
int getPriority (char op) const;
|
||||
|
||||
|
@ -53,6 +54,8 @@ namespace Compiler
|
|||
|
||||
int parseArguments (const std::string& arguments, Scanner& scanner);
|
||||
|
||||
bool handleMemberAccess (const std::string& name);
|
||||
|
||||
public:
|
||||
|
||||
ExprParser (ErrorHandler& errorHandler, Context& context, Locals& locals,
|
||||
|
|
|
@ -260,6 +260,36 @@ namespace
|
|||
code.push_back (Compiler::Generator::segment5 (44));
|
||||
}
|
||||
|
||||
void opStoreMemberShort (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (59));
|
||||
}
|
||||
|
||||
void opStoreMemberLong (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (60));
|
||||
}
|
||||
|
||||
void opStoreMemberFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (61));
|
||||
}
|
||||
|
||||
void opFetchMemberShort (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (62));
|
||||
}
|
||||
|
||||
void opFetchMemberLong (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (63));
|
||||
}
|
||||
|
||||
void opFetchMemberFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (64));
|
||||
}
|
||||
|
||||
void opRandom (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (Compiler::Generator::segment5 (45));
|
||||
|
@ -644,7 +674,7 @@ namespace Compiler
|
|||
|
||||
if (localType!=valueType)
|
||||
{
|
||||
if (localType=='f' && valueType=='l')
|
||||
if (localType=='f' && (valueType=='l' || valueType=='s'))
|
||||
{
|
||||
opIntToFloat (code);
|
||||
}
|
||||
|
@ -707,6 +737,88 @@ namespace Compiler
|
|||
}
|
||||
}
|
||||
|
||||
void assignToMember (CodeContainer& code, Literals& literals, char localType,
|
||||
const std::string& name, const std::string& id, const CodeContainer& value, char valueType)
|
||||
{
|
||||
int index = literals.addString (name);
|
||||
|
||||
opPushInt (code, index);
|
||||
|
||||
index = literals.addString (id);
|
||||
|
||||
opPushInt (code, index);
|
||||
|
||||
std::copy (value.begin(), value.end(), std::back_inserter (code));
|
||||
|
||||
if (localType!=valueType)
|
||||
{
|
||||
if (localType=='f' && (valueType=='l' || valueType=='s'))
|
||||
{
|
||||
opIntToFloat (code);
|
||||
}
|
||||
else if ((localType=='l' || localType=='s') && valueType=='f')
|
||||
{
|
||||
opFloatToInt (code);
|
||||
}
|
||||
}
|
||||
|
||||
switch (localType)
|
||||
{
|
||||
case 'f':
|
||||
|
||||
opStoreMemberFloat (code);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
|
||||
opStoreMemberShort (code);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
|
||||
opStoreMemberLong (code);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
void fetchMember (CodeContainer& code, Literals& literals, char localType,
|
||||
const std::string& name, const std::string& id)
|
||||
{
|
||||
int index = literals.addString (name);
|
||||
|
||||
opPushInt (code, index);
|
||||
|
||||
index = literals.addString (id);
|
||||
|
||||
opPushInt (code, index);
|
||||
|
||||
switch (localType)
|
||||
{
|
||||
case 'f':
|
||||
|
||||
opFetchMemberFloat (code);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
|
||||
opFetchMemberShort (code);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
|
||||
opFetchMemberLong (code);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
void random (CodeContainer& code)
|
||||
{
|
||||
opRandom (code);
|
||||
|
|
|
@ -101,6 +101,12 @@ namespace Compiler
|
|||
void fetchGlobal (CodeContainer& code, Literals& literals, char localType,
|
||||
const std::string& name);
|
||||
|
||||
void assignToMember (CodeContainer& code, Literals& literals, char memberType,
|
||||
const std::string& name, const std::string& id, const CodeContainer& value, char valueType);
|
||||
|
||||
void fetchMember (CodeContainer& code, Literals& literals, char memberType,
|
||||
const std::string& name, const std::string& id);
|
||||
|
||||
void random (CodeContainer& code);
|
||||
|
||||
void scriptRunning (CodeContainer& code);
|
||||
|
|
|
@ -18,6 +18,9 @@ namespace Compiler
|
|||
if (!mExplicit.empty())
|
||||
{
|
||||
mExprParser.parseName (mExplicit, loc, scanner);
|
||||
if (mState==MemberState)
|
||||
mExprParser.parseSpecial (Scanner::S_member, loc, scanner);
|
||||
else
|
||||
mExprParser.parseSpecial (Scanner::S_ref, loc, scanner);
|
||||
}
|
||||
|
||||
|
@ -110,12 +113,13 @@ namespace Compiler
|
|||
if (mState==SetState)
|
||||
{
|
||||
std::string name2 = toLower (name);
|
||||
mName = name2;
|
||||
|
||||
// local variable?
|
||||
char type = mLocals.getType (name2);
|
||||
if (type!=' ')
|
||||
{
|
||||
mName = name2;
|
||||
mType = type;
|
||||
mState = SetLocalVarState;
|
||||
return true;
|
||||
}
|
||||
|
@ -123,12 +127,27 @@ namespace Compiler
|
|||
type = getContext().getGlobalType (name2);
|
||||
if (type!=' ')
|
||||
{
|
||||
mName = name2;
|
||||
mType = type;
|
||||
mState = SetGlobalVarState;
|
||||
return true;
|
||||
}
|
||||
|
||||
mState = SetPotentialMemberVarState;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mState==SetMemberVarState)
|
||||
{
|
||||
mMemberName = toLower (name);
|
||||
char type = getContext().getMemberType (mMemberName, mName);
|
||||
|
||||
if (type!=' ')
|
||||
{
|
||||
mState = SetMemberVarState2;
|
||||
mType = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
getErrorHandler().error ("unknown variable", loc);
|
||||
SkipParser skip (getErrorHandler(), getContext());
|
||||
scanner.scan (skip);
|
||||
|
@ -256,6 +275,7 @@ namespace Compiler
|
|||
{
|
||||
scanner.putbackKeyword (keyword, loc);
|
||||
parseExpression (scanner, loc);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -269,6 +289,7 @@ namespace Compiler
|
|||
{
|
||||
scanner.putbackKeyword (keyword, loc);
|
||||
parseExpression (scanner, loc);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -333,6 +354,19 @@ namespace Compiler
|
|||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
else if (mState==SetMemberVarState2 && keyword==Scanner::K_to)
|
||||
{
|
||||
mExprParser.reset();
|
||||
scanner.scan (mExprParser);
|
||||
|
||||
std::vector<Interpreter::Type_Code> code;
|
||||
char type = mExprParser.append (code);
|
||||
|
||||
Generator::assignToMember (mCode, mLiterals, mType, mMemberName, mName, code, type);
|
||||
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mAllowExpression)
|
||||
{
|
||||
|
@ -342,6 +376,7 @@ namespace Compiler
|
|||
{
|
||||
scanner.putbackKeyword (keyword, loc);
|
||||
parseExpression (scanner, loc);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -366,6 +401,14 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
|
||||
if (code==Scanner::S_member && mState==PotentialExplicitState)
|
||||
{
|
||||
mState = MemberState;
|
||||
parseExpression (scanner, loc);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (code==Scanner::S_newline && mState==MessageButtonState)
|
||||
{
|
||||
Generator::message (mCode, mLiterals, mName, mButtons);
|
||||
|
@ -378,11 +421,18 @@ namespace Compiler
|
|||
return true;
|
||||
}
|
||||
|
||||
if (code==Scanner::S_member && mState==SetPotentialMemberVarState)
|
||||
{
|
||||
mState = SetMemberVarState;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mAllowExpression && mState==BeginState &&
|
||||
(code==Scanner::S_open || code==Scanner::S_minus))
|
||||
{
|
||||
scanner.putbackSpecial (code, loc);
|
||||
parseExpression (scanner, loc);
|
||||
mState = EndState;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,10 +21,11 @@ namespace Compiler
|
|||
{
|
||||
BeginState,
|
||||
ShortState, LongState, FloatState,
|
||||
SetState, SetLocalVarState, SetGlobalVarState,
|
||||
SetState, SetLocalVarState, SetGlobalVarState, SetPotentialMemberVarState,
|
||||
SetMemberVarState, SetMemberVarState2,
|
||||
MessageState, MessageCommaState, MessageButtonState, MessageButtonCommaState,
|
||||
EndState,
|
||||
PotentialExplicitState, ExplicitState
|
||||
PotentialExplicitState, ExplicitState, MemberState
|
||||
};
|
||||
|
||||
Locals& mLocals;
|
||||
|
@ -32,6 +33,7 @@ namespace Compiler
|
|||
std::vector<Interpreter::Type_Code>& mCode;
|
||||
State mState;
|
||||
std::string mName;
|
||||
std::string mMemberName;
|
||||
int mButtons;
|
||||
std::string mExplicit;
|
||||
char mType;
|
||||
|
|
|
@ -360,6 +360,8 @@ namespace Compiler
|
|||
special = S_open;
|
||||
else if (c==')')
|
||||
special = S_close;
|
||||
else if (c=='.')
|
||||
special = S_member;
|
||||
else if (c=='=')
|
||||
{
|
||||
if (get (c))
|
||||
|
|
|
@ -65,7 +65,8 @@ namespace Compiler
|
|||
S_cmpEQ, S_cmpNE, S_cmpLT, S_cmpLE, S_cmpGT, S_cmpGE,
|
||||
S_plus, S_minus, S_mult, S_div,
|
||||
S_comma,
|
||||
S_ref
|
||||
S_ref,
|
||||
S_member
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -65,6 +65,19 @@ namespace Interpreter
|
|||
virtual void enable (const std::string& id = "") = 0;
|
||||
|
||||
virtual void disable (const std::string& id = "") = 0;
|
||||
|
||||
virtual int getMemberShort (const std::string& id, const std::string& name) const = 0;
|
||||
|
||||
virtual int getMemberLong (const std::string& id, const std::string& name) const = 0;
|
||||
|
||||
virtual float getMemberFloat (const std::string& id, const std::string& name) const = 0;
|
||||
|
||||
virtual void setMemberShort (const std::string& id, const std::string& name, int value) = 0;
|
||||
|
||||
virtual void setMemberLong (const std::string& id, const std::string& name, int value) = 0;
|
||||
|
||||
virtual void setMemberFloat (const std::string& id, const std::string& name, float value)
|
||||
= 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -121,5 +121,11 @@ op 58: report string literal index in stack[0];
|
|||
additional arguments (if any) in stack[n]..stack[1];
|
||||
n is determined according to the message string
|
||||
all arguments are removed from stack
|
||||
opcodes 59-33554431 unused
|
||||
op 59: store stack[0] in member short stack[2] of object with ID stack[1]
|
||||
op 60: store stack[0] in member long stack[2] of object with ID stack[1]
|
||||
op 61: store stack[0] in member float stack[2] of object with ID stack[1]
|
||||
op 62: replace stack[0] with member short stack[1] of object with ID stack[0]
|
||||
op 63: replace stack[0] with member short stack[1] of object with ID stack[0]
|
||||
op 64: replace stack[0] with member short stack[1] of object with ID stack[0]
|
||||
opcodes 65-33554431 unused
|
||||
opcodes 33554432-67108863 reserved for extensions
|
||||
|
|
|
@ -40,6 +40,12 @@ namespace Interpreter
|
|||
interpreter.installSegment5 (42, new OpFetchGlobalShort);
|
||||
interpreter.installSegment5 (43, new OpFetchGlobalLong);
|
||||
interpreter.installSegment5 (44, new OpFetchGlobalFloat);
|
||||
interpreter.installSegment5 (59, new OpStoreMemberShort);
|
||||
interpreter.installSegment5 (60, new OpStoreMemberLong);
|
||||
interpreter.installSegment5 (61, new OpStoreMemberFloat);
|
||||
interpreter.installSegment5 (62, new OpFetchMemberShort);
|
||||
interpreter.installSegment5 (63, new OpFetchMemberLong);
|
||||
interpreter.installSegment5 (64, new OpFetchMemberFloat);
|
||||
|
||||
// math
|
||||
interpreter.installSegment5 (9, new OpAddInt<Type_Integer>);
|
||||
|
|
|
@ -205,7 +205,117 @@ namespace Interpreter
|
|||
runtime[0].mFloat = value;
|
||||
}
|
||||
};
|
||||
|
||||
class OpStoreMemberShort : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Integer data = runtime[0].mInteger;
|
||||
Type_Integer index = runtime[1].mInteger;
|
||||
std::string id = runtime.getStringLiteral (index);
|
||||
index = runtime[2].mInteger;
|
||||
std::string variable = runtime.getStringLiteral (index);
|
||||
|
||||
runtime.getContext().setMemberShort (id, variable, data);
|
||||
|
||||
runtime.pop();
|
||||
runtime.pop();
|
||||
runtime.pop();
|
||||
}
|
||||
};
|
||||
|
||||
class OpStoreMemberLong : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Integer data = runtime[0].mInteger;
|
||||
Type_Integer index = runtime[1].mInteger;
|
||||
std::string id = runtime.getStringLiteral (index);
|
||||
index = runtime[2].mInteger;
|
||||
std::string variable = runtime.getStringLiteral (index);
|
||||
|
||||
runtime.getContext().setMemberLong (id, variable, data);
|
||||
|
||||
runtime.pop();
|
||||
runtime.pop();
|
||||
runtime.pop();
|
||||
}
|
||||
};
|
||||
|
||||
class OpStoreMemberFloat : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Float data = runtime[0].mFloat;
|
||||
Type_Integer index = runtime[1].mInteger;
|
||||
std::string id = runtime.getStringLiteral (index);
|
||||
index = runtime[2].mInteger;
|
||||
std::string variable = runtime.getStringLiteral (index);
|
||||
|
||||
runtime.getContext().setMemberFloat (id, variable, data);
|
||||
|
||||
runtime.pop();
|
||||
runtime.pop();
|
||||
runtime.pop();
|
||||
}
|
||||
};
|
||||
|
||||
class OpFetchMemberShort : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Integer index = runtime[0].mInteger;
|
||||
std::string id = runtime.getStringLiteral (index);
|
||||
index = runtime[1].mInteger;
|
||||
std::string variable = runtime.getStringLiteral (index);
|
||||
runtime.pop();
|
||||
|
||||
int value = runtime.getContext().getMemberShort (id, variable);
|
||||
runtime[0].mInteger = value;
|
||||
}
|
||||
};
|
||||
|
||||
class OpFetchMemberLong : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Integer index = runtime[0].mInteger;
|
||||
std::string id = runtime.getStringLiteral (index);
|
||||
index = runtime[1].mInteger;
|
||||
std::string variable = runtime.getStringLiteral (index);
|
||||
runtime.pop();
|
||||
|
||||
int value = runtime.getContext().getMemberLong (id, variable);
|
||||
runtime[0].mInteger = value;
|
||||
}
|
||||
};
|
||||
|
||||
class OpFetchMemberFloat : public Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Runtime& runtime)
|
||||
{
|
||||
Type_Integer index = runtime[0].mInteger;
|
||||
std::string id = runtime.getStringLiteral (index);
|
||||
index = runtime[1].mInteger;
|
||||
std::string variable = runtime.getStringLiteral (index);
|
||||
runtime.pop();
|
||||
|
||||
float value = runtime.getContext().getMemberFloat (id, variable);
|
||||
runtime[0].mFloat = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue