1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-23 14:23:53 +00:00
openmw/components/compiler/extensions.cpp

208 lines
6.4 KiB
C++
Raw Normal View History

2010-07-03 07:54:01 +00:00
#include "extensions.hpp"
#include <cassert>
#include <stdexcept>
#include "generator.hpp"
#include "literals.hpp"
2010-07-03 07:54:01 +00:00
namespace Compiler
{
2022-09-22 18:26:05 +00:00
Extensions::Extensions()
: mNextKeywordIndex(-1)
{
}
2010-07-03 07:54:01 +00:00
2022-09-22 18:26:05 +00:00
int Extensions::searchKeyword(const std::string& keyword) const
2010-07-03 07:54:01 +00:00
{
2022-09-22 18:26:05 +00:00
auto iter = mKeywords.find(keyword);
if (iter == mKeywords.end())
2010-07-03 07:54:01 +00:00
return 0;
2010-07-03 07:54:01 +00:00
return iter->second;
}
2022-09-22 18:26:05 +00:00
bool Extensions::isFunction(
int keyword, ScriptReturn& returnType, ScriptArgs& argumentType, bool& explicitReference) const
{
2022-09-22 18:26:05 +00:00
auto iter = mFunctions.find(keyword);
if (iter == mFunctions.end())
return false;
2022-09-22 18:26:05 +00:00
if (explicitReference && iter->second.mCodeExplicit == -1)
explicitReference = false;
returnType = iter->second.mReturn;
argumentType = iter->second.mArguments;
return true;
}
2022-09-22 18:26:05 +00:00
bool Extensions::isInstruction(int keyword, ScriptArgs& argumentType, bool& explicitReference) const
{
2022-09-22 18:26:05 +00:00
auto iter = mInstructions.find(keyword);
if (iter == mInstructions.end())
return false;
2022-09-22 18:26:05 +00:00
if (explicitReference && iter->second.mCodeExplicit == -1)
explicitReference = false;
argumentType = iter->second.mArguments;
return true;
}
2022-09-22 18:26:05 +00:00
void Extensions::registerFunction(
const std::string& keyword, ScriptReturn returnType, const ScriptArgs& argumentType, int code, int codeExplicit)
{
Function function;
2022-09-22 18:26:05 +00:00
if (argumentType.find('/') == std::string::npos)
{
function.mSegment = 5;
2022-09-22 18:26:05 +00:00
assert(code >= 33554432 && code <= 67108863);
assert(codeExplicit == -1 || (codeExplicit >= 33554432 && codeExplicit <= 67108863));
}
else
{
function.mSegment = 3;
2022-09-22 18:26:05 +00:00
assert(code >= 0x20000 && code <= 0x2ffff);
assert(codeExplicit == -1 || (codeExplicit >= 0x20000 && codeExplicit <= 0x2ffff));
}
int keywordIndex = mNextKeywordIndex--;
2022-09-22 18:26:05 +00:00
mKeywords.insert(std::make_pair(keyword, keywordIndex));
function.mReturn = returnType;
function.mArguments = argumentType;
function.mCode = code;
function.mCodeExplicit = codeExplicit;
2022-09-22 18:26:05 +00:00
mFunctions.insert(std::make_pair(keywordIndex, function));
}
2022-09-22 18:26:05 +00:00
void Extensions::registerInstruction(
const std::string& keyword, const ScriptArgs& argumentType, int code, int codeExplicit)
{
Instruction instruction;
2022-09-22 18:26:05 +00:00
if (argumentType.find('/') == std::string::npos)
{
instruction.mSegment = 5;
2022-09-22 18:26:05 +00:00
assert(code >= 33554432 && code <= 67108863);
assert(codeExplicit == -1 || (codeExplicit >= 33554432 && codeExplicit <= 67108863));
}
else
{
instruction.mSegment = 3;
2022-09-22 18:26:05 +00:00
assert(code >= 0x20000 && code <= 0x2ffff);
assert(codeExplicit == -1 || (codeExplicit >= 0x20000 && codeExplicit <= 0x2ffff));
}
int keywordIndex = mNextKeywordIndex--;
2022-09-22 18:26:05 +00:00
mKeywords.insert(std::make_pair(keyword, keywordIndex));
instruction.mArguments = argumentType;
instruction.mCode = code;
instruction.mCodeExplicit = codeExplicit;
2022-09-22 18:26:05 +00:00
mInstructions.insert(std::make_pair(keywordIndex, instruction));
}
2022-09-22 18:26:05 +00:00
void Extensions::generateFunctionCode(int keyword, std::vector<Interpreter::Type_Code>& code, Literals& literals,
const std::string& id, int optionalArguments) const
{
2022-09-22 18:26:05 +00:00
assert(optionalArguments >= 0);
2022-09-22 18:26:05 +00:00
auto iter = mFunctions.find(keyword);
if (iter == mFunctions.end())
throw std::logic_error("unknown custom function keyword");
2022-09-22 18:26:05 +00:00
if (optionalArguments && iter->second.mSegment != 3)
throw std::logic_error("functions with optional arguments must be placed into segment 3");
if (!id.empty())
{
2022-09-22 18:26:05 +00:00
if (iter->second.mCodeExplicit == -1)
throw std::logic_error("explicit references not supported");
2022-09-22 18:26:05 +00:00
int index = literals.addString(id);
Generator::pushInt(code, literals, index);
}
switch (iter->second.mSegment)
{
case 3:
2022-09-22 18:26:05 +00:00
if (optionalArguments >= 256)
throw std::logic_error("number of optional arguments is too large for segment 3");
2022-09-22 18:26:05 +00:00
code.push_back(Generator::segment3(
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit, optionalArguments));
break;
case 5:
2022-09-22 18:26:05 +00:00
code.push_back(Generator::segment5(id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
break;
default:
2022-09-22 18:26:05 +00:00
throw std::logic_error("unsupported code segment");
}
}
2022-09-22 18:26:05 +00:00
void Extensions::generateInstructionCode(int keyword, std::vector<Interpreter::Type_Code>& code, Literals& literals,
const std::string& id, int optionalArguments) const
{
2022-09-22 18:26:05 +00:00
assert(optionalArguments >= 0);
2022-09-22 18:26:05 +00:00
auto iter = mInstructions.find(keyword);
if (iter == mInstructions.end())
throw std::logic_error("unknown custom instruction keyword");
2022-09-22 18:26:05 +00:00
if (optionalArguments && iter->second.mSegment != 3)
throw std::logic_error("instructions with optional arguments must be placed into segment 3");
if (!id.empty())
{
2022-09-22 18:26:05 +00:00
if (iter->second.mCodeExplicit == -1)
throw std::logic_error("explicit references not supported");
2022-09-22 18:26:05 +00:00
int index = literals.addString(id);
Generator::pushInt(code, literals, index);
}
switch (iter->second.mSegment)
{
case 3:
2022-09-22 18:26:05 +00:00
if (optionalArguments >= 256)
throw std::logic_error("number of optional arguments is too large for segment 3");
2022-09-22 18:26:05 +00:00
code.push_back(Generator::segment3(
id.empty() ? iter->second.mCode : iter->second.mCodeExplicit, optionalArguments));
break;
case 5:
2022-09-22 18:26:05 +00:00
code.push_back(Generator::segment5(id.empty() ? iter->second.mCode : iter->second.mCodeExplicit));
break;
default:
2022-09-22 18:26:05 +00:00
throw std::logic_error("unsupported code segment");
}
}
2011-01-12 17:24:00 +00:00
2022-09-22 18:26:05 +00:00
void Extensions::listKeywords(std::vector<std::string>& keywords) const
2011-01-12 17:24:00 +00:00
{
2022-09-22 18:26:05 +00:00
for (const auto& mKeyword : mKeywords)
keywords.push_back(mKeyword.first);
2011-01-12 17:24:00 +00:00
}
2010-07-03 07:54:01 +00:00
}