Skip to content

Commit

Permalink
[memory][scs][tests] Don't ignore arcs to types of elements nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
NikitaZotov committed Nov 14, 2024
1 parent 662c3fd commit b1904dc
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 90 deletions.
20 changes: 9 additions & 11 deletions sc-memory/sc-memory/include/sc-memory/scs/scs_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <stack>
#include <map>
#include <string>
#include <functional>

namespace scs
{
Expand Down Expand Up @@ -83,7 +84,7 @@ class ElementHandle
_SC_EXTERN bool operator<(ElementHandle const & other) const;

private:
static const ElementID INVALID_ID = std::numeric_limits<ElementID>::max();
static ElementID const INVALID_ID = std::numeric_limits<ElementID>::max();

ElementID m_id;
Visibility m_visibility;
Expand All @@ -109,7 +110,7 @@ class Parser
friend class scsParser;

// Number of parsed elements, to preallocate container
static const size_t PARSED_PREALLOC_NUM = 1024;
static size_t const PARSED_PREALLOC_NUM = 1024;

public:
using TripleVector = std::vector<ParsedTriple>;
Expand All @@ -122,24 +123,18 @@ class Parser
_SC_EXTERN bool Parse(std::string const & str);
_SC_EXTERN ParsedElement const & GetParsedElement(ElementHandle const & handle) const;
_SC_EXTERN TripleVector const & GetParsedTriples() const;
_SC_EXTERN void ForEachParsedTriple(
std::function<void(ParsedElement const &, ParsedElement const &, ParsedElement const &)> const & callback) const;
_SC_EXTERN std::string const & GetParseError() const;
_SC_EXTERN AliasHandles const & GetAliases() const;

template <typename TFunc>
void ForEachParsedElement(TFunc && fn) const
{
for (auto const & el : m_parsedElementsLocal)
{
if (el.IsMetaElement())
continue;
fn(el);
}
for (auto const & el : m_parsedElements)
{
if (el.IsMetaElement())
continue;
fn(el);
}
}

protected:
Expand All @@ -157,7 +152,10 @@ class Parser
void ProcessContourBegin();
void ProcessContourEnd(ElementHandle const & contourHandle);

void ProcessTriple(ElementHandle const & sourceHandle, ElementHandle const & connectorHandle, ElementHandle const & targetHandle);
void ProcessTriple(
ElementHandle const & sourceHandle,
ElementHandle const & connectorHandle,
ElementHandle const & targetHandle);
void ProcessAssign(std::string const & alias, ElementHandle const & value);

private:
Expand Down
51 changes: 25 additions & 26 deletions sc-memory/sc-memory/src/sc_scs_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,35 +43,33 @@ class StructGenerator
}

// generate triples
auto const & triples = parser.GetParsedTriples();
std::unordered_set<std::string> typeArcsCache;
for (auto const & t : triples)
{
auto const & source = parser.GetParsedElement(t.m_source);
auto const & connector = parser.GetParsedElement(t.m_connector);
auto const & target = parser.GetParsedElement(t.m_target);

auto const & sourceResult = ResolveElement(source);
auto const & targetResult = ResolveElement(target);
parser.ForEachParsedTriple(
[&](scs::ParsedElement const & source,
scs::ParsedElement const & connector,
scs::ParsedElement const & target) -> void
{
auto const & sourceResult = ResolveElement(source);
auto const & targetResult = ResolveElement(target);

ScType const & connectorType = connector.GetType();
std::string const & connectorIdtf = connector.GetIdtf();
if (!connectorType.IsConnector())
SC_THROW_EXCEPTION(
utils::ExceptionInvalidType,
"Specified in triple sc-connector `" << connectorIdtf << "` has incorrect type `"
<< std::string(connectorType) << "`.");
ScType const & connectorType = connector.GetType();
std::string const & connectorIdtf = connector.GetIdtf();
if (!connectorType.IsConnector())
SC_THROW_EXCEPTION(

Check warning on line 58 in sc-memory/sc-memory/src/sc_scs_helper.cpp

View check run for this annotation

Codecov / codecov/patch

sc-memory/sc-memory/src/sc_scs_helper.cpp#L58

Added line #L58 was not covered by tests
utils::ExceptionInvalidType,
"Specified in triple sc-connector `" << connectorIdtf << "` has incorrect type `"
<< std::string(connectorType) << "`.");

ScAddr const arcAddr = m_ctx.GenerateConnector(connectorType, sourceResult.first, targetResult.first);
m_idtfCache.insert({connectorIdtf, arcAddr});
ScAddr const connectorAddr = m_ctx.GenerateConnector(connectorType, sourceResult.first, targetResult.first);
m_idtfCache.insert({connectorIdtf, connectorAddr});

if (m_outputStructure.IsValid())
{
AppendToOutputStructure(sourceResult.first, arcAddr, targetResult.first);
AppendToOutputStructure(sourceResult.second);
AppendToOutputStructure(targetResult.second);
}
}
if (m_outputStructure.IsValid())
{
AppendToOutputStructure(sourceResult.first, connectorAddr, targetResult.first);
AppendToOutputStructure(sourceResult.second);
AppendToOutputStructure(targetResult.second);
}
});

