forked from teamnwah/openmw-tes3coop
enhanced compiler extenion system to support new instructions and functions with explicit references
This commit is contained in:
parent
69e607e140
commit
71c710f9f6
4 changed files with 73 additions and 29 deletions
|
@ -324,6 +324,27 @@ namespace Compiler
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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, mLiterals, mExplicit);
|
||||||
|
mOperands.push_back (returnType);
|
||||||
|
mExplicit.clear();
|
||||||
|
mRefOp = false;
|
||||||
|
|
||||||
|
mNextOperand = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseKeyword (keyword, loc, scanner);
|
return Parser::parseKeyword (keyword, loc, scanner);
|
||||||
|
@ -418,7 +439,7 @@ namespace Compiler
|
||||||
mTokenLoc = loc;
|
mTokenLoc = loc;
|
||||||
parseArguments (argumentType, scanner);
|
parseArguments (argumentType, scanner);
|
||||||
|
|
||||||
extensions->generateFunctionCode (keyword, mCode);
|
extensions->generateFunctionCode (keyword, mCode, mLiterals, "");
|
||||||
mOperands.push_back (returnType);
|
mOperands.push_back (returnType);
|
||||||
|
|
||||||
mNextOperand = false;
|
mNextOperand = false;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "generator.hpp"
|
#include "generator.hpp"
|
||||||
|
#include "literals.hpp"
|
||||||
|
|
||||||
namespace Compiler
|
namespace Compiler
|
||||||
{
|
{
|
||||||
|
@ -44,7 +45,7 @@ namespace Compiler
|
||||||
}
|
}
|
||||||
|
|
||||||
void Extensions::registerFunction (const std::string& keyword, char returnType,
|
void Extensions::registerFunction (const std::string& keyword, char returnType,
|
||||||
const std::string& argumentType, int segment5code)
|
const std::string& argumentType, int segment5code, int segment5codeExplicit)
|
||||||
{
|
{
|
||||||
assert (segment5code>=33554432 && segment5code<=67108863);
|
assert (segment5code>=33554432 && segment5code<=67108863);
|
||||||
|
|
||||||
|
@ -56,12 +57,13 @@ namespace Compiler
|
||||||
function.mReturn = returnType;
|
function.mReturn = returnType;
|
||||||
function.mArguments = argumentType;
|
function.mArguments = argumentType;
|
||||||
function.mCode = segment5code;
|
function.mCode = segment5code;
|
||||||
|
function.mCodeExplicit = segment5codeExplicit;
|
||||||
|
|
||||||
mFunctions.insert (std::make_pair (code, function));
|
mFunctions.insert (std::make_pair (code, function));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Extensions::registerInstruction (const std::string& keyword,
|
void Extensions::registerInstruction (const std::string& keyword,
|
||||||
const std::string& argumentType, int segment5code)
|
const std::string& argumentType, int segment5code, int segment5codeExplicit)
|
||||||
{
|
{
|
||||||
assert (segment5code>=33554432 && segment5code<=67108863);
|
assert (segment5code>=33554432 && segment5code<=67108863);
|
||||||
|
|
||||||
|
@ -72,23 +74,31 @@ namespace Compiler
|
||||||
Instruction instruction;
|
Instruction instruction;
|
||||||
instruction.mArguments = argumentType;
|
instruction.mArguments = argumentType;
|
||||||
instruction.mCode = segment5code;
|
instruction.mCode = segment5code;
|
||||||
|
instruction.mCodeExplicit = segment5codeExplicit;
|
||||||
|
|
||||||
mInstructions.insert (std::make_pair (code, instruction));
|
mInstructions.insert (std::make_pair (code, instruction));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code)
|
void Extensions::generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
|
||||||
const
|
Literals& literals, const std::string& id) const
|
||||||
{
|
{
|
||||||
std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
|
std::map<int, Function>::const_iterator iter = mFunctions.find (keyword);
|
||||||
|
|
||||||
if (iter==mFunctions.end())
|
if (iter==mFunctions.end())
|
||||||
throw std::logic_error ("unknown custom function keyword");
|
throw std::logic_error ("unknown custom function keyword");
|
||||||
|
|
||||||
code.push_back (Generator::segment5 (iter->second.mCode));
|
if (!id.empty())
|
||||||
|
{
|
||||||
|
int index = literals.addString (id);
|
||||||
|
Generator::pushInt (code, literals, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
code.push_back (Generator::segment5 (
|
||||||
|
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Extensions::generateInstructionCode (int keyword,
|
void Extensions::generateInstructionCode (int keyword,
|
||||||
std::vector<Interpreter::Type_Code>& code)
|
std::vector<Interpreter::Type_Code>& code, Literals& literals, const std::string& id)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
|
std::map<int, Instruction>::const_iterator iter = mInstructions.find (keyword);
|
||||||
|
@ -96,6 +106,13 @@ namespace Compiler
|
||||||
if (iter==mInstructions.end())
|
if (iter==mInstructions.end())
|
||||||
throw std::logic_error ("unknown custom instruction keyword");
|
throw std::logic_error ("unknown custom instruction keyword");
|
||||||
|
|
||||||
code.push_back (Generator::segment5 (iter->second.mCode));
|
if (!id.empty())
|
||||||
|
{
|
||||||
|
int index = literals.addString (id);
|
||||||
|
Generator::pushInt (code, literals, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
code.push_back (Generator::segment5 (
|
||||||
|
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
namespace Compiler
|
namespace Compiler
|
||||||
{
|
{
|
||||||
|
class Literals;
|
||||||
|
|
||||||
/// \brief Collection of compiler extensions
|
/// \brief Collection of compiler extensions
|
||||||
|
|
||||||
class Extensions
|
class Extensions
|
||||||
|
@ -18,12 +20,14 @@ namespace Compiler
|
||||||
char mReturn;
|
char mReturn;
|
||||||
std::string mArguments;
|
std::string mArguments;
|
||||||
int mCode;
|
int mCode;
|
||||||
|
int mCodeExplicit;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Instruction
|
struct Instruction
|
||||||
{
|
{
|
||||||
std::string mArguments;
|
std::string mArguments;
|
||||||
int mCode;
|
int mCode;
|
||||||
|
int mCodeExplicit;
|
||||||
};
|
};
|
||||||
|
|
||||||
int mNextKeywordIndex;
|
int mNextKeywordIndex;
|
||||||
|
@ -48,25 +52,27 @@ namespace Compiler
|
||||||
///< Is this keyword registered with a function? If yes, return argument types.
|
///< Is this keyword registered with a function? If yes, return argument types.
|
||||||
|
|
||||||
void registerFunction (const std::string& keyword, char returnType,
|
void registerFunction (const std::string& keyword, char returnType,
|
||||||
const std::string& argumentType, int segment5code);
|
const std::string& argumentType, int segment5code, int segment5codeExplicit = -1);
|
||||||
///< Register a custom function
|
///< Register a custom function
|
||||||
/// - keyword must be all lower case.
|
/// - keyword must be all lower case.
|
||||||
/// - keyword must be unique
|
/// - keyword must be unique
|
||||||
|
/// - if explicit references are not supported, segment5codeExplicit must be set to -1
|
||||||
/// \note Currently only segment 5 opcodes are supported.
|
/// \note Currently only segment 5 opcodes are supported.
|
||||||
|
|
||||||
void registerInstruction (const std::string& keyword,
|
void registerInstruction (const std::string& keyword,
|
||||||
const std::string& argumentType, int segment5code);
|
const std::string& argumentType, int segment5code, int segment5codeExplicit = -1);
|
||||||
///< Register a custom instruction
|
///< Register a custom instruction
|
||||||
/// - keyword must be all lower case.
|
/// - keyword must be all lower case.
|
||||||
/// - keyword must be unique
|
/// - keyword must be unique
|
||||||
|
/// - if explicit references are not supported, segment5codeExplicit must be set to -1
|
||||||
/// \note Currently only segment 5 opcodes are supported.
|
/// \note Currently only segment 5 opcodes are supported.
|
||||||
|
|
||||||
void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code)
|
void generateFunctionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
|
||||||
const;
|
Literals& literals, const std::string& id) const;
|
||||||
///< Append code for function to \a code.
|
///< Append code for function to \a code.
|
||||||
|
|
||||||
void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code)
|
void generateInstructionCode (int keyword, std::vector<Interpreter::Type_Code>& code,
|
||||||
const;
|
Literals& literals, const std::string& id) const;
|
||||||
///< Append code for function to \a code.
|
///< Append code for function to \a code.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,21 @@ namespace Compiler
|
||||||
mState = EndState;
|
mState = EndState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for custom extensions
|
||||||
|
if (const Extensions *extensions = getContext().getExtensions())
|
||||||
|
{
|
||||||
|
std::string argumentType;
|
||||||
|
|
||||||
|
if (extensions->isInstruction (keyword, argumentType))
|
||||||
|
{
|
||||||
|
mExprParser.parseArguments (argumentType, scanner, mCode, true);
|
||||||
|
|
||||||
|
extensions->generateInstructionCode (keyword, mCode, mLiterals, mExplicit);
|
||||||
|
mState = EndState;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mState==BeginState)
|
if (mState==BeginState)
|
||||||
|
@ -189,21 +204,6 @@ namespace Compiler
|
||||||
mState = EndState;
|
mState = EndState;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for custom extensions
|
|
||||||
if (const Extensions *extensions = getContext().getExtensions())
|
|
||||||
{
|
|
||||||
std::string argumentType;
|
|
||||||
|
|
||||||
if (extensions->isInstruction (keyword, argumentType))
|
|
||||||
{
|
|
||||||
mExprParser.parseArguments (argumentType, scanner, mCode, true);
|
|
||||||
|
|
||||||
extensions->generateInstructionCode (keyword, mCode);
|
|
||||||
mState = EndState;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (mState==SetLocalVarState && keyword==Scanner::K_to)
|
else if (mState==SetLocalVarState && keyword==Scanner::K_to)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue