mirror of
https://github.com/IRBorisov/ConceptCore.git
synced 2025-06-26 09:10:37 +03:00
Refactor RSLang code readability
This commit is contained in:
parent
c4db405fbe
commit
de81d4037f
10
.vscode/settings.json
vendored
10
.vscode/settings.json
vendored
|
@ -16,6 +16,7 @@
|
||||||
"cmake.ctestArgs": ["--test-dir build", "--output-on-failure"],
|
"cmake.ctestArgs": ["--test-dir build", "--output-on-failure"],
|
||||||
"cmake.installPrefix": "output",
|
"cmake.installPrefix": "output",
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"BIGPR",
|
||||||
"conanfile",
|
"conanfile",
|
||||||
"coredll",
|
"coredll",
|
||||||
"DCMAKE",
|
"DCMAKE",
|
||||||
|
@ -23,19 +24,28 @@
|
||||||
"DECART",
|
"DECART",
|
||||||
"Decartian",
|
"Decartian",
|
||||||
"defexpr",
|
"defexpr",
|
||||||
|
"EMPTYSET",
|
||||||
|
"FORALL",
|
||||||
"GNUC",
|
"GNUC",
|
||||||
"gtest",
|
"gtest",
|
||||||
"ifdef",
|
"ifdef",
|
||||||
|
"INTSET",
|
||||||
"MSVC",
|
"MSVC",
|
||||||
"nlohmann",
|
"nlohmann",
|
||||||
"noteq",
|
"noteq",
|
||||||
|
"NOTEQUAL",
|
||||||
|
"NOTIN",
|
||||||
"notsubset",
|
"notsubset",
|
||||||
|
"PUNC",
|
||||||
"pybind",
|
"pybind",
|
||||||
"pyconcept",
|
"pyconcept",
|
||||||
"rslang",
|
"rslang",
|
||||||
"setexpr",
|
"setexpr",
|
||||||
|
"SMALLPR",
|
||||||
"struct",
|
"struct",
|
||||||
"symmdiff",
|
"symmdiff",
|
||||||
|
"SYMMINUS",
|
||||||
|
"YYABORT",
|
||||||
"yylex",
|
"yylex",
|
||||||
"yylval",
|
"yylval",
|
||||||
"YYSTYPE",
|
"YYSTYPE",
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void Quantifier(SyntaxTree::Node& quant);
|
void Quantifier(SyntaxTree::Node& quant);
|
||||||
static void EnumDeclaration(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);
|
void TupleDeclaration(SyntaxTree::Node& target);
|
||||||
|
|
||||||
[[nodiscard]] std::string CreateTupleName(const SyntaxTree::Node& root);
|
[[nodiscard]] std::string CreateTupleName(const SyntaxTree::Node& root);
|
||||||
|
|
|
@ -333,7 +333,7 @@ namespace ccl { namespace rslang { namespace detail {
|
||||||
RST_IN = 282, // IN
|
RST_IN = 282, // IN
|
||||||
RST_NOTIN = 283, // NOTIN
|
RST_NOTIN = 283, // NOTIN
|
||||||
RST_SUBSET = 284, // SUBSET
|
RST_SUBSET = 284, // SUBSET
|
||||||
RST_SUBOR_EQ = 285, // SUBOR_EQ
|
RST_SUBSET_OR_EQ = 285, // SUBSET_OR_EQ
|
||||||
RST_NOTSUBSET = 286, // NOTSUBSET
|
RST_NOTSUBSET = 286, // NOTSUBSET
|
||||||
RST_DECART = 287, // DECART
|
RST_DECART = 287, // DECART
|
||||||
RST_UNION = 288, // UNION
|
RST_UNION = 288, // UNION
|
||||||
|
@ -412,7 +412,7 @@ namespace ccl { namespace rslang { namespace detail {
|
||||||
S_IN = 27, // IN
|
S_IN = 27, // IN
|
||||||
S_NOTIN = 28, // NOTIN
|
S_NOTIN = 28, // NOTIN
|
||||||
S_SUBSET = 29, // SUBSET
|
S_SUBSET = 29, // SUBSET
|
||||||
S_SUBOR_EQ = 30, // SUBOR_EQ
|
S_SUBSET_OR_EQ = 30, // SUBSET_OR_EQ
|
||||||
S_NOTSUBSET = 31, // NOTSUBSET
|
S_NOTSUBSET = 31, // NOTSUBSET
|
||||||
S_DECART = 32, // DECART
|
S_DECART = 32, // DECART
|
||||||
S_UNION = 33, // UNION
|
S_UNION = 33, // UNION
|
||||||
|
|
|
@ -42,10 +42,10 @@ enum class SemanticEID : uint32_t {
|
||||||
invalidProjectionTuple = 0x8811, // Не определена проекция
|
invalidProjectionTuple = 0x8811, // Не определена проекция
|
||||||
invalidProjectionSet = 0x8812, // Большая проекция определена только для множеств!
|
invalidProjectionSet = 0x8812, // Большая проекция определена только для множеств!
|
||||||
invalidEnumeration = 0x8813, // Типизация аргументов перечисления не совпадает
|
invalidEnumeration = 0x8813, // Типизация аргументов перечисления не совпадает
|
||||||
ivalidBinding = 0x8814, // Количество переменных в кортеже не соответствует размерности декартова произведения
|
invalidBinding = 0x8814, // Количество переменных в кортеже не соответствует размерности декартова произведения
|
||||||
localOutOfScope = 0x8815, // Использование имени вне области видимости
|
localOutOfScope = 0x8815, // Использование имени вне области видимости
|
||||||
invalidElementPredicat = 0x8816, // Несоответствие типов для проверки принадлежности
|
invalidElementPredicate = 0x8816, // Несоответствие типов для проверки принадлежности
|
||||||
invalidArgsArtity = 0x8818, // Некорректное количество аргументов терм-функции
|
invalidArgsArity = 0x8818, // Некорректное количество аргументов терм-функции
|
||||||
invalidArgumentType = 0x8819, // Типизация аргумента не совпадает с объявленной
|
invalidArgumentType = 0x8819, // Типизация аргумента не совпадает с объявленной
|
||||||
invalidEqualsEmpty = 0x881A, // Сравнение с пустым множеством не множества
|
invalidEqualsEmpty = 0x881A, // Сравнение с пустым множеством не множества
|
||||||
globalStructure = 0x881C, // Родовая структура должна быть ступенью
|
globalStructure = 0x881C, // Родовая структура должна быть ступенью
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "NameCollector.h"
|
#include "NameCollector.h"
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning( push )
|
#pragma warning( push )
|
||||||
|
@ -94,12 +95,12 @@ private:
|
||||||
auto element = parent.EvaluateChild(imperative, 0);
|
auto element = parent.EvaluateChild(imperative, 0);
|
||||||
if (!element.has_value()) {
|
if (!element.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
value.ModifyB().AddElement(std::get<StructuredData>(element.value()));
|
value.ModifyB().AddElement(std::get<StructuredData>(element.value()));
|
||||||
incrementIter = true;
|
incrementIter = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool ProcessBlock() {
|
[[nodiscard]] bool ProcessBlock() {
|
||||||
auto child = imperative;
|
auto child = imperative;
|
||||||
|
@ -188,8 +189,7 @@ void ASTInterpreter::OnError(const ValueEID eid, const StrPos position, std::str
|
||||||
|
|
||||||
std::optional<ExpressionValue> ASTInterpreter::Evaluate(const rslang::SyntaxTree& tree) {
|
std::optional<ExpressionValue> ASTInterpreter::Evaluate(const rslang::SyntaxTree& tree) {
|
||||||
Clear();
|
Clear();
|
||||||
if (!NameCollector{ *this }.Visit(tree.Root())
|
if (!NameCollector{ *this }.Visit(tree.Root()) || !tree.Root().DispatchVisit(*this)) {
|
||||||
|| !tree.Root().DispatchVisit(*this)) {
|
|
||||||
AfterVisit(false);
|
AfterVisit(false);
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
} else {
|
} else {
|
||||||
|
@ -247,11 +247,14 @@ bool ASTInterpreter::ViEmptySet(Cursor /*iter*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViArithmetic(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;
|
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;
|
return false;
|
||||||
} else {
|
}
|
||||||
const auto op1 = std::get<StructuredData>(val1.value()).E().Value();
|
const auto op1 = std::get<StructuredData>(val1.value()).E().Value();
|
||||||
const auto op2 = std::get<StructuredData>(val2.value()).E().Value();
|
const auto op2 = std::get<StructuredData>(val2.value()).E().Value();
|
||||||
switch (iter->id) {
|
switch (iter->id) {
|
||||||
|
@ -263,30 +266,30 @@ bool ASTInterpreter::ViArithmetic(Cursor iter) {
|
||||||
case TokenID::MULTIPLY:
|
case TokenID::MULTIPLY:
|
||||||
return VisitAndReturn(Factory::Val(op1 * op2));
|
return VisitAndReturn(Factory::Val(op1 * op2));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViCard(Cursor iter) {
|
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;
|
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));
|
OnError(ValueEID::typedOverflow, iter->pos.start, std::to_string(StructuredData::SET_INFINITY));
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
return VisitAndReturn(Factory::Val(size));
|
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(Factory::Val(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViQuantifier(Cursor iter) {
|
bool ASTInterpreter::ViQuantifier(Cursor iter) {
|
||||||
const auto quantorDomain = ExtractDomain(iter);
|
const auto domain = ExtractDomain(iter);
|
||||||
if (!quantorDomain.has_value()) {
|
if (!domain.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto varID = *begin(nodeVars[iter.Child(0).get()]);
|
const auto varID = *begin(nodeVars[iter.Child(0).get()]);
|
||||||
const auto quantorForAll = iter->id == TokenID::FORALL;
|
const auto isUniversal = iter->id == TokenID::FORALL;
|
||||||
for (const auto& child : quantorDomain->B()) {
|
for (const auto& child : domain->B()) {
|
||||||
if (++iterationCounter > MAX_ITERATIONS) {
|
if (++iterationCounter > MAX_ITERATIONS) {
|
||||||
OnError(ValueEID::iterationsLimit, iter->pos.start, std::to_string(MAX_ITERATIONS));
|
OnError(ValueEID::iterationsLimit, iter->pos.start, std::to_string(MAX_ITERATIONS));
|
||||||
return false;
|
return false;
|
||||||
|
@ -294,37 +297,42 @@ bool ASTInterpreter::ViQuantifier(Cursor iter) {
|
||||||
idsData[varID] = child;
|
idsData[varID] = child;
|
||||||
if (const auto iterationValue = EvaluateChild(iter, 2); !iterationValue.has_value()) {
|
if (const auto iterationValue = EvaluateChild(iter, 2); !iterationValue.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (std::get<bool>(iterationValue.value()) != quantorForAll) {
|
} else if (std::get<bool>(iterationValue.value()) != isUniversal) {
|
||||||
return VisitAndReturn(!quantorForAll);
|
return VisitAndReturn(!isUniversal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return VisitAndReturn(quantorForAll);
|
return VisitAndReturn(isUniversal);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<StructuredData> ASTInterpreter::ExtractDomain(Cursor iter) {
|
std::optional<StructuredData> ASTInterpreter::ExtractDomain(Cursor iter) {
|
||||||
if (!VisitChild(iter, 1)) {
|
if (!VisitChild(iter, 1)) {
|
||||||
return std::nullopt;
|
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) {
|
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;
|
return false;
|
||||||
} else {
|
|
||||||
return VisitAndReturn(!std::get<bool>(childValue.value()));
|
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(!std::get<bool>(childValue.value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViLogicBinary(Cursor iter) {
|
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;
|
return false;
|
||||||
} else if (TryEvaluateFromFirstArg(iter->id, std::get<bool>(val1.value()))) {
|
}
|
||||||
|
|
||||||
|
if (TryEvaluateFromFirstArg(iter->id, std::get<bool>(val1.value()))) {
|
||||||
return true;
|
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;
|
return false;
|
||||||
} else {
|
}
|
||||||
const auto op1 = std::get<bool>(val1.value());
|
const auto op1 = std::get<bool>(val1.value());
|
||||||
const auto op2 = std::get<bool>(val2.value());
|
const auto op2 = std::get<bool>(val2.value());
|
||||||
switch (iter->id) {
|
switch (iter->id) {
|
||||||
|
@ -334,7 +342,6 @@ bool ASTInterpreter::ViLogicBinary(Cursor iter) {
|
||||||
case TokenID::IMPLICATION: 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;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::TryEvaluateFromFirstArg(TokenID operation, bool firstArgValue) noexcept {
|
bool ASTInterpreter::TryEvaluateFromFirstArg(TokenID operation, bool firstArgValue) noexcept {
|
||||||
|
@ -349,21 +356,26 @@ bool ASTInterpreter::TryEvaluateFromFirstArg(TokenID operation, bool firstArgVal
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViEquals(Cursor iter) {
|
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;
|
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) {
|
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;
|
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;
|
return false;
|
||||||
} else {
|
}
|
||||||
const auto op1 = std::get<StructuredData>(val1.value()).E().Value();
|
const auto op1 = std::get<StructuredData>(val1.value()).E().Value();
|
||||||
const auto op2 = std::get<StructuredData>(val2.value()).E().Value();
|
const auto op2 = std::get<StructuredData>(val2.value()).E().Value();
|
||||||
switch (iter->id) {
|
switch (iter->id) {
|
||||||
|
@ -373,7 +385,6 @@ bool ASTInterpreter::ViOrdering(Cursor iter) {
|
||||||
case TokenID::GREATER_OR_EQ: return VisitAndReturn(op1 >= op2);
|
case TokenID::GREATER_OR_EQ: return VisitAndReturn(op1 >= op2);
|
||||||
case TokenID::LESSER_OR_EQ: return VisitAndReturn(op1 <= op2);
|
case TokenID::LESSER_OR_EQ: return VisitAndReturn(op1 <= op2);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViDeclarative(Cursor iter) {
|
bool ASTInterpreter::ViDeclarative(Cursor iter) {
|
||||||
|
@ -389,9 +400,11 @@ bool ASTInterpreter::ViDeclarative(Cursor iter) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
idsData[varID] = child;
|
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;
|
return false;
|
||||||
} else if (std::get<bool>(predicatValue.value())) {
|
}
|
||||||
|
if (std::get<bool>(predicatValue.value())) {
|
||||||
result.ModifyB().AddElement(child);
|
result.ModifyB().AddElement(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -402,9 +415,8 @@ bool ASTInterpreter::ViImperative(const Cursor iter) {
|
||||||
ImpEvaluator eval{ *this, iter };
|
ImpEvaluator eval{ *this, iter };
|
||||||
if (!eval.Evaluate()) {
|
if (!eval.Evaluate()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
return VisitAndReturn(eval.value);
|
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(eval.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViRecursion(Cursor iter) {
|
bool ASTInterpreter::ViRecursion(Cursor iter) {
|
||||||
|
@ -422,9 +434,11 @@ bool ASTInterpreter::ViRecursion(Cursor iter) {
|
||||||
|
|
||||||
idsData[varID] = current;
|
idsData[varID] = current;
|
||||||
if (iter->id == TokenID::NT_RECURSIVE_FULL) {
|
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;
|
return false;
|
||||||
} else if (!std::get<bool>(predicat.value())) {
|
}
|
||||||
|
if (!std::get<bool>(predicat.value())) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -451,32 +465,38 @@ bool ASTInterpreter::ViDecart(Cursor iter) {
|
||||||
if (std::get<StructuredData>(curValue).B().Cardinality() == StructuredData::SET_INFINITY) {
|
if (std::get<StructuredData>(curValue).B().Cardinality() == StructuredData::SET_INFINITY) {
|
||||||
OnError(ValueEID::typedOverflow, iter->pos.start, std::to_string(StructuredData::SET_INFINITY));
|
OnError(ValueEID::typedOverflow, iter->pos.start, std::to_string(StructuredData::SET_INFINITY));
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViBoolean(Cursor iter) {
|
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;
|
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) {
|
bool ASTInterpreter::ViTuple(Cursor iter) {
|
||||||
std::vector<StructuredData> args{};
|
std::vector<StructuredData> args{};
|
||||||
for (Index child = 0; child < iter.ChildrenCount(); ++child) {
|
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;
|
return false;
|
||||||
} else {
|
|
||||||
args.emplace_back(std::get<StructuredData>(childValue.value()));
|
|
||||||
}
|
}
|
||||||
|
args.emplace_back(std::get<StructuredData>(childValue.value()));
|
||||||
}
|
}
|
||||||
return VisitAndReturn(Factory::Tuple(args));
|
return VisitAndReturn(Factory::Tuple(args));
|
||||||
}
|
}
|
||||||
|
@ -484,29 +504,33 @@ bool ASTInterpreter::ViTuple(Cursor iter) {
|
||||||
bool ASTInterpreter::ViSetEnum(Cursor iter) {
|
bool ASTInterpreter::ViSetEnum(Cursor iter) {
|
||||||
std::vector<StructuredData> args{};
|
std::vector<StructuredData> args{};
|
||||||
for (Index child = 0; child < iter.ChildrenCount(); ++child) {
|
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;
|
return false;
|
||||||
} else {
|
|
||||||
args.emplace_back(std::get<StructuredData>(childValue.value()));
|
|
||||||
}
|
}
|
||||||
|
args.emplace_back(std::get<StructuredData>(childValue.value()));
|
||||||
}
|
}
|
||||||
return VisitAndReturn(Factory::Set(args));
|
return VisitAndReturn(Factory::Set(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViBool(Cursor iter) {
|
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;
|
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) {
|
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;
|
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;
|
return false;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
const auto& op1 = std::get<StructuredData>(val1.value());
|
const auto& op1 = std::get<StructuredData>(val1.value());
|
||||||
const auto& op2 = std::get<StructuredData>(val2.value());
|
const auto& op2 = std::get<StructuredData>(val2.value());
|
||||||
switch (iter->id) {
|
switch (iter->id) {
|
||||||
|
@ -522,15 +546,14 @@ bool ASTInterpreter::ViTypedBinary(Cursor iter) {
|
||||||
case TokenID::NOTSUBSET: 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()));
|
case TokenID::SUBSET_OR_EQ: return VisitAndReturn(op1.B().IsSubsetOrEq(op2.B()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViProjectSet(Cursor iter) {
|
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;
|
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) {
|
bool ASTInterpreter::ViProjectTuple(Cursor iter) {
|
||||||
|
@ -562,9 +585,11 @@ bool ASTInterpreter::ViFilter(Cursor iter) {
|
||||||
std::vector<StructuredData> params{};
|
std::vector<StructuredData> params{};
|
||||||
params.reserve(size(indicies));
|
params.reserve(size(indicies));
|
||||||
for (Index child = 0; child < iter.ChildrenCount() - 1; ++child) {
|
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;
|
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());
|
return VisitAndReturn(Factory::EmptySet());
|
||||||
} else {
|
} else {
|
||||||
params.emplace_back(val);
|
params.emplace_back(val);
|
||||||
|
@ -588,23 +613,24 @@ bool ASTInterpreter::ViFilter(Cursor iter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::ViReduce(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;
|
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) {
|
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;
|
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);
|
OnError(ValueEID::invalidDebool, iter->pos.start);
|
||||||
return false;
|
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) {
|
std::optional<ExpressionValue> ASTInterpreter::EvaluateChild(Cursor iter, const Index index) {
|
||||||
|
|
|
@ -57,14 +57,15 @@ void Normalizer::EnumDeclaration(SyntaxTree::Node& quant) {
|
||||||
quant(0) = quant(0)(0);
|
quant(0) = quant(0)(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Normalizer::TupleDeclaration(SyntaxTree::Node& declaration,
|
void Normalizer::TupleDeclaration(
|
||||||
SyntaxTree::Node& predicat) {
|
SyntaxTree::Node& declaration,
|
||||||
|
SyntaxTree::Node& predicate
|
||||||
|
) {
|
||||||
const auto newName = CreateTupleName(declaration);
|
const auto newName = CreateTupleName(declaration);
|
||||||
declaration.RemoveAll();
|
declaration.RemoveAll();
|
||||||
declaration.token.data = TokenData{ newName };
|
declaration.token.data = TokenData{ newName };
|
||||||
declaration.token.id = TokenID::ID_LOCAL;
|
declaration.token.id = TokenID::ID_LOCAL;
|
||||||
|
SubstituteTupleVariables(predicate, newName);
|
||||||
SubstituteTupleVariables(predicat, newName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Normalizer::TupleDeclaration(SyntaxTree::Node& target) {
|
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) {
|
void Normalizer::SubstituteTupleVariables(SyntaxTree::Node& target, const std::string& newName) {
|
||||||
for (Index child = 0; child < target.ChildrenCount(); ++child) {
|
for (Index child = 0; child < target.ChildrenCount(); ++child) {
|
||||||
if (target(child).token.id == TokenID::ID_LOCAL) {
|
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);
|
const auto& indexes = tuples.at(localName);
|
||||||
target(child).token.data = TokenData{ newName };
|
target(child).token.data = TokenData{ newName };
|
||||||
for (const auto prIndex : indexes) {
|
for (const auto prIndex : indexes) {
|
||||||
|
@ -164,12 +166,14 @@ void Normalizer::SubstituteArgs(SyntaxTree::Node& target, const StrRange pos) {
|
||||||
SubstituteArgs(target(child), pos);
|
SubstituteArgs(target(child), pos);
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
target = *nodes.at(localName);
|
||||||
} else {
|
} else {
|
||||||
const auto& oldName = target.token.ToString();
|
const auto& oldName = target.token.ToString();
|
||||||
std::string newName{};
|
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;
|
++localVarBase;
|
||||||
newName = R"(__var)" + std::to_string(localVarBase);
|
newName = R"(__var)" + std::to_string(localVarBase);
|
||||||
nameSubstitutes.insert(make_pair(oldName, newName));
|
nameSubstitutes.insert(make_pair(oldName, newName));
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] StrRange Range() const {
|
[[nodiscard]] StrRange Range() const {
|
||||||
// Note: returning byte position, not code point! Assume input is ASCII
|
// Note: returning byte position, not code point! Assume input is ASCII
|
||||||
return StrRange{ static_cast<StrPos>(matcher().first()),
|
return StrRange{
|
||||||
static_cast<StrPos>(matcher().last()) };
|
static_cast<StrPos>(matcher().first()),
|
||||||
|
static_cast<StrPos>(matcher().last())
|
||||||
|
};
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,15 @@ void ErrorLogger::LogError(const Error& error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ErrorLogger::Count(const ErrorStatus status) const {
|
int32_t ErrorLogger::Count(const ErrorStatus status) const {
|
||||||
return static_cast<int32_t>(std::count_if(begin(errors), end(errors),
|
return static_cast<int32_t>(
|
||||||
[&](const Error& error) noexcept
|
std::count_if(
|
||||||
{ return ResolveErrorType(error.eid) == status; }));
|
begin(errors),
|
||||||
|
end(errors),
|
||||||
|
[&](const Error& error) noexcept {
|
||||||
|
return ResolveErrorType(error.eid) == status;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorReporter ErrorLogger::SendReporter() {
|
ErrorReporter ErrorLogger::SendReporter() {
|
||||||
|
@ -33,17 +39,24 @@ ErrorReporter ErrorLogger::SendReporter() {
|
||||||
StrPos ErrorLogger::FirstErrorPos() const {
|
StrPos ErrorLogger::FirstErrorPos() const {
|
||||||
if (std::empty(errors)) {
|
if (std::empty(errors)) {
|
||||||
return 0;
|
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 {
|
bool ErrorLogger::HasCriticalErrors() const {
|
||||||
return std::any_of(begin(errors), end(errors),
|
return std::any_of(
|
||||||
[](const Error& error) noexcept
|
begin(errors),
|
||||||
{ return error.IsCritical(); });
|
end(errors),
|
||||||
|
[](const Error& error) noexcept {
|
||||||
|
return error.IsCritical();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ccl::rslang
|
} // namespace ccl::rslang
|
|
@ -47,19 +47,24 @@ Typification operator""_t(const char* input, const size_t /*size*/) {
|
||||||
if (!parser.Parse(lexer(input).Stream())) {
|
if (!parser.Parse(lexer(input).Stream())) {
|
||||||
assert(false);
|
assert(false);
|
||||||
return Typification::Integer();
|
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) {
|
std::string operator"" _rs(const char* input, const size_t size) {
|
||||||
|
|
|
@ -26,8 +26,10 @@ public:
|
||||||
StrPos lineBase{ 0 };
|
StrPos lineBase{ 0 };
|
||||||
|
|
||||||
[[nodiscard]] StrRange Range() const {
|
[[nodiscard]] StrRange Range() const {
|
||||||
return StrRange{ static_cast<StrPos>(lineBase + columno()),
|
return StrRange{
|
||||||
static_cast<StrPos>(lineBase + columno() + columns()) };
|
static_cast<StrPos>(lineBase + columno()),
|
||||||
|
static_cast<StrPos>(lineBase + columno() + columns())
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -49,14 +49,15 @@ bool ASTInterpreter::NameCollector::ViGlobal(Cursor iter) {
|
||||||
|
|
||||||
const auto nextID = static_cast<uint32_t>(size(parent.idsData));
|
const auto nextID = static_cast<uint32_t>(size(parent.idsData));
|
||||||
parent.idsBase.insert({ idName, nextID });
|
parent.idsBase.insert({ idName, nextID });
|
||||||
if (const auto data = parent.context(iter->data.ToText()); data.has_value()) {
|
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.idsData.emplace_back(data.value());
|
||||||
parent.nodeVars[iter.get()] = { nextID };
|
parent.nodeVars[iter.get()] = { nextID };
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
parent.OnError(ValueEID::globalMissingValue, iter->pos.start, iter->data.ToText());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTInterpreter::NameCollector::ViLocal(Cursor iter) {
|
bool ASTInterpreter::NameCollector::ViLocal(Cursor iter) {
|
||||||
|
|
|
@ -6,10 +6,14 @@
|
||||||
#include "ccl/rslang/RSExpr.h"
|
#include "ccl/rslang/RSExpr.h"
|
||||||
#include "ccl/rslang/Parser.h"
|
#include "ccl/rslang/Parser.h"
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
namespace ccl::rslang {
|
namespace ccl::rslang {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using Description = Generator::StructureDescription;
|
||||||
|
|
||||||
[[nodiscard]] size_t FindArgumentSectionEnd(const std::string& input) {
|
[[nodiscard]] size_t FindArgumentSectionEnd(const std::string& input) {
|
||||||
auto counter = 0;
|
auto counter = 0;
|
||||||
for (auto iter = UTF8Iterator(input); iter != UTF8End(input); ++iter) {
|
for (auto iter = UTF8Iterator(input); iter != UTF8End(input); ++iter) {
|
||||||
|
@ -26,46 +30,55 @@ namespace {
|
||||||
return std::string::npos;
|
return std::string::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::string SubstituteInPrefix(const StrSubstitutes& substitutes,
|
[[nodiscard]] std::string SubstituteInPrefix(
|
||||||
const std::vector<std::string>& args, const TypeContext& env) {
|
const StrSubstitutes& substitutes,
|
||||||
|
const std::vector<std::string>& args,
|
||||||
|
const TypeContext& env
|
||||||
|
) {
|
||||||
FunctionArguments argsTypes{};
|
FunctionArguments argsTypes{};
|
||||||
for (const auto& argName : args) {
|
for (const auto& argName : args) {
|
||||||
if (const auto* type = env.TypeFor(argName); type == nullptr) {
|
const auto* type = env.TypeFor(argName);
|
||||||
|
if (type == nullptr) {
|
||||||
return {};
|
return {};
|
||||||
} else {
|
}
|
||||||
const auto& newName = substitutes.at(argName);
|
const auto& newName = substitutes.at(argName);
|
||||||
argsTypes.emplace_back(TypedID{ newName, std::get<Typification>(*type) });
|
argsTypes.emplace_back(TypedID{ newName, std::get<Typification>(*type) });
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return Generator::CreatePrefix(argsTypes);
|
return Generator::CreatePrefix(argsTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
class StructureContextGenerator final {
|
class StructureGenerator final {
|
||||||
private:
|
private:
|
||||||
Generator::StructureDescription structure{};
|
Description structure{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] static Generator::StructureDescription GenerateFor(const std::string& cstName,
|
[[nodiscard]] static Description GenerateFor(
|
||||||
const Typification& type);
|
const std::string& cstName,
|
||||||
|
const Typification& type
|
||||||
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GenerateRecursive(const std::string& currentStr, const Typification& type);
|
void GenerateRecursive(const std::string& currentStr, const Typification& type);
|
||||||
void GenerateReduce(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 GenerateProjection(const std::string& currentStr, const Typification& type);
|
||||||
void CallRecursionForToken(const std::string& tokenText,
|
void CallRecursionForToken(
|
||||||
|
const std::string& tokenText,
|
||||||
const std::string& currentStr,
|
const std::string& currentStr,
|
||||||
const Typification& type);
|
const Typification& type
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Generator::StructureDescription StructureContextGenerator::GenerateFor(const std::string& cstName,
|
Description StructureGenerator::GenerateFor(
|
||||||
const Typification& type) {
|
const std::string& cstName,
|
||||||
static StructureContextGenerator generator{};
|
const Typification& type
|
||||||
|
) {
|
||||||
|
static StructureGenerator generator{};
|
||||||
generator.structure.clear();
|
generator.structure.clear();
|
||||||
generator.GenerateRecursive(cstName, type);
|
generator.GenerateRecursive(cstName, type);
|
||||||
return generator.structure;
|
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()) {
|
if (!empty(currentStr) && type.IsCollection()) {
|
||||||
const auto& elementType = type.B().Base();
|
const auto& elementType = type.B().Base();
|
||||||
switch (elementType.Structure()) {
|
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);
|
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) {
|
for (Index i = 0; i < type.T().Arity(); ++i) {
|
||||||
Typification component = type.T().Component(Typification::PR_START + i); // NOLINT
|
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);
|
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,
|
void StructureGenerator::CallRecursionForToken(
|
||||||
|
const std::string& tokenText,
|
||||||
const std::string& currentStr,
|
const std::string& currentStr,
|
||||||
const Typification& type) {
|
const Typification& type
|
||||||
|
) {
|
||||||
std::string newStr = tokenText;
|
std::string newStr = tokenText;
|
||||||
newStr += '(';
|
newStr += '(';
|
||||||
newStr += currentStr;
|
newStr += currentStr;
|
||||||
|
@ -99,8 +114,10 @@ void StructureContextGenerator::CallRecursionForToken(const std::string& tokenTe
|
||||||
GenerateRecursive(newStr, type);
|
GenerateRecursive(newStr, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] StrSubstitutes UniqueSubstitutes(const std::vector<std::string>& args,
|
[[nodiscard]] StrSubstitutes UniqueSubstitutes(
|
||||||
const std::unordered_set<std::string>& takenNames) {
|
const std::vector<std::string>& args,
|
||||||
|
const std::unordered_set<std::string>& takenNames
|
||||||
|
) {
|
||||||
static constexpr auto LOCAL_ID_BASE = 1;
|
static constexpr auto LOCAL_ID_BASE = 1;
|
||||||
static const std::string_view LOCAL_NAME_BASE = "arg";
|
static const std::string_view LOCAL_NAME_BASE = "arg";
|
||||||
StrSubstitutes substitutes{};
|
StrSubstitutes substitutes{};
|
||||||
|
@ -152,8 +169,10 @@ std::string Generator::ExtractPrefix(const std::string& declaration) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Generator::FunctionFromExpr(const std::vector<std::string>& args,
|
std::string Generator::FunctionFromExpr(
|
||||||
const std::string& expression) const {
|
const std::vector<std::string>& args,
|
||||||
|
const std::string& expression
|
||||||
|
) const {
|
||||||
if (empty(args) || empty(expression)) {
|
if (empty(args) || empty(expression)) {
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
|
@ -183,9 +202,11 @@ std::string Generator::CreateCall(const std::string& funcName, const std::vector
|
||||||
return funcName + '[' + argString + ']';
|
return funcName + '[' + argString + ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Generator::TermFromFunction(const std::string& funcName,
|
std::string Generator::TermFromFunction(
|
||||||
|
const std::string& funcName,
|
||||||
const std::string& expression,
|
const std::string& expression,
|
||||||
const std::vector<std::string>& args) const {
|
const std::vector<std::string>& args
|
||||||
|
) const {
|
||||||
const auto* argsTypes = environment.FunctionArgsFor(funcName);
|
const auto* argsTypes = environment.FunctionArgsFor(funcName);
|
||||||
if (argsTypes == nullptr || ssize(*argsTypes) != ssize(args)) {
|
if (argsTypes == nullptr || ssize(*argsTypes) != ssize(args)) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -208,9 +229,11 @@ std::string Generator::TermFromFunction(const std::string& funcName,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Generator::StructureDescription Generator::StructureFor(const std::string& globalName,
|
Generator::StructureDescription Generator::StructureFor(
|
||||||
const Typification& type) {
|
const std::string& globalName,
|
||||||
return StructureContextGenerator::GenerateFor(globalName, type);
|
const Typification& type
|
||||||
|
) {
|
||||||
|
return StructureGenerator::GenerateFor(globalName, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ConvertTo(const std::string& input, const Syntax targetSyntax) {
|
std::string ConvertTo(const std::string& input, const Syntax targetSyntax) {
|
||||||
|
|
|
@ -1569,20 +1569,20 @@ namespace ccl { namespace rslang { namespace detail {
|
||||||
"PLUS", "MINUS", "MULTIPLY", "GREATER", "LESSER", "GREATER_OR_EQ",
|
"PLUS", "MINUS", "MULTIPLY", "GREATER", "LESSER", "GREATER_OR_EQ",
|
||||||
"LESSER_OR_EQ", "EQUAL", "NOTEQUAL", "FORALL", "EXISTS", "NOT",
|
"LESSER_OR_EQ", "EQUAL", "NOTEQUAL", "FORALL", "EXISTS", "NOT",
|
||||||
"EQUIVALENT", "IMPLICATION", "OR", "AND", "IN", "NOTIN", "SUBSET",
|
"EQUIVALENT", "IMPLICATION", "OR", "AND", "IN", "NOTIN", "SUBSET",
|
||||||
"SUBOR_EQ", "NOTSUBSET", "DECART", "UNION", "INTERSECTION", "SET_MINUS",
|
"SUBSET_OR_EQ", "NOTSUBSET", "DECART", "UNION", "INTERSECTION",
|
||||||
"SYMMINUS", "BOOLEAN", "BIGPR", "SMALLPR", "FILTER", "CARD", "BOOL",
|
"SET_MINUS", "SYMMINUS", "BOOLEAN", "BIGPR", "SMALLPR", "FILTER", "CARD",
|
||||||
"DEBOOL", "RED", "DECLARATIVE", "RECURSIVE", "IMPERATIVE", "DEFINE",
|
"BOOL", "DEBOOL", "RED", "DECLARATIVE", "RECURSIVE", "IMPERATIVE",
|
||||||
"STRUCT", "ASSIGN", "ITERATE", "LP", "RP", "LC", "RC", "LS", "RS", "BAR",
|
"DEFINE", "STRUCT", "ASSIGN", "ITERATE", "LP", "RP", "LC", "RC", "LS",
|
||||||
"COMMA", "SEMICOLON", "$accept", "expression", "global_declaration",
|
"RS", "BAR", "COMMA", "SEMICOLON", "$accept", "expression",
|
||||||
"function_name", "logic_or_setexpr", "function_decl", "arguments",
|
"global_declaration", "function_name", "logic_or_setexpr",
|
||||||
"declaration", "variable", "var_enum", "var_all", "logic", "logic_all",
|
"function_decl", "arguments", "declaration", "variable", "var_enum",
|
||||||
"logic_par", "logic_predicates", "binary_predicate", "logic_unary",
|
"var_all", "logic", "logic_all", "logic_par", "logic_predicates",
|
||||||
"logic_no_binary", "quantifier", "quant_var", "quant_var_enum",
|
"binary_predicate", "logic_unary", "logic_no_binary", "quantifier",
|
||||||
"logic_binary", "setexpr", "operation_name", "setexpr_enum",
|
"quant_var", "quant_var_enum", "logic_binary", "setexpr",
|
||||||
"setexpr_enum_min2", "literal", "identifier", "setexpr_binary",
|
"operation_name", "setexpr_enum", "setexpr_enum_min2", "literal",
|
||||||
"setexpr_generators", "enumeration", "tuple", "boolean",
|
"identifier", "setexpr_binary", "setexpr_generators", "enumeration",
|
||||||
"filter_expression", "declarative", "recursion", "imperative",
|
"tuple", "boolean", "filter_expression", "declarative", "recursion",
|
||||||
"imp_blocks", "imp_block", "RPE", "RCE", YY_NULLPTR
|
"imperative", "imp_blocks", "imp_block", "RPE", "RCE", YY_NULLPTR
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -199,7 +199,7 @@ RawNode Imperative(
|
||||||
IN // IsElement
|
IN // IsElement
|
||||||
NOTIN // NotElement
|
NOTIN // NotElement
|
||||||
SUBSET // IsSubset and NotEqual
|
SUBSET // IsSubset and NotEqual
|
||||||
SUBOR_EQ // IsSubset
|
SUBSET_OR_EQ // IsSubset
|
||||||
NOTSUBSET // NotSubset
|
NOTSUBSET // NotSubset
|
||||||
|
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ binary_predicate
|
||||||
: IN
|
: IN
|
||||||
| NOTIN
|
| NOTIN
|
||||||
| SUBSET
|
| SUBSET
|
||||||
| SUBOR_EQ
|
| SUBSET_OR_EQ
|
||||||
| NOTSUBSET
|
| NOTSUBSET
|
||||||
| NOTEQUAL
|
| NOTEQUAL
|
||||||
| EQUAL
|
| EQUAL
|
||||||
|
|
|
@ -12,10 +12,12 @@ namespace {
|
||||||
void MangleRadicals(const std::string& funcName, Typification& type);
|
void MangleRadicals(const std::string& funcName, Typification& type);
|
||||||
|
|
||||||
std::string ToString(const ExpressionType& type) noexcept(false) {
|
std::string ToString(const ExpressionType& type) noexcept(false) {
|
||||||
return std::visit(meta::Overloads{
|
return std::visit(
|
||||||
|
meta::Overloads{
|
||||||
[](const Typification& t) { return t.ToString(); },
|
[](const Typification& t) { return t.ToString(); },
|
||||||
[](const LogicT& /*t*/) { return std::string{"LOGIC"}; },
|
[](const LogicT& /*t*/) { return std::string{"LOGIC"}; },
|
||||||
}, type);
|
}
|
||||||
|
, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool IsSubset(const TokenID token) noexcept {
|
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 {
|
std::optional<Typification> TypeEnv::Merge(const Typification& type1, const Typification& type2) const {
|
||||||
if (type1 == type2) {
|
if (type1 == type2) {
|
||||||
return type1;
|
return type1;
|
||||||
} else if (type1.Structure() != type2.Structure()) {
|
}
|
||||||
|
if (type1.Structure() != type2.Structure()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
switch (type1.Structure()) {
|
switch (type1.Structure()) {
|
||||||
default:
|
default:
|
||||||
case rslang::StructureType::basic: {
|
case rslang::StructureType::basic: {
|
||||||
if (const auto* type = CommonType(type1, type2); type == nullptr) {
|
const auto* type = CommonType(type1, type2);
|
||||||
|
if (type == nullptr) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
} else {
|
}
|
||||||
return *type;
|
return *type;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
case rslang::StructureType::collection: {
|
case rslang::StructureType::collection: {
|
||||||
if (auto base = Merge(type1.B().Base(), type2.B().Base()); !base.has_value()) {
|
auto base = Merge(type1.B().Base(), type2.B().Base());
|
||||||
|
if (!base.has_value()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
} else {
|
|
||||||
return base.value().ApplyBool();
|
|
||||||
}
|
}
|
||||||
|
return base.value().ApplyBool();
|
||||||
}
|
}
|
||||||
case rslang::StructureType::tuple: {
|
case rslang::StructureType::tuple: {
|
||||||
if (type1.T().Arity() != type2.T().Arity()) {
|
if (type1.T().Arity() != type2.T().Arity()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
} else {
|
}
|
||||||
std::vector<Typification> components{};
|
std::vector<Typification> components{};
|
||||||
for (auto index = Typification::PR_START; index < type1.T().Arity() + Typification::PR_START; ++index) {
|
const auto maxIndex = Typification::PR_START + type1.T().Arity();
|
||||||
if (auto component = Merge(type1.T().Component(index), type2.T().Component(index));
|
for (auto index = Typification::PR_START; index < maxIndex; ++index) {
|
||||||
!component.has_value()) {
|
auto component = Merge(type1.T().Component(index), type2.T().Component(index));
|
||||||
|
if (!component.has_value()) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
} else {
|
}
|
||||||
components.emplace_back(std::move(component.value()));
|
components.emplace_back(std::move(component.value()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return Typification::Tuple(components);
|
return Typification::Tuple(components);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeEnv::CompareTemplated(
|
bool TypeEnv::CompareTemplated(
|
||||||
|
@ -189,28 +191,33 @@ bool TypeEnv::CompareTemplated(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (arg.IsElement() && IsRadical(arg.E().baseID)) {
|
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 });
|
substitutes.insert({ base, value });
|
||||||
return true;
|
return true;
|
||||||
} else if (auto mergeType = Merge(substitutes.at(base), value);
|
}
|
||||||
!mergeType.has_value()) {
|
|
||||||
|
auto mergeType = Merge(substitutes.at(base), value);
|
||||||
|
if (!mergeType.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
substitutes.at(base) = std::move(mergeType.value());
|
substitutes.at(base) = std::move(mergeType.value());
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
} else if (arg.Structure() != value.Structure()) {
|
} else if (arg.Structure() != value.Structure()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
switch (arg.Structure()) {
|
switch (arg.Structure()) {
|
||||||
default:
|
default:
|
||||||
case rslang::StructureType::basic: return CommonType(arg, value) != nullptr;
|
case rslang::StructureType::basic:
|
||||||
case rslang::StructureType::collection: return CompareTemplated(substitutes, arg.B().Base(), value.B().Base());
|
return CommonType(arg, value) != nullptr;
|
||||||
|
case rslang::StructureType::collection:
|
||||||
|
return CompareTemplated(substitutes, arg.B().Base(), value.B().Base());
|
||||||
case rslang::StructureType::tuple: {
|
case rslang::StructureType::tuple: {
|
||||||
if (arg.T().Arity() != value.T().Arity()) {
|
if (arg.T().Arity() != value.T().Arity()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
for (auto index = Typification::PR_START; index < arg.T().Arity() + Typification::PR_START; ++index) {
|
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))) {
|
if (!CompareTemplated(substitutes, arg.T().Component(index), value.T().Component(index))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +226,6 @@ bool TypeEnv::CompareTemplated(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace details
|
} // namespace details
|
||||||
|
@ -270,44 +276,59 @@ bool TypeAuditor::ViGlobalDefinition(Cursor iter) {
|
||||||
if (childrenCount != 2 || !IsEchelon(iter, 1)) {
|
if (childrenCount != 2 || !IsEchelon(iter, 1)) {
|
||||||
OnError(SemanticEID::globalStructure, iter(0).pos.finish);
|
OnError(SemanticEID::globalStructure, iter(0).pos.finish);
|
||||||
return false;
|
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 {
|
} else {
|
||||||
assert(iter->id == TokenID::PUNC_DEFINE);
|
assert(iter->id == TokenID::PUNC_DEFINE);
|
||||||
if (childrenCount == 1) {
|
if (childrenCount == 1) {
|
||||||
return VisitAndReturn(Typification{ iter(0).data.ToText() }.ApplyBool());
|
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) {
|
bool TypeAuditor::ViFunctionDefinition(Cursor iter) {
|
||||||
if (const auto guard = isFuncDeclaration.CreateGuard(); !VisitChild(iter, 0)) {
|
{
|
||||||
|
const auto guard = isFuncDeclaration.CreateGuard();
|
||||||
|
if (!VisitChild(iter, 0)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto n : functionArgsID) {
|
for (auto n : functionArgsID) {
|
||||||
functionArgs.emplace_back(localVars.at(n).arg);
|
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;
|
return false;
|
||||||
} else {
|
|
||||||
return VisitAndReturn(type.value());
|
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(type.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViFunctionCall(Cursor iter) {
|
bool TypeAuditor::ViFunctionCall(Cursor iter) {
|
||||||
const auto& funcName = iter(0).data.ToText();
|
const auto& funcName = iter(0).data.ToText();
|
||||||
const auto* funcType = env.context.TypeFor(funcName);
|
const auto* funcType = env.context.TypeFor(funcName);
|
||||||
if (funcType == nullptr) {
|
if (funcType == nullptr) {
|
||||||
OnError(SemanticEID::globalNotTyped, iter->pos.start, funcName);
|
OnError(
|
||||||
|
SemanticEID::globalNotTyped,
|
||||||
|
iter->pos.start,
|
||||||
|
funcName
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto substitutes = CheckFuncArguments(iter, funcName);
|
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) {
|
std::optional<Typification::Substitutes> TypeAuditor::CheckFuncArguments(Cursor iter, const std::string& funcName) {
|
||||||
const auto* args = env.context.FunctionArgsFor(funcName);
|
const auto* args = env.context.FunctionArgsFor(funcName);
|
||||||
if (args == nullptr) {
|
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;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
const auto expectedArguments = iter.ChildrenCount() - 1;
|
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(
|
OnError(
|
||||||
SemanticEID::invalidArgsArtity,
|
SemanticEID::invalidArgsArity,
|
||||||
iter(1).pos.start,
|
iter(1).pos.start,
|
||||||
{ std::to_string(expectedArguments), std::to_string(argCount) }
|
{ 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;
|
Typification argType = args->at(static_cast<size_t>(child) - 1).type;
|
||||||
MangleRadicals(funcName, argType);
|
MangleRadicals(funcName, argType);
|
||||||
if (!env.CompareTemplated(substitutes, argType, std::get<Typification>(childType.value()))) {
|
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;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -361,19 +391,33 @@ std::optional<Typification::Substitutes> TypeAuditor::CheckFuncArguments(Cursor
|
||||||
bool TypeAuditor::ViGlobal(Cursor iter) {
|
bool TypeAuditor::ViGlobal(Cursor iter) {
|
||||||
const auto& globalName = iter->data.ToText();
|
const auto& globalName = iter->data.ToText();
|
||||||
if (iter->id == TokenID::ID_RADICAL) {
|
if (iter->id == TokenID::ID_RADICAL) {
|
||||||
if (isFuncDeclaration) {
|
if (!isFuncDeclaration) {
|
||||||
return VisitAndReturn(Typification(globalName).ApplyBool());
|
OnError(
|
||||||
} else {
|
SemanticEID::radicalUsage,
|
||||||
OnError(SemanticEID::radicalUsage, iter->pos.start, globalName);
|
iter->pos.start,
|
||||||
|
globalName
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (env.context.FunctionArgsFor(globalName) != nullptr) {
|
return VisitAndReturn(Typification(globalName).ApplyBool());
|
||||||
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;
|
|
||||||
} else {
|
} 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);
|
return VisitAndReturn(*type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,11 +428,10 @@ bool TypeAuditor::ViLocal(Cursor iter) {
|
||||||
return AddLocalVar(localName, std::get<Typification>(currentType), iter->pos.start);
|
return AddLocalVar(localName, std::get<Typification>(currentType), iter->pos.start);
|
||||||
} else {
|
} else {
|
||||||
const auto* local = GetLocalTypification(localName, iter->pos.start);
|
const auto* local = GetLocalTypification(localName, iter->pos.start);
|
||||||
if (local != nullptr) {
|
if (local == nullptr) {
|
||||||
return VisitAndReturn(*local);
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(*local);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +444,7 @@ bool TypeAuditor::ViLocalBind(Cursor iter) {
|
||||||
assert(isLocalDeclaration || isFuncDeclaration);
|
assert(isLocalDeclaration || isFuncDeclaration);
|
||||||
const Typification type = std::get<Typification>(currentType);
|
const Typification type = std::get<Typification>(currentType);
|
||||||
if (!type.IsTuple() || type.T().Arity() != iter.ChildrenCount()) {
|
if (!type.IsTuple() || type.T().Arity() != iter.ChildrenCount()) {
|
||||||
OnError(SemanticEID::ivalidBinding, iter(0).pos.start);
|
OnError(SemanticEID::invalidBinding, iter(0).pos.start);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Index child = 0; child < iter.ChildrenCount(); ++child) {
|
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);
|
const auto domain = ChildTypeDebool(iter, 1, SemanticEID::invalidTypeOperation);
|
||||||
if (!domain.has_value()) {
|
if (!domain.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
const auto guard{ isArgDeclaration.CreateGuard() };
|
const auto guard{ isArgDeclaration.CreateGuard() };
|
||||||
currentType = domain.value();
|
currentType = domain.value();
|
||||||
return VisitChild(iter, 0) && VisitAndReturn(LogicT{});
|
return VisitChild(iter, 0) && VisitAndReturn(LogicT{});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViCard(Cursor iter) {
|
bool TypeAuditor::ViCard(Cursor iter) {
|
||||||
|
@ -430,66 +472,114 @@ bool TypeAuditor::ViCard(Cursor iter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViArithmetic(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;
|
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) {
|
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;
|
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) {
|
bool TypeAuditor::ViQuantifier(Cursor iter) {
|
||||||
StartScope();
|
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;
|
return false;
|
||||||
} else if (!VisitChildDeclaration(iter, 0, domain.value())) {
|
} else if (!VisitChildDeclaration(iter, 0, domain.value())) {
|
||||||
return false;
|
return false;
|
||||||
} else if (!VisitChild(iter, 2)) {
|
} else if (!VisitChild(iter, 2)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
EndScope(iter->pos.start);
|
EndScope(iter->pos.start);
|
||||||
return VisitAndReturn(LogicT{});
|
return VisitAndReturn(LogicT{});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViEquals(Cursor iter) {
|
bool TypeAuditor::ViEquals(Cursor iter) {
|
||||||
if (iter(1).id == TokenID::LIT_EMPTYSET) {
|
if (iter(1).id == TokenID::LIT_EMPTYSET) {
|
||||||
const auto type = ChildTypeDebool(iter, 0, SemanticEID::invalidEqualsEmpty);
|
const auto type = ChildTypeDebool(iter, 0, SemanticEID::invalidEqualsEmpty);
|
||||||
return type.has_value() && VisitAndReturn(LogicT{});
|
return type.has_value() && VisitAndReturn(LogicT{});
|
||||||
} else {
|
}
|
||||||
|
|
||||||
const auto test1 = ChildType(iter, 0);
|
const auto test1 = ChildType(iter, 0);
|
||||||
if (!test1.has_value()) {
|
if (!test1.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -503,12 +593,15 @@ bool TypeAuditor::ViEquals(Cursor iter) {
|
||||||
const auto& type2 = std::get<Typification>(test2.value());
|
const auto& type2 = std::get<Typification>(test2.value());
|
||||||
|
|
||||||
if (!env.AreCompatible(type1, type2)) {
|
if (!env.AreCompatible(type1, type2)) {
|
||||||
OnError(SemanticEID::typesNotCompatible, iter(1).pos.start, type1, type2);
|
OnError(
|
||||||
|
SemanticEID::typesNotCompatible,
|
||||||
|
iter(1).pos.start,
|
||||||
|
type1,
|
||||||
|
type2
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
return VisitAndReturn(LogicT{});
|
return VisitAndReturn(LogicT{});
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViTypedPredicate(Cursor iter) {
|
bool TypeAuditor::ViTypedPredicate(Cursor iter) {
|
||||||
|
@ -527,44 +620,56 @@ bool TypeAuditor::ViTypedPredicate(Cursor iter) {
|
||||||
|
|
||||||
if (!env.AreCompatible(type1.value(), type2.value())) {
|
if (!env.AreCompatible(type1.value(), type2.value())) {
|
||||||
if (isSubset) {
|
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 {
|
} else {
|
||||||
OnError(SemanticEID::invalidElementPredicat, iter(1).pos.start,
|
OnError(
|
||||||
{ ToString(type1.value()), iter->ToString(), type2->Bool().ToString() });
|
SemanticEID::invalidElementPredicate,
|
||||||
|
iter(1).pos.start,
|
||||||
|
{ ToString(type1.value()), iter->ToString(), type2->Bool().ToString() }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
return VisitAndReturn(LogicT{});
|
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(LogicT{});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViDeclarative(Cursor iter) {
|
bool TypeAuditor::ViDeclarative(Cursor iter) {
|
||||||
StartScope();
|
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;
|
return false;
|
||||||
} else if (!VisitChildDeclaration(iter, 0, domain.value())) {
|
} else if (!VisitChildDeclaration(iter, 0, domain.value())) {
|
||||||
return false;
|
return false;
|
||||||
} else if (!VisitChild(iter, 2)) {
|
} else if (!VisitChild(iter, 2)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
EndScope(iter->pos.start);
|
EndScope(iter->pos.start);
|
||||||
return VisitAndReturn(domain->ApplyBool());
|
return VisitAndReturn(domain->ApplyBool());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViImperative(Cursor iter) {
|
bool TypeAuditor::ViImperative(Cursor iter) {
|
||||||
StartScope();
|
StartScope();
|
||||||
|
|
||||||
for (Index child = 1; child < iter.ChildrenCount(); ++child) {
|
for (Index child = 1; child < iter.ChildrenCount(); ++child) {
|
||||||
if (!VisitChild(iter, child)) {
|
if (!VisitChild(iter, child)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (auto type = ChildType(iter, 0); !type.has_value()) {
|
|
||||||
|
auto type = ChildType(iter, 0);
|
||||||
|
if (!type.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
EndScope(iter->pos.start);
|
EndScope(iter->pos.start);
|
||||||
return VisitAndReturn(std::get<Typification>(type.value()).Bool());
|
return VisitAndReturn(std::get<Typification>(type.value()).Bool());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViImpDeclare(Cursor iter) {
|
bool TypeAuditor::ViImpDeclare(Cursor iter) {
|
||||||
|
@ -581,6 +686,7 @@ bool TypeAuditor::ViImpAssign(Cursor iter) {
|
||||||
|
|
||||||
bool TypeAuditor::ViRecursion(Cursor iter) {
|
bool TypeAuditor::ViRecursion(Cursor iter) {
|
||||||
StartScope();
|
StartScope();
|
||||||
|
|
||||||
auto initType = ChildType(iter, 1);
|
auto initType = ChildType(iter, 1);
|
||||||
if (!initType.has_value()) {
|
if (!initType.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -600,10 +706,15 @@ bool TypeAuditor::ViRecursion(Cursor iter) {
|
||||||
if (!iterationType.has_value()) {
|
if (!iterationType.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (!env.AreCompatible(iterationType.value(), initType.value())) {
|
} else if (!env.AreCompatible(iterationType.value(), initType.value())) {
|
||||||
OnError(SemanticEID::typesNotEqual, iter(iterationIndex).pos.start,
|
OnError(
|
||||||
iterationType.value(), initType.value());
|
SemanticEID::typesNotEqual,
|
||||||
|
iter(iterationIndex).pos.start,
|
||||||
|
iterationType.value(),
|
||||||
|
initType.value()
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EndScope(iter->pos.start);
|
EndScope(iter->pos.start);
|
||||||
return VisitAndReturn(iterationType.value());
|
return VisitAndReturn(iterationType.value());
|
||||||
}
|
}
|
||||||
|
@ -622,21 +733,21 @@ bool TypeAuditor::ViDecart(Cursor iter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViBoolean(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;
|
return false;
|
||||||
} else {
|
|
||||||
return VisitAndReturn(type->ApplyBool().ApplyBool());
|
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(type->ApplyBool().ApplyBool());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViTuple(Cursor iter) {
|
bool TypeAuditor::ViTuple(Cursor iter) {
|
||||||
std::vector<Typification> components{};
|
std::vector<Typification> components{};
|
||||||
for (Index child = 0; child < iter.ChildrenCount(); ++child) {
|
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;
|
return false;
|
||||||
} else {
|
|
||||||
components.emplace_back(std::get<Typification>(type.value()));
|
|
||||||
}
|
}
|
||||||
|
components.emplace_back(std::get<Typification>(type.value()));
|
||||||
}
|
}
|
||||||
return VisitAndReturn(Typification::Tuple(components));
|
return VisitAndReturn(Typification::Tuple(components));
|
||||||
}
|
}
|
||||||
|
@ -648,25 +759,32 @@ bool TypeAuditor::ViSetEnum(Cursor iter) {
|
||||||
}
|
}
|
||||||
auto& type = std::get<Typification>(test.value());
|
auto& type = std::get<Typification>(test.value());
|
||||||
for (Index child = 1; child < iter.ChildrenCount(); ++child) {
|
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;
|
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());
|
return VisitAndReturn(type.Bool());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViDebool(Cursor iter) {
|
bool TypeAuditor::ViDebool(Cursor iter) {
|
||||||
if (auto type = ChildTypeDebool(iter, 0, SemanticEID::invalidDebool); type.has_value()) {
|
auto type = ChildTypeDebool(iter, 0, SemanticEID::invalidDebool);
|
||||||
return VisitAndReturn(type.value());
|
if (!type.has_value()) {
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(type.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViTypedBinary(Cursor iter) {
|
bool TypeAuditor::ViTypedBinary(Cursor iter) {
|
||||||
|
@ -674,16 +792,23 @@ bool TypeAuditor::ViTypedBinary(Cursor iter) {
|
||||||
if (!type1.has_value()) {
|
if (!type1.has_value()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto type2 = ChildTypeDebool(iter, 1, SemanticEID::invalidTypeOperation);
|
auto type2 = ChildTypeDebool(iter, 1, SemanticEID::invalidTypeOperation);
|
||||||
if (!type2.has_value()) {
|
if (!type2.has_value()) {
|
||||||
return false;
|
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;
|
return false;
|
||||||
} else {
|
|
||||||
return VisitAndReturn(result.value().Bool());
|
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(result.value().Bool());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::ViProjectSet(Cursor iter) {
|
bool TypeAuditor::ViProjectSet(Cursor iter) {
|
||||||
|
@ -693,7 +818,11 @@ bool TypeAuditor::ViProjectSet(Cursor iter) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!baseType->IsTuple()) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,7 +831,11 @@ bool TypeAuditor::ViProjectSet(Cursor iter) {
|
||||||
components.reserve(size(indicies));
|
components.reserve(size(indicies));
|
||||||
for (const auto index : indicies) {
|
for (const auto index : indicies) {
|
||||||
if (!baseType->T().TestIndex(index)) {
|
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;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
components.emplace_back(baseType->T().Component(index));
|
components.emplace_back(baseType->T().Component(index));
|
||||||
|
@ -787,11 +920,14 @@ bool TypeAuditor::ViReduce(Cursor iter) {
|
||||||
}
|
}
|
||||||
const auto& base = std::get<Typification>(baseType.value());
|
const auto& base = std::get<Typification>(baseType.value());
|
||||||
if (!base.IsCollection() || !base.B().Base().IsCollection()) {
|
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;
|
return false;
|
||||||
} else {
|
|
||||||
return VisitAndReturn(base.B().Base());
|
|
||||||
}
|
}
|
||||||
|
return VisitAndReturn(base.B().Base());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeAuditor::VisitAndReturn(ExpressionType type) noexcept {
|
bool TypeAuditor::VisitAndReturn(ExpressionType type) noexcept {
|
||||||
|
@ -832,16 +968,22 @@ std::optional<Typification> TypeAuditor::ChildTypeDebool(Cursor iter, const Inde
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
if (!std::get<Typification>(result.value()).IsCollection()) {
|
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;
|
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 Typification* TypeAuditor::GetLocalTypification(const std::string& name, const StrPos pos) {
|
||||||
const auto varIter = std::find_if(begin(localVars), end(localVars),
|
const auto varIter = std::find_if(
|
||||||
[&](const auto& data) noexcept { return data.arg.name == name; });
|
begin(localVars),
|
||||||
|
end(localVars),
|
||||||
|
[&](const auto& data) noexcept { return data.arg.name == name; }
|
||||||
|
);
|
||||||
if (varIter == end(localVars)) {
|
if (varIter == end(localVars)) {
|
||||||
if (!isArgDeclaration) {
|
if (!isArgDeclaration) {
|
||||||
OnError(SemanticEID::localUndeclared, pos, name);
|
OnError(SemanticEID::localUndeclared, pos, name);
|
||||||
|
@ -868,7 +1010,11 @@ void TypeAuditor::EndScope(const StrPos pos) {
|
||||||
if (var.level < 0 && var.enabled) {
|
if (var.level < 0 && var.enabled) {
|
||||||
var.enabled = false;
|
var.enabled = false;
|
||||||
if (var.useCount == 0) {
|
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; });
|
[&](const auto& data) noexcept { return data.arg.name == name; });
|
||||||
if (varIter != end(localVars)) {
|
if (varIter != end(localVars)) {
|
||||||
if (varIter->enabled) {
|
if (varIter->enabled) {
|
||||||
OnError(SemanticEID::localShadowing, pos, name);
|
OnError(
|
||||||
|
SemanticEID::localShadowing,
|
||||||
|
pos,
|
||||||
|
name
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
OnError(SemanticEID::localDoubleDeclare, pos, name);
|
OnError(
|
||||||
|
SemanticEID::localDoubleDeclare,
|
||||||
|
pos,
|
||||||
|
name
|
||||||
|
);
|
||||||
varIter->arg.type = type;
|
varIter->arg.type = type;
|
||||||
varIter->enabled = true;
|
varIter->enabled = true;
|
||||||
varIter->level = 0;
|
varIter->level = 0;
|
||||||
|
|
|
@ -102,9 +102,11 @@ bool ValueAuditor::ViFunctionCall(Cursor iter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValueAuditor::RunCheckOnFunc(Cursor iter,
|
bool ValueAuditor::RunCheckOnFunc(
|
||||||
|
Cursor iter,
|
||||||
const std::string& funcName,
|
const std::string& funcName,
|
||||||
const std::vector<ValueClass>& argumentVals) {
|
const std::vector<ValueClass>& argumentVals
|
||||||
|
) {
|
||||||
const auto* ast = globalAST(funcName);
|
const auto* ast = globalAST(funcName);
|
||||||
if (ast == nullptr) {
|
if (ast == nullptr) {
|
||||||
OnError(SemanticEID::globalMissingAST, iter->pos.start, funcName);
|
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)) {
|
if (!ast->Root().Child(1).Child(1).DispatchVisit(funcAuditor)) {
|
||||||
OnError(SemanticEID::globalFuncNoInterpretation, iter->pos.start);
|
OnError(SemanticEID::globalFuncNoInterpretation, iter->pos.start);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
current = funcAuditor.VType();
|
current = funcAuditor.VType();
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValueAuditor::ViGlobal(Cursor iter) {
|
bool ValueAuditor::ViGlobal(Cursor iter) {
|
||||||
|
@ -138,11 +139,10 @@ bool ValueAuditor::ViGlobal(Cursor iter) {
|
||||||
if (type == ValueClass::invalid) {
|
if (type == ValueClass::invalid) {
|
||||||
OnError(SemanticEID::globalNoValue, iter->pos.start, globalName);
|
OnError(SemanticEID::globalNoValue, iter->pos.start, globalName);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
current = type;
|
current = type;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValueAuditor::ViLocal(Cursor iter) {
|
bool ValueAuditor::ViLocal(Cursor iter) {
|
||||||
|
|
|
@ -215,8 +215,8 @@ TEST_F(UTTypeAuditor, LogicErrors) {
|
||||||
ExpectError(R"(\A a \in X1*X1 a \eq {})", SemanticEID::invalidEqualsEmpty, 15);
|
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,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) \in X1 1 \eq 1)", SemanticEID::invalidBinding, 4);
|
||||||
ExpectError(R"(\A (a,b,c) \in S1 1 \eq 1)", SemanticEID::ivalidBinding, 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 \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);
|
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) {
|
TEST_F(UTTypeAuditor, TypedPredicatesError) {
|
||||||
SetupConstants();
|
SetupConstants();
|
||||||
|
|
||||||
ExpectError(R"(X1 \in X1)", SemanticEID::invalidElementPredicat, 7);
|
ExpectError(R"(X1 \in X1)", SemanticEID::invalidElementPredicate, 7);
|
||||||
ExpectError(R"(S4 \in C2)", SemanticEID::invalidElementPredicat, 7);
|
ExpectError(R"(S4 \in C2)", SemanticEID::invalidElementPredicate, 7);
|
||||||
ExpectError(R"(S5 \in Z)", SemanticEID::invalidElementPredicat, 7);
|
ExpectError(R"(S5 \in Z)", SemanticEID::invalidElementPredicate, 7);
|
||||||
ExpectError(R"(S6 \in Z)", SemanticEID::invalidElementPredicat, 7);
|
ExpectError(R"(S6 \in Z)", SemanticEID::invalidElementPredicate, 7);
|
||||||
ExpectError(R"((1,2) \in Z)", SemanticEID::invalidElementPredicat, 10);
|
ExpectError(R"((1,2) \in Z)", SemanticEID::invalidElementPredicate, 10);
|
||||||
ExpectError(R"({1} \in Z)", SemanticEID::invalidElementPredicat, 8);
|
ExpectError(R"({1} \in Z)", SemanticEID::invalidElementPredicate, 8);
|
||||||
ExpectError(R"((1,2) \in Z)", SemanticEID::invalidElementPredicat, 10);
|
ExpectError(R"((1,2) \in Z)", SemanticEID::invalidElementPredicate, 10);
|
||||||
|
|
||||||
ExpectError(R"(X1 \subset S2)", SemanticEID::typesNotEqual, 11);
|
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 \subseteq S2)", SemanticEID::typesNotEqual, 13);
|
||||||
ExpectError(R"(X1 \notsubset S2)", SemanticEID::typesNotEqual, 14);
|
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);
|
ExpectTypification(R"(F1[Pr1(S1), Pr2(S1)])", "B(X1)"_t);
|
||||||
|
|
||||||
ExpectError(R"(F1)", SemanticEID::globalFuncWithoutArgs, 0);
|
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[0], "1");
|
||||||
EXPECT_EQ(parser.log.All()[0].params[1], "2");
|
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[0], "3");
|
||||||
EXPECT_EQ(parser.log.All()[0].params[1], "2");
|
EXPECT_EQ(parser.log.All()[0].params[1], "2");
|
||||||
|
|
||||||
|
@ -388,8 +388,8 @@ TEST_F(UTTypeAuditor, LogicFunctions) {
|
||||||
ExpectLogic(R"(P1[Pr1(S1), Pr2(S1)])");
|
ExpectLogic(R"(P1[Pr1(S1), Pr2(S1)])");
|
||||||
|
|
||||||
ExpectError(R"(P1)", SemanticEID::globalFuncWithoutArgs, 0);
|
ExpectError(R"(P1)", SemanticEID::globalFuncWithoutArgs, 0);
|
||||||
ExpectError(R"(P1[X1])", SemanticEID::invalidArgsArtity, 3);
|
ExpectError(R"(P1[X1])", SemanticEID::invalidArgsArity, 3);
|
||||||
ExpectError(R"(P1[X1, X1, X1])", SemanticEID::invalidArgsArtity, 3);
|
ExpectError(R"(P1[X1, X1, X1])", SemanticEID::invalidArgsArity, 3);
|
||||||
|
|
||||||
ExpectError(R"(P1[S1, X1])", SemanticEID::invalidArgumentType, 3);
|
ExpectError(R"(P1[S1, X1])", SemanticEID::invalidArgumentType, 3);
|
||||||
ExpectError(R"(P1[X1, S1])", SemanticEID::invalidArgumentType, 7);
|
ExpectError(R"(P1[X1, S1])", SemanticEID::invalidArgumentType, 7);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user