mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 17:29:55 +00:00
added custom function handling (compiler)
This commit is contained in:
parent
a1beffc3cd
commit
32eafaa301
6 changed files with 186 additions and 83 deletions
|
@ -18,8 +18,15 @@ namespace Compiler
|
|||
virtual bool canDeclareLocals() const = 0;
|
||||
///< Is the compiler allowed to declare local variables?
|
||||
|
||||
void setExtensions (const Extensions *extensions = 0);
|
||||
///< Set compiler extensions.
|
||||
void setExtensions (const Extensions *extensions = 0)
|
||||
{
|
||||
mExtensions = extensions;
|
||||
}
|
||||
|
||||
const Extensions *getExtensions() const
|
||||
{
|
||||
return mExtensions;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "errorhandler.hpp"
|
||||
#include "locals.hpp"
|
||||
#include "stringparser.hpp"
|
||||
#include "extensions.hpp"
|
||||
#include "context.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
|
@ -279,6 +281,27 @@ namespace Compiler
|
|||
mNextOperand = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// check for custom extensions
|
||||
if (const Extensions *extensions = getContext().getExtensions())
|
||||
{
|
||||
char returnType;
|
||||
std::string argumentType;
|
||||
|
||||
if (extensions->isFunction (keyword, returnType, argumentType))
|
||||
{
|
||||
mTokenLoc = loc;
|
||||
parseArguments (argumentType, scanner);
|
||||
|
||||
extensions->generateFunctionCode (keyword, mCode);
|
||||
mOperands.push_back (returnType);
|
||||
|
||||
mNextOperand = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
|
||||
#include "extensions.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "generator.hpp"
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
|
||||
Extensions::Extensions() : mNextKeywordIndex (-1) {}
|
||||
|
||||
int Extensions::searchKeyword (const std::string& keyword) const
|
||||
|
@ -15,4 +19,44 @@ namespace Compiler
|
|||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
bool Extensions::isFunction (int keyword, char& returnType, std::string& argumentType) const
|
||||
{
|
||||
std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
|
||||
|
||||
if (iter==mFunctions.end())
|
||||
return false;
|
||||
|
||||
returnType = iter->second.mReturn;
|
||||
argumentType = iter->second.mArguments;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Extensions::registerFunction (const std::string& keyword, char returnType,
|
||||
const std::string& argumentType, int segment5code)
|
||||
{
|
||||
assert (segment5code>=33554432 && segment5code<=67108863);
|
||||
|
||||
int code = mNextKeywordIndex--;
|
||||
|
||||
mKeywords.insert (std::make_pair (keyword, code));
|
||||
|
||||
Function function;
|
||||
function.mReturn = returnType;
|
||||
function.mArguments = argumentType;
|
||||
function.mCode = segment5code;
|
||||
|
||||
mFunctions.insert (std::make_pair (code, function));
|
||||
}
|
||||
|
||||
void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code)
|
||||
const
|
||||
{
|
||||
std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
|
||||
|
||||
if (iter==mFunctions.end())
|
||||
throw std::logic_error ("unknown custom function keyword");
|
||||
|
||||
Generator::segment5 (iter->second.mCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <components/interpreter/types.hpp>
|
||||
|
||||
namespace Compiler
|
||||
{
|
||||
|
@ -10,8 +13,16 @@ namespace Compiler
|
|||
|
||||
class Extensions
|
||||
{
|
||||
struct Function
|
||||
{
|
||||
char mReturn;
|
||||
std::string mArguments;
|
||||
int mCode;
|
||||
};
|
||||
|
||||
int mNextKeywordIndex;
|
||||
std::map<std::string, int> mKeywords;
|
||||
std::map<int, Function> mFunctions;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -21,6 +32,21 @@ namespace Compiler
|
|||
///< Return extension keyword code, that is assigned to the string \a keyword.
|
||||
/// - if no match is found 0 is returned.
|
||||
/// - keyword must be all lower case.
|
||||
|
||||
bool isFunction (int keyword, char& returnType, std::string& argumentType) const;
|
||||
///< Is this keyword registered with a function? If yes, return return and argument
|
||||
/// types.
|
||||
|
||||
void registerFunction (const std::string& keyword, char returnType,
|
||||
const std::string& argumentType, int segment5code);
|
||||
///< Register a custom function
|
||||
/// - keyword must be all lower case.
|
||||
/// - keyword must be unique
|
||||
/// \note Currently only segment 5 opcodes are supported.
|
||||
|
||||
void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code)
|
||||
const;
|
||||
///< Append code for function to \a code.
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -10,250 +10,214 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
Interpreter::Type_Code segment0 (unsigned int c, unsigned int arg0)
|
||||
{
|
||||
assert (c<64);
|
||||
return (c<<24) | (arg0 & 0xffffff);
|
||||
}
|
||||
|
||||
Interpreter::Type_Code segment1 (unsigned int c, unsigned int arg0, unsigned int arg1)
|
||||
{
|
||||
assert (c<64);
|
||||
return 0x40000000 | (c<<24) | ((arg0 & 0xfff)<<12) | (arg1 & 0xfff);
|
||||
}
|
||||
|
||||
Interpreter::Type_Code segment2 (unsigned int c, unsigned int arg0)
|
||||
{
|
||||
assert (c<1024);
|
||||
return 0x80000000 | (c<<20) | (arg0 & 0xfffff);
|
||||
}
|
||||
|
||||
Interpreter::Type_Code segment3 (unsigned int c, unsigned int arg0)
|
||||
{
|
||||
assert (c<1024);
|
||||
return 0xc0000000 | (c<<20) | (arg0 & 0xffff);
|
||||
}
|
||||
|
||||
Interpreter::Type_Code segment4 (unsigned int c, unsigned int arg0, unsigned int arg1)
|
||||
{
|
||||
assert (c<1024);
|
||||
return 0xc4000000 | (c<<16) | ((arg0 & 0xff)<<8) | (arg1 & 0xff);
|
||||
}
|
||||
|
||||
Interpreter::Type_Code segment5 (unsigned int c)
|
||||
{
|
||||
assert (c<67108864);
|
||||
return 0xc8000000 | c;
|
||||
}
|
||||
|
||||
void opPushInt (Compiler::Generator::CodeContainer& code, int value)
|
||||
{
|
||||
code.push_back (segment0 (0, value));
|
||||
code.push_back (Compiler::Generator::segment0 (0, value));
|
||||
}
|
||||
|
||||
void opFetchIntLiteral (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (4));
|
||||
code.push_back (Compiler::Generator::segment5 (4));
|
||||
}
|
||||
|
||||
void opFetchFloatLiteral (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (5));
|
||||
code.push_back (Compiler::Generator::segment5 (5));
|
||||
}
|
||||
|
||||
void opIntToFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (3));
|
||||
code.push_back (Compiler::Generator::segment5 (3));
|
||||
}
|
||||
|
||||
void opFloatToInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (6));
|
||||
code.push_back (Compiler::Generator::segment5 (6));
|
||||
}
|
||||
|
||||
void opStoreLocalShort (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (0));
|
||||
code.push_back (Compiler::Generator::segment5 (0));
|
||||
}
|
||||
|
||||
void opStoreLocalLong (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (1));
|
||||
code.push_back (Compiler::Generator::segment5 (1));
|
||||
}
|
||||
|
||||
void opStoreLocalFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (2));
|
||||
code.push_back (Compiler::Generator::segment5 (2));
|
||||
}
|
||||
|
||||
void opNegateInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (7));
|
||||
code.push_back (Compiler::Generator::segment5 (7));
|
||||
}
|
||||
|
||||
void opNegateFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (8));
|
||||
code.push_back (Compiler::Generator::segment5 (8));
|
||||
}
|
||||
|
||||
void opAddInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (9));
|
||||
code.push_back (Compiler::Generator::segment5 (9));
|
||||
}
|
||||
|
||||
void opAddFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (10));
|
||||
code.push_back (Compiler::Generator::segment5 (10));
|
||||
}
|
||||
|
||||
void opSubInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (11));
|
||||
code.push_back (Compiler::Generator::segment5 (11));
|
||||
}
|
||||
|
||||
void opSubFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (12));
|
||||
code.push_back (Compiler::Generator::segment5 (12));
|
||||
}
|
||||
|
||||
void opMulInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (13));
|
||||
code.push_back (Compiler::Generator::segment5 (13));
|
||||
}
|
||||
|
||||
void opMulFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (14));
|
||||
code.push_back (Compiler::Generator::segment5 (14));
|
||||
}
|
||||
|
||||
void opDivInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (15));
|
||||
code.push_back (Compiler::Generator::segment5 (15));
|
||||
}
|
||||
|
||||
void opDivFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (16));
|
||||
code.push_back (Compiler::Generator::segment5 (16));
|
||||
}
|
||||
|
||||
void opIntToFloat1 (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (17));
|
||||
code.push_back (Compiler::Generator::segment5 (17));
|
||||
}
|
||||
|
||||
void opFloatToInt1 (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (18));
|
||||
code.push_back (Compiler::Generator::segment5 (18));
|
||||
}
|
||||
|
||||
void opSquareRoot (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (19));
|
||||
code.push_back (Compiler::Generator::segment5 (19));
|
||||
}
|
||||
|
||||
void opReturn (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (20));
|
||||
code.push_back (Compiler::Generator::segment5 (20));
|
||||
}
|
||||
|
||||
void opMessageBox (Compiler::Generator::CodeContainer& code, int buttons)
|
||||
{
|
||||
code.push_back (segment3 (0, buttons));
|
||||
code.push_back (Compiler::Generator::segment3 (0, buttons));
|
||||
}
|
||||
|
||||
void opFetchLocalShort (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (21));
|
||||
code.push_back (Compiler::Generator::segment5 (21));
|
||||
}
|
||||
|
||||
void opFetchLocalLong (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (22));
|
||||
code.push_back (Compiler::Generator::segment5 (22));
|
||||
}
|
||||
|
||||
void opFetchLocalFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (23));
|
||||
code.push_back (Compiler::Generator::segment5 (23));
|
||||
}
|
||||
|
||||
void opJumpForward (Compiler::Generator::CodeContainer& code, int offset)
|
||||
{
|
||||
code.push_back (segment0 (1, offset));
|
||||
code.push_back (Compiler::Generator::segment0 (1, offset));
|
||||
}
|
||||
|
||||
void opJumpBackward (Compiler::Generator::CodeContainer& code, int offset)
|
||||
{
|
||||
code.push_back (segment0 (2, offset));
|
||||
code.push_back (Compiler::Generator::segment0 (2, offset));
|
||||
}
|
||||
|
||||
void opSkipOnZero (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (24));
|
||||
code.push_back (Compiler::Generator::segment5 (24));
|
||||
}
|
||||
|
||||
void opSkipOnNonZero (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (25));
|
||||
code.push_back (Compiler::Generator::segment5 (25));
|
||||
}
|
||||
|
||||
void opEqualInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (26));
|
||||
code.push_back (Compiler::Generator::segment5 (26));
|
||||
}
|
||||
|
||||
void opNonEqualInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (27));
|
||||
code.push_back (Compiler::Generator::segment5 (27));
|
||||
}
|
||||
|
||||
void opLessThanInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (28));
|
||||
code.push_back (Compiler::Generator::segment5 (28));
|
||||
}
|
||||
|
||||
void opLessOrEqualInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (29));
|
||||
code.push_back (Compiler::Generator::segment5 (29));
|
||||
}
|
||||
|
||||
void opGreaterThanInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (30));
|
||||
code.push_back (Compiler::Generator::segment5 (30));
|
||||
}
|
||||
|
||||
void opGreaterOrEqualInt (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (31));
|
||||
code.push_back (Compiler::Generator::segment5 (31));
|
||||
}
|
||||
|
||||
void opEqualFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (32));
|
||||
code.push_back (Compiler::Generator::segment5 (32));
|
||||
}
|
||||
|
||||
void opNonEqualFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (33));
|
||||
code.push_back (Compiler::Generator::segment5 (33));
|
||||
}
|
||||
|
||||
void opLessThanFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (34));
|
||||
code.push_back (Compiler::Generator::segment5 (34));
|
||||
}
|
||||
|
||||
void opLessOrEqualFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (35));
|
||||
code.push_back (Compiler::Generator::segment5 (35));
|
||||
}
|
||||
|
||||
void opGreaterThanFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (36));
|
||||
code.push_back (Compiler::Generator::segment5 (36));
|
||||
}
|
||||
|
||||
void opGreaterOrEqualFloat (Compiler::Generator::CodeContainer& code)
|
||||
{
|
||||
code.push_back (segment5 (37));
|
||||
code.push_back (Compiler::Generator::segment5 (37));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include <components/interpreter/types.hpp>
|
||||
|
||||
|
@ -14,6 +15,44 @@ namespace Compiler
|
|||
{
|
||||
typedef std::vector<Interpreter::Type_Code> CodeContainer;
|
||||
|
||||
inline Interpreter::Type_Code segment0 (unsigned int c, unsigned int arg0)
|
||||
{
|
||||
assert (c<64);
|
||||
return (c<<24) | (arg0 & 0xffffff);
|
||||
}
|
||||
|
||||
inline Interpreter::Type_Code segment1 (unsigned int c, unsigned int arg0,
|
||||
unsigned int arg1)
|
||||
{
|
||||
assert (c<64);
|
||||
return 0x40000000 | (c<<24) | ((arg0 & 0xfff)<<12) | (arg1 & 0xfff);
|
||||
}
|
||||
|
||||
inline Interpreter::Type_Code segment2 (unsigned int c, unsigned int arg0)
|
||||
{
|
||||
assert (c<1024);
|
||||
return 0x80000000 | (c<<20) | (arg0 & 0xfffff);
|
||||
}
|
||||
|
||||
inline Interpreter::Type_Code segment3 (unsigned int c, unsigned int arg0)
|
||||
{
|
||||
assert (c<1024);
|
||||
return 0xc0000000 | (c<<20) | (arg0 & 0xffff);
|
||||
}
|
||||
|
||||
inline Interpreter::Type_Code segment4 (unsigned int c, unsigned int arg0,
|
||||
unsigned int arg1)
|
||||
{
|
||||
assert (c<1024);
|
||||
return 0xc4000000 | (c<<16) | ((arg0 & 0xff)<<8) | (arg1 & 0xff);
|
||||
}
|
||||
|
||||
inline Interpreter::Type_Code segment5 (unsigned int c)
|
||||
{
|
||||
assert (c<67108864);
|
||||
return 0xc8000000 | c;
|
||||
}
|
||||
|
||||
void pushInt (CodeContainer& code, Literals& literals, int value);
|
||||
|
||||
void pushFloat (CodeContainer& code, Literals& literals, float value);
|
||||
|
|
Loading…
Reference in a new issue