parser.ForEachParsedElement(
[this](scs::ParsedElement const & el)
Expand Down Expand Up @@ -174,7 +172,8 @@ class StructGenerator
else
SC_THROW_EXCEPTION(

Check warning on line 173 in sc-memory/sc-memory/src/sc_scs_helper.cpp

View check run for this annotation

Codecov / codecov/patch

sc-memory/sc-memory/src/sc_scs_helper.cpp#L173

Added line #L173 was not covered by tests
utils::ExceptionInvalidState,
"Incorrect element type `" << std::string(type) << "` for element `" << el.GetIdtf() << "`.");
"Element `" << el.GetIdtf() << "` can't be resolved, because it has not sc-node type `"
<< std::string(type) << "`.");

// setup system identifier
if (el.GetVisibility() == scs::Visibility::System)
Expand Down
35 changes: 12 additions & 23 deletions sc-memory/sc-memory/src/sc_template_scs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,56 +36,45 @@ class ScTemplateBuilderFromScs
utils::ScKeynodeCache keynodes(m_ctx);
std::unordered_set<std::string> passed;

auto const MakeTemplItem = [&passed, &keynodes](scs::ParsedElement const & el, ScTemplateItem & outValue) -> bool
auto const MakeTemplItem = [&passed, &keynodes](scs::ParsedElement const & el, ScTemplateItem & outValue) -> void
{
std::string const & idtf = el.GetIdtf();
bool const isUnnamed = scs::TypeResolver::IsUnnamed(idtf);
bool const isPassed = passed.find(idtf) != passed.cend();

if (!isUnnamed && isPassed)
{
outValue.SetReplacement(idtf.c_str());
}
else
{
sc_char const * alias = (isUnnamed ? nullptr : idtf.c_str());
ScAddr const addr = keynodes.GetKeynode(idtf);
if (addr.IsValid())
{
outValue.SetAddr(addr, alias);
}
else
{
if (el.GetType().IsVar())
{
outValue.SetType(el.GetType(), alias);
}
else
{
SC_THROW_EXCEPTION(utils::ExceptionInvalidState, "Can't find element " << idtf);
return false;
}
}
}

passed.insert(idtf);

return true;
};

for (scs::ParsedTriple const & t : m_parser.GetParsedTriples())
{
scs::ParsedElement const & src = m_parser.GetParsedElement(t.m_source);
scs::ParsedElement const & connector = m_parser.GetParsedElement(t.m_connector);
scs::ParsedElement const & trg = m_parser.GetParsedElement(t.m_target);

ScTemplateItem srcItem, connectorItem, trgItem;
m_parser.ForEachParsedTriple(
[&](scs::ParsedElement const & source,
scs::ParsedElement const & connector,
scs::ParsedElement const & target) -> void
{
ScTemplateItem sourceItem, connectorItem, targetItem;

if (!MakeTemplItem(src, srcItem) || !MakeTemplItem(connector, connectorItem) || !MakeTemplItem(trg, trgItem))
break;
MakeTemplItem(source, sourceItem);
MakeTemplItem(connector, connectorItem);
MakeTemplItem(target, targetItem);

templ->Triple(srcItem, connectorItem, trgItem);
}
templ->Triple(sourceItem, connectorItem, targetItem);
});
}

