mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-02-05 15:18:45 +00:00
804 lines
34 KiB
C++
804 lines
34 KiB
C++
#include "entity_value.h"
|
|
#include "../exception.h"
|
|
#include "variable_entity.h"
|
|
#include "definition_entity.h"
|
|
#include "../constvariant.inl"
|
|
#include "../support.h"
|
|
#include "../parser.h"
|
|
|
|
CEntityValueNode::CEntityValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
|
m_ptrEntity(ptrEntity), m_ptrParent(ptrParent)
|
|
{
|
|
if (!ptrEntity) throw CCompileException("Internal error: expected a valid entity.");
|
|
|
|
CLog log;
|
|
if (!ptrParent)
|
|
log << "The value node of '" << ptrEntity->GetName() << "' has no parent node..." << std::endl;
|
|
else
|
|
log << "The value node of '" << ptrEntity->GetName() << "' has a parent node..." << std::endl;
|
|
}
|
|
|
|
CEntityValueNode::CEntityValueNode(const CEntityValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
|
m_ptrEntity(ptrEntity), m_ptrParent(ptrParent), m_vecChildren(rValueNode.m_vecChildren)
|
|
{
|
|
if (!ptrEntity) throw CCompileException("Internal error: expected a valid entity.");
|
|
|
|
CLog log;
|
|
if (!ptrParent)
|
|
log << "The value node of '" << ptrEntity->GetName() << "' has no parent node..." << std::endl;
|
|
else
|
|
log << "The value node of '" << ptrEntity->GetName() << "' has a parent node..." << std::endl;
|
|
}
|
|
|
|
void CEntityValueNode::ProcessChildNodes(const CTokenList& rlstExpression)
|
|
{
|
|
CLog log;
|
|
log << "Processing " << m_vecChildren.size() << " child nodes..." << std::endl;
|
|
bool bInitial = true;
|
|
for (CValueNodePtr& rptrValue : m_vecChildren)
|
|
{
|
|
// Check for a comma separator.
|
|
if (!bInitial)
|
|
{
|
|
if (rlstExpression.Current() != ",")
|
|
throw CCompileException(rlstExpression.LastValid(), "Missing comma ',' for value separation.");
|
|
++rlstExpression;
|
|
}
|
|
bInitial = false;
|
|
|
|
log << "Processing child node..." << std::endl;
|
|
rptrValue->ProcessValueAssignment(rlstExpression);
|
|
}
|
|
}
|
|
|
|
void CEntityValueNode::AddChild(CValueNodePtr ptrChild)
|
|
{
|
|
CLog log;
|
|
log << "Adding child node..." << std::endl;
|
|
if (!ptrChild)
|
|
throw CCompileException("Internal error: cannot add an empty child node.");
|
|
m_vecChildren.push_back(ptrChild);
|
|
}
|
|
|
|
std::string CEntityValueNode::GetDeclTypeStr(bool bResolveTypedef) const
|
|
{
|
|
return GetDeclEntity()->GetDeclTypeStr(bResolveTypedef);
|
|
}
|
|
|
|
bool CEntityValueNode::IsConst() const
|
|
{
|
|
// Default implementation
|
|
// - In case the entity is a const entity, return 'true'.
|
|
// - Otherwise check whether the parent value is available and ask the parent if the declaration entity is a const entity.
|
|
// - If no parent is available, this entity must be a declaration entity and is therefore not a const entity.
|
|
if (m_ptrEntity->Get<CVariableEntity>() && m_ptrEntity->Get<CVariableEntity>()->IsReadOnly()) return true;
|
|
if (m_ptrParent) return m_ptrParent->IsConst();
|
|
return false;
|
|
}
|
|
|
|
bool CEntityValueNode::IsDeclaration() const
|
|
{
|
|
// Default implementation
|
|
return m_ptrEntity->Get<CVariableEntity>();
|
|
}
|
|
|
|
CSimpleTypeValueNode::CSimpleTypeValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
|
CEntityValueNode(ptrEntity, ptrParent)
|
|
{}
|
|
|
|
CSimpleTypeValueNode::CSimpleTypeValueNode(const CSimpleTypeValueNode& rValueNode, CEntityPtr ptrEntity,
|
|
const CValueNodePtr ptrParent) :
|
|
CEntityValueNode(rValueNode, ptrEntity, ptrParent), m_varValue(rValueNode.m_varValue),
|
|
m_lstExpression(rValueNode.m_lstExpression), m_eValueDef(rValueNode.m_eValueDef)
|
|
{}
|
|
|
|
CValueNodePtr CSimpleTypeValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
|
{
|
|
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
|
}
|
|
|
|
void CSimpleTypeValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
|
{
|
|
CLog log("Processing declaration value assignment...");
|
|
|
|
if (!m_ptrEntity) throw CCompileException("Internal error: no entity assigned to the value node.");
|
|
|
|
const CDeclarationEntity* pSystemTypeEntity = m_ptrEntity->Get<CDeclarationEntity>();
|
|
if (!pSystemTypeEntity)
|
|
throw CCompileException("Internal error: type mismatch between value node and entity type.");
|
|
|
|
// Process the assignment expression and convert the result in the target type.
|
|
std::pair<CConstVariant, bool> prValue{0, false};
|
|
switch (pSystemTypeEntity->GetBaseType())
|
|
{
|
|
case sdv::idl::EDeclType::decltype_short:
|
|
log << "Processing system type value node of type 'int16/short'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<int16_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<int64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_long:
|
|
log << "Processing system type value node of type 'int32/long'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<int32_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<int64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_long_long:
|
|
log << "Processing system type value node of type 'int64/long long'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<int64_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<int64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_unsigned_short:
|
|
log << "Processing system type value node of type 'uint16/unsigned short'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<uint16_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_unsigned_long:
|
|
log << "Processing system type value node of type 'uint32/unsigned long'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<uint32_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_unsigned_long_long:
|
|
log << "Processing system type value node of type 'uint64/unsigned long long'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<uint64_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_char:
|
|
log << "Processing system type value node of type 'int8/UTF-8 or ASCII char'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<int8_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<int64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_char16:
|
|
log << "Processing system type value node of type 'UTF-16 char'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<uint16_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_char32:
|
|
log << "Processing system type value node of type 'UTF-32 char'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<uint32_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_wchar:
|
|
log << "Processing system type value node of type 'wchar'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
if (sizeof(wchar_t) == 2)
|
|
prValue.first.Convert<uint16_t>();
|
|
else
|
|
prValue.first.Convert<uint32_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_float:
|
|
log << "Processing system type value node of type 'float'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<float>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<long double>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_double:
|
|
log << "Processing system type value node of type 'double'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<double>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<long double>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_long_double:
|
|
log << "Processing system type value node of type 'long double'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<long double>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<long double>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_fixed:
|
|
log << "Processing system type value node of type 'fixed'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<fixed>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<long double>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_boolean:
|
|
log << "Processing system type value node of type 'boolean'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<bool>();
|
|
log << "Simple type value node has calculated value " << (prValue.first.Get<bool>() ? "'true'" : "'false'") << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_native:
|
|
log << "Processing system type value node of type 'native'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<size_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<size_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_octet:
|
|
log << "Processing system type value node of type 'uint8/octet'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessNumericExpression(rlstExpression);
|
|
prValue.first.Convert<uint8_t>();
|
|
log << "Simple type value node has calculated value " << prValue.first.Get<uint64_t>() << "..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_string:
|
|
log << "Processing system type value node of type 'ASCII string'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
|
prValue.first.Convert<std::string>();
|
|
log << "Simple type value node has constructed string \"" << prValue.first.Get<std::string>() << "\"..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_u8string:
|
|
log << "Processing system type value node of type 'UTF-8 string'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
|
prValue.first.Convert<std::string>();
|
|
log << "Simple type value node has constructed string \"" << prValue.first.Get<std::string>() << "\"..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_u16string:
|
|
log << "Processing system type value node of type 'UTF-16 string'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
|
prValue.first.Convert<std::u16string>();
|
|
log << "Simple type value node has constructed string..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_u32string:
|
|
log << "Processing system type value node of type 'UTF-32 string'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
|
prValue.first.Convert<std::u32string>();
|
|
log << "Simple type value node has constructed string..." << std::endl;
|
|
break;
|
|
case sdv::idl::EDeclType::decltype_wstring:
|
|
log << "Processing system type value node of type 'wstring'..." << std::endl;
|
|
prValue = pSystemTypeEntity->ProcessStringExpression(rlstExpression);
|
|
prValue.first.Convert<std::wstring>();
|
|
log << "Simple type value node has constructed string..." << std::endl;
|
|
break;
|
|
default:
|
|
log << "Processing system type value node of unknown type..." << std::endl;
|
|
throw CCompileException("Internal error: expression build error.");
|
|
}
|
|
|
|
// Check for a dynamic result
|
|
if (prValue.second)
|
|
SetDynamicValue(rlstExpression);
|
|
else
|
|
SetFixedValue(prValue.first, rlstExpression);
|
|
}
|
|
|
|
void CSimpleTypeValueNode::SetFixedValue(const CConstVariant& rvarValue, const CTokenList& rlstExpression)
|
|
{
|
|
CLog log;
|
|
switch (m_eValueDef)
|
|
{
|
|
case EValueDef::dynamic:
|
|
log << "The value was re-assigned; the previous value was a dynamic value..." << std::endl;
|
|
break;
|
|
case EValueDef::fixed:
|
|
log << "The value was re-assigned; the previous value was a fixed value of " <<
|
|
m_varValue.GetAsString() << "..." << std::endl;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
m_eValueDef = EValueDef::fixed;
|
|
|
|
log << "The system type value node was set to a fixed value of " << rvarValue.GetAsString() << "..." << std::endl;
|
|
|
|
m_varValue = rvarValue;
|
|
m_lstExpression = rlstExpression;
|
|
}
|
|
|
|
void CSimpleTypeValueNode::SetDynamicValue(const CTokenList& rlstExpression)
|
|
{
|
|
CLog log;
|
|
switch (m_eValueDef)
|
|
{
|
|
case EValueDef::dynamic:
|
|
log << "The value was re-assigned; the previous value was a dynamic value..." << std::endl;
|
|
break;
|
|
case EValueDef::fixed:
|
|
log << "The value was re-assigned; the previous value was a fixed value of " <<
|
|
m_varValue.GetAsString() << "..." << std::endl;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
m_eValueDef = EValueDef::dynamic;
|
|
|
|
log << "The system type value node was set to a dynamic value..." << std::endl;
|
|
|
|
m_lstExpression = rlstExpression;
|
|
}
|
|
|
|
CArrayValueNode::CArrayValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
|
CEntityValueNode(ptrEntity, ptrParent)
|
|
{}
|
|
|
|
CArrayValueNode::CArrayValueNode(const CArrayValueNode& rValueNode, CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
|
CEntityValueNode(rValueNode, ptrEntity, ptrParent), m_lstArraySizeExpression(rValueNode.m_lstArraySizeExpression),
|
|
m_eSizeDef(rValueNode.m_eSizeDef)
|
|
{
|
|
m_vecChildren = rValueNode.m_vecChildren;
|
|
}
|
|
|
|
CValueNodePtr CArrayValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
|
{
|
|
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
|
}
|
|
|
|
void CArrayValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
|
{
|
|
CLog log("Process array value node...");
|
|
|
|
if (rlstExpression.End())
|
|
throw CCompileException(rlstExpression.LastValid(), "Expecting left curly bracket '{'");
|
|
|
|
// The array assignment is placed between brackets.
|
|
// In case the type is a character, the array might also be defined as a string literal
|
|
// Or identified as a value sequence.
|
|
|
|
if (rlstExpression.Current() == "{")
|
|
{
|
|
// Skip the bracket
|
|
++rlstExpression;
|
|
|
|
// Process the child nodes
|
|
ProcessChildNodes(rlstExpression);
|
|
|
|
// Expecting '}'
|
|
if (rlstExpression.End() || rlstExpression.Current() != "}")
|
|
throw CCompileException(rlstExpression.LastValid(), "Expecting right curly bracket '}'");
|
|
++rlstExpression;
|
|
}
|
|
else if (rlstExpression.Current().GetType() == ETokenType::token_literal && rlstExpression.Current().IsString())
|
|
{
|
|
// Process the string node
|
|
ProcessStringNode(rlstExpression.Current());
|
|
++rlstExpression;
|
|
}
|
|
else
|
|
throw CCompileException(rlstExpression.LastValid(), "Expecting left curly bracket '{'");
|
|
}
|
|
|
|
void CArrayValueNode::ProcessChildNodes(const CTokenList& rlstExpression)
|
|
{
|
|
CLog log;
|
|
CValueNodePtr ptrValueTemplateUnbound;
|
|
if (IsUnbound())
|
|
{
|
|
// The array should have one node. This is a template for all the nodes.
|
|
if (m_vecChildren.size() != 1)
|
|
throw CCompileException(rlstExpression.LastValid(), "Internal error: the size of the array value nodes is not as expected for the"
|
|
" unbound array.");
|
|
ptrValueTemplateUnbound = std::move(m_vecChildren[0]);
|
|
|
|
log << "Processing ubound element nodes..." << std::endl;
|
|
}
|
|
else
|
|
log << "Processing " << m_vecChildren.size() << " element nodes..." << std::endl;
|
|
|
|
size_t nIndex = 0;
|
|
while (!rlstExpression.End() && rlstExpression.Current() != "}")
|
|
{
|
|
// Check for a comma separator.
|
|
if (nIndex)
|
|
{
|
|
if (rlstExpression.Current() != ",")
|
|
throw CCompileException(rlstExpression.LastValid(), "Missing comma ',' for value separation.");
|
|
++rlstExpression;
|
|
}
|
|
|
|
// Extend the array for unbound
|
|
if (IsUnbound())
|
|
{
|
|
m_vecChildren.resize(nIndex + 1);
|
|
m_vecChildren[nIndex] = ptrValueTemplateUnbound->CreateCopy(m_ptrEntity, shared_from_this());
|
|
}
|
|
|
|
// Does the size fit?
|
|
if (nIndex >= m_vecChildren.size())
|
|
throw CCompileException(rlstExpression.LastValid(), "The assignment doesn't fit the amount of elements.");
|
|
|
|
log << "Processing element node #" << nIndex << std::endl;
|
|
m_vecChildren[nIndex]->ProcessValueAssignment(rlstExpression);
|
|
|
|
// Next node
|
|
nIndex++;
|
|
}
|
|
|
|
// Check whether the index corresponds to the size of the aray.
|
|
if (nIndex != m_vecChildren.size())
|
|
throw CCompileException(rlstExpression.LastValid(), "Missing elements for array assignment.");
|
|
}
|
|
|
|
void CArrayValueNode::ProcessStringNode(const CToken& rToken)
|
|
{
|
|
CLog log;
|
|
|
|
if (!rToken.IsString())
|
|
throw CCompileException(rToken, "Internal error: token is expected to be a string literal.");
|
|
|
|
|
|
// Check for unbound arrays.
|
|
CValueNodePtr ptrValueTemplateUnbound;
|
|
if (IsUnbound())
|
|
{
|
|
// The array should have one node. This is a template for all the nodes.
|
|
if (m_vecChildren.size() != 1)
|
|
throw CCompileException(rToken, "Internal error: the size of the array value nodes is not as expected for the"
|
|
" unbound array.");
|
|
ptrValueTemplateUnbound = std::move(m_vecChildren[0]);
|
|
|
|
log << "Processing ubound element nodes..." << std::endl;
|
|
}
|
|
else
|
|
log << "Processing " << m_vecChildren.size() << " element nodes..." << std::endl;
|
|
|
|
// Determine the start position of the string
|
|
const std::string ssValue = static_cast<std::string>(rToken);
|
|
size_t nStart = ssValue.find('"');
|
|
if (nStart == std::string::npos)
|
|
throw CCompileException(rToken, "Internal error: invalid string token.");
|
|
nStart++;
|
|
|
|
// For raw string, determine the delimiter
|
|
std::string ssDelimiter = "\"";
|
|
bool bRaw = false;
|
|
if (rToken.IsRawString())
|
|
{
|
|
bRaw = true;
|
|
size_t nStart2 = ssValue.find('(', nStart);
|
|
if (nStart2 == std::string::npos)
|
|
throw CCompileException(rToken, "Internal error: invalid raw string token.");
|
|
ssDelimiter = ")" + ssValue.substr(nStart, nStart2 - nStart) + "\"";
|
|
nStart = nStart2;
|
|
}
|
|
|
|
// Check whether the base type corresponds to the string and count the characters.
|
|
bool bError = true;
|
|
uint32_t uiByteCnt = 0;
|
|
std::vector<CConstVariant> lstValues;
|
|
switch (GetDeclEntity()->GetBaseType())
|
|
{
|
|
case sdv::idl::EDeclType::decltype_char:
|
|
{
|
|
if (!rToken.IsAscii() && !rToken.IsUtf8()) break;
|
|
bError = false;
|
|
std::string ssText;
|
|
InterpretCText(ssValue.c_str() + nStart, ssDelimiter.c_str(), ssText, uiByteCnt, bRaw, rToken.IsAscii());
|
|
for (char c : ssText)
|
|
lstValues.push_back(c);
|
|
break;
|
|
}
|
|
case sdv::idl::EDeclType::decltype_wchar:
|
|
{
|
|
if (!rToken.IsWide()) break;
|
|
bError = false;
|
|
std::wstring ssText;
|
|
InterpretCText(ssValue.c_str() + nStart, ssDelimiter.c_str(), ssText, uiByteCnt, bRaw);
|
|
for (wchar_t c : ssText)
|
|
lstValues.push_back(c);
|
|
break;
|
|
}
|
|
case sdv::idl::EDeclType::decltype_char16:
|
|
{
|
|
if (!rToken.IsUtf16()) break;
|
|
bError = false;
|
|
std::u16string ssText;
|
|
InterpretCText(ssValue.c_str() + nStart, ssDelimiter.c_str(), ssText, uiByteCnt, bRaw);
|
|
for (char16_t c : ssText)
|
|
lstValues.push_back(c);
|
|
break;
|
|
}
|
|
case sdv::idl::EDeclType::decltype_char32:
|
|
{
|
|
if (!rToken.IsUtf32()) break;
|
|
bError = false;
|
|
std::u32string ssText;
|
|
InterpretCText(ssValue.c_str() + nStart, ssDelimiter.c_str(), ssText, uiByteCnt, bRaw);
|
|
for (char32_t c : ssText)
|
|
lstValues.push_back(c);
|
|
break;
|
|
}
|
|
default:
|
|
throw CCompileException(rToken, "Expecting left curly bracket '{'");
|
|
break;
|
|
}
|
|
if (bError)
|
|
throw CCompileException(rToken, "Invalid string type for the assignment");
|
|
|
|
// Add the terminateing zero
|
|
lstValues.push_back(0);
|
|
|
|
// Extend the array for unbound
|
|
if (IsUnbound())
|
|
{
|
|
m_vecChildren.resize(lstValues.size());
|
|
for (size_t nIndex = 0; nIndex < lstValues.size(); nIndex++)
|
|
m_vecChildren[nIndex] = ptrValueTemplateUnbound->CreateCopy(m_ptrEntity, shared_from_this());
|
|
}
|
|
|
|
// Does the size fit?
|
|
if (lstValues.size() != m_vecChildren.size())
|
|
throw CCompileException(rToken, "The assignment doesn't fit the amount of elements.");
|
|
|
|
// Assign the values
|
|
for (size_t nIndex = 0; nIndex < m_vecChildren.size(); nIndex++)
|
|
{
|
|
log << "Processing element node #" << nIndex << std::endl;
|
|
CSimpleTypeValueNode* pValueNode = m_vecChildren[nIndex]->Get<CSimpleTypeValueNode>();
|
|
if (!pValueNode)
|
|
throw CCompileException(rToken, "Internal error: the array element is not of type simple value node.");
|
|
|
|
CTokenList lstExpression;
|
|
lstExpression.push_back(rToken);
|
|
pValueNode->SetFixedValue(lstValues[0], lstExpression);
|
|
}
|
|
}
|
|
|
|
void CArrayValueNode::SetFixedSize(size_t nSize, const CTokenList& rlstExpression)
|
|
{
|
|
CLog log;
|
|
if constexpr (std::is_signed_v<size_t>)
|
|
{
|
|
if (static_cast<int64_t>(nSize) < 0)
|
|
throw CCompileException("Internal error: array index is negative.");
|
|
}
|
|
|
|
if (m_eSizeDef != ESizeDef::not_defined)
|
|
throw CCompileException("Internal error: size of the value array was defined more than once.");
|
|
m_eSizeDef = ESizeDef::fixed;
|
|
|
|
// Allocate the array with empty value pointers.
|
|
m_vecChildren.resize(nSize);
|
|
log << "Array set to a fixed size of " << nSize << "..." << std::endl;
|
|
|
|
// Copy the token list resulting in the size.
|
|
m_lstArraySizeExpression = rlstExpression;
|
|
}
|
|
|
|
void CArrayValueNode::SetDynamicSize(size_t nSize, const CTokenList& rlstExpression)
|
|
{
|
|
if (IsConst()) throw CCompileException("Cannot use a value of a variable declaration as size within a const declaration.");
|
|
|
|
CLog log;
|
|
if (m_eSizeDef != ESizeDef::not_defined)
|
|
throw CCompileException("Internal error: size of the value array was defined more than once.");
|
|
m_eSizeDef = ESizeDef::dynamic;
|
|
|
|
// Allocate the array with one element.
|
|
m_vecChildren.resize(nSize);
|
|
log << "Array set to a dynamic size based on a variable of " << nSize << "..." << std::endl;
|
|
|
|
// Copy the token list resulting in the size.
|
|
m_lstArraySizeExpression = rlstExpression;
|
|
}
|
|
|
|
void CArrayValueNode::SetFixedSizeUnbound()
|
|
{
|
|
CLog log;
|
|
if (m_eSizeDef != ESizeDef::not_defined)
|
|
throw CCompileException("Internal error: size of the value array was defined more than once.");
|
|
|
|
m_eSizeDef = ESizeDef::fixed_unbound;
|
|
|
|
// Allocate the array with one element.
|
|
m_vecChildren.resize(1);
|
|
log << "Array set to be unbound..." << std::endl;
|
|
}
|
|
|
|
const CValueNodePtr& CArrayValueNode::operator[](size_t nIndex) const
|
|
{
|
|
if (m_eSizeDef == ESizeDef::not_defined)
|
|
throw CCompileException("Internal error: accessing the array can only take place after the size has been defined.");
|
|
|
|
if constexpr (std::is_signed_v<size_t>)
|
|
{
|
|
if (static_cast<int64_t>(nIndex) < 0)
|
|
throw CCompileException("Internal error: array index is negative.");
|
|
}
|
|
|
|
return m_vecChildren[nIndex];
|
|
}
|
|
|
|
CValueNodePtr& CArrayValueNode::operator[](size_t nIndex)
|
|
{
|
|
if (m_eSizeDef == ESizeDef::not_defined)
|
|
throw CCompileException("Internal error: accessing the array can only take place after the size has been defined.");
|
|
|
|
if constexpr (std::is_signed_v<size_t>)
|
|
{
|
|
if (static_cast<int64_t>(nIndex) < 0)
|
|
throw CCompileException("Internal error: array index is negative.");
|
|
}
|
|
|
|
return m_vecChildren[nIndex];
|
|
}
|
|
|
|
size_t CArrayValueNode::GetSize() const
|
|
{
|
|
return m_vecChildren.size();
|
|
}
|
|
|
|
bool CArrayValueNode::IsArray() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool CArrayValueNode::IsUnbound() const
|
|
{
|
|
return m_eSizeDef == ESizeDef::fixed_unbound;
|
|
}
|
|
|
|
std::string CArrayValueNode::GetSizeExpression() const
|
|
{
|
|
if (IsUnbound()) return std::string();
|
|
std::string ss;
|
|
for (const CToken& rtoken : m_lstArraySizeExpression)
|
|
ss += static_cast<std::string>(rtoken);
|
|
return ss;
|
|
}
|
|
|
|
std::string CArrayValueNode::GetDeclTypeStr(bool bResolveTypedef) const
|
|
{
|
|
if (!GetSize()) return "[]"; // Not resolved yet...
|
|
|
|
CValueNodePtr ptrValue = (*this)[0];
|
|
if (!ptrValue) return std::string("[" + std::to_string(GetSize()) + "]"); // Not resolved yet...
|
|
return ptrValue->GetDeclTypeStr(bResolveTypedef) + "[" + std::to_string(GetSize()) + "]";
|
|
}
|
|
|
|
CCompoundTypeValueNode::CCompoundTypeValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
|
CEntityValueNode(ptrEntity, ptrParent)
|
|
{}
|
|
|
|
CCompoundTypeValueNode::CCompoundTypeValueNode(const CCompoundTypeValueNode& rValueNode, CEntityPtr ptrEntity,
|
|
const CValueNodePtr ptrParent) : CEntityValueNode(rValueNode, ptrEntity, ptrParent)
|
|
{}
|
|
|
|
CValueNodePtr CCompoundTypeValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
|
{
|
|
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
|
}
|
|
|
|
void CCompoundTypeValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
|
{
|
|
CLog log("Processing struct value node...");
|
|
|
|
if (rlstExpression.End())
|
|
throw CCompileException(rlstExpression.LastValid(), "Missing assignment");
|
|
if (!m_ptrEntity)
|
|
throw CCompileException(rlstExpression.LastValid(), "Internal error: a value node should be assigned to an entity.");
|
|
|
|
// There are two options: either a scoped name representing a type (or typedef) being of the same type (identical name), or a
|
|
// compound value (between curly brackets '{...}').
|
|
if (rlstExpression.Current() != "{") // Type value assignment
|
|
{
|
|
CValueNodePtr ptrValue = m_ptrEntity->FindValue(rlstExpression);
|
|
|
|
// Check if the original type of the assginee and the assigned are identical. For this both entities must be declarations.
|
|
if (!GetDeclEntity()->Get<CDeclarationEntity>())
|
|
throw CCompileException(rlstExpression.LastValid(), "Internal error: the assignee entity must be a declaration entity.");
|
|
|
|
// Assignment can only work if the types are identical. This is regardless of the typedefs that have been made from the
|
|
// type.
|
|
if (GetDeclTypeStr(true) != ptrValue->GetDeclTypeStr(true))
|
|
throw CCompileException(rlstExpression.LastValid(), "For '", GetDeclEntity()->GetName(), "', cannot assign '",
|
|
ptrValue->GetDeclTypeStr(true), "' to '", ptrValue->GetDeclTypeStr(true), "'; base types are different.");
|
|
|
|
// Replace the value by the value chain of the assigned to the assignee.
|
|
m_ptrEntity->ValueRef() = ptrValue->CreateCopy(m_ptrEntity, m_ptrParent);
|
|
} else // Compound value assignment
|
|
{
|
|
++rlstExpression; // Skip left bracket
|
|
|
|
// Process the child nodes
|
|
ProcessChildNodes(rlstExpression);
|
|
|
|
// Expecting '}'
|
|
if (rlstExpression.End() || rlstExpression.Current() != "}")
|
|
throw CCompileException(rlstExpression.LastValid(), "Expecting right curly bracket '}'");
|
|
++rlstExpression; // Skip right bracket
|
|
}
|
|
}
|
|
|
|
CInterfaceValueNode::CInterfaceValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
|
CEntityValueNode(ptrEntity, ptrParent)
|
|
{}
|
|
|
|
CInterfaceValueNode::CInterfaceValueNode(const CInterfaceValueNode& rValueNode, CEntityPtr ptrEntity,
|
|
const CValueNodePtr ptrParent) :
|
|
CEntityValueNode(rValueNode, ptrEntity, ptrParent)
|
|
{}
|
|
|
|
CValueNodePtr CInterfaceValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
|
{
|
|
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
|
}
|
|
|
|
void CInterfaceValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
|
{
|
|
CLog log("Processing declaration value assignment...");
|
|
|
|
if (!m_ptrEntity) throw CCompileException("Internal error: no entity assigned to the value node.");
|
|
|
|
const CDeclarationEntity* pSystemTypeEntity = m_ptrEntity->Get<CDeclarationEntity>();
|
|
if (!pSystemTypeEntity)
|
|
throw CCompileException("Internal error: type mismatch between value node and entity type.");
|
|
|
|
// Only "null" and "0" are allowed.
|
|
if ((!m_ptrEntity->GetParserRef().GetEnvironment().InterfaceTypeExtension() || rlstExpression.Current() != "null") &&
|
|
rlstExpression.Current() != "0")
|
|
throw CCompileException(rlstExpression.Current(),
|
|
"Error: assignment of interface values is only possible with the value \"null\".");
|
|
|
|
// Skip the value.
|
|
++rlstExpression;
|
|
}
|
|
|
|
|
|
CValueNodePtr CCompoundTypeValueNode::Member(const std::string& rssName) const
|
|
{
|
|
// Check the entity names of the child value nodes.
|
|
// ATTENTION: The child value nodes are copies of the original definition. They still contain the link to the declarations
|
|
// that were part of the definition. The entity belonging to a declaration of a compound type does not have any children (the
|
|
// entity itself is just the declaration and not the definition):
|
|
for (const CValueNodePtr& rptrValue : m_vecChildren)
|
|
if (rptrValue->GetDeclEntity()->GetName() == rssName) return rptrValue;
|
|
return nullptr; // Value not found.
|
|
}
|
|
|
|
CEnumValueNode::CEnumValueNode(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) :
|
|
CEntityValueNode(ptrEntity, ptrParent)
|
|
{}
|
|
|
|
CEnumValueNode::CEnumValueNode(const CEnumValueNode& rValueNode, CEntityPtr ptrEntity,
|
|
const CValueNodePtr ptrParent) :
|
|
CEntityValueNode(rValueNode, ptrEntity, ptrParent), m_ptrEntryVal(rValueNode.m_ptrEntryVal),
|
|
m_lstExpression(rValueNode.m_lstExpression)
|
|
{}
|
|
|
|
CValueNodePtr CEnumValueNode::CreateCopy(CEntityPtr ptrEntity, const CValueNodePtr ptrParent) const
|
|
{
|
|
return std::make_shared<std::decay_t<std::remove_pointer_t<decltype(this)>>>(*this, ptrEntity, ptrParent);
|
|
}
|
|
|
|
void CEnumValueNode::ProcessValueAssignment(const CTokenList& rlstExpression)
|
|
{
|
|
CLog log("Processing enum value assignment...");
|
|
// The assignment is done using the enum entry type. Find the scoped name. This could be the enum value. Check the type first.
|
|
CTokenList rlstExpressionTemp = rlstExpression;
|
|
std::pair<std::string, CEntityPtr> prEntity = GetDeclEntity()->GetTypeEntity()->ProcessScopedName(rlstExpression, true);
|
|
// If not an enum value from the type, use as scope the parent of the current enum to search for other declarations.
|
|
if (!prEntity.second) prEntity = GetDeclEntity()->GetParentEntity()->ProcessScopedName(rlstExpressionTemp, true);
|
|
if (!prEntity.second) throw CCompileException(rlstExpression.LastValid(), "Expecting an enum value.");
|
|
|
|
// This could either be an assignment of an enum to another enum or an enum entry to an enum.
|
|
log << "The to be assigned type is '" << prEntity.second->GetDeclTypeStr(true) << "'..." << std::endl;
|
|
log << "The assignee type is '" << GetDeclEntity()->GetDeclTypeStr(true) << "'..." << std::endl;
|
|
if (prEntity.second->GetDeclTypeStr(true) == GetDeclEntity()->GetDeclTypeStr(true))
|
|
{
|
|
if (!prEntity.second->ValueRef())
|
|
throw CCompileException(rlstExpression.LastValid(), "Internal error: the enum doesn't have an assigned value.");
|
|
if (!prEntity.second->ValueRef()->Get<CEnumValueNode>())
|
|
throw CCompileException(rlstExpression.LastValid(), "Internal error: the enum doesn't have an assigned enum value.");
|
|
m_ptrEntryVal = prEntity.second->ValueRef()->Get<CEnumValueNode>()->m_ptrEntryVal;
|
|
} else if (prEntity.second->GetParentEntity()->GetDeclTypeStr(true) == GetDeclEntity()->GetDeclTypeStr(true))
|
|
{
|
|
log << "Assigning enum entry..." << std::endl;
|
|
m_ptrEntryVal = prEntity.second;
|
|
} else
|
|
throw CCompileException(rlstExpression.LastValid(), "Invalid enum value; enum types are not identical.");
|
|
log << "Enum entity was assigned value '" << m_ptrEntryVal->GetParentEntity()->GetName() << "::" <<
|
|
m_ptrEntryVal->GetName() << "'..." << std::endl;
|
|
}
|
|
|
|
const CConstVariant& CEnumValueNode::Variant() const
|
|
{
|
|
static CConstVariant temp;
|
|
if (!m_ptrEntryVal) return temp;
|
|
if (!m_ptrEntryVal->ValueRef()) return temp;
|
|
const CSimpleTypeValueNode* pValueNode = m_ptrEntryVal->ValueRef()->Get<CSimpleTypeValueNode>();
|
|
if (!pValueNode) return temp;
|
|
return pValueNode->Variant();
|
|
}
|
|
|
|
std::string CEnumValueNode::String() const
|
|
{
|
|
if (!m_ptrEntryVal) return std::string();
|
|
return m_ptrEntryVal->GetParentEntity()->GetScopedName() + "::" + m_ptrEntryVal->GetName();
|
|
}
|