2013-04-10 20:49:22 +00:00
|
|
|
#include "scriptcontext.hpp"
|
|
|
|
|
2013-09-19 10:30:42 +00:00
|
|
|
#include <algorithm>
|
2022-06-27 19:32:46 +00:00
|
|
|
#include <sstream>
|
2022-10-19 17:02:00 +00:00
|
|
|
#include <type_traits>
|
2013-09-19 10:30:42 +00:00
|
|
|
|
2022-10-19 17:02:00 +00:00
|
|
|
#include <apps/opencs/model/world/columns.hpp>
|
|
|
|
#include <apps/opencs/model/world/idcollection.hpp>
|
|
|
|
#include <apps/opencs/model/world/record.hpp>
|
|
|
|
#include <apps/opencs/model/world/refidcollection.hpp>
|
2013-09-19 10:30:42 +00:00
|
|
|
|
2014-02-14 11:46:54 +00:00
|
|
|
#include <components/compiler/nullerrorhandler.hpp>
|
|
|
|
#include <components/compiler/quickfileparser.hpp>
|
|
|
|
#include <components/compiler/scanner.hpp>
|
2022-10-19 17:02:00 +00:00
|
|
|
#include <components/esm3/loadglob.hpp>
|
|
|
|
#include <components/esm3/loadscpt.hpp>
|
|
|
|
#include <components/esm3/variant.hpp>
|
|
|
|
#include <components/misc/strings/lower.hpp>
|
2014-02-14 11:46:54 +00:00
|
|
|
|
2013-09-19 10:30:42 +00:00
|
|
|
#include "data.hpp"
|
|
|
|
|
|
|
|
CSMWorld::ScriptContext::ScriptContext(const Data& data)
|
|
|
|
: mData(data)
|
|
|
|
, mIdsUpdated(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-04-10 20:49:22 +00:00
|
|
|
bool CSMWorld::ScriptContext::canDeclareLocals() const
|
|
|
|
{
|
2014-02-14 12:38:30 +00:00
|
|
|
return true;
|
2013-04-10 20:49:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char CSMWorld::ScriptContext::getGlobalType(const std::string& name) const
|
|
|
|
{
|
2014-02-14 10:59:33 +00:00
|
|
|
int index = mData.getGlobals().searchId(name);
|
|
|
|
|
|
|
|
if (index != -1)
|
|
|
|
{
|
|
|
|
switch (mData.getGlobals().getRecord(index).get().mValue.getType())
|
|
|
|
{
|
|
|
|
case ESM::VT_Short:
|
|
|
|
return 's';
|
|
|
|
case ESM::VT_Long:
|
|
|
|
return 'l';
|
|
|
|
case ESM::VT_Float:
|
|
|
|
return 'f';
|
2022-09-22 18:26:05 +00:00
|
|
|
|
2014-02-14 10:59:33 +00:00
|
|
|
default:
|
|
|
|
return ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-10 20:49:22 +00:00
|
|
|
return ' ';
|
|
|
|
}
|
|
|
|
|
2022-10-06 17:39:46 +00:00
|
|
|
std::pair<char, bool> CSMWorld::ScriptContext::getMemberType(const std::string& name, const ESM::RefId& id) const
|
2013-04-10 20:49:22 +00:00
|
|
|
{
|
2022-10-06 17:39:46 +00:00
|
|
|
ESM::RefId id2 = id;
|
2014-02-14 11:46:54 +00:00
|
|
|
|
|
|
|
int index = mData.getScripts().searchId(id2);
|
|
|
|
bool reference = false;
|
|
|
|
|
2014-10-13 13:23:00 +00:00
|
|
|
if (index == -1)
|
2014-02-14 11:46:54 +00:00
|
|
|
{
|
|
|
|
// ID is not a script ID. Search for a matching referenceable instead.
|
|
|
|
index = mData.getReferenceables().searchId(id2);
|
|
|
|
|
|
|
|
if (index != -1)
|
|
|
|
{
|
|
|
|
// Referenceable found.
|
2014-10-13 13:26:47 +00:00
|
|
|
int columnIndex = mData.getReferenceables().findColumnIndex(Columns::ColumnId_Script);
|
2014-02-14 11:46:54 +00:00
|
|
|
|
2022-10-06 17:39:46 +00:00
|
|
|
id2 = ESM::RefId::stringRefId(
|
2014-10-13 13:26:47 +00:00
|
|
|
mData.getReferenceables().getData(index, columnIndex).toString().toUtf8().constData());
|
|
|
|
|
|
|
|
if (!id2.empty())
|
2014-02-14 11:46:54 +00:00
|
|
|
{
|
2014-10-13 13:26:47 +00:00
|
|
|
// Referenceable has a script -> use it.
|
|
|
|
index = mData.getScripts().searchId(id2);
|
|
|
|
reference = true;
|
2014-02-14 11:46:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index == -1)
|
|
|
|
return std::make_pair(' ', false);
|
|
|
|
|
2022-10-06 17:39:46 +00:00
|
|
|
std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find(id2.getRefIdString());
|
2014-02-14 11:46:54 +00:00
|
|
|
|
|
|
|
if (iter == mLocals.end())
|
|
|
|
{
|
|
|
|
Compiler::Locals locals;
|
|
|
|
|
|
|
|
Compiler::NullErrorHandler errorHandler;
|
|
|
|
std::istringstream stream(mData.getScripts().getRecord(index).get().mScriptText);
|
|
|
|
Compiler::QuickFileParser parser(errorHandler, *this, locals);
|
|
|
|
Compiler::Scanner scanner(errorHandler, stream, getExtensions());
|
|
|
|
scanner.scan(parser);
|
|
|
|
|
2022-10-06 17:39:46 +00:00
|
|
|
iter = mLocals.insert(std::make_pair(id2.getRefIdString(), locals)).first;
|
2014-02-14 11:46:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return std::make_pair(iter->second.getType(Misc::StringUtils::lowerCase(name)), reference);
|
2013-04-10 20:49:22 +00:00
|
|
|
}
|
|
|
|
|
2022-10-06 17:39:46 +00:00
|
|
|
bool CSMWorld::ScriptContext::isId(const ESM::RefId& name) const
|
2013-04-10 20:49:22 +00:00
|
|
|
{
|
2013-09-19 10:30:42 +00:00
|
|
|
if (!mIdsUpdated)
|
|
|
|
{
|
|
|
|
mIds = mData.getIds();
|
2022-10-18 07:26:55 +00:00
|
|
|
|
2014-02-15 12:09:43 +00:00
|
|
|
std::sort(mIds.begin(), mIds.end());
|
2013-09-19 10:30:42 +00:00
|
|
|
|
|
|
|
mIdsUpdated = true;
|
|
|
|
}
|
|
|
|
|
2022-10-06 17:39:46 +00:00
|
|
|
return std::binary_search(mIds.begin(), mIds.end(), name);
|
2013-09-19 10:30:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSMWorld::ScriptContext::invalidateIds()
|
|
|
|
{
|
|
|
|
mIdsUpdated = false;
|
2014-02-14 12:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSMWorld::ScriptContext::clear()
|
|
|
|
{
|
|
|
|
mIds.clear();
|
|
|
|
mIdsUpdated = false;
|
|
|
|
mLocals.clear();
|
2015-03-11 14:54:45 +00:00
|
|
|
}
|
2015-09-22 13:36:00 +00:00
|
|
|
|
|
|
|
bool CSMWorld::ScriptContext::clearLocals(const std::string& script)
|
|
|
|
{
|
2022-11-15 23:07:33 +00:00
|
|
|
std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find(script);
|
2015-09-22 13:36:00 +00:00
|
|
|
|
|
|
|
if (iter != mLocals.end())
|
|
|
|
{
|
|
|
|
mLocals.erase(iter);
|
|
|
|
mIdsUpdated = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|