private:
Expand Down
6 changes: 1 addition & 5 deletions sc-memory/sc-memory/src/scs/scs.g4
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,7 @@ idtf_set_elements [std::string setType]
locals [ElementHandle prevArc]
: {
std::string const setIdtf = "..set_" + std::to_string($ctx->start->getLine()) + "_" + std::to_string($ctx->start->getCharPositionInLine());
$ctx->handle = m_parser->ProcessIdentifier(setIdtf);
ElementHandle const typeArc = m_parser->ProcessConnector("->");
ElementHandle const typeClass = m_parser->ProcessIdentifier("sc_node_tuple");
m_parser->ProcessTriple(typeClass, typeArc, $ctx->handle);
$ctx->handle = m_parser->ProcessIdentifierLevel1("sc_node_tuple", setIdtf);
}
a1=attr_list? i1=idtf_common
{
Expand Down
44 changes: 33 additions & 11 deletions sc-memory/sc-memory/src/scs/scs_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ ParsedElement::ParsedElement(
{
ResolveVisibility();

// all connectors has a local visibility
// all connectors have a local visibility
if (type.IsConnector())
m_visibility = Visibility::Local;
}
Expand Down Expand Up @@ -316,7 +316,10 @@ ParsedElement & Parser::GetParsedElementRef(ElementHandle const & handle)
if (*handle >= container.size())
SC_THROW_EXCEPTION(
utils::ExceptionItemNotFound,
"ElementId{" << std::to_string(*handle) << ", " << (size_t)handle.GetVisibility() << "}");
"Parsed element not found. "
"ElementId: {"
<< std::to_string(*handle) << ", " << (size_t)handle.GetVisibility() << "}. Valid range: [0, "
<< container.size() - 1 << "].");

return container[*handle];
}
Expand All @@ -328,7 +331,10 @@ ParsedElement const & Parser::GetParsedElement(ElementHandle const & handle) con
if (*handle >= container.size())
SC_THROW_EXCEPTION(
utils::ExceptionItemNotFound,
"ElementId{" << std::to_string(*handle) << ", " << (size_t)handle.GetVisibility() << "}");
"Error: Parsed element not found. "
"ElementId: {"
<< std::to_string(*handle) << ", " << (size_t)handle.GetVisibility() << "}. Valid range: [0, "
<< container.size() - 1 << "].");

return container[*handle];
}
Expand All @@ -338,6 +344,23 @@ Parser::TripleVector const & Parser::GetParsedTriples() const
return m_parsedTriples;
}

void Parser::ForEachParsedTriple(
std::function<void(ParsedElement const &, ParsedElement const &, ParsedElement const &)> const & callback) const
{
for (auto const & triple : m_parsedTriples)
{
auto const & source = GetParsedElement(triple.m_source);
auto const & connector = GetParsedElement(triple.m_connector);
auto const & target = GetParsedElement(triple.m_target);

if ((source.IsMetaElement() && (connector.GetType() == ScType::ConstPermPosArc))
|| (target.IsMetaElement() && (target.GetType() == ScType::ConstPermPosArc)))
continue;

callback(source, connector, target);
}
}

std::string const & Parser::GetParseError() const
{
return m_lastError;
Expand Down Expand Up @@ -447,8 +470,7 @@ void Parser::ProcessTriple(
[this, &connector](
ElementHandle const & sourceHdl, ElementHandle const & connectorHdl, ElementHandle const & targetHdl)
{
if (((connector.GetType() == ScType::ConstPermPosArc) || (connector.GetType() == ScType::ConstActualTempPosArc))
&& sourceHdl.IsMetaElement())
if (sourceHdl.IsMetaElement() && (connector.GetType() == ScType::ConstPermPosArc))
{
ParsedElement const & source = GetParsedElement(sourceHdl);
ParsedElement & target = GetParsedElementRef(targetHdl);
Expand All @@ -464,14 +486,14 @@ void Parser::ProcessTriple(
"Can't extend type `" << std::string(target.m_type) << "` to type `" << std::string(newType)
<< "` for element `" << target.GetIdtf() << "`.");

// TODO(NikitaZotov): Unfortunately, parser collects all sc.s-elements, and only then form sc.s-triples based on
// TODO(NikitaZotov): Unfortunately, parser collects all sc.s-elements, and only then forms sc.s-triples based on
// the parsed sc.s-elements. Due to this, it is difficult to handle cases when it is necessary not to generate a
// sc-arc from a type of sc-elements to sc-element. Therefore, now the parser marks this arcs after that they were
// parsed.
connector.m_isMetaElement = true;
}
else
m_parsedTriples.emplace_back(sourceHdl, connectorHdl, targetHdl);

m_parsedTriples.emplace_back(sourceHdl, connectorHdl, targetHdl);
};

if (connector.IsReversed())
Expand Down Expand Up @@ -554,12 +576,12 @@ void Parser::ProcessContourEnd(ElementHandle const & contourHandle)

// append all new elements into contour
for (size_t i = ind.first; i < last; ++i)
newElements.insert(ElementHandle(
ElementID(i), m_parsedElements[i].GetVisibility(), m_parsedElements[i].IsMetaElement()));
newElements.insert(
ElementHandle(ElementID(i), m_parsedElements[i].GetVisibility(), m_parsedElements[i].IsMetaElement()));

for (size_t i = ind.second; i < lastLocal; ++i)
newElements.insert(ElementHandle(
ElementID(i), m_parsedElementsLocal[i].GetVisibility(), m_parsedElementsLocal[i].IsMetaElement()));
ElementID(i), m_parsedElementsLocal[i].GetVisibility(), m_parsedElementsLocal[i].IsMetaElement()));

