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