From 4786ba851b9ec48670ac405d2fc63c9140722b22 Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Thu, 9 May 2024 17:21:57 +0300 Subject: [PATCH] Fix EmptySet type check errors --- .../include/ccl/rslang/ASTInterpreter.h | 4 +- ccl/rslang/include/ccl/rslang/TypeAuditor.h | 23 +- ccl/rslang/include/ccl/rslang/Typification.h | 2 + ccl/rslang/include/ccl/rslang/ValueAuditor.h | 24 +- ccl/rslang/src/ASTInterpreter.cpp | 84 ++--- ccl/rslang/src/TypeAuditor.cpp | 332 +++++++++++------- ccl/rslang/src/Typification.cpp | 4 + ccl/rslang/src/ValueAuditor.cpp | 24 +- ccl/rslang/test/src/testTypeAuditor.cpp | 15 + ccl/rslang/test/src/testTypification.cpp | 20 ++ 10 files changed, 318 insertions(+), 214 deletions(-) diff --git a/ccl/rslang/include/ccl/rslang/ASTInterpreter.h b/ccl/rslang/include/ccl/rslang/ASTInterpreter.h index 300d299..6b83db8 100644 --- a/ccl/rslang/include/ccl/rslang/ASTInterpreter.h +++ b/ccl/rslang/include/ccl/rslang/ASTInterpreter.h @@ -106,8 +106,8 @@ private: void OnError(ValueEID eid, StrPos position); void OnError(ValueEID eid, StrPos position, std::string param); - [[nodiscard]] bool VisitAndReturn(ExpressionValue&& value) noexcept; - [[nodiscard]] bool VisitAndReturn(const ExpressionValue& value) noexcept; + [[nodiscard]] bool SetCurrent(ExpressionValue&& value) noexcept; + [[nodiscard]] bool SetCurrent(const ExpressionValue& value) noexcept; [[nodiscard]] std::optional EvaluateChild(Cursor iter, Index index); [[nodiscard]] std::optional ExtractDomain(Cursor iter); diff --git a/ccl/rslang/include/ccl/rslang/TypeAuditor.h b/ccl/rslang/include/ccl/rslang/TypeAuditor.h index dd147f6..29dafc5 100644 --- a/ccl/rslang/include/ccl/rslang/TypeAuditor.h +++ b/ccl/rslang/include/ccl/rslang/TypeAuditor.h @@ -58,6 +58,7 @@ class TypeAuditor final : public ASTVisitor { types::GuardableBool isArgDeclaration{ false }; types::GuardableBool isLocalDeclaration{ false }; types::GuardableBool isFuncDeclaration{ false }; + types::GuardableBool noWarnings{ false }; public: explicit TypeAuditor(const TypeContext& context) noexcept @@ -79,21 +80,21 @@ protected: bool ViGlobal(Cursor iter); bool ViLocal(Cursor iter); - bool ViInteger(Cursor /*iter*/) { return VisitAndReturn(Typification::Integer()); } - bool ViIntegerSet(Cursor /*iter*/) { return VisitAndReturn(Typification::Integer().Bool()); } + bool ViInteger(Cursor /*iter*/) { return SetCurrent(Typification::Integer()); } + bool ViIntegerSet(Cursor /*iter*/) { return SetCurrent(Typification::Integer().Bool()); } bool ViEmptySet(Cursor /*iter*/); bool ViLocalBind(Cursor iter); - bool ViLocalEnum(Cursor iter) { return VisitAllAndReturn(iter, LogicT{}); } - bool ViArgumentsEnum(Cursor iter) { return VisitAllAndReturn(iter, LogicT{}); } + bool ViLocalEnum(Cursor iter) { return VisitAllAndSetCurrent(iter, LogicT{}); } + bool ViArgumentsEnum(Cursor iter) { return VisitAllAndSetCurrent(iter, LogicT{}); } bool ViArgument(Cursor iter); bool ViArithmetic(Cursor iter); bool ViCard(Cursor iter); bool ViQuantifier(Cursor iter); - bool ViNegation(Cursor iter) { return VisitAllAndReturn(iter, LogicT{}); } - bool ViLogicBinary(Cursor iter) { return VisitAllAndReturn(iter, LogicT{}); } + bool ViNegation(Cursor iter) { return VisitAllAndSetCurrent(iter, LogicT{}); } + bool ViLogicBinary(Cursor iter) { return VisitAllAndSetCurrent(iter, LogicT{}); } bool ViEquals(Cursor iter); bool ViOrdering(Cursor iter); bool ViTypedPredicate(Cursor iter); @@ -105,7 +106,7 @@ protected: bool ViImperative(Cursor iter); bool ViImpDeclare(Cursor iter); bool ViImpAssign(Cursor iter); - bool ViImpCheck(Cursor iter) { return VisitAllAndReturn(iter, LogicT{}); } + bool ViImpCheck(Cursor iter) { return VisitAllAndSetCurrent(iter, LogicT{}); } bool ViRecursion(Cursor iter); bool ViTuple(Cursor iter); @@ -124,8 +125,8 @@ private: [[nodiscard]] bool VisitChildDeclaration(const Cursor& iter, Index index, const Typification& domain); - [[nodiscard]] bool VisitAndReturn(ExpressionType type) noexcept; - [[nodiscard]] bool VisitAllAndReturn(Cursor iter, const ExpressionType& type); + [[nodiscard]] bool SetCurrent(ExpressionType type) noexcept; + [[nodiscard]] bool VisitAllAndSetCurrent(Cursor iter, const ExpressionType& type); [[nodiscard]] std::optional ChildType(Cursor iter, Index index); [[nodiscard]] std::optional ChildTypeDebool(Cursor iter, Index index, SemanticEID eid); @@ -139,7 +140,9 @@ private: CheckFuncArguments(Cursor iter, const std::string& funcName); [[nodiscard]] const Typification* GetLocalTypification(const std::string& name, StrPos pos); - [[nodiscard]] bool AddLocalVar(const std::string& name, const Typification& type, StrPos pos); + [[nodiscard]] bool AddLocalVariable(const std::string& name, const Typification& type, StrPos pos); + void ClearLocalVariables(); + void StartScope() noexcept; void EndScope(StrPos pos); }; diff --git a/ccl/rslang/include/ccl/rslang/Typification.h b/ccl/rslang/include/ccl/rslang/Typification.h index 03e90da..243995d 100644 --- a/ccl/rslang/include/ccl/rslang/Typification.h +++ b/ccl/rslang/include/ccl/rslang/Typification.h @@ -93,6 +93,8 @@ public: public: using Substitutes = std::unordered_map; + [[nodiscard]] bool IsAnyType() const noexcept; + Typification& ApplyBool(); [[nodiscard]] Typification Bool() const; diff --git a/ccl/rslang/include/ccl/rslang/ValueAuditor.h b/ccl/rslang/include/ccl/rslang/ValueAuditor.h index 5ba35de..4e24fad 100644 --- a/ccl/rslang/include/ccl/rslang/ValueAuditor.h +++ b/ccl/rslang/include/ccl/rslang/ValueAuditor.h @@ -40,23 +40,23 @@ protected: bool ViGlobal(Cursor iter); bool ViLocal(Cursor iter); - bool ViInteger(Cursor /*iter*/) noexcept { return VisitAndReturn(ValueClass::value); } - bool ViIntegerSet(Cursor /*iter*/) noexcept { return VisitAndReturn(ValueClass::props); } - bool ViEmptySet(Cursor /*iter*/) noexcept { return VisitAndReturn(ValueClass::value); } + bool ViInteger(Cursor /*iter*/) noexcept { return SetCurrent(ValueClass::value); } + bool ViIntegerSet(Cursor /*iter*/) noexcept { return SetCurrent(ValueClass::props); } + bool ViEmptySet(Cursor /*iter*/) noexcept { return SetCurrent(ValueClass::value); } - bool ViLocalBind(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } - bool ViLocalEnum(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } + bool ViLocalBind(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); } + bool ViLocalEnum(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); } bool ViArgumentsEnum(Cursor iter) { return VisitAllChildren(iter); } bool ViArgument(Cursor iter) { return VisitAllChildren(iter); } - bool ViArithmetic(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } + bool ViArithmetic(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); } bool ViCard(Cursor iter) { return AssertChildIsValue(iter, 0); } bool ViQuantifier(Cursor iter); - bool ViNegation(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } - bool ViLogicBinary(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } + bool ViNegation(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); } + bool ViLogicBinary(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); } bool ViEquals(Cursor iter) { return AssertAllValues(iter); } - bool ViOrdering(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } + bool ViOrdering(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); } bool ViTypedPredicate(Cursor iter); bool ViDecart(Cursor iter); @@ -66,7 +66,7 @@ protected: bool ViImperative(Cursor iter); bool ViImpDeclare(Cursor iter) { return AssertChildIsValue(iter, 1); } bool ViImpAssign(Cursor iter) { return AssertChildIsValue(iter, 1); } - bool ViImpCheck(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } + bool ViImpCheck(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); } bool ViRecursion(Cursor iter) { return AssertAllValues(iter); } bool ViTuple(Cursor iter) { return AssertAllValues(iter); } @@ -82,8 +82,8 @@ protected: private: void Clear() noexcept; - [[nodiscard]] bool VisitAndReturn(ValueClass type) noexcept; - [[nodiscard]] bool VisitAllAndReturn(Cursor iter, ValueClass type); + [[nodiscard]] bool SetCurrent(ValueClass type) noexcept; + [[nodiscard]] bool VisitAllAndSetCurrent(Cursor iter, ValueClass type); [[nodiscard]] bool AssertAllValues(Cursor iter); [[nodiscard]] bool AssertChildIsValue(Cursor iter, Index index); diff --git a/ccl/rslang/src/ASTInterpreter.cpp b/ccl/rslang/src/ASTInterpreter.cpp index d2b328a..5eb6852 100644 --- a/ccl/rslang/src/ASTInterpreter.cpp +++ b/ccl/rslang/src/ASTInterpreter.cpp @@ -215,12 +215,12 @@ void ASTInterpreter::Clear() noexcept { countCriticalErrors = 0; } -bool ASTInterpreter::VisitAndReturn(ExpressionValue&& value) noexcept { +bool ASTInterpreter::SetCurrent(ExpressionValue&& value) noexcept { curValue = std::move(value); return true; } -bool ASTInterpreter::VisitAndReturn(const ExpressionValue& value) noexcept { +bool ASTInterpreter::SetCurrent(const ExpressionValue& value) noexcept { curValue = value; return true; } @@ -230,11 +230,11 @@ bool ASTInterpreter::ViGlobalDefinition(Cursor iter) { } bool ASTInterpreter::ViLocal(Cursor iter) { - return VisitAndReturn(idsData[*begin(nodeVars[iter.get()])]); + return SetCurrent(idsData[*begin(nodeVars[iter.get()])]); } bool ASTInterpreter::ViInteger(Cursor iter) { - return VisitAndReturn(Factory::Val(iter->data.ToInt())); + return SetCurrent(Factory::Val(iter->data.ToInt())); } bool ASTInterpreter::ViIntegerSet(Cursor iter) { @@ -243,7 +243,7 @@ bool ASTInterpreter::ViIntegerSet(Cursor iter) { } bool ASTInterpreter::ViEmptySet(Cursor /*iter*/) { - return VisitAndReturn(Factory::EmptySet()); + return SetCurrent(Factory::EmptySet()); } bool ASTInterpreter::ViArithmetic(Cursor iter) { @@ -260,11 +260,11 @@ bool ASTInterpreter::ViArithmetic(Cursor iter) { switch (iter->id) { default: case TokenID::PLUS: - return VisitAndReturn(Factory::Val(op1 + op2)); + return SetCurrent(Factory::Val(op1 + op2)); case TokenID::MINUS: - return VisitAndReturn(Factory::Val(op1 - op2)); + return SetCurrent(Factory::Val(op1 - op2)); case TokenID::MULTIPLY: - return VisitAndReturn(Factory::Val(op1 * op2)); + return SetCurrent(Factory::Val(op1 * op2)); } } @@ -278,7 +278,7 @@ bool ASTInterpreter::ViCard(Cursor iter) { OnError(ValueEID::typedOverflow, iter->pos.start, std::to_string(StructuredData::SET_INFINITY)); return false; } - return VisitAndReturn(Factory::Val(size)); + return SetCurrent(Factory::Val(size)); } bool ASTInterpreter::ViQuantifier(Cursor iter) { @@ -298,10 +298,10 @@ bool ASTInterpreter::ViQuantifier(Cursor iter) { if (const auto iterationValue = EvaluateChild(iter, 2); !iterationValue.has_value()) { return false; } else if (std::get(iterationValue.value()) != isUniversal) { - return VisitAndReturn(!isUniversal); + return SetCurrent(!isUniversal); } } - return VisitAndReturn(isUniversal); + return SetCurrent(isUniversal); } std::optional ASTInterpreter::ExtractDomain(Cursor iter) { @@ -316,7 +316,7 @@ bool ASTInterpreter::ViNegation(Cursor iter) { if (!childValue.has_value()) { return false; } - return VisitAndReturn(!std::get(childValue.value())); + return SetCurrent(!std::get(childValue.value())); } bool ASTInterpreter::ViLogicBinary(Cursor iter) { @@ -347,9 +347,9 @@ bool ASTInterpreter::ViLogicBinary(Cursor iter) { bool ASTInterpreter::TryEvaluateFromFirstArg(TokenID operation, bool firstArgValue) noexcept { if ((operation == TokenID::AND && !firstArgValue) || (operation == TokenID::OR && firstArgValue)) { - return VisitAndReturn(firstArgValue); + return SetCurrent(firstArgValue); } else if (operation == TokenID::IMPLICATION && !firstArgValue) { - return VisitAndReturn(!firstArgValue); + return SetCurrent(!firstArgValue); } else { return false; } @@ -364,7 +364,7 @@ bool ASTInterpreter::ViEquals(Cursor iter) { if (!val2.has_value()) { return false; } - return VisitAndReturn((val1 == val2) != (iter->id == TokenID::NOTEQUAL)); + return SetCurrent((val1 == val2) != (iter->id == TokenID::NOTEQUAL)); } bool ASTInterpreter::ViOrdering(Cursor iter) { @@ -380,10 +380,10 @@ bool ASTInterpreter::ViOrdering(Cursor iter) { const auto op2 = std::get(val2.value()).E().Value(); switch (iter->id) { default: - case TokenID::GREATER: return VisitAndReturn(op1 > op2); - case TokenID::LESSER: return VisitAndReturn(op1 < op2); - case TokenID::GREATER_OR_EQ: return VisitAndReturn(op1 >= op2); - case TokenID::LESSER_OR_EQ: return VisitAndReturn(op1 <= op2); + case TokenID::GREATER: return SetCurrent(op1 > op2); + case TokenID::LESSER: return SetCurrent(op1 < op2); + case TokenID::GREATER_OR_EQ: return SetCurrent(op1 >= op2); + case TokenID::LESSER_OR_EQ: return SetCurrent(op1 <= op2); } } @@ -408,7 +408,7 @@ bool ASTInterpreter::ViDeclarative(Cursor iter) { result.ModifyB().AddElement(child); } } - return VisitAndReturn(std::move(result)); + return SetCurrent(std::move(result)); } bool ASTInterpreter::ViImperative(const Cursor iter) { @@ -416,7 +416,7 @@ bool ASTInterpreter::ViImperative(const Cursor iter) { if (!eval.Evaluate()) { return false; } - return VisitAndReturn(eval.value); + return SetCurrent(eval.value); } bool ASTInterpreter::ViRecursion(Cursor iter) { @@ -448,7 +448,7 @@ bool ASTInterpreter::ViRecursion(Cursor iter) { } current = std::get(curValue); } while (idsData[varID] != current); - return VisitAndReturn(std::move(current)); + return SetCurrent(std::move(current)); } bool ASTInterpreter::ViDecart(Cursor iter) { @@ -486,7 +486,7 @@ bool ASTInterpreter::ViBoolean(Cursor iter) { ); return false; } - return VisitAndReturn(Factory::Boolean(value)); + return SetCurrent(Factory::Boolean(value)); } bool ASTInterpreter::ViTuple(Cursor iter) { @@ -498,7 +498,7 @@ bool ASTInterpreter::ViTuple(Cursor iter) { } args.emplace_back(std::get(childValue.value())); } - return VisitAndReturn(Factory::Tuple(args)); + return SetCurrent(Factory::Tuple(args)); } bool ASTInterpreter::ViSetEnum(Cursor iter) { @@ -510,7 +510,7 @@ bool ASTInterpreter::ViSetEnum(Cursor iter) { } args.emplace_back(std::get(childValue.value())); } - return VisitAndReturn(Factory::Set(args)); + return SetCurrent(Factory::Set(args)); } bool ASTInterpreter::ViBool(Cursor iter) { @@ -518,7 +518,7 @@ bool ASTInterpreter::ViBool(Cursor iter) { if (!childValue.has_value()) { return false; } - return VisitAndReturn(Factory::Singleton(std::get(childValue.value()))); + return SetCurrent(Factory::Singleton(std::get(childValue.value()))); } bool ASTInterpreter::ViTypedBinary(Cursor iter) { @@ -535,16 +535,16 @@ bool ASTInterpreter::ViTypedBinary(Cursor iter) { const auto& op2 = std::get(val2.value()); switch (iter->id) { default: - case TokenID::UNION: return VisitAndReturn(op1.B().Union(op2.B())); - case TokenID::INTERSECTION: return VisitAndReturn(op1.B().Intersect(op2.B())); - case TokenID::SET_MINUS: return VisitAndReturn(op1.B().Diff(op2.B())); - case TokenID::SYMMINUS: return VisitAndReturn(op1.B().SymDiff(op2.B())); + case TokenID::UNION: return SetCurrent(op1.B().Union(op2.B())); + case TokenID::INTERSECTION: return SetCurrent(op1.B().Intersect(op2.B())); + case TokenID::SET_MINUS: return SetCurrent(op1.B().Diff(op2.B())); + case TokenID::SYMMINUS: return SetCurrent(op1.B().SymDiff(op2.B())); - case TokenID::IN: return VisitAndReturn(op2.B().Contains(op1)); - case TokenID::NOTIN: return VisitAndReturn(!op2.B().Contains(op1)); - case TokenID::SUBSET: return VisitAndReturn(!(op1 == op2) && op1.B().IsSubsetOrEq(op2.B())); - case TokenID::NOTSUBSET: return VisitAndReturn(op1 == op2 || !op1.B().IsSubsetOrEq(op2.B())); - case TokenID::SUBSET_OR_EQ: return VisitAndReturn(op1.B().IsSubsetOrEq(op2.B())); + case TokenID::IN: return SetCurrent(op2.B().Contains(op1)); + case TokenID::NOTIN: return SetCurrent(!op2.B().Contains(op1)); + case TokenID::SUBSET: return SetCurrent(!(op1 == op2) && op1.B().IsSubsetOrEq(op2.B())); + case TokenID::NOTSUBSET: return SetCurrent(op1 == op2 || !op1.B().IsSubsetOrEq(op2.B())); + case TokenID::SUBSET_OR_EQ: return SetCurrent(op1.B().IsSubsetOrEq(op2.B())); } } @@ -553,7 +553,7 @@ bool ASTInterpreter::ViProjectSet(Cursor iter) { if (!childValue.has_value()) { return false; } - return VisitAndReturn(std::get(childValue.value()).B().Projection(iter->data.ToTuple())); + return SetCurrent(std::get(childValue.value()).B().Projection(iter->data.ToTuple())); } bool ASTInterpreter::ViProjectTuple(Cursor iter) { @@ -568,7 +568,7 @@ bool ASTInterpreter::ViProjectTuple(Cursor iter) { for (const auto index : indicies) { components.emplace_back(std::get(childValue.value()).T().Component(index)); } - return VisitAndReturn(Factory::Tuple(components)); + return SetCurrent(Factory::Tuple(components)); } bool ASTInterpreter::ViFilter(Cursor iter) { @@ -578,7 +578,7 @@ bool ASTInterpreter::ViFilter(Cursor iter) { } const auto& argument = std::get(argumentValue.value()); if (argument.B().IsEmpty()) { - return VisitAndReturn(Factory::EmptySet()); + return SetCurrent(Factory::EmptySet()); } const auto& indicies = iter->data.ToTuple(); @@ -590,7 +590,7 @@ bool ASTInterpreter::ViFilter(Cursor iter) { return false; } if (const auto val = std::get(param.value()); val.B().IsEmpty()) { - return VisitAndReturn(Factory::EmptySet()); + return SetCurrent(Factory::EmptySet()); } else { params.emplace_back(val); } @@ -609,7 +609,7 @@ bool ASTInterpreter::ViFilter(Cursor iter) { result.ModifyB().AddElement(element); } } - return VisitAndReturn(std::move(result)); + return SetCurrent(std::move(result)); } bool ASTInterpreter::ViReduce(Cursor iter) { @@ -617,7 +617,7 @@ bool ASTInterpreter::ViReduce(Cursor iter) { if (!childValue.has_value()) { return false; } - return VisitAndReturn(std::get(childValue.value()).B().Reduce()); + return SetCurrent(std::get(childValue.value()).B().Reduce()); } bool ASTInterpreter::ViDebool(Cursor iter) { @@ -630,7 +630,7 @@ bool ASTInterpreter::ViDebool(Cursor iter) { OnError(ValueEID::invalidDebool, iter->pos.start); return false; } - return VisitAndReturn(std::get(childValue.value()).B().Debool()); + return SetCurrent(std::get(childValue.value()).B().Debool()); } std::optional ASTInterpreter::EvaluateChild(Cursor iter, const Index index) { diff --git a/ccl/rslang/src/TypeAuditor.cpp b/ccl/rslang/src/TypeAuditor.cpp index aa279ae..02785b9 100644 --- a/ccl/rslang/src/TypeAuditor.cpp +++ b/ccl/rslang/src/TypeAuditor.cpp @@ -50,7 +50,7 @@ bool IsEchelon(SyntaxTree::Cursor iter, const Index index) { } bool IsRadical(const std::string& globalName) { - return !empty(globalName) && globalName.at(0) == 'R'; + return !empty(globalName) && globalName.at(0) == 'R' && globalName.at(1) != '0'; } void MangleRadicals(const std::string& funcName, Typification& type) { @@ -122,12 +122,11 @@ bool TypeEnv::AreCompatible(const Typification& type1, const Typification& type2 } const auto struct1 = type1.Structure(); - const auto struct2 = type2.Structure(); - - if (struct1 == rslang::StructureType::basic && type1.E().baseID == Typification::anyTypificationName) { + if (struct1 == rslang::StructureType::basic && type1.IsAnyType()) { return true; } - if (struct2 == rslang::StructureType::basic && type2.E().baseID == Typification::anyTypificationName) { + const auto struct2 = type2.Structure(); + if (struct2 == rslang::StructureType::basic && type2.IsAnyType()) { return true; } if (struct1 != struct2) { @@ -157,19 +156,18 @@ std::optional TypeEnv::Merge(const Typification& type1, const Typi if (type1 == type2) { return type1; } - if (type1.Structure() != type2.Structure()) { - return std::nullopt; - } const auto struct1 = type1.Structure(); - const auto struct2 = type2.Structure(); - - if (struct1 == rslang::StructureType::basic && type1.E().baseID == Typification::anyTypificationName) { + if (struct1 == rslang::StructureType::basic && type1.IsAnyType()) { return type2; } - if (struct2 == rslang::StructureType::basic && type2.E().baseID == Typification::anyTypificationName) { + const auto struct2 = type2.Structure(); + if (struct2 == rslang::StructureType::basic && type2.IsAnyType()) { return type1; } + if (struct1 != struct2) { + return std::nullopt; + } switch (struct1) { default: @@ -218,35 +216,41 @@ bool TypeEnv::CompareTemplated( if (!substitutes.contains(base)) { substitutes.insert({ base, value }); return true; + } else { + auto mergeType = Merge(substitutes.at(base), value); + if (!mergeType.has_value()) { + return false; + } + substitutes.at(base) = std::move(mergeType.value()); + return true; } + } - auto mergeType = Merge(substitutes.at(base), value); - if (!mergeType.has_value()) { - return false; - } - substitutes.at(base) = std::move(mergeType.value()); + const auto valueStructure = value.Structure(); + if (valueStructure == rslang::StructureType::basic && value.IsAnyType()) { return true; - } else if (arg.Structure() != value.Structure()) { + } + const auto argStructure = arg.Structure(); + if (argStructure != valueStructure) { return false; - } else { - switch (arg.Structure()) { - default: - case rslang::StructureType::basic: - return CommonType(arg, value) != nullptr; - case rslang::StructureType::collection: - return CompareTemplated(substitutes, arg.B().Base(), value.B().Base()); - case rslang::StructureType::tuple: { - if (arg.T().Arity() != value.T().Arity()) { + } + switch (argStructure) { + default: + case rslang::StructureType::basic: + return CommonType(arg, value) != nullptr; + case rslang::StructureType::collection: + return CompareTemplated(substitutes, arg.B().Base(), value.B().Base()); + case rslang::StructureType::tuple: { + if (arg.T().Arity() != value.T().Arity()) { + return false; + } + const auto maxIndex = Typification::PR_START + arg.T().Arity(); + for (auto index = Typification::PR_START; index < maxIndex; ++index) { + if (!CompareTemplated(substitutes, arg.T().Component(index), value.T().Component(index))) { return false; } - 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; - } - } - return true; } + return true; } } } @@ -313,18 +317,18 @@ bool TypeAuditor::ViGlobalDefinition(Cursor iter) { if (!type.IsCollection()) { return false; } - return VisitAndReturn(type.B().Base()); + return SetCurrent(type.B().Base()); } else { assert(iter->id == TokenID::PUNC_DEFINE); if (childrenCount == 1) { - return VisitAndReturn(Typification{ iter(0).data.ToText() }.ApplyBool()); + return SetCurrent(Typification{ iter(0).data.ToText() }.ApplyBool()); } const auto type = ChildType(iter, 1); if (!type.has_value()) { return false; } - return VisitAndReturn(type.value()); + return SetCurrent(type.value()); } } @@ -344,7 +348,7 @@ bool TypeAuditor::ViFunctionDefinition(Cursor iter) { if (!type.has_value()) { return false; } - return VisitAndReturn(type.value()); + return SetCurrent(type.value()); } bool TypeAuditor::ViFunctionCall(Cursor iter) { @@ -363,14 +367,14 @@ bool TypeAuditor::ViFunctionCall(Cursor iter) { return false; } if (!std::holds_alternative(*funcType)) { - return VisitAndReturn(*funcType); + return SetCurrent(*funcType); } else { Typification fixedType = std::get(*funcType); MangleRadicals(funcName, fixedType); if (!empty(substitutes.value())) { fixedType.SubstituteBase(substitutes.value()); } - return VisitAndReturn(fixedType); + return SetCurrent(fixedType); } } @@ -426,7 +430,7 @@ bool TypeAuditor::ViGlobal(Cursor iter) { ); return false; } - return VisitAndReturn(Typification(globalName).ApplyBool()); + return SetCurrent(Typification(globalName).ApplyBool()); } else { if (env.context.FunctionArgsFor(globalName) != nullptr) { OnError( @@ -445,25 +449,25 @@ bool TypeAuditor::ViGlobal(Cursor iter) { ); return false; } - return VisitAndReturn(*type); + return SetCurrent(*type); } } bool TypeAuditor::ViLocal(Cursor iter) { const auto& localName = iter->data.ToText(); if (isLocalDeclaration || isArgDeclaration) { - return AddLocalVar(localName, std::get(currentType), iter->pos.start); + return AddLocalVariable(localName, std::get(currentType), iter->pos.start); } else { const auto* local = GetLocalTypification(localName, iter->pos.start); if (local == nullptr) { return false; } - return VisitAndReturn(*local); + return SetCurrent(*local); } } bool TypeAuditor::ViEmptySet(Cursor /*iter*/) { - return VisitAndReturn(Typification::EmptySet()); + return SetCurrent(Typification::EmptySet()); } bool TypeAuditor::ViLocalBind(Cursor iter) { @@ -479,7 +483,7 @@ bool TypeAuditor::ViLocalBind(Cursor iter) { return false; } } - return VisitAndReturn(type); + return SetCurrent(type); } bool TypeAuditor::ViArgument(Cursor iter) { @@ -489,12 +493,12 @@ bool TypeAuditor::ViArgument(Cursor iter) { } const auto guard{ isArgDeclaration.CreateGuard() }; currentType = domain.value(); - return VisitChild(iter, 0) && VisitAndReturn(LogicT{}); + return VisitChild(iter, 0) && SetCurrent(LogicT{}); } bool TypeAuditor::ViCard(Cursor iter) { return ChildTypeDebool(iter, 0, SemanticEID::invalidCard).has_value() - && VisitAndReturn(Typification::Integer()); + && SetCurrent(Typification::Integer()); } bool TypeAuditor::ViArithmetic(Cursor iter) { @@ -538,7 +542,7 @@ bool TypeAuditor::ViArithmetic(Cursor iter) { ); return false; } - return VisitAndReturn(result.value()); + return SetCurrent(result.value()); } bool TypeAuditor::ViOrdering(Cursor iter) { @@ -581,7 +585,7 @@ bool TypeAuditor::ViOrdering(Cursor iter) { ); return false; } - return VisitAndReturn(LogicT{}); + return SetCurrent(LogicT{}); } bool TypeAuditor::ViQuantifier(Cursor iter) { @@ -597,7 +601,7 @@ bool TypeAuditor::ViQuantifier(Cursor iter) { } EndScope(iter->pos.start); - return VisitAndReturn(LogicT{}); + return SetCurrent(LogicT{}); } bool TypeAuditor::ViEquals(Cursor iter) { @@ -622,7 +626,7 @@ bool TypeAuditor::ViEquals(Cursor iter) { ); return false; } - return VisitAndReturn(LogicT{}); + return SetCurrent(LogicT{}); } bool TypeAuditor::ViTypedPredicate(Cursor iter) { @@ -656,7 +660,7 @@ bool TypeAuditor::ViTypedPredicate(Cursor iter) { } return false; } - return VisitAndReturn(LogicT{}); + return SetCurrent(LogicT{}); } bool TypeAuditor::ViDeclarative(Cursor iter) { @@ -672,7 +676,7 @@ bool TypeAuditor::ViDeclarative(Cursor iter) { } EndScope(iter->pos.start); - return VisitAndReturn(domain->ApplyBool()); + return SetCurrent(domain->ApplyBool()); } bool TypeAuditor::ViImperative(Cursor iter) { @@ -690,7 +694,7 @@ bool TypeAuditor::ViImperative(Cursor iter) { } EndScope(iter->pos.start); - return VisitAndReturn(std::get(type.value()).Bool()); + return SetCurrent(std::get(type.value()).Bool()); } bool TypeAuditor::ViImpDeclare(Cursor iter) { @@ -711,22 +715,19 @@ bool TypeAuditor::ViRecursion(Cursor iter) { auto initType = ChildType(iter, 1); if (!initType.has_value()) { return false; - } else if (!VisitChildDeclaration(iter, 0, std::get(initType.value()))) { + } + if (!VisitChildDeclaration(iter, 0, std::get(initType.value()))) { return false; } - Index iterationIndex{ 2 }; - if (iter->id == TokenID::NT_RECURSIVE_FULL) { - iterationIndex = 3; - if (!VisitChild(iter, 2)) { - return false; - } - } + const bool isFull = iter->id == TokenID::NT_RECURSIVE_FULL; + Index iterationIndex{ isFull ? 3 : 2 }; const auto iterationType = ChildType(iter, iterationIndex); if (!iterationType.has_value()) { return false; - } else if (!env.AreCompatible(iterationType.value(), initType.value())) { + } + if (!env.AreCompatible(iterationType.value(), initType.value())) { OnError( SemanticEID::typesNotEqual, iter(iterationIndex).pos.start, @@ -736,8 +737,25 @@ bool TypeAuditor::ViRecursion(Cursor iter) { return false; } + { + const auto guard = noWarnings.CreateGuard(); + ClearLocalVariables(); + if (!VisitChildDeclaration(iter, 0, std::get(iterationType.value()))) { + return false; + } + if (!VisitChild(iter, iterationIndex)) { + return false; + } + } + + if (isFull) { + if (!VisitChild(iter, 2)) { + return false; + } + } + EndScope(iter->pos.start); - return VisitAndReturn(iterationType.value()); + return SetCurrent(iterationType.value()); } bool TypeAuditor::ViDecart(Cursor iter) { @@ -750,7 +768,7 @@ bool TypeAuditor::ViDecart(Cursor iter) { factors.emplace_back(type.value()); } } - return VisitAndReturn(Typification::Tuple(factors).ApplyBool()); + return SetCurrent(Typification::Tuple(factors).ApplyBool()); } bool TypeAuditor::ViBoolean(Cursor iter) { @@ -758,7 +776,7 @@ bool TypeAuditor::ViBoolean(Cursor iter) { if (!type.has_value()) { return false; } - return VisitAndReturn(type->ApplyBool().ApplyBool()); + return SetCurrent(type->ApplyBool().ApplyBool()); } bool TypeAuditor::ViTuple(Cursor iter) { @@ -770,7 +788,7 @@ bool TypeAuditor::ViTuple(Cursor iter) { } components.emplace_back(std::get(type.value())); } - return VisitAndReturn(Typification::Tuple(components)); + return SetCurrent(Typification::Tuple(components)); } bool TypeAuditor::ViSetEnum(Cursor iter) { @@ -797,7 +815,7 @@ bool TypeAuditor::ViSetEnum(Cursor iter) { } type = std::move(merge.value()); } - return VisitAndReturn(type.Bool()); + return SetCurrent(type.Bool()); } bool TypeAuditor::ViDebool(Cursor iter) { @@ -805,7 +823,7 @@ bool TypeAuditor::ViDebool(Cursor iter) { if (!type.has_value()) { return false; } - return VisitAndReturn(type.value()); + return SetCurrent(type.value()); } bool TypeAuditor::ViTypedBinary(Cursor iter) { @@ -829,20 +847,24 @@ bool TypeAuditor::ViTypedBinary(Cursor iter) { ); return false; } - return VisitAndReturn(result.value().Bool()); + return SetCurrent(result.value().Bool()); } bool TypeAuditor::ViProjectSet(Cursor iter) { // T(Pri(a)) = B(Pi(D(T(a)))) - const auto baseType = ChildTypeDebool(iter, 0, SemanticEID::invalidProjectionSet); - if (!baseType.has_value()) { + const auto maybeArgument = ChildTypeDebool(iter, 0, SemanticEID::invalidProjectionSet); + if (!maybeArgument.has_value()) { return false; } - if (!baseType->IsTuple()) { + const auto& argument = maybeArgument.value(); + if (argument.IsAnyType()) { + return SetCurrent(Typification::EmptySet()); + } + if (!argument.IsTuple()) { OnError( SemanticEID::invalidProjectionSet, iter(0).pos.start, - { iter->ToString(), baseType->ToString() } + { iter->ToString(), argument.ToString() } ); return false; } @@ -851,30 +873,36 @@ bool TypeAuditor::ViProjectSet(Cursor iter) { std::vector components{}; components.reserve(size(indicies)); for (const auto index : indicies) { - if (!baseType->T().TestIndex(index)) { + if (!argument.T().TestIndex(index)) { OnError( SemanticEID::invalidProjectionSet, iter(0).pos.start, - { iter->ToString(), baseType->ToString() } + { iter->ToString(), argument.ToString() } ); return false; } else { - components.emplace_back(baseType->T().Component(index)); + components.emplace_back(argument.T().Component(index)); } } - currentType = Typification::Tuple(components).ApplyBool(); - return true; + return SetCurrent(Typification::Tuple(components).ApplyBool()); } bool TypeAuditor::ViProjectTuple(Cursor iter) { // T(pri(a)) = Pi(T(a)) - const auto baseType = ChildType(iter, 0); - if (!baseType.has_value()) { + const auto maybeArgument = ChildType(iter, 0); + if (!maybeArgument.has_value()) { return false; } - const auto& base = std::get(baseType.value()); - if (!base.IsTuple()) { - OnError(SemanticEID::invalidProjectionTuple, iter(0).pos.start, { iter->ToString(), base.ToString() }); + const auto& argument = std::get(maybeArgument.value()); + if (argument.IsAnyType()) { + return SetCurrent(argument); + } + if (!argument.IsTuple()) { + OnError( + SemanticEID::invalidProjectionTuple, + iter(0).pos.start, + { iter->ToString(), argument.ToString() } + ); return false; } @@ -882,39 +910,52 @@ bool TypeAuditor::ViProjectTuple(Cursor iter) { std::vector components{}; components.reserve(size(indicies)); for (const auto index : indicies) { - if (!base.T().TestIndex(index)) { - OnError(SemanticEID::invalidProjectionTuple, iter(0).pos.start, { iter->ToString(), base.ToString() }); + if (!argument.T().TestIndex(index)) { + OnError( + SemanticEID::invalidProjectionTuple, + iter(0).pos.start, + { iter->ToString(), argument.ToString() } + ); return false; } else { - components.emplace_back(base.T().Component(index)); + components.emplace_back(argument.T().Component(index)); } } - return VisitAndReturn(Typification::Tuple(components)); + return SetCurrent(Typification::Tuple(components)); } bool TypeAuditor::ViFilter(Cursor iter) { - const auto baseType = ChildType(iter, static_cast(iter.ChildrenCount() - 1)); - if (!baseType.has_value()) { - return false; - } - const auto& base = std::get(baseType.value()); - if (!base.IsCollection() || !base.B().Base().IsTuple()) { - OnError(SemanticEID::invalidFilterArgumentType, - iter(static_cast(iter.ChildrenCount() - 1)).pos.start, - { iter->ToString(), base.ToString() }); - return false; - } - const auto& indicies = iter->data.ToTuple(); if (ssize(indicies) + 1 != iter.ChildrenCount()) { OnError(SemanticEID::invalidFilterArity, iter->pos.start); return false; } + + const auto maybeArgument = ChildType(iter, static_cast(iter.ChildrenCount() - 1)); + if (!maybeArgument.has_value()) { + return false; + } + const auto& argument = std::get(maybeArgument.value()); + if (argument.IsAnyType() || (argument.IsCollection() && argument.B().Base().IsAnyType())) { + return SetCurrent(Typification::EmptySet()); + } + if (!argument.IsCollection() || !argument.B().Base().IsTuple()) { + OnError( + SemanticEID::invalidFilterArgumentType, + iter(static_cast(iter.ChildrenCount() - 1)).pos.start, + { iter->ToString(), argument.ToString() } + ); + return false; + } + Index child{ 0 }; for (const auto index : indicies) { - if (!base.B().Base().T().TestIndex(index)) { - OnError(SemanticEID::invalidFilterArgumentType, iter(static_cast(iter.ChildrenCount() - 1)).pos.start, - { iter->ToString(), base.ToString() }); + if (!argument.B().Base().T().TestIndex(index)) { + OnError( + SemanticEID::invalidFilterArgumentType, + iter(static_cast(iter.ChildrenCount() - 1)).pos.start, + { iter->ToString(), argument.ToString() } + ); return false; } const auto param = ChildType(iter, child); @@ -923,50 +964,56 @@ bool TypeAuditor::ViFilter(Cursor iter) { } const auto& paramType = std::get(param.value()); if (!paramType.IsCollection() || - !env.AreCompatible(base.B().Base().T().Component(index), paramType.B().Base())) { - OnError(SemanticEID::typesNotEqual, iter(child).pos.start, - base.B().Base().T().Component(index).Bool(), paramType); + !env.AreCompatible(argument.B().Base().T().Component(index), paramType.B().Base())) { + OnError( + SemanticEID::typesNotEqual, + iter(child).pos.start, + argument.B().Base().T().Component(index).Bool(), paramType + ); return false; } ++child; } - return VisitAndReturn(baseType.value()); + return SetCurrent(maybeArgument.value()); } bool TypeAuditor::ViReduce(Cursor iter) { // T(red(a)) = B(DD(T(a))) - const auto baseType = ChildType(iter, 0); - if (!baseType.has_value()) { + const auto maybeArgument = ChildType(iter, 0); + if (!maybeArgument.has_value()) { return false; } - const auto& base = std::get(baseType.value()); - if (!base.IsCollection() || !base.B().Base().IsCollection()) { + const auto& argument = std::get(maybeArgument.value()); + if (argument.IsAnyType() || (argument.IsCollection() && argument.B().Base().IsAnyType())) { + return SetCurrent(Typification::EmptySet()); + } + if (!argument.IsCollection() || !argument.B().Base().IsCollection()) { OnError( SemanticEID::invalidReduce, iter(0).pos.start + 1, - base.ToString() + argument.ToString() ); return false; } - return VisitAndReturn(base.B().Base()); + return SetCurrent(argument.B().Base()); } -bool TypeAuditor::VisitAndReturn(ExpressionType type) noexcept { +bool TypeAuditor::SetCurrent(ExpressionType type) noexcept { currentType = std::move(type); return true; } -bool TypeAuditor::VisitAllAndReturn(Cursor iter, const ExpressionType& type) { - return VisitAllChildren(iter) && VisitAndReturn(type); +bool TypeAuditor::VisitAllAndSetCurrent(Cursor iter, const ExpressionType& type) { + return VisitAllChildren(iter) && SetCurrent(type); } bool TypeAuditor::VisitChildDeclaration(const Cursor& iter, const Index index, const Typification& domain) { currentType = domain; - if (const auto guard = isLocalDeclaration.CreateGuard(); - !VisitChild(iter, index)) { + const auto guard = isLocalDeclaration.CreateGuard(); + if (!VisitChild(iter, index)) { return false; } - return VisitAndReturn(LogicT{}); + return SetCurrent(LogicT{}); } std::optional TypeAuditor::ChildType(Cursor iter, const Index index) { @@ -984,19 +1031,23 @@ std::optional TypeAuditor::ChildType(Cursor iter, const Index in } std::optional TypeAuditor::ChildTypeDebool(Cursor iter, const Index index, const SemanticEID eid) { - const auto result = ChildType(iter, index); - if (!result.has_value() || !std::holds_alternative(result.value())) { + const auto maybeResult = ChildType(iter, index); + if (!maybeResult.has_value() || !std::holds_alternative(maybeResult.value())) { return std::nullopt; } - if (!std::get(result.value()).IsCollection()) { + const auto& result = std::get(maybeResult.value()); + if (result.IsAnyType()) { + return result; + } + if (!result.IsCollection()) { OnError( eid, iter(index).pos.start, - ToString(result.value()) + ToString(maybeResult.value()) ); return std::nullopt; } - return std::get(result.value()).B().Base(); + return result.B().Base(); } const Typification* TypeAuditor::GetLocalTypification(const std::string& name, const StrPos pos) { @@ -1030,7 +1081,7 @@ void TypeAuditor::EndScope(const StrPos pos) { --var.level; if (var.level < 0 && var.enabled) { var.enabled = false; - if (var.useCount == 0) { + if (var.useCount == 0 && !noWarnings) { OnError( SemanticEID::localNotUsed, pos, @@ -1041,9 +1092,12 @@ void TypeAuditor::EndScope(const StrPos pos) { } } -bool TypeAuditor::AddLocalVar(const std::string& name, const Typification& type, const StrPos pos) { - auto varIter = std::find_if(begin(localVars), end(localVars), - [&](const auto& data) noexcept { return data.arg.name == name; }); +bool TypeAuditor::AddLocalVariable(const std::string& name, const Typification& type, const StrPos pos) { + auto varIter = std::find_if( + begin(localVars), + end(localVars), + [&](const auto& data) noexcept { return data.arg.name == name; } + ); if (varIter != end(localVars)) { if (varIter->enabled) { OnError( @@ -1053,16 +1107,17 @@ bool TypeAuditor::AddLocalVar(const std::string& name, const Typification& type, ); return false; } else { - OnError( - SemanticEID::localDoubleDeclare, - pos, - name - ); + if (!noWarnings) { + OnError( + SemanticEID::localDoubleDeclare, + pos, + name + ); + } varIter->arg.type = type; varIter->enabled = true; varIter->level = 0; - varIter->useCount = 0; - return true; + return true; } } else { localVars.emplace_back(LocalData{ TypedID{name, type}, 0, 0, true }); @@ -1073,4 +1128,9 @@ bool TypeAuditor::AddLocalVar(const std::string& name, const Typification& type, } } + +void TypeAuditor::ClearLocalVariables() { + std::erase_if(localVars, [&](const auto& data) noexcept { return data.level <= 0; }); +} + } // namespace ccl::rslang \ No newline at end of file diff --git a/ccl/rslang/src/Typification.cpp b/ccl/rslang/src/Typification.cpp index bb3c709..016ceb4 100644 --- a/ccl/rslang/src/Typification.cpp +++ b/ccl/rslang/src/Typification.cpp @@ -7,6 +7,10 @@ namespace ccl::rslang { +bool Typification::IsAnyType() const noexcept { + return IsElement() && E().baseID == anyTypificationName; +} + Typification& Typification::ApplyBool() { state = EchelonBool(*this); return *this; diff --git a/ccl/rslang/src/ValueAuditor.cpp b/ccl/rslang/src/ValueAuditor.cpp index 5c196b2..21aff70 100644 --- a/ccl/rslang/src/ValueAuditor.cpp +++ b/ccl/rslang/src/ValueAuditor.cpp @@ -37,13 +37,13 @@ void ValueAuditor::Clear() noexcept { current = ValueClass::invalid; } -bool ValueAuditor::VisitAndReturn(const ValueClass type) noexcept { +bool ValueAuditor::SetCurrent(const ValueClass type) noexcept { current = type; return true; } -bool ValueAuditor::VisitAllAndReturn(Cursor iter, const ValueClass type) { - return VisitAllChildren(iter) && VisitAndReturn(type); +bool ValueAuditor::VisitAllAndSetCurrent(Cursor iter, const ValueClass type) { + return VisitAllChildren(iter) && SetCurrent(type); } bool ValueAuditor::AssertChildIsValue(Cursor iter, const Index index) { @@ -68,9 +68,9 @@ bool ValueAuditor::AssertAllValues(Cursor iter) { bool ValueAuditor::ViGlobalDefinition(Cursor iter) { if (iter->id == TokenID::PUNC_STRUCT) { - return VisitChild(iter, 1) && VisitAndReturn(ValueClass::value); + return VisitChild(iter, 1) && SetCurrent(ValueClass::value); } else if (iter.ChildrenCount() == 1) { - return VisitAndReturn(ValueClass::value); + return SetCurrent(ValueClass::value); } else { return VisitChild(iter, 1); } @@ -133,7 +133,7 @@ bool ValueAuditor::RunCheckOnFunc( bool ValueAuditor::ViGlobal(Cursor iter) { const auto& globalName = iter->data.ToText(); if (iter->id == TokenID::ID_RADICAL) { - return VisitAndReturn(ValueClass::value); + return SetCurrent(ValueClass::value); } else { const auto type = globalClass(globalName); if (type == ValueClass::invalid) { @@ -148,9 +148,9 @@ bool ValueAuditor::ViGlobal(Cursor iter) { bool ValueAuditor::ViLocal(Cursor iter) { const auto& localName = iter->data.ToText(); if (std::find(begin(localProps), end(localProps), localName) == end(localProps)) { - return VisitAndReturn(ValueClass::value); + return SetCurrent(ValueClass::value); } else { - return VisitAndReturn(ValueClass::props); + return SetCurrent(ValueClass::props); } } @@ -195,11 +195,11 @@ bool ValueAuditor::ViDecart(Cursor iter) { type = current; } } - return VisitAndReturn(type); + return SetCurrent(type); } bool ValueAuditor::ViBoolean(Cursor iter) { - return VisitChild(iter, 0) && VisitAndReturn(ValueClass::props); + return VisitChild(iter, 0) && SetCurrent(ValueClass::props); } bool ValueAuditor::ViTypedBinary(Cursor iter) { @@ -214,9 +214,9 @@ bool ValueAuditor::ViTypedBinary(Cursor iter) { const auto secondValue = current == ValueClass::value; if (CombineOperationValues(iter->id, firstValue, secondValue)) { - return VisitAndReturn(ValueClass::value); + return SetCurrent(ValueClass::value); } else { - return VisitAndReturn(ValueClass::props); + return SetCurrent(ValueClass::props); } } diff --git a/ccl/rslang/test/src/testTypeAuditor.cpp b/ccl/rslang/test/src/testTypeAuditor.cpp index 30896a9..8a037aa 100644 --- a/ccl/rslang/test/src/testTypeAuditor.cpp +++ b/ccl/rslang/test/src/testTypeAuditor.cpp @@ -227,6 +227,9 @@ TEST_F(UTTypeAuditor, ConstructorsCorrect) { SetupConstants(); ExpectTypification(R"({X1, X1})", "BB(X1)"_t); + ExpectTypification(R"({{}, X1})", "BB(X1)"_t); + ExpectTypification(R"({X1, {}})", "BB(X1)"_t); + ExpectTypification(R"({{}})", "BB(R0)"_t); ExpectTypification(R"({1})", "B(Z)"_t); ExpectTypification(R"({1, card(X1)})", "B(Z)"_t); ExpectTypification(R"({S4, 1})", "B(C1)"_t); @@ -245,6 +248,9 @@ TEST_F(UTTypeAuditor, ConstructorsCorrect) { ExpectTypification(R"(R{a \assign 1 | a \ls 10 | a \plus 1})", "Z"_t); ExpectTypification(R"(R{a \assign 1 | a \ls S4 | a \plus S4})", "C1"_t); ExpectTypification(R"(R{a \assign {} | a \union {S4}})", "B(C1)"_t); + ExpectTypification(R"(R{a \assign {} | Pr1(a) \eq Pr2(a) | a \union (X1*X1)})", "B(X1*X1)"_t); + ExpectTypification(R"(R{a \assign {} | a \union D{x \in X1 | x \eq x}})", "B(X1)"_t); + ExpectTypification(R"(R{a \assign {} | red(a) \eq {} | a \union {X1}})", "BB(X1)"_t); ExpectTypification(R"(I{(a, b) | a \from X1; b \assign a})", "B(X1*X1)"_t); ExpectTypification(R"(I{(a, b) | a \from X1; b \assign a; 1 \eq 1})", "B(X1*X1)"_t); @@ -264,6 +270,8 @@ TEST_F(UTTypeAuditor, ConstructorsErrors) { ExpectError(R"(R{a \assign S1 | {a}})", SemanticEID::typesNotEqual, 17); ExpectError(R"(R{a \assign {} | a \union S4})", SemanticEID::invalidTypeOperation, 26); + ExpectError(R"(R{a \assign {} | Pr1(a) \eq Pr2(a) | a \union X1})", SemanticEID::invalidProjectionSet, 21); + ExpectError(R"(R{a \assign {} | red(a) \eq {} | a \union (X1*X1)})", SemanticEID::invalidReduce, 22); ExpectError(R"(\A a \in S1 R{(a1, a2) \assign a | a1} \eq a)", SemanticEID::typesNotEqual, 35); ExpectError(R"(I{(a, b) | a \from X1; b \assign {a}; a \noteq b})", SemanticEID::typesNotCompatible, 47); @@ -327,10 +335,12 @@ TEST_F(UTTypeAuditor, TypedOperationsCorrect) { ExpectTypification(R"(B(X1))", "BB(X1)"_t); ExpectTypification(R"(X1*X1)", "B(X1*X1)"_t); ExpectTypification(R"(Pr1(S1))", "B(X1)"_t); + ExpectTypification(R"(Pr1({}))", "B(R0)"_t); ExpectTypification(R"(Fi1[X1](S1))", "B(X1*X1)"_t); ExpectTypification(R"(Fi1[{1,2,3}](Z*X1))", "B(Z*X1)"_t); ExpectTypification(R"(Fi1[{1,2,3}](C1*X1))", "B(C1*X1)"_t); ExpectTypification(R"(Pr1,2(S1))", "B(X1*X1)"_t); + ExpectTypification(R"(Pr1,2({}))", "B(R0)"_t); ExpectTypification(R"(bool(X1))", "BB(X1)"_t); ExpectTypification(R"(debool({X1}))", "B(X1)"_t); ExpectTypification(R"(red(S2))", "B(X1)"_t); @@ -365,6 +375,8 @@ TEST_F(UTTypeAuditor, TypedOperationsErrors) { TEST_F(UTTypeAuditor, TypedFunctions) { ExpectTypification(R"(F1[X1, X1])", "B(X1)"_t); + ExpectTypification(R"(F1[{}, X1])", "B(X1)"_t); + ExpectTypification(R"(F1[X1, {}])", "B(X1)"_t); ExpectTypification(R"(F1[X1 \union X1, X1])", "B(X1)"_t); ExpectTypification(R"(F1[Pr1(S1), Pr2(S1)])", "B(X1)"_t); @@ -410,6 +422,9 @@ TEST_F(UTTypeAuditor, TemplatedFunctions) { env.data["F2"].arguments = f2Args; ExpectTypification(R"(F2[B(X1), X1])", "BB(X1)"_t); + ExpectTypification(R"(F2[{}, X1])", "BB(X1)"_t); + ExpectTypification(R"(F2[B(X1), {}])", "BB(X1)"_t); + ExpectTypification(R"(F2[{}, {}])", "BB(R0)"_t); ExpectTypification(R"(F2[Z, 1])", "B(Z)"_t); ExpectTypification(R"(F2[Z, S4])", "B(C1)"_t); ExpectTypification(R"(F2[{S4}, 1])", "B(C1)"_t); diff --git a/ccl/rslang/test/src/testTypification.cpp b/ccl/rslang/test/src/testTypification.cpp index 3ec1273..9149cf7 100644 --- a/ccl/rslang/test/src/testTypification.cpp +++ b/ccl/rslang/test/src/testTypification.cpp @@ -30,6 +30,24 @@ TEST_F(UTTypification, Basic) { EXPECT_TRUE(newBasic.IsElement()); EXPECT_FALSE(newBasic.IsCollection()); EXPECT_FALSE(newBasic.IsTuple()); + EXPECT_FALSE(newBasic.IsAnyType()); +} + +TEST_F(UTTypification, EmptySet) { + auto empty = Typification::EmptySet(); + EXPECT_EQ(empty, Typification::EmptySet()); + EXPECT_FALSE(empty.IsElement()); + EXPECT_FALSE(empty.IsTuple()); + EXPECT_TRUE(empty.IsCollection()); + EXPECT_FALSE(empty.IsAnyType()); + EXPECT_EQ(empty.Structure(), StructureType::collection); + + const auto& base = empty.B().Base(); + EXPECT_TRUE(base.IsElement()); + EXPECT_FALSE(base.IsCollection()); + EXPECT_FALSE(base.IsCollection()); + EXPECT_TRUE(base.IsAnyType()); + EXPECT_EQ(base.Structure(), StructureType::basic); } TEST_F(UTTypification, Tuple) { @@ -37,6 +55,7 @@ TEST_F(UTTypification, Tuple) { EXPECT_FALSE(tuple.IsElement()); EXPECT_FALSE(tuple.IsCollection()); EXPECT_TRUE(tuple.IsTuple()); + EXPECT_FALSE(tuple.IsAnyType()); EXPECT_EQ(tuple.T().Arity(), 2); tuple = Typification::Tuple({ basic }); @@ -74,6 +93,7 @@ TEST_F(UTTypification, Bool) { EXPECT_FALSE(sBool.IsElement()); EXPECT_TRUE(sBool.IsCollection()); EXPECT_FALSE(sBool.IsTuple()); + EXPECT_FALSE(sBool.IsAnyType()); } TEST_F(UTTypification, ElementTypification) {