size_t const tripleFirst = m_contourTriplesStack.top();
m_contourTriplesStack.pop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,65 @@ TEST_F(SCsHelperTest, GenerateBySCs_SingleNode)
EXPECT_FALSE(m_ctx->CheckConnector(nodeClass, node, ScType::ConstPermPosArc));
}

TEST_F(SCsHelperTest, GenerateBySCs_ElementTypes)
{
SCsHelper helper(*m_ctx, std::make_shared<DummyFileInterface>());
std::string const scsData = "sc_node_class"
"-> class1;"
"-> rrel_1: class2;;"
"class3"
"-> sc_node_class;;"
"class4"
"-> rrel_1: sc_node_class;;"
"sc_node_class "
"_-> class5;"
"_-> _class6;"
"_-> rrel_3: class7;"
"_-> rrel_4:: _class8;;";

EXPECT_TRUE(helper.GenerateBySCsText(scsData));

ScAddr const & nodeClass = m_ctx->SearchElementBySystemIdentifier("sc_node_class");
ScAddr const & class1 = m_ctx->SearchElementBySystemIdentifier("class1");
EXPECT_EQ(m_ctx->GetElementType(class1), ScType::ConstNodeClass);
EXPECT_FALSE(m_ctx->CheckConnector(nodeClass, class1, ScType::ConstPermPosArc));

ScAddr const & class2 = m_ctx->SearchElementBySystemIdentifier("class2");
EXPECT_EQ(m_ctx->GetElementType(class2), ScType::ConstNodeClass);
EXPECT_FALSE(m_ctx->CheckConnector(nodeClass, class2, ScType::ConstPermPosArc));

ScAddr const & class3 = m_ctx->SearchElementBySystemIdentifier("class3");
EXPECT_EQ(m_ctx->GetElementType(class3), ScType::ConstNode);
EXPECT_TRUE(m_ctx->CheckConnector(class3, nodeClass, ScType::ConstPermPosArc));

ScAddr const & class4 = m_ctx->SearchElementBySystemIdentifier("class4");
EXPECT_EQ(m_ctx->GetElementType(class4), ScType::ConstNode);
EXPECT_TRUE(
m_ctx->CreateIterator5(class4, ScType::ConstPermPosArc, nodeClass, ScType::ConstPermPosArc, ScKeynodes::rrel_1)
->Next());

ScAddr const & class5 = m_ctx->SearchElementBySystemIdentifier("class5");
EXPECT_EQ(m_ctx->GetElementType(class5), ScType::ConstNode);
EXPECT_TRUE(m_ctx->CheckConnector(nodeClass, class5, ScType::VarPermPosArc));

ScAddr const & class6 = m_ctx->SearchElementBySystemIdentifier("_class6");
EXPECT_EQ(m_ctx->GetElementType(class6), ScType::VarNode);
EXPECT_TRUE(m_ctx->CheckConnector(nodeClass, class6, ScType::VarPermPosArc));

ScAddr const & class7 = m_ctx->SearchElementBySystemIdentifier("class7");
EXPECT_EQ(m_ctx->GetElementType(class7), ScType::ConstNode);
EXPECT_TRUE(
m_ctx->CreateIterator5(nodeClass, ScType::VarPermPosArc, class7, ScType::ConstPermPosArc, ScKeynodes::rrel_3)
->Next());

ScAddr const & class8 = m_ctx->SearchElementBySystemIdentifier("_class8");
ScAddr const & rrel_4 = m_ctx->SearchElementBySystemIdentifier("rrel_4");
EXPECT_EQ(m_ctx->GetElementType(class8), ScType::VarNode);
EXPECT_TRUE(
m_ctx->CreateIterator5(nodeClass, ScType::VarPermPosArc, class8, ScType::VarPermPosArc, rrel_4)
->Next());
}

TEST_F(SCsHelperTest, GenerateBySCs_Visibility_System)
{
SCsHelper helper(*m_ctx, std::make_shared<DummyFileInterface>());
Expand Down
Loading

0 comments on commit b1904dc

Please sign in to comment.