Refactor RSLang code readability

This commit is contained in:
IRBorisov 2024-05-06 15:02:37 +03:00
parent c4db405fbe
commit de81d4037f
17 changed files with 763 additions and 523 deletions

10
.vscode/settings.json vendored
View File

@ -16,6 +16,7 @@
"cmake.ctestArgs": ["--test-dir build", "--output-on-failure"],
"cmake.installPrefix": "output",
"cSpell.words": [
"BIGPR",
"conanfile",
"coredll",
"DCMAKE",
@ -23,19 +24,28 @@
"DECART",
"Decartian",
"defexpr",
"EMPTYSET",
"FORALL",
"GNUC",
"gtest",
"ifdef",
"INTSET",
"MSVC",
"nlohmann",
"noteq",
"NOTEQUAL",
"NOTIN",
"notsubset",
"PUNC",
"pybind",
"pyconcept",
"rslang",
"setexpr",
"SMALLPR",
"struct",
"symmdiff",
"SYMMINUS",
"YYABORT",
"yylex",
"yylval",
"YYSTYPE",

View File

@ -30,7 +30,7 @@ public:
private:
void Quantifier(SyntaxTree::Node& quant);
static void EnumDeclaration(SyntaxTree::Node& quant);
void TupleDeclaration(SyntaxTree::Node& declaration, SyntaxTree::Node& predicat);
void TupleDeclaration(SyntaxTree::Node& declaration, SyntaxTree::Node& predicate);
void TupleDeclaration(SyntaxTree::Node& target);
[[nodiscard]] std::string CreateTupleName(const SyntaxTree::Node& root);

View File

@ -333,7 +333,7 @@ namespace ccl { namespace rslang { namespace detail {
RST_IN = 282, // IN
RST_NOTIN = 283, // NOTIN
RST_SUBSET = 284, // SUBSET
RST_SUBOR_EQ = 285, // SUBOR_EQ
RST_SUBSET_OR_EQ = 285, // SUBSET_OR_EQ
RST_NOTSUBSET = 286, // NOTSUBSET
RST_DECART = 287, // DECART
RST_UNION = 288, // UNION
@ -412,7 +412,7 @@ namespace ccl { namespace rslang { namespace detail {
S_IN = 27, // IN
S_NOTIN = 28, // NOTIN
S_SUBSET = 29, // SUBSET
S_SUBOR_EQ = 30, // SUBOR_EQ
S_SUBSET_OR_EQ = 30, // SUBSET_OR_EQ
S_NOTSUBSET = 31, // NOTSUBSET
S_DECART = 32, // DECART
S_UNION = 33, // UNION

View File

@ -42,10 +42,10 @@ enum class SemanticEID : uint32_t {
invalidProjectionTuple = 0x8811, // Не определена проекция
invalidProjectionSet = 0x8812, // Большая проекция определена только для множеств!
invalidEnumeration = 0x8813, // Типизация аргументов перечисления не совпадает
ivalidBinding = 0x8814, // Количество переменных в кортеже не соответствует размерности декартова произведения
invalidBinding = 0x8814, // Количество переменных в кортеже не соответствует размерности декартова произведения
localOutOfScope = 0x8815, // Использование имени вне области видимости
invalidElementPredicat = 0x8816, // Несоответствие типов для проверки принадлежности
invalidArgsArtity = 0x8818, // Некорректное количество аргументов терм-функции
invalidElementPredicate = 0x8816, // Несоответствие типов для проверки принадлежности
invalidArgsArity = 0x8818, // Некорректное количество аргументов терм-функции
invalidArgumentType = 0x8819, // Типизация аргумента не совпадает с объявленной
invalidEqualsEmpty = 0x881A, // Сравнение с пустым множеством не множества
globalStructure = 0x881C, // Родовая структура должна быть ступенью

View File

@ -3,6 +3,7 @@
#include "NameCollector.h"
#include <stack>
#include <optional>
#ifdef _MSC_VER
#pragma warning( push )
@ -94,11 +95,11 @@ private:
auto element = parent.EvaluateChild(imperative, 0);
if (!element.has_value()) {
return false;
} else {
value.ModifyB().AddElement(std::get<StructuredData>(element.value()));
incrementIter = true;
return true;
}
value.ModifyB().AddElement(std::get<StructuredData>(element.value()));
incrementIter = true;
return true;
}
[[nodiscard]] bool ProcessBlock() {
@ -188,8 +189,7 @@ void ASTInterpreter::OnError(const ValueEID eid, const StrPos position, std::str
std::optional<ExpressionValue> ASTInterpreter::Evaluate(const rslang::SyntaxTree& tree) {
Clear();
if (!NameCollector{ *this }.Visit(tree.Root())
|| !tree.Root().DispatchVisit(*this)) {
if (!NameCollector{ *this }.Visit(tree.Root()) || !tree.Root().DispatchVisit(*this)) {
AfterVisit(false);
return std::nullopt;
} else {
@ -247,46 +247,49 @@ bool ASTInterpreter::ViEmptySet(Cursor /*iter*/) {
}
bool ASTInterpreter::ViArithmetic(Cursor iter) {
if (const auto val1 = EvaluateChild(iter, 0); !val1.has_value()) {
const auto val1 = EvaluateChild(iter, 0);
if (!val1.has_value()) {
return false;
} else if (const auto val2 = EvaluateChild(iter, 1); !val2.has_value()) {
}
const auto val2 = EvaluateChild(iter, 1);
if (!val2.has_value()) {
return false;
} else {
const auto op1 = std::get<StructuredData>(val1.value()).E().Value();
const auto op2 = std::get<StructuredData>(val2.value()).E().Value();
switch (iter->id) {
default:
case TokenID::PLUS:
return VisitAndReturn(Factory::Val(op1 + op2));
case TokenID::MINUS:
return VisitAndReturn(Factory::Val(op1 - op2));
case TokenID::MULTIPLY:
return VisitAndReturn(Factory::Val(op1 * op2));
}
}
const auto op1 = std::get<StructuredData>(val1.value()).E().Value();
const auto op2 = std::get<StructuredData>(val2.value()).E().Value();
switch (iter->id) {
default:
case TokenID::PLUS:
return VisitAndReturn(Factory::Val(op1 + op2));
case TokenID::MINUS:
return VisitAndReturn(Factory::Val(op1 - op2));
case TokenID::MULTIPLY:
return VisitAndReturn(Factory::Val(op1 * op2));
}
}
bool ASTInterpreter::ViCard(Cursor iter) {
if (const auto base = EvaluateChild(iter, 0); !base.has_value()) {
const auto base = EvaluateChild(iter, 0);
if (!base.has_value()) {
return false;
} else if (const auto size = std::get<StructuredData>(base.value()).B().Cardinality();
size == StructuredData::SET_INFINITY) {
}
const auto size = std::get<StructuredData>(base.value()).B().Cardinality();
if (size == StructuredData::SET_INFINITY) {
OnError(ValueEID::typedOverflow, iter->pos.start, std::to_string(StructuredData::SET_INFINITY));
return false;
} else {
return VisitAndReturn(Factory::Val(size));
}
return VisitAndReturn(Factory::Val(size));
}
bool ASTInterpreter::ViQuantifier(Cursor iter) {
const auto quantorDomain = ExtractDomain(iter);
if (!quantorDomain.has_value()) {
const auto domain = ExtractDomain(iter);
if (!domain.has_value()) {
return false;
}
const auto varID = *begin(nodeVars[iter.Child(0).get()]);
const auto quantorForAll = iter->id == TokenID::FORALL;
for (const auto& child : quantorDomain->B()) {
const auto isUniversal = iter->id == TokenID::FORALL;
for (const auto& child : domain->B()) {
if (++iterationCounter > MAX_ITERATIONS) {
OnError(ValueEID::iterationsLimit, iter->pos.start, std::to_string(MAX_ITERATIONS));
return false;
@ -294,46 +297,50 @@ bool ASTInterpreter::ViQuantifier(Cursor iter) {
idsData[varID] = child;
if (const auto iterationValue = EvaluateChild(iter, 2); !iterationValue.has_value()) {
return false;
} else if (std::get<bool>(iterationValue.value()) != quantorForAll) {
return VisitAndReturn(!quantorForAll);
} else if (std::get<bool>(iterationValue.value()) != isUniversal) {
return VisitAndReturn(!isUniversal);
}
}
return VisitAndReturn(quantorForAll);
return VisitAndReturn(isUniversal);
}
std::optional<StructuredData> ASTInterpreter::ExtractDomain(Cursor iter) {
if (!VisitChild(iter, 1)) {
return std::nullopt;
} else {
return std::optional<StructuredData>{std::get<StructuredData>(curValue)};
}
return std::optional<StructuredData>{std::get<StructuredData>(curValue)};
}
bool ASTInterpreter::ViNegation(Cursor iter) {
if (const auto childValue = EvaluateChild(iter, 0); !childValue.has_value()) {
const auto childValue = EvaluateChild(iter, 0);
if (!childValue.has_value()) {
return false;
} else {
return VisitAndReturn(!std::get<bool>(childValue.value()));
}
return VisitAndReturn(!std::get<bool>(childValue.value()));
}
bool ASTInterpreter::ViLogicBinary(Cursor iter) {
if (const auto val1 = EvaluateChild(iter, 0); !val1.has_value()) {
const auto val1 = EvaluateChild(iter, 0);
if (!val1.has_value()) {
return false;
} else if (TryEvaluateFromFirstArg(iter->id, std::get<bool>(val1.value()))) {
}
if (TryEvaluateFromFirstArg(iter->id, std::get<bool>(val1.value()))) {
return true;
} else if (const auto val2 = EvaluateChild(iter, 1); !val2.has_value()) {
}
const auto val2 = EvaluateChild(iter, 1);
if (!val2.has_value()) {
return false;
} else {
const auto op1 = std::get<bool>(val1.value());
const auto op2 = std::get<bool>(val2.value());
switch (iter->id) {
}
const auto op1 = std::get<bool>(val1.value());
const auto op2 = std::get<bool>(val2.value());
switch (iter->id) {
default:
case TokenID::AND: curValue = op1 && op2; return true;
case TokenID::OR: curValue = op1 || op2; return true;
case TokenID::IMPLICATION: curValue = !op1 || op2; return true;
case TokenID::EQUIVALENT: curValue = op1 == op2; return true;
}
case TokenID::EQUIVALENT: curValue = op1 == op2; return true;
}
}
@ -349,30 +356,34 @@ bool ASTInterpreter::TryEvaluateFromFirstArg(TokenID operation, bool firstArgVal
}
bool ASTInterpreter::ViEquals(Cursor iter) {
if (const auto val1 = EvaluateChild(iter, 0); !val1.has_value()) {
const auto val1 = EvaluateChild(iter, 0);
if (!val1.has_value()) {
return false;
} else if (const auto val2 = EvaluateChild(iter, 1); !val2.has_value()) {
return false;
} else {
return VisitAndReturn((val1 == val2) != (iter->id == TokenID::NOTEQUAL));
}
const auto val2 = EvaluateChild(iter, 1);
if (!val2.has_value()) {
return false;
}
return VisitAndReturn((val1 == val2) != (iter->id == TokenID::NOTEQUAL));
}
bool ASTInterpreter::ViOrdering(Cursor iter) {
if (const auto val1 = EvaluateChild(iter, 0); !val1.has_value()) {
const auto val1 = EvaluateChild(iter, 0);
if (!val1.has_value()) {
return false;
} else if (const auto val2 = EvaluateChild(iter, 1); !val2.has_value()) {
}
const auto val2 = EvaluateChild(iter, 1);
if (!val2.has_value()) {
return false;
} else {
const auto op1 = std::get<StructuredData>(val1.value()).E().Value();
const auto op2 = std::get<StructuredData>(val2.value()).E().Value();
switch (iter->id) {
}
const auto op1 = std::get<StructuredData>(val1.value()).E().Value();
const auto op2 = std::get<StructuredData>(val2.value()).E().Value();
switch (iter->id) {
default:
case TokenID::GREATER: return VisitAndReturn(op1 > op2);
case TokenID::LESSER: return VisitAndReturn(op1 < op2);
case TokenID::GREATER_OR_EQ: return VisitAndReturn(op1 >= op2);
case TokenID::LESSER_OR_EQ: return VisitAndReturn(op1 <= op2);
}
}
}
@ -389,9 +400,11 @@ bool ASTInterpreter::ViDeclarative(Cursor iter) {
return false;
}
idsData[varID] = child;
if (const auto predicatValue = EvaluateChild(iter, 2); !predicatValue.has_value()) {
const auto predicatValue = EvaluateChild(iter, 2);
if (!predicatValue.has_value()) {
return false;
} else if (std::get<bool>(predicatValue.value())) {
}
if (std::get<bool>(predicatValue.value())) {
result.ModifyB().AddElement(child);
}
}
@ -402,9 +415,8 @@ bool ASTInterpreter::ViImperative(const Cursor iter) {
ImpEvaluator eval{ *this, iter };
if (!eval.Evaluate()) {
return false;
} else {
return VisitAndReturn(eval.value);
}
return VisitAndReturn(eval.value);
}
bool ASTInterpreter::ViRecursion(Cursor iter) {
@ -422,9 +434,11 @@ bool ASTInterpreter::ViRecursion(Cursor iter) {
idsData[varID] = current;
if (iter->id == TokenID::NT_RECURSIVE_FULL) {
if (const auto predicat = EvaluateChild(iter, 2); !predicat.has_value()) {
const auto predicat = EvaluateChild(iter, 2);
if (!predicat.has_value()) {
return false;
} else if (!std::get<bool>(predicat.value())) {
}
if (!std::get<bool>(predicat.value())) {
break;
}
}
@ -451,32 +465,38 @@ bool ASTInterpreter::ViDecart(Cursor iter) {
if (std::get<StructuredData>(curValue).B().Cardinality() == StructuredData::SET_INFINITY) {
OnError(ValueEID::typedOverflow, iter->pos.start, std::to_string(StructuredData::SET_INFINITY));
return false;
} else {
return true;
}
return true;
}
bool ASTInterpreter::ViBoolean(Cursor iter) {
if (const auto childValue = EvaluateChild(iter, 0); !childValue.has_value()) {
const auto childValue = EvaluateChild(iter, 0);
if (!childValue.has_value()) {
return false;
} else if (const auto value = std::get<StructuredData>(childValue.value());
(iter.IsRoot() || (iter.Parent().id != TokenID::IN && iter.Parent().id != TokenID::NT_DECLARATIVE_EXPR)) &&
value.B().Cardinality() >= StructuredData::BOOL_INFINITY) {
OnError(ValueEID::booleanLimit, iter->pos.start, std::to_string(StructuredData::BOOL_INFINITY));
return false;
} else {
return VisitAndReturn(Factory::Boolean(value));
}
const auto value = std::get<StructuredData>(childValue.value());
if (
(iter.IsRoot() || (iter.Parent().id != TokenID::IN && iter.Parent().id != TokenID::NT_DECLARATIVE_EXPR)) &&
value.B().Cardinality() >= StructuredData::BOOL_INFINITY
) {
OnError(
ValueEID::booleanLimit,
iter->pos.start,
std::to_string(StructuredData::BOOL_INFINITY)
);
return false;
}
return VisitAndReturn(Factory::Boolean(value));
}
bool ASTInterpreter::ViTuple(Cursor iter) {
std::vector<StructuredData> args{};
for (Index child = 0; child < iter.ChildrenCount(); ++child) {
if (const auto childValue = EvaluateChild(iter, child); !childValue.has_value()) {
const auto childValue = EvaluateChild(iter, child);
if (!childValue.has_value()) {
return false;
} else {
args.emplace_back(std::get<StructuredData>(childValue.value()));
}
args.emplace_back(std::get<StructuredData>(childValue.value()));
}
return VisitAndReturn(Factory::Tuple(args));
}
@ -484,32 +504,36 @@ bool ASTInterpreter::ViTuple(Cursor iter) {
bool ASTInterpreter::ViSetEnum(Cursor iter) {
std::vector<StructuredData> args{};
for (Index child = 0; child < iter.ChildrenCount(); ++child) {
if (const auto childValue = EvaluateChild(iter, child); !childValue.has_value()) {
const auto childValue = EvaluateChild(iter, child);
if (!childValue.has_value()) {
return false;
} else {
args.emplace_back(std::get<StructuredData>(childValue.value()));
}
args.emplace_back(std::get<StructuredData>(childValue.value()));
}
return VisitAndReturn(Factory::Set(args));
}
bool ASTInterpreter::ViBool(Cursor iter) {
if (const auto childValue = EvaluateChild(iter, 0); !childValue.has_value()) {
const auto childValue = EvaluateChild(iter, 0);
if (!childValue.has_value()) {
return false;
} else {
return VisitAndReturn(Factory::Singleton(std::get<StructuredData>(childValue.value())));
}
return VisitAndReturn(Factory::Singleton(std::get<StructuredData>(childValue.value())));
}
bool ASTInterpreter::ViTypedBinary(Cursor iter) {
if (const auto val1 = EvaluateChild(iter, 0); !val1.has_value()) {
const auto val1 = EvaluateChild(iter, 0);
if (!val1.has_value()) {
return false;
} else if (const auto val2 = EvaluateChild(iter, 1); !val2.has_value()) {
}
const auto val2 = EvaluateChild(iter, 1);
if (!val2.has_value()) {
return false;
} else {
const auto& op1 = std::get<StructuredData>(val1.value());
const auto& op2 = std::get<StructuredData>(val2.value());
switch (iter->id) {
}
const auto& op1 = std::get<StructuredData>(val1.value());
const auto& op2 = std::get<StructuredData>(val2.value());
switch (iter->id) {
default:
case TokenID::UNION: return VisitAndReturn(op1.B().Union(op2.B()));
case TokenID::INTERSECTION: return VisitAndReturn(op1.B().Intersect(op2.B()));
@ -521,16 +545,15 @@ bool ASTInterpreter::ViTypedBinary(Cursor iter) {
case TokenID::SUBSET: return VisitAndReturn(!(op1 == op2) && op1.B().IsSubsetOrEq(op2.B()));
case TokenID::NOTSUBSET: return VisitAndReturn(op1 == op2 || !op1.B().IsSubsetOrEq(op2.B()));
case TokenID::SUBSET_OR_EQ: return VisitAndReturn(op1.B().IsSubsetOrEq(op2.B()));
}
}
}
bool ASTInterpreter::ViProjectSet(Cursor iter) {
if (const auto childValue = EvaluateChild(iter, 0); !childValue.has_value()) {
const auto childValue = EvaluateChild(iter, 0);
if (!childValue.has_value()) {
return false;
} else {
return VisitAndReturn(std::get<StructuredData>(childValue.value()).B().Projection(iter->data.ToTuple()));
}
return VisitAndReturn(std::get<StructuredData>(childValue.value()).B().Projection(iter->data.ToTuple()));
}
bool ASTInterpreter::ViProjectTuple(Cursor iter) {
@ -562,9 +585,11 @@ bool ASTInterpreter::ViFilter(Cursor iter) {
std::vector<StructuredData> params{};
params.reserve(size(indicies));
for (Index child = 0; child < iter.ChildrenCount() - 1; ++child) {
if (const auto param = EvaluateChild(iter, child); !param.has_value()) {
const auto param = EvaluateChild(iter, child);
if (!param.has_value()) {
return false;
} else if (const auto val = std::get<StructuredData>(param.value()); val.B().IsEmpty()) {
}
if (const auto val = std::get<StructuredData>(param.value()); val.B().IsEmpty()) {
return VisitAndReturn(Factory::EmptySet());
} else {
params.emplace_back(val);
@ -588,23 +613,24 @@ bool ASTInterpreter::ViFilter(Cursor iter) {
}
bool ASTInterpreter::ViReduce(Cursor iter) {
if (const auto childValue = EvaluateChild(iter, 0); !childValue.has_value()) {
const auto childValue = EvaluateChild(iter, 0);
if (!childValue.has_value()) {
return false;
} else {
return VisitAndReturn(std::get<StructuredData>(childValue.value()).B().Reduce());
}
return VisitAndReturn(std::get<StructuredData>(childValue.value()).B().Reduce());
}
bool ASTInterpreter::ViDebool(Cursor iter) {
if (const auto childValue = EvaluateChild(iter, 0); !childValue.has_value()) {
const auto childValue = EvaluateChild(iter, 0);
if (!childValue.has_value()) {
return false;
} else if (const auto value = std::get<StructuredData>(childValue.value());
value.B().Cardinality() != 1) {
}
const auto value = std::get<StructuredData>(childValue.value());
if (value.B().Cardinality() != 1) {
OnError(ValueEID::invalidDebool, iter->pos.start);
return false;
} else {
return VisitAndReturn(std::get<StructuredData>(childValue.value()).B().Debool());
}
return VisitAndReturn(std::get<StructuredData>(childValue.value()).B().Debool());
}
std::optional<ExpressionValue> ASTInterpreter::EvaluateChild(Cursor iter, const Index index) {

View File

@ -57,14 +57,15 @@ void Normalizer::EnumDeclaration(SyntaxTree::Node& quant) {
quant(0) = quant(0)(0);
}
void Normalizer::TupleDeclaration(SyntaxTree::Node& declaration,
SyntaxTree::Node& predicat) {
void Normalizer::TupleDeclaration(
SyntaxTree::Node& declaration,
SyntaxTree::Node& predicate
) {
const auto newName = CreateTupleName(declaration);
declaration.RemoveAll();
declaration.token.data = TokenData{ newName };
declaration.token.id = TokenID::ID_LOCAL;
SubstituteTupleVariables(predicat, newName);
SubstituteTupleVariables(predicate, newName);
}
void Normalizer::TupleDeclaration(SyntaxTree::Node& target) {
@ -116,7 +117,8 @@ std::string Normalizer::CreateTupleName(const SyntaxTree::Node& root) {
void Normalizer::SubstituteTupleVariables(SyntaxTree::Node& target, const std::string& newName) {
for (Index child = 0; child < target.ChildrenCount(); ++child) {
if (target(child).token.id == TokenID::ID_LOCAL) {
if (const auto& localName = target(child).token.data.ToText(); tuples.contains(localName)) {
const auto& localName = target(child).token.data.ToText();
if (tuples.contains(localName)) {
const auto& indexes = tuples.at(localName);
target(child).token.data = TokenData{ newName };
for (const auto prIndex : indexes) {
@ -164,12 +166,14 @@ void Normalizer::SubstituteArgs(SyntaxTree::Node& target, const StrRange pos) {
SubstituteArgs(target(child), pos);
}
} else {
if (const auto& localName = target.token.ToString(); nodes.contains(localName)) {
const auto& localName = target.token.ToString();
if (nodes.contains(localName)) {
target = *nodes.at(localName);
} else {
const auto& oldName = target.token.ToString();
std::string newName{};
if (const auto iter = nameSubstitutes.find(oldName); iter == std::end(nameSubstitutes)) {
const auto iter = nameSubstitutes.find(oldName);
if (iter == std::end(nameSubstitutes)) {
++localVarBase;
newName = R"(__var)" + std::to_string(localVarBase);
nameSubstitutes.insert(make_pair(oldName, newName));

View File

@ -23,97 +23,99 @@
public:
[[nodiscard]] StrRange Range() const {
// Note: returning byte position, not code point! Assume input is ASCII
return StrRange{ static_cast<StrPos>(matcher().first()),
static_cast<StrPos>(matcher().last()) };
return StrRange{
static_cast<StrPos>(matcher().first()),
static_cast<StrPos>(matcher().last())
};
}
%}
ws [ \t\r\n]+
digit [0-9]
upper [A-Z]
lower [a-z]
alpha ({upper}|{lower})
alnum (_|{digit}|{alpha})
ws [ \t\r\n]+
digit [0-9]
upper [A-Z]
lower [a-z]
alpha ({upper}|{lower})
alnum (_|{digit}|{alpha})
number {digit}+
index {number}(,{number})*
index {number}(,{number})*
global_id [||{upper}--[B]]{alnum}*
global_id [||{upper}--[B]]{alnum}*
local_id (_|{lower}){alnum}*
%%
"\A" { return TokenID::FORALL; }
"\E" { return TokenID::EXISTS; }
"\A" { return TokenID::FORALL; }
"\E" { return TokenID::EXISTS; }
"\neg" { return TokenID::NOT; }
"\and" { return TokenID::AND; }
"\or" { return TokenID::OR; }
"\impl" { return TokenID::IMPLICATION; }
"\equiv" { return TokenID::EQUIVALENT; }
"\neg" { return TokenID::NOT; }
"\and" { return TokenID::AND; }
"\or" { return TokenID::OR; }
"\impl" { return TokenID::IMPLICATION; }
"\equiv" { return TokenID::EQUIVALENT; }
"\plus" { return TokenID::PLUS; }
"\minus" { return TokenID::MINUS; }
"\multiply" { return TokenID::MULTIPLY; }
"\gr" { return TokenID::GREATER; }
"\ls" { return TokenID::LESSER; }
"\ge" { return TokenID::GREATER_OR_EQ; }
"\le" { return TokenID::LESSER_OR_EQ; }
"\plus" { return TokenID::PLUS; }
"\minus" { return TokenID::MINUS; }
"\multiply" { return TokenID::MULTIPLY; }
"\gr" { return TokenID::GREATER; }
"\ls" { return TokenID::LESSER; }
"\ge" { return TokenID::GREATER_OR_EQ; }
"\le" { return TokenID::LESSER_OR_EQ; }
"\eq" { return TokenID::EQUAL; }
"\noteq" { return TokenID::NOTEQUAL; }
"\eq" { return TokenID::EQUAL; }
"\noteq" { return TokenID::NOTEQUAL; }
"\in" { return TokenID::IN; }
"\notin" { return TokenID::NOTIN; }
"\subseteq" { return TokenID::SUBSET_OR_EQ; }
"\subset" { return TokenID::SUBSET; }
"\notsubset" { return TokenID::NOTSUBSET; }
"\in" { return TokenID::IN; }
"\notin" { return TokenID::NOTIN; }
"\subseteq" { return TokenID::SUBSET_OR_EQ; }
"\subset" { return TokenID::SUBSET; }
"\notsubset" { return TokenID::NOTSUBSET; }
"*" { return TokenID::DECART; }
"\union" { return TokenID::UNION; }
"\intersect" { return TokenID::INTERSECTION; }
"\setminus" { return TokenID::SET_MINUS; }
"\symmdiff" { return TokenID::SYMMINUS; }
"B" { return TokenID::BOOLEAN; }
"*" { return TokenID::DECART; }
"\union" { return TokenID::UNION; }
"\intersect" { return TokenID::INTERSECTION; }
"\setminus" { return TokenID::SET_MINUS; }
"\symmdiff" { return TokenID::SYMMINUS; }
"B" { return TokenID::BOOLEAN; }
pr{index} { return TokenID::SMALLPR; }
Pr{index} { return TokenID::BIGPR; }
Fi{index} { return TokenID::FILTER; }
card { return TokenID::CARD; }
bool { return TokenID::BOOL; }
red { return TokenID::REDUCE; }
debool { return TokenID::DEBOOL; }
pr{index} { return TokenID::SMALLPR; }
Pr{index} { return TokenID::BIGPR; }
Fi{index} { return TokenID::FILTER; }
card { return TokenID::CARD; }
bool { return TokenID::BOOL; }
red { return TokenID::REDUCE; }
debool { return TokenID::DEBOOL; }
D { return TokenID::DECLARATIVE; }
R { return TokenID::RECURSIVE; }
I { return TokenID::IMPERATIVE; }
D { return TokenID::DECLARATIVE; }
R { return TokenID::RECURSIVE; }
I { return TokenID::IMPERATIVE; }
Z { return TokenID::LIT_INTSET; }
"{}" { return TokenID::LIT_EMPTYSET; }
{number} { return TokenID::LIT_INTEGER; }
Z { return TokenID::LIT_INTSET; }
"{}" { return TokenID::LIT_EMPTYSET; }
{number} { return TokenID::LIT_INTEGER; }
F{number} { return TokenID::ID_FUNCTION; }
P{number} { return TokenID::ID_PREDICATE; }
R{number} { return TokenID::ID_RADICAL; }
F{number} { return TokenID::ID_FUNCTION; }
P{number} { return TokenID::ID_PREDICATE; }
R{number} { return TokenID::ID_RADICAL; }
{global_id} { return TokenID::ID_GLOBAL; }
{local_id} { return TokenID::ID_LOCAL; }
{global_id} { return TokenID::ID_GLOBAL; }
{local_id} { return TokenID::ID_LOCAL; }
"\assign" { return TokenID::PUNC_ASSIGN; }
"\from" { return TokenID::PUNC_ITERATE; }
"\defexpr" { return TokenID::PUNC_DEFINE; }
"\deftype" { return TokenID::PUNC_STRUCT; }
"(" { return TokenID::PUNC_PL; }
")" { return TokenID::PUNC_PR; }
"{" { return TokenID::PUNC_CL; }
"}" { return TokenID::PUNC_CR; }
"[" { return TokenID::PUNC_SL; }
"]" { return TokenID::PUNC_SR; }
"|" { return TokenID::PUNC_BAR; }
"," { return TokenID::PUNC_COMMA; }
";" { return TokenID::PUNC_SEMICOLON; }
"\assign" { return TokenID::PUNC_ASSIGN; }
"\from" { return TokenID::PUNC_ITERATE; }
"\defexpr" { return TokenID::PUNC_DEFINE; }
"\deftype" { return TokenID::PUNC_STRUCT; }
"(" { return TokenID::PUNC_PL; }
")" { return TokenID::PUNC_PR; }
"{" { return TokenID::PUNC_CL; }
"}" { return TokenID::PUNC_CR; }
"[" { return TokenID::PUNC_SL; }
"]" { return TokenID::PUNC_SR; }
"|" { return TokenID::PUNC_BAR; }
"," { return TokenID::PUNC_COMMA; }
";" { return TokenID::PUNC_SEMICOLON; }
{ws} ;
<<EOF>> { return TokenID::END; }
. { return TokenID::INTERRUPT; }
{ws} ;
<<EOF>> { return TokenID::END; }
. { return TokenID::INTERRUPT; }
%%

View File

@ -21,9 +21,15 @@ void ErrorLogger::LogError(const Error& error) {
}
int32_t ErrorLogger::Count(const ErrorStatus status) const {
return static_cast<int32_t>(std::count_if(begin(errors), end(errors),
[&](const Error& error) noexcept
{ return ResolveErrorType(error.eid) == status; }));
return static_cast<int32_t>(
std::count_if(
begin(errors),
end(errors),
[&](const Error& error) noexcept {
return ResolveErrorType(error.eid) == status;
}
)
);
}
ErrorReporter ErrorLogger::SendReporter() {
@ -33,17 +39,24 @@ ErrorReporter ErrorLogger::SendReporter() {
StrPos ErrorLogger::FirstErrorPos() const {
if (std::empty(errors)) {
return 0;
} else {
return std::accumulate(next(begin(errors)), end(errors), begin(errors)->position,
[](StrPos minimum, const Error& error)
{ return std::min(error.position, minimum); });
}
return std::accumulate(
next(begin(errors)),
end(errors),
begin(errors)->position,
[](StrPos minimum, const Error& error) {
return std::min(error.position, minimum);
});
}
bool ErrorLogger::HasCriticalErrors() const {
return std::any_of(begin(errors), end(errors),
[](const Error& error) noexcept
{ return error.IsCritical(); });
return std::any_of(
begin(errors),
end(errors),
[](const Error& error) noexcept {
return error.IsCritical();
}
);
}
} // namespace ccl::rslang

View File

@ -47,19 +47,24 @@ Typification operator""_t(const char* input, const size_t /*size*/) {
if (!parser.Parse(lexer(input).Stream())) {
assert(false);
return Typification::Integer();
} else if (!analyse.CheckType(parser.AST())) {
assert(false);
return Typification::Integer();
} else if (const auto& result = analyse.GetType();
!std::holds_alternative<Typification>(result)) {
assert(false);
return Typification::Integer();
} else if (const auto& type = std::get<Typification>(result); !type.IsCollection()) {
assert(false);
return Typification::Integer();
} else {
return type.B().Base();
}
if (!analyse.CheckType(parser.AST())) {
assert(false);
return Typification::Integer();
}
const auto& result = analyse.GetType();
if (!std::holds_alternative<Typification>(result)) {
assert(false);
return Typification::Integer();
}
const auto& type = std::get<Typification>(result);
if (!type.IsCollection()) {
assert(false);
return Typification::Integer();
}
return type.B().Base();
}
std::string operator"" _rs(const char* input, const size_t size) {

View File

@ -26,98 +26,100 @@ public:
StrPos lineBase{ 0 };
[[nodiscard]] StrRange Range() const {
return StrRange{ static_cast<StrPos>(lineBase + columno()),
static_cast<StrPos>(lineBase + columno() + columns()) };
return StrRange{
static_cast<StrPos>(lineBase + columno()),
static_cast<StrPos>(lineBase + columno() + columns())
};
}
%}
digit [0-9]
upper [A-Z]
lower [a-z\x{03B1}-\x{03C9}]
alpha ({upper}|{lower})
alnum (_|{digit}|{alpha})
digit [0-9]
upper [A-Z]
lower [a-z\x{03B1}-\x{03C9}]
alpha ({upper}|{lower})
alnum (_|{digit}|{alpha})
number {digit}+
index {number}(,{number})*
index {number}(,{number})*
global_id [||{upper}--[B]]{alnum}*
global_id [||{upper}--[B]]{alnum}*
local_id (_|{lower}){alnum}*
%%
"+" { return TokenID::PLUS; }
"-" { return TokenID::MINUS; }
"*" { return TokenID::MULTIPLY; }
">" { return TokenID::GREATER; }
"<" { return TokenID::LESSER; }
\x{2265} { return TokenID::GREATER_OR_EQ; }
\x{2264} { return TokenID::LESSER_OR_EQ; }
"+" { return TokenID::PLUS; }
"-" { return TokenID::MINUS; }
"*" { return TokenID::MULTIPLY; }
">" { return TokenID::GREATER; }
"<" { return TokenID::LESSER; }
\x{2265} { return TokenID::GREATER_OR_EQ; }
\x{2264} { return TokenID::LESSER_OR_EQ; }
"=" { return TokenID::EQUAL; }
\x{2260} { return TokenID::NOTEQUAL; }
"=" { return TokenID::EQUAL; }
\x{2260} { return TokenID::NOTEQUAL; }
\x{2200} { return TokenID::FORALL; }
\x{2203} { return TokenID::EXISTS; }
\x{2200} { return TokenID::FORALL; }
\x{2203} { return TokenID::EXISTS; }
\x{00AC} { return TokenID::NOT; }
"&" { return TokenID::AND; }
\x{2228} { return TokenID::OR; }
\x{21D2} { return TokenID::IMPLICATION; }
\x{21D4} { return TokenID::EQUIVALENT; }
\x{00AC} { return TokenID::NOT; }
"&" { return TokenID::AND; }
\x{2228} { return TokenID::OR; }
\x{21D2} { return TokenID::IMPLICATION; }
\x{21D4} { return TokenID::EQUIVALENT; }
:\x{2208} { return TokenID::PUNC_ITERATE; }
\x{2208} { return TokenID::IN; }
\x{2209} { return TokenID::NOTIN; }
\x{2286} { return TokenID::SUBSET_OR_EQ; }
\x{2282} { return TokenID::SUBSET; }
\x{2284} { return TokenID::NOTSUBSET; }
:\x{2208} { return TokenID::PUNC_ITERATE; }
\x{2208} { return TokenID::IN; }
\x{2209} { return TokenID::NOTIN; }
\x{2286} { return TokenID::SUBSET_OR_EQ; }
\x{2282} { return TokenID::SUBSET; }
\x{2284} { return TokenID::NOTSUBSET; }
\x{00D7} { return TokenID::DECART; }
\x{222A} { return TokenID::UNION; }
\x{2229} { return TokenID::INTERSECTION; }
\x{005C} { return TokenID::SET_MINUS; }
\x{2206} { return TokenID::SYMMINUS; }
\x{212C} { return TokenID::BOOLEAN; }
\x{00D7} { return TokenID::DECART; }
\x{222A} { return TokenID::UNION; }
\x{2229} { return TokenID::INTERSECTION; }
\x{005C} { return TokenID::SET_MINUS; }
\x{2206} { return TokenID::SYMMINUS; }
\x{212C} { return TokenID::BOOLEAN; }
pr{index} { return TokenID::SMALLPR; }
Pr{index} { return TokenID::BIGPR; }
Fi{index} { return TokenID::FILTER; }
card { return TokenID::CARD; }
bool { return TokenID::BOOL; }
red { return TokenID::REDUCE; }
debool { return TokenID::DEBOOL; }
pr{index} { return TokenID::SMALLPR; }
Pr{index} { return TokenID::BIGPR; }
Fi{index} { return TokenID::FILTER; }
card { return TokenID::CARD; }
bool { return TokenID::BOOL; }
red { return TokenID::REDUCE; }
debool { return TokenID::DEBOOL; }
D { return TokenID::DECLARATIVE; }
R { return TokenID::RECURSIVE; }
I { return TokenID::IMPERATIVE; }
D { return TokenID::DECLARATIVE; }
R { return TokenID::RECURSIVE; }
I { return TokenID::IMPERATIVE; }
Z { return TokenID::LIT_INTSET; }
\x{2205} { return TokenID::LIT_EMPTYSET; }
{number} { return TokenID::LIT_INTEGER; }
Z { return TokenID::LIT_INTSET; }
\x{2205} { return TokenID::LIT_EMPTYSET; }
{number} { return TokenID::LIT_INTEGER; }
F{number} { return TokenID::ID_FUNCTION; }
P{number} { return TokenID::ID_PREDICATE; }
R{number} { return TokenID::ID_RADICAL; }
F{number} { return TokenID::ID_FUNCTION; }
P{number} { return TokenID::ID_PREDICATE; }
R{number} { return TokenID::ID_RADICAL; }
{global_id} { return TokenID::ID_GLOBAL; }
{local_id} { return TokenID::ID_LOCAL; }
{global_id} { return TokenID::ID_GLOBAL; }
{local_id} { return TokenID::ID_LOCAL; }
":=" { return TokenID::PUNC_ASSIGN; }
":==" { return TokenID::PUNC_DEFINE; }
"::=" { return TokenID::PUNC_STRUCT; }
"(" { return TokenID::PUNC_PL; }
")" { return TokenID::PUNC_PR; }
"{" { return TokenID::PUNC_CL; }
"}" { return TokenID::PUNC_CR; }
"[" { return TokenID::PUNC_SL; }
"]" { return TokenID::PUNC_SR; }
"|" { return TokenID::PUNC_BAR; }
"," { return TokenID::PUNC_COMMA; }
";" { return TokenID::PUNC_SEMICOLON; }
":=" { return TokenID::PUNC_ASSIGN; }
":==" { return TokenID::PUNC_DEFINE; }
"::=" { return TokenID::PUNC_STRUCT; }
"(" { return TokenID::PUNC_PL; }
")" { return TokenID::PUNC_PR; }
"{" { return TokenID::PUNC_CL; }
"}" { return TokenID::PUNC_CR; }
"[" { return TokenID::PUNC_SL; }
"]" { return TokenID::PUNC_SR; }
"|" { return TokenID::PUNC_BAR; }
"," { return TokenID::PUNC_COMMA; }
";" { return TokenID::PUNC_SEMICOLON; }
\n { lineBase += static_cast<StrPos>(columno() + 1); }
[ \t]+ ;
<<EOF>> { return TokenID::END; }
. { return TokenID::INTERRUPT; }
\n { lineBase += static_cast<StrPos>(columno() + 1); }
[ \t]+ ;
<<EOF>> { return TokenID::END; }
. { return TokenID::INTERRUPT; }
%%

View File

@ -49,14 +49,15 @@ bool ASTInterpreter::NameCollector::ViGlobal(Cursor iter) {
const auto nextID = static_cast<uint32_t>(size(parent.idsData));
parent.idsBase.insert({ idName, nextID });
if (const auto data = parent.context(iter->data.ToText()); data.has_value()) {
parent.idsData.emplace_back(data.value());
parent.nodeVars[iter.get()] = { nextID };
return true;
} else {
const auto data = parent.context(iter->data.ToText());
if (!data.has_value()) {
parent.OnError(ValueEID::globalMissingValue, iter->pos.start, iter->data.ToText());
return false;
}
parent.idsData.emplace_back(data.value());
parent.nodeVars[iter.get()] = { nextID };
return true;
}
bool ASTInterpreter::NameCollector::ViLocal(Cursor iter) {

View File

@ -6,10 +6,14 @@
#include "ccl/rslang/RSExpr.h"
#include "ccl/rslang/Parser.h"
#include <string_view>
namespace ccl::rslang {
namespace {
using Description = Generator::StructureDescription;
[[nodiscard]] size_t FindArgumentSectionEnd(const std::string& input) {
auto counter = 0;
for (auto iter = UTF8Iterator(input); iter != UTF8End(input); ++iter) {
@ -26,46 +30,55 @@ namespace {
return std::string::npos;
}
[[nodiscard]] std::string SubstituteInPrefix(const StrSubstitutes& substitutes,
const std::vector<std::string>& args, const TypeContext& env) {
[[nodiscard]] std::string SubstituteInPrefix(
const StrSubstitutes& substitutes,
const std::vector<std::string>& args,
const TypeContext& env
) {
FunctionArguments argsTypes{};
for (const auto& argName : args) {
if (const auto* type = env.TypeFor(argName); type == nullptr) {
const auto* type = env.TypeFor(argName);
if (type == nullptr) {
return {};
} else {
const auto& newName = substitutes.at(argName);
argsTypes.emplace_back(TypedID{ newName, std::get<Typification>(*type) });
}
const auto& newName = substitutes.at(argName);
argsTypes.emplace_back(TypedID{ newName, std::get<Typification>(*type) });
}
return Generator::CreatePrefix(argsTypes);
}
class StructureContextGenerator final {
class StructureGenerator final {
private:
Generator::StructureDescription structure{};
Description structure{};
public:
[[nodiscard]] static Generator::StructureDescription GenerateFor(const std::string& cstName,
const Typification& type);
[[nodiscard]] static Description GenerateFor(
const std::string& cstName,
const Typification& type
);
private:
void GenerateRecursive(const std::string& currentStr, const Typification& type);
void GenerateReduce(const std::string& currentStr, const Typification& type);
void GenerateProjection(const std::string& currentStr, const Typification& type);
void CallRecursionForToken(const std::string& tokenText,
const std::string& currentStr,
const Typification& type);
void CallRecursionForToken(
const std::string& tokenText,
const std::string& currentStr,
const Typification& type
);
};
Generator::StructureDescription StructureContextGenerator::GenerateFor(const std::string& cstName,
const Typification& type) {
static StructureContextGenerator generator{};
Description StructureGenerator::GenerateFor(
const std::string& cstName,
const Typification& type
) {
static StructureGenerator generator{};
generator.structure.clear();
generator.GenerateRecursive(cstName, type);
return generator.structure;
}
void StructureContextGenerator::GenerateRecursive(const std::string& currentStr, const Typification& type) {
void StructureGenerator::GenerateRecursive(const std::string& currentStr, const Typification& type) {
if (!empty(currentStr) && type.IsCollection()) {
const auto& elementType = type.B().Base();
switch (elementType.Structure()) {
@ -76,11 +89,11 @@ void StructureContextGenerator::GenerateRecursive(const std::string& currentStr,
}
}
void StructureContextGenerator::GenerateReduce(const std::string& currentStr, const Typification& type) {
void StructureGenerator::GenerateReduce(const std::string& currentStr, const Typification& type) {
CallRecursionForToken(rslang::Token::Str(rslang::TokenID::REDUCE), currentStr, type);
}
void StructureContextGenerator::GenerateProjection(const std::string& currentStr, const Typification& type) {
void StructureGenerator::GenerateProjection(const std::string& currentStr, const Typification& type) {
for (Index i = 0; i < type.T().Arity(); ++i) {
Typification component = type.T().Component(Typification::PR_START + i); // NOLINT
const auto tokenText = rslang::Token::Str(rslang::TokenID::BIGPR) + std::to_string(Typification::PR_START + i);
@ -88,9 +101,11 @@ void StructureContextGenerator::GenerateProjection(const std::string& currentStr
}
}
void StructureContextGenerator::CallRecursionForToken(const std::string& tokenText,
const std::string& currentStr,
const Typification& type) {
void StructureGenerator::CallRecursionForToken(
const std::string& tokenText,
const std::string& currentStr,
const Typification& type
) {
std::string newStr = tokenText;
newStr += '(';
newStr += currentStr;
@ -99,8 +114,10 @@ void StructureContextGenerator::CallRecursionForToken(const std::string& tokenTe
GenerateRecursive(newStr, type);
}
[[nodiscard]] StrSubstitutes UniqueSubstitutes(const std::vector<std::string>& args,
const std::unordered_set<std::string>& takenNames) {
[[nodiscard]] StrSubstitutes UniqueSubstitutes(
const std::vector<std::string>& args,
const std::unordered_set<std::string>& takenNames
) {
static constexpr auto LOCAL_ID_BASE = 1;
static const std::string_view LOCAL_NAME_BASE = "arg";
StrSubstitutes substitutes{};
@ -152,8 +169,10 @@ std::string Generator::ExtractPrefix(const std::string& declaration) {
}
}
std::string Generator::FunctionFromExpr(const std::vector<std::string>& args,
const std::string& expression) const {
std::string Generator::FunctionFromExpr(
const std::vector<std::string>& args,
const std::string& expression
) const {
if (empty(args) || empty(expression)) {
return expression;
}
@ -183,9 +202,11 @@ std::string Generator::CreateCall(const std::string& funcName, const std::vector
return funcName + '[' + argString + ']';
}
std::string Generator::TermFromFunction(const std::string& funcName,
const std::string& expression,
const std::vector<std::string>& args) const {
std::string Generator::TermFromFunction(
const std::string& funcName,
const std::string& expression,
const std::vector<std::string>& args
) const {
const auto* argsTypes = environment.FunctionArgsFor(funcName);
if (argsTypes == nullptr || ssize(*argsTypes) != ssize(args)) {
return {};
@ -208,9 +229,11 @@ std::string Generator::TermFromFunction(const std::string& funcName,
return result;
}
Generator::StructureDescription Generator::StructureFor(const std::string& globalName,
const Typification& type) {
return StructureContextGenerator::GenerateFor(globalName, type);
Generator::StructureDescription Generator::StructureFor(
const std::string& globalName,
const Typification& type
) {
return StructureGenerator::GenerateFor(globalName, type);
}
std::string ConvertTo(const std::string& input, const Syntax targetSyntax) {

View File

@ -1569,20 +1569,20 @@ namespace ccl { namespace rslang { namespace detail {
"PLUS", "MINUS", "MULTIPLY", "GREATER", "LESSER", "GREATER_OR_EQ",
"LESSER_OR_EQ", "EQUAL", "NOTEQUAL", "FORALL", "EXISTS", "NOT",
"EQUIVALENT", "IMPLICATION", "OR", "AND", "IN", "NOTIN", "SUBSET",
"SUBOR_EQ", "NOTSUBSET", "DECART", "UNION", "INTERSECTION", "SET_MINUS",
"SYMMINUS", "BOOLEAN", "BIGPR", "SMALLPR", "FILTER", "CARD", "BOOL",
"DEBOOL", "RED", "DECLARATIVE", "RECURSIVE", "IMPERATIVE", "DEFINE",
"STRUCT", "ASSIGN", "ITERATE", "LP", "RP", "LC", "RC", "LS", "RS", "BAR",
"COMMA", "SEMICOLON", "$accept", "expression", "global_declaration",
"function_name", "logic_or_setexpr", "function_decl", "arguments",
"declaration", "variable", "var_enum", "var_all", "logic", "logic_all",
"logic_par", "logic_predicates", "binary_predicate", "logic_unary",
"logic_no_binary", "quantifier", "quant_var", "quant_var_enum",
"logic_binary", "setexpr", "operation_name", "setexpr_enum",
"setexpr_enum_min2", "literal", "identifier", "setexpr_binary",
"setexpr_generators", "enumeration", "tuple", "boolean",
"filter_expression", "declarative", "recursion", "imperative",
"imp_blocks", "imp_block", "RPE", "RCE", YY_NULLPTR
"SUBSET_OR_EQ", "NOTSUBSET", "DECART", "UNION", "INTERSECTION",
"SET_MINUS", "SYMMINUS", "BOOLEAN", "BIGPR", "SMALLPR", "FILTER", "CARD",
"BOOL", "DEBOOL", "RED", "DECLARATIVE", "RECURSIVE", "IMPERATIVE",
"DEFINE", "STRUCT", "ASSIGN", "ITERATE", "LP", "RP", "LC", "RC", "LS",
"RS", "BAR", "COMMA", "SEMICOLON", "$accept", "expression",
"global_declaration", "function_name", "logic_or_setexpr",
"function_decl", "arguments", "declaration", "variable", "var_enum",
"var_all", "logic", "logic_all", "logic_par", "logic_predicates",
"binary_predicate", "logic_unary", "logic_no_binary", "quantifier",
"quant_var", "quant_var_enum", "logic_binary", "setexpr",
"operation_name", "setexpr_enum", "setexpr_enum_min2", "literal",
"identifier", "setexpr_binary", "setexpr_generators", "enumeration",
"tuple", "boolean", "filter_expression", "declarative", "recursion",
"imperative", "imp_blocks", "imp_block", "RPE", "RCE", YY_NULLPTR
};
#endif

View File

@ -199,7 +199,7 @@ RawNode Imperative(
IN // IsElement
NOTIN // NotElement
SUBSET // IsSubset and NotEqual
SUBOR_EQ // IsSubset
SUBSET_OR_EQ // IsSubset
NOTSUBSET // NotSubset
@ -331,7 +331,7 @@ binary_predicate
: IN
| NOTIN
| SUBSET
| SUBOR_EQ
| SUBSET_OR_EQ
| NOTSUBSET
| NOTEQUAL
| EQUAL

View File

@ -12,10 +12,12 @@ namespace {
void MangleRadicals(const std::string& funcName, Typification& type);
std::string ToString(const ExpressionType& type) noexcept(false) {
return std::visit(meta::Overloads{
[](const Typification& t) { return t.ToString(); },
[](const LogicT& /*t*/) { return std::string{"LOGIC"}; },
}, type);
return std::visit(
meta::Overloads{
[](const Typification& t) { return t.ToString(); },
[](const LogicT& /*t*/) { return std::string{"LOGIC"}; },
}
, type);
}
constexpr bool IsSubset(const TokenID token) noexcept {
@ -142,42 +144,42 @@ bool TypeEnv::AreCompatible(const Typification& type1, const Typification& type2
std::optional<Typification> TypeEnv::Merge(const Typification& type1, const Typification& type2) const {
if (type1 == type2) {
return type1;
} else if (type1.Structure() != type2.Structure()) {
}
if (type1.Structure() != type2.Structure()) {
return std::nullopt;
}
switch (type1.Structure()) {
default:
case rslang::StructureType::basic: {
if (const auto* type = CommonType(type1, type2); type == nullptr) {
return std::nullopt;
} else {
case rslang::StructureType::basic: {
const auto* type = CommonType(type1, type2);
if (type == nullptr) {
return std::nullopt;
}
return *type;
}
}
case rslang::StructureType::collection: {
if (auto base = Merge(type1.B().Base(), type2.B().Base()); !base.has_value()) {
return std::nullopt;
} else {
case rslang::StructureType::collection: {
auto base = Merge(type1.B().Base(), type2.B().Base());
if (!base.has_value()) {
return std::nullopt;
}
return base.value().ApplyBool();
}
}
case rslang::StructureType::tuple: {
if (type1.T().Arity() != type2.T().Arity()) {
return std::nullopt;
} else {
case rslang::StructureType::tuple: {
if (type1.T().Arity() != type2.T().Arity()) {
return std::nullopt;
}
std::vector<Typification> components{};
for (auto index = Typification::PR_START; index < type1.T().Arity() + Typification::PR_START; ++index) {
if (auto component = Merge(type1.T().Component(index), type2.T().Component(index));
!component.has_value()) {
const auto maxIndex = Typification::PR_START + type1.T().Arity();
for (auto index = Typification::PR_START; index < maxIndex; ++index) {
auto component = Merge(type1.T().Component(index), type2.T().Component(index));
if (!component.has_value()) {
return std::nullopt;
} else {
components.emplace_back(std::move(component.value()));
}
components.emplace_back(std::move(component.value()));
}
return Typification::Tuple(components);
}
}
}
}
bool TypeEnv::CompareTemplated(
@ -189,28 +191,33 @@ bool TypeEnv::CompareTemplated(
return true;
}
if (arg.IsElement() && IsRadical(arg.E().baseID)) {
if (const auto& base = arg.E().baseID; !substitutes.contains(base)) {
const auto& base = arg.E().baseID;
if (!substitutes.contains(base)) {
substitutes.insert({ base, value });
return true;
} else if (auto mergeType = Merge(substitutes.at(base), value);
!mergeType.has_value()) {
return false;
} else {
substitutes.at(base) = std::move(mergeType.value());
return true;
}
auto mergeType = Merge(substitutes.at(base), value);
if (!mergeType.has_value()) {
return false;
}
substitutes.at(base) = std::move(mergeType.value());
return true;
} else if (arg.Structure() != value.Structure()) {
return false;
} else {
switch (arg.Structure()) {
default:
case rslang::StructureType::basic: return CommonType(arg, value) != nullptr;
case rslang::StructureType::collection: return CompareTemplated(substitutes, arg.B().Base(), value.B().Base());
case rslang::StructureType::tuple: {
if (arg.T().Arity() != value.T().Arity()) {
return false;
} else {
for (auto index = Typification::PR_START; index < arg.T().Arity() + Typification::PR_START; ++index) {
default:
case rslang::StructureType::basic:
return CommonType(arg, value) != nullptr;
case rslang::StructureType::collection:
return CompareTemplated(substitutes, arg.B().Base(), value.B().Base());
case rslang::StructureType::tuple: {
if (arg.T().Arity() != value.T().Arity()) {
return false;
}
const auto maxIndex = Typification::PR_START + arg.T().Arity();
for (auto index = Typification::PR_START; index < maxIndex; ++index) {
if (!CompareTemplated(substitutes, arg.T().Component(index), value.T().Component(index))) {
return false;
}
@ -218,7 +225,6 @@ bool TypeEnv::CompareTemplated(
return true;
}
}
}
}
}
@ -270,44 +276,59 @@ bool TypeAuditor::ViGlobalDefinition(Cursor iter) {
if (childrenCount != 2 || !IsEchelon(iter, 1)) {
OnError(SemanticEID::globalStructure, iter(0).pos.finish);
return false;
} else if (const auto maybeType = ChildType(iter, 1); !maybeType.has_value()) {
return false;
} else if (const auto& type = std::get<Typification>(maybeType.value()); !type.IsCollection()) {
return false;
} else {
return VisitAndReturn(type.B().Base());
}
const auto maybeType = ChildType(iter, 1);
if (!maybeType.has_value()) {
return false;
}
const auto& type = std::get<Typification>(maybeType.value());
if (!type.IsCollection()) {
return false;
}
return VisitAndReturn(type.B().Base());
} else {
assert(iter->id == TokenID::PUNC_DEFINE);
if (childrenCount == 1) {
return VisitAndReturn(Typification{ iter(0).data.ToText() }.ApplyBool());
} else if (const auto type = ChildType(iter, 1); !type.has_value()) {
return false;
} else {
return VisitAndReturn(type.value());
}
const auto type = ChildType(iter, 1);
if (!type.has_value()) {
return false;
}
return VisitAndReturn(type.value());
}
}
bool TypeAuditor::ViFunctionDefinition(Cursor iter) {
if (const auto guard = isFuncDeclaration.CreateGuard(); !VisitChild(iter, 0)) {
return false;
{
const auto guard = isFuncDeclaration.CreateGuard();
if (!VisitChild(iter, 0)) {
return false;
}
}
for (auto n : functionArgsID) {
functionArgs.emplace_back(localVars.at(n).arg);
}
if (const auto type = ChildType(iter, 1); !type.has_value()) {
const auto type = ChildType(iter, 1);
if (!type.has_value()) {
return false;
} else {
return VisitAndReturn(type.value());
}
return VisitAndReturn(type.value());
}
bool TypeAuditor::ViFunctionCall(Cursor iter) {
const auto& funcName = iter(0).data.ToText();
const auto* funcType = env.context.TypeFor(funcName);
if (funcType == nullptr) {
OnError(SemanticEID::globalNotTyped, iter->pos.start, funcName);
OnError(
SemanticEID::globalNotTyped,
iter->pos.start,
funcName
);
return false;
}
const auto substitutes = CheckFuncArguments(iter, funcName);
@ -329,13 +350,18 @@ bool TypeAuditor::ViFunctionCall(Cursor iter) {
std::optional<Typification::Substitutes> TypeAuditor::CheckFuncArguments(Cursor iter, const std::string& funcName) {
const auto* args = env.context.FunctionArgsFor(funcName);
if (args == nullptr) {
OnError(SemanticEID::globalFuncMissing, iter(0).pos.start, iter(0).data.ToText());
OnError(
SemanticEID::globalFuncMissing,
iter(0).pos.start,
iter(0).data.ToText()
);
return std::nullopt;
}
const auto expectedArguments = iter.ChildrenCount() - 1;
if (const auto argCount = static_cast<Index>(ssize(*args)); argCount != expectedArguments) {
const auto argCount = static_cast<Index>(ssize(*args));
if (argCount != expectedArguments) {
OnError(
SemanticEID::invalidArgsArtity,
SemanticEID::invalidArgsArity,
iter(1).pos.start,
{ std::to_string(expectedArguments), std::to_string(argCount) }
);
@ -351,7 +377,11 @@ std::optional<Typification::Substitutes> TypeAuditor::CheckFuncArguments(Cursor
Typification argType = args->at(static_cast<size_t>(child) - 1).type;
MangleRadicals(funcName, argType);
if (!env.CompareTemplated(substitutes, argType, std::get<Typification>(childType.value()))) {
OnError(SemanticEID::invalidArgumentType, iter(child).pos.start, argType, childType.value());
OnError(
SemanticEID::invalidArgumentType,
iter(child).pos.start, argType,
childType.value()
);
return std::nullopt;
}
}
@ -361,19 +391,33 @@ std::optional<Typification::Substitutes> TypeAuditor::CheckFuncArguments(Cursor
bool TypeAuditor::ViGlobal(Cursor iter) {
const auto& globalName = iter->data.ToText();
if (iter->id == TokenID::ID_RADICAL) {
if (isFuncDeclaration) {
return VisitAndReturn(Typification(globalName).ApplyBool());
} else {
OnError(SemanticEID::radicalUsage, iter->pos.start, globalName);
if (!isFuncDeclaration) {
OnError(
SemanticEID::radicalUsage,
iter->pos.start,
globalName
);
return false;
}
} else if (env.context.FunctionArgsFor(globalName) != nullptr) {
OnError(SemanticEID::globalFuncWithoutArgs, iter->pos.start, globalName);
return false;
} else if (const auto* type = env.context.TypeFor(globalName); type == nullptr) {
OnError(SemanticEID::globalNotTyped, iter->pos.start, globalName);
return false;
return VisitAndReturn(Typification(globalName).ApplyBool());
} else {
if (env.context.FunctionArgsFor(globalName) != nullptr) {
OnError(
SemanticEID::globalFuncWithoutArgs,
iter->pos.start,
globalName
);
return false;
}
const auto* type = env.context.TypeFor(globalName);
if (type == nullptr) {
OnError(
SemanticEID::globalNotTyped,
iter->pos.start,
globalName
);
return false;
}
return VisitAndReturn(*type);
}
}
@ -384,11 +428,10 @@ bool TypeAuditor::ViLocal(Cursor iter) {
return AddLocalVar(localName, std::get<Typification>(currentType), iter->pos.start);
} else {
const auto* local = GetLocalTypification(localName, iter->pos.start);
if (local != nullptr) {
return VisitAndReturn(*local);
} else {
if (local == nullptr) {
return false;
}
return VisitAndReturn(*local);
}
}
@ -401,7 +444,7 @@ bool TypeAuditor::ViLocalBind(Cursor iter) {
assert(isLocalDeclaration || isFuncDeclaration);
const Typification type = std::get<Typification>(currentType);
if (!type.IsTuple() || type.T().Arity() != iter.ChildrenCount()) {
OnError(SemanticEID::ivalidBinding, iter(0).pos.start);
OnError(SemanticEID::invalidBinding, iter(0).pos.start);
return false;
}
for (Index child = 0; child < iter.ChildrenCount(); ++child) {
@ -417,11 +460,10 @@ bool TypeAuditor::ViArgument(Cursor iter) {
const auto domain = ChildTypeDebool(iter, 1, SemanticEID::invalidTypeOperation);
if (!domain.has_value()) {
return false;
} else {
const auto guard{ isArgDeclaration.CreateGuard() };
currentType = domain.value();
return VisitChild(iter, 0) && VisitAndReturn(LogicT{});
}
const auto guard{ isArgDeclaration.CreateGuard() };
currentType = domain.value();
return VisitChild(iter, 0) && VisitAndReturn(LogicT{});
}
bool TypeAuditor::ViCard(Cursor iter) {
@ -430,85 +472,136 @@ bool TypeAuditor::ViCard(Cursor iter) {
}
bool TypeAuditor::ViArithmetic(Cursor iter) {
if (const auto test1 = ChildType(iter, 0); !test1.has_value()) {
const auto test1 = ChildType(iter, 0);
if (!test1.has_value()) {
return false;
} else if (const auto& type1 = std::get<Typification>(test1.value());
!env.IsArithmetic(type1)) {
OnError(SemanticEID::arithmeticNotSupported, iter(0).pos.start, type1.ToString());
return false;
} else if (const auto test2 = ChildType(iter, 1); !test2.has_value()) {
return false;
} else if (const auto& type2 = std::get<Typification>(test2.value());
!env.IsArithmetic(type2)) {
OnError(SemanticEID::arithmeticNotSupported, iter(1).pos.start, type2.ToString());
return false;
} else if (const auto result = env.Merge(type1, type2); !result.has_value()) {
OnError(SemanticEID::typesNotCompatible, iter(1).pos.start, type1, type2);
return false;
} else {
return VisitAndReturn(result.value());
}
const auto& type1 = std::get<Typification>(test1.value());
if (!env.IsArithmetic(type1)) {
OnError(
SemanticEID::arithmeticNotSupported,
iter(0).pos.start,
type1.ToString()
);
return false;
}
const auto test2 = ChildType(iter, 1);
if (!test2.has_value()) {
return false;
}
const auto& type2 = std::get<Typification>(test2.value());
if (!env.IsArithmetic(type2)) {
OnError(
SemanticEID::arithmeticNotSupported,
iter(1).pos.start,
type2.ToString()
);
return false;
}
const auto result = env.Merge(type1, type2);
if (!result.has_value()) {
OnError(
SemanticEID::typesNotCompatible,
iter(1).pos.start,
type1,
type2
);
return false;
}
return VisitAndReturn(result.value());
}
bool TypeAuditor::ViOrdering(Cursor iter) {
if(const auto test1 = ChildType(iter, 0); !test1.has_value()) {
const auto test1 = ChildType(iter, 0);
if(!test1.has_value()) {
return false;
} else if (const auto& type1 = std::get<Typification>(test1.value());
!env.IsOrdered(type1)) {
OnError(SemanticEID::orderingNotSupported, iter(0).pos.start, type1.ToString());
return false;
} else if (const auto test2 = ChildType(iter, 1); !test2.has_value()) {
return false;
} else if (const auto& type2 = std::get<Typification>(test2.value());
!env.IsOrdered(type2)) {
OnError(SemanticEID::orderingNotSupported, iter(1).pos.start, type2.ToString());
return false;
} else if (!env.AreCompatible(type1, type2)) {
OnError(SemanticEID::typesNotCompatible, iter(1).pos.start, type1, type2);
return false;
} else {
return VisitAndReturn(LogicT{});
}
const auto& type1 = std::get<Typification>(test1.value());
if (!env.IsOrdered(type1)) {
OnError(
SemanticEID::orderingNotSupported,
iter(0).pos.start,
type1.ToString()
);
return false;
}
const auto test2 = ChildType(iter, 1);
if (!test2.has_value()) {
return false;
}
const auto& type2 = std::get<Typification>(test2.value());
if (!env.IsOrdered(type2)) {
OnError(
SemanticEID::orderingNotSupported,
iter(1).pos.start,
type2.ToString()
);
return false;
}
if (!env.AreCompatible(type1, type2)) {
OnError(
SemanticEID::typesNotCompatible,
iter(1).pos.start,
type1,
type2
);
return false;
}
return VisitAndReturn(LogicT{});
}
bool TypeAuditor::ViQuantifier(Cursor iter) {
StartScope();
if (const auto domain = ChildTypeDebool(iter, 1, SemanticEID::invalidTypeOperation); !domain.has_value()) {
const auto domain = ChildTypeDebool(iter, 1, SemanticEID::invalidTypeOperation);
if (!domain.has_value()) {
return false;
} else if (!VisitChildDeclaration(iter, 0, domain.value())) {
return false;
} else if (!VisitChild(iter, 2)) {
return false;
} else {
EndScope(iter->pos.start);
return VisitAndReturn(LogicT{});
}
EndScope(iter->pos.start);
return VisitAndReturn(LogicT{});
}
bool TypeAuditor::ViEquals(Cursor iter) {
if (iter(1).id == TokenID::LIT_EMPTYSET) {
const auto type = ChildTypeDebool(iter, 0, SemanticEID::invalidEqualsEmpty);
return type.has_value() && VisitAndReturn(LogicT{});
} else {
const auto test1 = ChildType(iter, 0);
if (!test1.has_value()) {
return false;
}
const auto& type1 = std::get<Typification>(test1.value());
const auto test2 = ChildType(iter, 1);
if (!test2.has_value()) {
return false;
}
const auto& type2 = std::get<Typification>(test2.value());
if (!env.AreCompatible(type1, type2)) {
OnError(SemanticEID::typesNotCompatible, iter(1).pos.start, type1, type2);
return false;
} else {
return VisitAndReturn(LogicT{});
}
}
const auto test1 = ChildType(iter, 0);
if (!test1.has_value()) {
return false;
}
const auto& type1 = std::get<Typification>(test1.value());
const auto test2 = ChildType(iter, 1);
if (!test2.has_value()) {
return false;
}
const auto& type2 = std::get<Typification>(test2.value());
if (!env.AreCompatible(type1, type2)) {
OnError(
SemanticEID::typesNotCompatible,
iter(1).pos.start,
type1,
type2
);
return false;
}
return VisitAndReturn(LogicT{});
}
bool TypeAuditor::ViTypedPredicate(Cursor iter) {
@ -527,44 +620,56 @@ bool TypeAuditor::ViTypedPredicate(Cursor iter) {
if (!env.AreCompatible(type1.value(), type2.value())) {
if (isSubset) {
OnError(SemanticEID::typesNotEqual, iter(1).pos.start, type1.value(), type2.value());
OnError(
SemanticEID::typesNotEqual,
iter(1).pos.start,
type1.value(),
type2.value()
);
} else {
OnError(SemanticEID::invalidElementPredicat, iter(1).pos.start,
{ ToString(type1.value()), iter->ToString(), type2->Bool().ToString() });
OnError(
SemanticEID::invalidElementPredicate,
iter(1).pos.start,
{ ToString(type1.value()), iter->ToString(), type2->Bool().ToString() }
);
}
return false;
} else {
return VisitAndReturn(LogicT{});
}
return VisitAndReturn(LogicT{});
}
bool TypeAuditor::ViDeclarative(Cursor iter) {
StartScope();
if (auto domain = ChildTypeDebool(iter, 1, SemanticEID::invalidTypeOperation); !domain.has_value()) {
auto domain = ChildTypeDebool(iter, 1, SemanticEID::invalidTypeOperation);
if (!domain.has_value()) {
return false;
} else if (!VisitChildDeclaration(iter, 0, domain.value())) {
return false;
} else if (!VisitChild(iter, 2)) {
return false;
} else {
EndScope(iter->pos.start);
return VisitAndReturn(domain->ApplyBool());
}
EndScope(iter->pos.start);
return VisitAndReturn(domain->ApplyBool());
}
bool TypeAuditor::ViImperative(Cursor iter) {
StartScope();
for (Index child = 1; child < iter.ChildrenCount(); ++child) {
if (!VisitChild(iter, child)) {
return false;
}
}
if (auto type = ChildType(iter, 0); !type.has_value()) {
auto type = ChildType(iter, 0);
if (!type.has_value()) {
return false;
} else {
EndScope(iter->pos.start);
return VisitAndReturn(std::get<Typification>(type.value()).Bool());
}
EndScope(iter->pos.start);
return VisitAndReturn(std::get<Typification>(type.value()).Bool());
}
bool TypeAuditor::ViImpDeclare(Cursor iter) {
@ -581,6 +686,7 @@ bool TypeAuditor::ViImpAssign(Cursor iter) {
bool TypeAuditor::ViRecursion(Cursor iter) {
StartScope();
auto initType = ChildType(iter, 1);
if (!initType.has_value()) {
return false;
@ -600,10 +706,15 @@ bool TypeAuditor::ViRecursion(Cursor iter) {
if (!iterationType.has_value()) {
return false;
} else if (!env.AreCompatible(iterationType.value(), initType.value())) {
OnError(SemanticEID::typesNotEqual, iter(iterationIndex).pos.start,
iterationType.value(), initType.value());
OnError(
SemanticEID::typesNotEqual,
iter(iterationIndex).pos.start,
iterationType.value(),
initType.value()
);
return false;
}
EndScope(iter->pos.start);
return VisitAndReturn(iterationType.value());
}
@ -622,21 +733,21 @@ bool TypeAuditor::ViDecart(Cursor iter) {
}
bool TypeAuditor::ViBoolean(Cursor iter) {
if (auto type = ChildTypeDebool(iter, 0, SemanticEID::invalidBoolean); !type.has_value()) {
auto type = ChildTypeDebool(iter, 0, SemanticEID::invalidBoolean);
if (!type.has_value()) {
return false;
} else {
return VisitAndReturn(type->ApplyBool().ApplyBool());
}
return VisitAndReturn(type->ApplyBool().ApplyBool());
}
bool TypeAuditor::ViTuple(Cursor iter) {
std::vector<Typification> components{};
for (Index child = 0; child < iter.ChildrenCount(); ++child) {
if (const auto type = ChildType(iter, child); !type.has_value()) {
const auto type = ChildType(iter, child);
if (!type.has_value()) {
return false;
} else {
components.emplace_back(std::get<Typification>(type.value()));
}
components.emplace_back(std::get<Typification>(type.value()));
}
return VisitAndReturn(Typification::Tuple(components));
}
@ -648,25 +759,32 @@ bool TypeAuditor::ViSetEnum(Cursor iter) {
}
auto& type = std::get<Typification>(test.value());
for (Index child = 1; child < iter.ChildrenCount(); ++child) {
if (auto childType = ChildType(iter, child); !childType.has_value()) {
auto childType = ChildType(iter, child);
if (!childType.has_value()) {
return false;
} else if (auto merge = env.Merge(type, std::get<Typification>(childType.value()));
!merge.has_value()) {
OnError(SemanticEID::invalidEnumeration, iter(child).pos.start, type, childType.value());
return false;
} else {
type = std::move(merge.value());
}
auto merge = env.Merge(type, std::get<Typification>(childType.value()));
if (!merge.has_value()) {
OnError(
SemanticEID::invalidEnumeration,
iter(child).pos.start,
type,
childType.value()
);
return false;
}
type = std::move(merge.value());
}
return VisitAndReturn(type.Bool());
}
bool TypeAuditor::ViDebool(Cursor iter) {
if (auto type = ChildTypeDebool(iter, 0, SemanticEID::invalidDebool); type.has_value()) {
return VisitAndReturn(type.value());
} else {
auto type = ChildTypeDebool(iter, 0, SemanticEID::invalidDebool);
if (!type.has_value()) {
return false;
}
return VisitAndReturn(type.value());
}
bool TypeAuditor::ViTypedBinary(Cursor iter) {
@ -674,16 +792,23 @@ bool TypeAuditor::ViTypedBinary(Cursor iter) {
if (!type1.has_value()) {
return false;
}
auto type2 = ChildTypeDebool(iter, 1, SemanticEID::invalidTypeOperation);
if (!type2.has_value()) {
return false;
}
if (const auto result = env.Merge(type1.value(), type2.value()); !result.has_value()) {
OnError(SemanticEID::typesNotEqual, iter(1).pos.start, type1->Bool(), type2->Bool());
const auto result = env.Merge(type1.value(), type2.value());
if (!result.has_value()) {
OnError(
SemanticEID::typesNotEqual,
iter(1).pos.start,
type1->Bool(),
type2->Bool()
);
return false;
} else {
return VisitAndReturn(result.value().Bool());
}
return VisitAndReturn(result.value().Bool());
}
bool TypeAuditor::ViProjectSet(Cursor iter) {
@ -693,7 +818,11 @@ bool TypeAuditor::ViProjectSet(Cursor iter) {
return false;
}
if (!baseType->IsTuple()) {
OnError(SemanticEID::invalidProjectionSet, iter(0).pos.start, { iter->ToString(), baseType->ToString() });
OnError(
SemanticEID::invalidProjectionSet,
iter(0).pos.start,
{ iter->ToString(), baseType->ToString() }
);
return false;
}
@ -702,7 +831,11 @@ bool TypeAuditor::ViProjectSet(Cursor iter) {
components.reserve(size(indicies));
for (const auto index : indicies) {
if (!baseType->T().TestIndex(index)) {
OnError(SemanticEID::invalidProjectionSet, iter(0).pos.start, { iter->ToString(), baseType->ToString() });
OnError(
SemanticEID::invalidProjectionSet,
iter(0).pos.start,
{ iter->ToString(), baseType->ToString() }
);
return false;
} else {
components.emplace_back(baseType->T().Component(index));
@ -787,11 +920,14 @@ bool TypeAuditor::ViReduce(Cursor iter) {
}
const auto& base = std::get<Typification>(baseType.value());
if (!base.IsCollection() || !base.B().Base().IsCollection()) {
OnError(SemanticEID::invalidReduce, iter(0).pos.start + 1, base.ToString());
OnError(
SemanticEID::invalidReduce,
iter(0).pos.start + 1,
base.ToString()
);
return false;
} else {
return VisitAndReturn(base.B().Base());
}
return VisitAndReturn(base.B().Base());
}
bool TypeAuditor::VisitAndReturn(ExpressionType type) noexcept {
@ -832,16 +968,22 @@ std::optional<Typification> TypeAuditor::ChildTypeDebool(Cursor iter, const Inde
return std::nullopt;
}
if (!std::get<Typification>(result.value()).IsCollection()) {
OnError(eid, iter(index).pos.start, ToString(result.value()));
OnError(
eid,
iter(index).pos.start,
ToString(result.value())
);
return std::nullopt;
} else {
return std::get<Typification>(result.value()).B().Base();
}
return std::get<Typification>(result.value()).B().Base();
}
const Typification* TypeAuditor::GetLocalTypification(const std::string& name, const StrPos pos) {
const auto varIter = std::find_if(begin(localVars), end(localVars),
[&](const auto& data) noexcept { return data.arg.name == name; });
const auto varIter = std::find_if(
begin(localVars),
end(localVars),
[&](const auto& data) noexcept { return data.arg.name == name; }
);
if (varIter == end(localVars)) {
if (!isArgDeclaration) {
OnError(SemanticEID::localUndeclared, pos, name);
@ -868,7 +1010,11 @@ void TypeAuditor::EndScope(const StrPos pos) {
if (var.level < 0 && var.enabled) {
var.enabled = false;
if (var.useCount == 0) {
OnError(SemanticEID::localNotUsed, pos, var.arg.name);
OnError(
SemanticEID::localNotUsed,
pos,
var.arg.name
);
}
}
}
@ -879,10 +1025,18 @@ bool TypeAuditor::AddLocalVar(const std::string& name, const Typification& type,
[&](const auto& data) noexcept { return data.arg.name == name; });
if (varIter != end(localVars)) {
if (varIter->enabled) {
OnError(SemanticEID::localShadowing, pos, name);
OnError(
SemanticEID::localShadowing,
pos,
name
);
return false;
} else {
OnError(SemanticEID::localDoubleDeclare, pos, name);
OnError(
SemanticEID::localDoubleDeclare,
pos,
name
);
varIter->arg.type = type;
varIter->enabled = true;
varIter->level = 0;

View File

@ -102,9 +102,11 @@ bool ValueAuditor::ViFunctionCall(Cursor iter) {
}
}
bool ValueAuditor::RunCheckOnFunc(Cursor iter,
const std::string& funcName,
const std::vector<ValueClass>& argumentVals) {
bool ValueAuditor::RunCheckOnFunc(
Cursor iter,
const std::string& funcName,
const std::vector<ValueClass>& argumentVals
) {
const auto* ast = globalAST(funcName);
if (ast == nullptr) {
OnError(SemanticEID::globalMissingAST, iter->pos.start, funcName);
@ -123,10 +125,9 @@ bool ValueAuditor::RunCheckOnFunc(Cursor iter,
if (!ast->Root().Child(1).Child(1).DispatchVisit(funcAuditor)) {
OnError(SemanticEID::globalFuncNoInterpretation, iter->pos.start);
return false;
} else {
current = funcAuditor.VType();
return true;
}
current = funcAuditor.VType();
return true;
}
bool ValueAuditor::ViGlobal(Cursor iter) {
@ -138,10 +139,9 @@ bool ValueAuditor::ViGlobal(Cursor iter) {
if (type == ValueClass::invalid) {
OnError(SemanticEID::globalNoValue, iter->pos.start, globalName);
return false;
} else {
current = type;
return true;
}
current = type;
return true;
}
}

View File

@ -215,8 +215,8 @@ TEST_F(UTTypeAuditor, LogicErrors) {
ExpectError(R"(\A a \in X1*X1 a \eq {})", SemanticEID::invalidEqualsEmpty, 15);
ExpectError(R"(\A (a,a) \in S1 pr2(a) \in X1)", SemanticEID::localShadowing, 6);
ExpectError(R"(\A (a,b) \in X1 1 \eq 1)", SemanticEID::ivalidBinding, 4);
ExpectError(R"(\A (a,b,c) \in S1 1 \eq 1)", SemanticEID::ivalidBinding, 4);
ExpectError(R"(\A (a,b) \in X1 1 \eq 1)", SemanticEID::invalidBinding, 4);
ExpectError(R"(\A (a,b,c) \in S1 1 \eq 1)", SemanticEID::invalidBinding, 4);
ExpectError(R"(\A t \in X1 {t \in X1 | t \eq t} \eq X1)", SemanticEID::localShadowing, 13);
ExpectError(R"(\A t \in X1 t \eq t \and t \eq X1)", SemanticEID::localOutOfScope, 25);
@ -289,17 +289,17 @@ TEST_F(UTTypeAuditor, TypedPredicatesCorrect) {
TEST_F(UTTypeAuditor, TypedPredicatesError) {
SetupConstants();
ExpectError(R"(X1 \in X1)", SemanticEID::invalidElementPredicat, 7);
ExpectError(R"(S4 \in C2)", SemanticEID::invalidElementPredicat, 7);
ExpectError(R"(S5 \in Z)", SemanticEID::invalidElementPredicat, 7);
ExpectError(R"(S6 \in Z)", SemanticEID::invalidElementPredicat, 7);
ExpectError(R"((1,2) \in Z)", SemanticEID::invalidElementPredicat, 10);
ExpectError(R"({1} \in Z)", SemanticEID::invalidElementPredicat, 8);
ExpectError(R"((1,2) \in Z)", SemanticEID::invalidElementPredicat, 10);
ExpectError(R"(X1 \in X1)", SemanticEID::invalidElementPredicate, 7);
ExpectError(R"(S4 \in C2)", SemanticEID::invalidElementPredicate, 7);
ExpectError(R"(S5 \in Z)", SemanticEID::invalidElementPredicate, 7);
ExpectError(R"(S6 \in Z)", SemanticEID::invalidElementPredicate, 7);
ExpectError(R"((1,2) \in Z)", SemanticEID::invalidElementPredicate, 10);
ExpectError(R"({1} \in Z)", SemanticEID::invalidElementPredicate, 8);
ExpectError(R"((1,2) \in Z)", SemanticEID::invalidElementPredicate, 10);
ExpectError(R"(X1 \subset S2)", SemanticEID::typesNotEqual, 11);
ExpectError(R"(X1 \notin X1)", SemanticEID::invalidElementPredicat, 10);
ExpectError(R"(X1 \notin X1)", SemanticEID::invalidElementPredicate, 10);
ExpectError(R"(X1 \subseteq S2)", SemanticEID::typesNotEqual, 13);
ExpectError(R"(X1 \notsubset S2)", SemanticEID::typesNotEqual, 14);
}
@ -364,10 +364,10 @@ TEST_F(UTTypeAuditor, TypedFunctions) {
ExpectTypification(R"(F1[Pr1(S1), Pr2(S1)])", "B(X1)"_t);
ExpectError(R"(F1)", SemanticEID::globalFuncWithoutArgs, 0);
ExpectError(R"(F1[X1])", SemanticEID::invalidArgsArtity, 3);
ExpectError(R"(F1[X1])", SemanticEID::invalidArgsArity, 3);
EXPECT_EQ(parser.log.All()[0].params[0], "1");
EXPECT_EQ(parser.log.All()[0].params[1], "2");
ExpectError(R"(F1[X1, X1, X1])", SemanticEID::invalidArgsArtity, 3);
ExpectError(R"(F1[X1, X1, X1])", SemanticEID::invalidArgsArity, 3);
EXPECT_EQ(parser.log.All()[0].params[0], "3");
EXPECT_EQ(parser.log.All()[0].params[1], "2");
@ -388,8 +388,8 @@ TEST_F(UTTypeAuditor, LogicFunctions) {
ExpectLogic(R"(P1[Pr1(S1), Pr2(S1)])");
ExpectError(R"(P1)", SemanticEID::globalFuncWithoutArgs, 0);
ExpectError(R"(P1[X1])", SemanticEID::invalidArgsArtity, 3);
ExpectError(R"(P1[X1, X1, X1])", SemanticEID::invalidArgsArtity, 3);
ExpectError(R"(P1[X1])", SemanticEID::invalidArgsArity, 3);
ExpectError(R"(P1[X1, X1, X1])", SemanticEID::invalidArgsArity, 3);
ExpectError(R"(P1[S1, X1])", SemanticEID::invalidArgumentType, 3);
ExpectError(R"(P1[X1, S1])", SemanticEID::invalidArgumentType, 7);