forked from teamnwah/openmw-tes3coop
added return and messagebox statements (messagebox does neither formating nor buttons yet)
This commit is contained in:
parent
8bb2a6039d
commit
fac8fb8fcb
14 changed files with 156 additions and 5 deletions
|
@ -67,6 +67,14 @@ namespace SAInterpreter
|
||||||
mFloats.at (index) = value;
|
mFloats.at (index) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::messageBox (const std::string& message,
|
||||||
|
const std::vector<std::string>& buttons)
|
||||||
|
{
|
||||||
|
std::cout << "message box: " << message << std::endl;
|
||||||
|
for (std::size_t i=0; i<buttons.size(); ++i)
|
||||||
|
std::cout << " button " << i << ": " << buttons[i] << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
void Context::report()
|
void Context::report()
|
||||||
{
|
{
|
||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
|
|
|
@ -35,6 +35,9 @@ namespace SAInterpreter
|
||||||
|
|
||||||
virtual void setLocalFloat (int index, float value);
|
virtual void setLocalFloat (int index, float value);
|
||||||
|
|
||||||
|
virtual void messageBox (const std::string& message,
|
||||||
|
const std::vector<std::string>& buttons);
|
||||||
|
|
||||||
void report();
|
void report();
|
||||||
///< Write state to std::cout
|
///< Write state to std::cout
|
||||||
};
|
};
|
||||||
|
|
|
@ -150,6 +150,16 @@ namespace
|
||||||
{
|
{
|
||||||
code.push_back (segment5 (19));
|
code.push_back (segment5 (19));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opReturn (Compiler::Generator::CodeContainer& code)
|
||||||
|
{
|
||||||
|
code.push_back (segment5 (20));
|
||||||
|
}
|
||||||
|
|
||||||
|
void opMessageBox (Compiler::Generator::CodeContainer& code, int buttons)
|
||||||
|
{
|
||||||
|
code.push_back (segment3 (0, buttons));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Compiler
|
namespace Compiler
|
||||||
|
@ -321,6 +331,22 @@ namespace Compiler
|
||||||
{
|
{
|
||||||
opSquareRoot (code);
|
opSquareRoot (code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exit (CodeContainer& code)
|
||||||
|
{
|
||||||
|
opReturn (code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void message (CodeContainer& code, Literals& literals, const std::string& message,
|
||||||
|
int buttons)
|
||||||
|
{
|
||||||
|
assert (buttons==0);
|
||||||
|
|
||||||
|
int index = literals.addString (message);
|
||||||
|
|
||||||
|
opPushInt (code, index);
|
||||||
|
opMessageBox (code, buttons);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define COMPILER_GENERATOR_H_INCLUDED
|
#define COMPILER_GENERATOR_H_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <components/interpreter/types.hpp>
|
#include <components/interpreter/types.hpp>
|
||||||
|
|
||||||
|
@ -33,6 +34,11 @@ namespace Compiler
|
||||||
void convert (CodeContainer& code, char fromType, char toType);
|
void convert (CodeContainer& code, char fromType, char toType);
|
||||||
|
|
||||||
void squareRoot (CodeContainer& code);
|
void squareRoot (CodeContainer& code);
|
||||||
|
|
||||||
|
void exit (CodeContainer& code);
|
||||||
|
|
||||||
|
void message (CodeContainer& code, Literals& literals, const std::string& message,
|
||||||
|
int buttons);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,13 @@ namespace Compiler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mState==MessageState || mState==MessageCommaState)
|
||||||
|
{
|
||||||
|
Generator::message (mCode, mLiterals, name, 0);
|
||||||
|
mState = EndState;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return Parser::parseName (name, loc, scanner);
|
return Parser::parseName (name, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +96,13 @@ namespace Compiler
|
||||||
case Scanner::K_long: mState = LongState; return true;
|
case Scanner::K_long: mState = LongState; return true;
|
||||||
case Scanner::K_float: mState = FloatState; return true;
|
case Scanner::K_float: mState = FloatState; return true;
|
||||||
case Scanner::K_set: mState = SetState; return true;
|
case Scanner::K_set: mState = SetState; return true;
|
||||||
|
case Scanner::K_messagebox: mState = MessageState; return true;
|
||||||
|
|
||||||
|
case Scanner::K_return:
|
||||||
|
|
||||||
|
Generator::exit (mCode);
|
||||||
|
mState = EndState;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mState==SetLocalVarState && keyword==Scanner::K_to)
|
else if (mState==SetLocalVarState && keyword==Scanner::K_to)
|
||||||
|
@ -114,6 +128,12 @@ namespace Compiler
|
||||||
if (code==Scanner::S_newline && mState==EndState)
|
if (code==Scanner::S_newline && mState==EndState)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (code==Scanner::S_comma && mState==MessageState)
|
||||||
|
{
|
||||||
|
mState = MessageCommaState;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return Parser::parseSpecial (code, loc, scanner);
|
return Parser::parseSpecial (code, loc, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace Compiler
|
||||||
BeginState,
|
BeginState,
|
||||||
ShortState, LongState, FloatState,
|
ShortState, LongState, FloatState,
|
||||||
SetState, SetLocalVarState,
|
SetState, SetLocalVarState,
|
||||||
|
MessageState, MessageCommaState,
|
||||||
EndState
|
EndState
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Compiler
|
||||||
K_if, K_endif, K_else, K_elseif,
|
K_if, K_endif, K_else, K_elseif,
|
||||||
K_while, K_endwhile,
|
K_while, K_endwhile,
|
||||||
K_return,
|
K_return,
|
||||||
K_messageBox,
|
K_messagebox,
|
||||||
K_set, K_to,
|
K_set, K_to,
|
||||||
K_getsquareroot
|
K_getsquareroot
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,6 +20,9 @@ namespace Interpreter
|
||||||
virtual void setLocalLong (int index, int value) = 0;
|
virtual void setLocalLong (int index, int value) = 0;
|
||||||
|
|
||||||
virtual void setLocalFloat (int index, float value) = 0;
|
virtual void setLocalFloat (int index, float value) = 0;
|
||||||
|
|
||||||
|
virtual void messageBox (const std::string& message,
|
||||||
|
const std::vector<std::string>& buttons) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
20
components/interpreter/controlopcodes.hpp
Normal file
20
components/interpreter/controlopcodes.hpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef INTERPRETER_CONTROLOPCODES_H_INCLUDED
|
||||||
|
#define INTERPRETER_CONTROLOPCODES_H_INCLUDED
|
||||||
|
|
||||||
|
#include "opcodes.hpp"
|
||||||
|
#include "runtime.hpp"
|
||||||
|
|
||||||
|
namespace Interpreter
|
||||||
|
{
|
||||||
|
class OpReturn : public Opcode0
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Runtime& runtime)
|
||||||
|
{
|
||||||
|
runtime.setPC (-1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -43,7 +43,12 @@ opcodes 0-511 unused
|
||||||
opcodes 512-1023 reserved for extensions
|
opcodes 512-1023 reserved for extensions
|
||||||
|
|
||||||
Segment 3:
|
Segment 3:
|
||||||
opcodes 0-511 unused
|
op 0: show message box with message string literal index in stack[0];
|
||||||
|
buttons (if any) in stack[arg0]..stack[1];
|
||||||
|
additional arguments (if any) in stack[arg0+n]..stack[arg0+1];
|
||||||
|
n is determined according to the message string
|
||||||
|
all arguments are removed from stack
|
||||||
|
opcodes 1-511 unused
|
||||||
opcodes 512-1023 reserved for extensions
|
opcodes 512-1023 reserved for extensions
|
||||||
|
|
||||||
Segment 4:
|
Segment 4:
|
||||||
|
@ -71,6 +76,7 @@ op 16: div (float) stack[1] by stack[0], pop twice, push result
|
||||||
op 17: convert stack[1] from integer to float
|
op 17: convert stack[1] from integer to float
|
||||||
op 18: convert stack[1] from float to integer
|
op 18: convert stack[1] from float to integer
|
||||||
op 19: take square root of stack[0] (float)
|
op 19: take square root of stack[0] (float)
|
||||||
opcodes 20-33554431 unused
|
op 20: return
|
||||||
|
opcodes 21-33554431 unused
|
||||||
opcodes 33554432-67108863 reserved for extensions
|
opcodes 33554432-67108863 reserved for extensions
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include "genericopcodes.hpp"
|
#include "genericopcodes.hpp"
|
||||||
#include "localopcodes.hpp"
|
#include "localopcodes.hpp"
|
||||||
#include "mathopcodes.hpp"
|
#include "mathopcodes.hpp"
|
||||||
|
#include "controlopcodes.hpp"
|
||||||
|
#include "miscopcodes.hpp"
|
||||||
|
|
||||||
namespace Interpreter
|
namespace Interpreter
|
||||||
{
|
{
|
||||||
|
@ -36,6 +38,12 @@ namespace Interpreter
|
||||||
interpreter.installSegment5 (15, new OpDivInt<Type_Integer>);
|
interpreter.installSegment5 (15, new OpDivInt<Type_Integer>);
|
||||||
interpreter.installSegment5 (16, new OpDivInt<Type_Float>);
|
interpreter.installSegment5 (16, new OpDivInt<Type_Float>);
|
||||||
interpreter.installSegment5 (19, new OpSquareRoot);
|
interpreter.installSegment5 (19, new OpSquareRoot);
|
||||||
|
|
||||||
|
// control structures
|
||||||
|
interpreter.installSegment5 (20, new OpReturn);
|
||||||
|
|
||||||
|
// misc
|
||||||
|
interpreter.installSegment3 (0, new OpMessageBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
components/interpreter/miscopcodes.hpp
Normal file
31
components/interpreter/miscopcodes.hpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef INTERPRETER_MISCOPCODES_H_INCLUDED
|
||||||
|
#define INTERPRETER_MISCOPCODES_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "opcodes.hpp"
|
||||||
|
#include "runtime.hpp"
|
||||||
|
|
||||||
|
namespace Interpreter
|
||||||
|
{
|
||||||
|
class OpMessageBox : public Opcode1
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void execute (Runtime& runtime, unsigned int arg0)
|
||||||
|
{
|
||||||
|
if (arg0!=0)
|
||||||
|
throw std::logic_error ("message box buttons not implemented yet");
|
||||||
|
|
||||||
|
int index = runtime[0];
|
||||||
|
runtime.pop();
|
||||||
|
std::vector<std::string> buttons;
|
||||||
|
runtime.getContext().messageBox (runtime.getStringLiteral (index), buttons);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace Interpreter
|
namespace Interpreter
|
||||||
{
|
{
|
||||||
|
@ -31,6 +32,21 @@ namespace Interpreter
|
||||||
return *reinterpret_cast<const float *> (&literalBlock[index]);
|
return *reinterpret_cast<const float *> (&literalBlock[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Runtime::getStringLiteral (int index) const
|
||||||
|
{
|
||||||
|
assert (index>=0 && index<static_cast<int> (mCode[3]));
|
||||||
|
|
||||||
|
const char *literalBlock =
|
||||||
|
reinterpret_cast<const char *> (mCode + 4 + mCode[0] + mCode[1] + mCode[2]);
|
||||||
|
|
||||||
|
for (; index; --index)
|
||||||
|
{
|
||||||
|
literalBlock += std::strlen (literalBlock) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return literalBlock;
|
||||||
|
}
|
||||||
|
|
||||||
void Runtime::configure (const Interpreter::Type_Code *code, int codeSize)
|
void Runtime::configure (const Interpreter::Type_Code *code, int codeSize)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define INTERPRETER_RUNTIME_H_INCLUDED
|
#define INTERPRETER_RUNTIME_H_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
|
||||||
|
@ -30,6 +31,8 @@ namespace Interpreter
|
||||||
|
|
||||||
float getFloatLiteral (int index) const;
|
float getFloatLiteral (int index) const;
|
||||||
|
|
||||||
|
std::string getStringLiteral (int index) const;
|
||||||
|
|
||||||
void configure (const Type_Code *code, int codeSize);
|
void configure (const Type_Code *code, int codeSize);
|
||||||
///< \a context and \a code must exist as least until either configure, clear or
|
///< \a context and \a code must exist as least until either configure, clear or
|
||||||
/// the destructor is called. \a codeSize is given in 32-bit words.
|
/// the destructor is called. \a codeSize is given in 32-bit words.
|
||||||
|
|
Loading…
Reference in a new issue