Fix EmptySet type check errors

This commit is contained in:
IRBorisov 2024-05-09 17:21:57 +03:00
parent de8e6df46b
commit 4786ba851b
10 changed files with 318 additions and 214 deletions

View File

@ -106,8 +106,8 @@ private:
void OnError(ValueEID eid, StrPos position); void OnError(ValueEID eid, StrPos position);
void OnError(ValueEID eid, StrPos position, std::string param); void OnError(ValueEID eid, StrPos position, std::string param);
[[nodiscard]] bool VisitAndReturn(ExpressionValue&& value) noexcept; [[nodiscard]] bool SetCurrent(ExpressionValue&& value) noexcept;
[[nodiscard]] bool VisitAndReturn(const ExpressionValue& value) noexcept; [[nodiscard]] bool SetCurrent(const ExpressionValue& value) noexcept;
[[nodiscard]] std::optional<ExpressionValue> EvaluateChild(Cursor iter, Index index); [[nodiscard]] std::optional<ExpressionValue> EvaluateChild(Cursor iter, Index index);
[[nodiscard]] std::optional<object::StructuredData> ExtractDomain(Cursor iter); [[nodiscard]] std::optional<object::StructuredData> ExtractDomain(Cursor iter);

View File

@ -58,6 +58,7 @@ class TypeAuditor final : public ASTVisitor<TypeAuditor> {
types::GuardableBool isArgDeclaration{ false }; types::GuardableBool isArgDeclaration{ false };
types::GuardableBool isLocalDeclaration{ false }; types::GuardableBool isLocalDeclaration{ false };
types::GuardableBool isFuncDeclaration{ false }; types::GuardableBool isFuncDeclaration{ false };
types::GuardableBool noWarnings{ false };
public: public:
explicit TypeAuditor(const TypeContext& context) noexcept explicit TypeAuditor(const TypeContext& context) noexcept
@ -79,21 +80,21 @@ protected:
bool ViGlobal(Cursor iter); bool ViGlobal(Cursor iter);
bool ViLocal(Cursor iter); bool ViLocal(Cursor iter);
bool ViInteger(Cursor /*iter*/) { return VisitAndReturn(Typification::Integer()); } bool ViInteger(Cursor /*iter*/) { return SetCurrent(Typification::Integer()); }
bool ViIntegerSet(Cursor /*iter*/) { return VisitAndReturn(Typification::Integer().Bool()); } bool ViIntegerSet(Cursor /*iter*/) { return SetCurrent(Typification::Integer().Bool()); }
bool ViEmptySet(Cursor /*iter*/); bool ViEmptySet(Cursor /*iter*/);
bool ViLocalBind(Cursor iter); bool ViLocalBind(Cursor iter);
bool ViLocalEnum(Cursor iter) { return VisitAllAndReturn(iter, LogicT{}); } bool ViLocalEnum(Cursor iter) { return VisitAllAndSetCurrent(iter, LogicT{}); }
bool ViArgumentsEnum(Cursor iter) { return VisitAllAndReturn(iter, LogicT{}); } bool ViArgumentsEnum(Cursor iter) { return VisitAllAndSetCurrent(iter, LogicT{}); }
bool ViArgument(Cursor iter); bool ViArgument(Cursor iter);
bool ViArithmetic(Cursor iter); bool ViArithmetic(Cursor iter);
bool ViCard(Cursor iter); bool ViCard(Cursor iter);
bool ViQuantifier(Cursor iter); bool ViQuantifier(Cursor iter);
bool ViNegation(Cursor iter) { return VisitAllAndReturn(iter, LogicT{}); } bool ViNegation(Cursor iter) { return VisitAllAndSetCurrent(iter, LogicT{}); }
bool ViLogicBinary(Cursor iter) { return VisitAllAndReturn(iter, LogicT{}); } bool ViLogicBinary(Cursor iter) { return VisitAllAndSetCurrent(iter, LogicT{}); }
bool ViEquals(Cursor iter); bool ViEquals(Cursor iter);
bool ViOrdering(Cursor iter); bool ViOrdering(Cursor iter);
bool ViTypedPredicate(Cursor iter); bool ViTypedPredicate(Cursor iter);
@ -105,7 +106,7 @@ protected:
bool ViImperative(Cursor iter); bool ViImperative(Cursor iter);
bool ViImpDeclare(Cursor iter); bool ViImpDeclare(Cursor iter);
bool ViImpAssign(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 ViRecursion(Cursor iter);
bool ViTuple(Cursor iter); bool ViTuple(Cursor iter);
@ -124,8 +125,8 @@ private:
[[nodiscard]] bool VisitChildDeclaration(const Cursor& iter, Index index, const Typification& domain); [[nodiscard]] bool VisitChildDeclaration(const Cursor& iter, Index index, const Typification& domain);
[[nodiscard]] bool VisitAndReturn(ExpressionType type) noexcept; [[nodiscard]] bool SetCurrent(ExpressionType type) noexcept;
[[nodiscard]] bool VisitAllAndReturn(Cursor iter, const ExpressionType& type); [[nodiscard]] bool VisitAllAndSetCurrent(Cursor iter, const ExpressionType& type);
[[nodiscard]] std::optional<ExpressionType> ChildType(Cursor iter, Index index); [[nodiscard]] std::optional<ExpressionType> ChildType(Cursor iter, Index index);
[[nodiscard]] std::optional<Typification> ChildTypeDebool(Cursor iter, Index index, SemanticEID eid); [[nodiscard]] std::optional<Typification> ChildTypeDebool(Cursor iter, Index index, SemanticEID eid);
@ -139,7 +140,9 @@ private:
CheckFuncArguments(Cursor iter, const std::string& funcName); CheckFuncArguments(Cursor iter, const std::string& funcName);
[[nodiscard]] const Typification* GetLocalTypification(const std::string& name, StrPos pos); [[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 StartScope() noexcept;
void EndScope(StrPos pos); void EndScope(StrPos pos);
}; };

View File

@ -93,6 +93,8 @@ public:
public: public:
using Substitutes = std::unordered_map<std::string, Typification>; using Substitutes = std::unordered_map<std::string, Typification>;
[[nodiscard]] bool IsAnyType() const noexcept;
Typification& ApplyBool(); Typification& ApplyBool();
[[nodiscard]] Typification Bool() const; [[nodiscard]] Typification Bool() const;

View File

@ -40,23 +40,23 @@ protected:
bool ViGlobal(Cursor iter); bool ViGlobal(Cursor iter);
bool ViLocal(Cursor iter); bool ViLocal(Cursor iter);
bool ViInteger(Cursor /*iter*/) noexcept { return VisitAndReturn(ValueClass::value); } bool ViInteger(Cursor /*iter*/) noexcept { return SetCurrent(ValueClass::value); }
bool ViIntegerSet(Cursor /*iter*/) noexcept { return VisitAndReturn(ValueClass::props); } bool ViIntegerSet(Cursor /*iter*/) noexcept { return SetCurrent(ValueClass::props); }
bool ViEmptySet(Cursor /*iter*/) noexcept { return VisitAndReturn(ValueClass::value); } bool ViEmptySet(Cursor /*iter*/) noexcept { return SetCurrent(ValueClass::value); }
bool ViLocalBind(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } bool ViLocalBind(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); }
bool ViLocalEnum(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } bool ViLocalEnum(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); }
bool ViArgumentsEnum(Cursor iter) { return VisitAllChildren(iter); } bool ViArgumentsEnum(Cursor iter) { return VisitAllChildren(iter); }
bool ViArgument(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 ViCard(Cursor iter) { return AssertChildIsValue(iter, 0); }
bool ViQuantifier(Cursor iter); bool ViQuantifier(Cursor iter);
bool ViNegation(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } bool ViNegation(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); }
bool ViLogicBinary(Cursor iter) { return VisitAllAndReturn(iter, ValueClass::value); } bool ViLogicBinary(Cursor iter) { return VisitAllAndSetCurrent(iter, ValueClass::value); }
bool ViEquals(Cursor iter) { return AssertAllValues(iter); } 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 ViTypedPredicate(Cursor iter);
bool ViDecart(Cursor iter); bool ViDecart(Cursor iter);
@ -66,7 +66,7 @@ protected:
bool ViImperative(Cursor iter); bool ViImperative(Cursor iter);
bool ViImpDeclare(Cursor iter) { return AssertChildIsValue(iter, 1); } bool ViImpDeclare(Cursor iter) { return AssertChildIsValue(iter, 1); }
bool ViImpAssign(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 ViRecursion(Cursor iter) { return AssertAllValues(iter); }
bool ViTuple(Cursor iter) { return AssertAllValues(iter); } bool ViTuple(Cursor iter) { return AssertAllValues(iter); }
@ -82,8 +82,8 @@ protected:
private: private:
void Clear() noexcept; void Clear() noexcept;
[[nodiscard]] bool VisitAndReturn(ValueClass type) noexcept; [[nodiscard]] bool SetCurrent(ValueClass type) noexcept;
[[nodiscard]] bool VisitAllAndReturn(Cursor iter, ValueClass type); [[nodiscard]] bool VisitAllAndSetCurrent(Cursor iter, ValueClass type);
[[nodiscard]] bool AssertAllValues(Cursor iter); [[nodiscard]] bool AssertAllValues(Cursor iter);
[[nodiscard]] bool AssertChildIsValue(Cursor iter, Index index); [[nodiscard]] bool AssertChildIsValue(Cursor iter, Index index);

View File

@ -215,12 +215,12 @@ void ASTInterpreter::Clear() noexcept {
countCriticalErrors = 0; countCriticalErrors = 0;
} }
bool ASTInterpreter::VisitAndReturn(ExpressionValue&& value) noexcept { bool ASTInterpreter::SetCurrent(ExpressionValue&& value) noexcept {
curValue = std::move(value); curValue = std::move(value);
return true; return true;
} }
bool ASTInterpreter::VisitAndReturn(const ExpressionValue& value) noexcept { bool ASTInterpreter::SetCurrent(const ExpressionValue& value) noexcept {
curValue = value; curValue = value;
return true; return true;
} }
@ -230,11 +230,11 @@ bool ASTInterpreter::ViGlobalDefinition(Cursor iter) {
} }
bool ASTInterpreter::ViLocal(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) { bool ASTInterpreter::ViInteger(Cursor iter) {
return VisitAndReturn(Factory::Val(iter->data.ToInt())); return SetCurrent(Factory::Val(iter->data.ToInt()));
} }
bool ASTInterpreter::ViIntegerSet(Cursor iter) { bool ASTInterpreter::ViIntegerSet(Cursor iter) {
@ -243,7 +243,7 @@ bool ASTInterpreter::ViIntegerSet(Cursor iter) {
} }
bool ASTInterpreter::ViEmptySet(Cursor /*iter*/) { bool ASTInterpreter::ViEmptySet(Cursor /*iter*/) {
return VisitAndReturn(Factory::EmptySet()); return SetCurrent(Factory::EmptySet());
} }
bool ASTInterpreter::ViArithmetic(Cursor iter) { bool ASTInterpreter::ViArithmetic(Cursor iter) {
@ -260,11 +260,11 @@ bool ASTInterpreter::ViArithmetic(Cursor iter) {
switch (iter->id) { switch (iter->id) {
default: default:
case TokenID::PLUS: case TokenID::PLUS:
return VisitAndReturn(Factory::Val(op1 + op2)); return SetCurrent(Factory::Val(op1 + op2));
case TokenID::MINUS: case TokenID::MINUS:
return VisitAndReturn(Factory::Val(op1 - op2)); return SetCurrent(Factory::Val(op1 - op2));
case TokenID::MULTIPLY: 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)); OnError(ValueEID::typedOverflow, iter->pos.start, std::to_string(StructuredData::SET_INFINITY));
return false; return false;
} }
return VisitAndReturn(Factory::Val(size)); return SetCurrent(Factory::Val(size));
} }
bool ASTInterpreter::ViQuantifier(Cursor iter) { bool ASTInterpreter::ViQuantifier(Cursor iter) {
@ -298,10 +298,10 @@ bool ASTInterpreter::ViQuantifier(Cursor iter) {
if (const auto iterationValue = EvaluateChild(iter, 2); !iterationValue.has_value()) { if (const auto iterationValue = EvaluateChild(iter, 2); !iterationValue.has_value()) {
return false; return false;
} else if (std::get<bool>(iterationValue.value()) != isUniversal) { } else if (std::get<bool>(iterationValue.value()) != isUniversal) {
return VisitAndReturn(!isUniversal); return SetCurrent(!isUniversal);
} }
} }
return VisitAndReturn(isUniversal); return SetCurrent(isUniversal);
} }
std::optional<StructuredData> ASTInterpreter::ExtractDomain(Cursor iter) { std::optional<StructuredData> ASTInterpreter::ExtractDomain(Cursor iter) {
@ -316,7 +316,7 @@ bool ASTInterpreter::ViNegation(Cursor iter) {
if (!childValue.has_value()) { if (!childValue.has_value()) {
return false; return false;
} }
return VisitAndReturn(!std::get<bool>(childValue.value())); return SetCurrent(!std::get<bool>(childValue.value()));
} }
bool ASTInterpreter::ViLogicBinary(Cursor iter) { bool ASTInterpreter::ViLogicBinary(Cursor iter) {
@ -347,9 +347,9 @@ bool ASTInterpreter::ViLogicBinary(Cursor iter) {
bool ASTInterpreter::TryEvaluateFromFirstArg(TokenID operation, bool firstArgValue) noexcept { bool ASTInterpreter::TryEvaluateFromFirstArg(TokenID operation, bool firstArgValue) noexcept {
if ((operation == TokenID::AND && !firstArgValue) || if ((operation == TokenID::AND && !firstArgValue) ||
(operation == TokenID::OR && firstArgValue)) { (operation == TokenID::OR && firstArgValue)) {
return VisitAndReturn(firstArgValue); return SetCurrent(firstArgValue);
} else if (operation == TokenID::IMPLICATION && !firstArgValue) { } else if (operation == TokenID::IMPLICATION && !firstArgValue) {
return VisitAndReturn(!firstArgValue); return SetCurrent(!firstArgValue);
} else { } else {
return false; return false;
} }
@ -364,7 +364,7 @@ bool ASTInterpreter::ViEquals(Cursor iter) {
if (!val2.has_value()) { if (!val2.has_value()) {
return false; return false;
} }
return VisitAndReturn((val1 == val2) != (iter->id == TokenID::NOTEQUAL)); return SetCurrent((val1 == val2) != (iter->id == TokenID::NOTEQUAL));
} }
bool ASTInterpreter::ViOrdering(Cursor iter) { bool ASTInterpreter::ViOrdering(Cursor iter) {
@ -380,10 +380,10 @@ bool ASTInterpreter::ViOrdering(Cursor iter) {
const auto op2 = std::get<StructuredData>(val2.value()).E().Value(); const auto op2 = std::get<StructuredData>(val2.value()).E().Value();
switch (iter->id) { switch (iter->id) {
default: default:
case TokenID::GREATER: return VisitAndReturn(op1 > op2); case TokenID::GREATER: return SetCurrent(op1 > op2);
case TokenID::LESSER: return VisitAndReturn(op1 < op2); case TokenID::LESSER: return SetCurrent(op1 < op2);
case TokenID::GREATER_OR_EQ: return VisitAndReturn(op1 >= op2); case TokenID::GREATER_OR_EQ: return SetCurrent(op1 >= op2);
case TokenID::LESSER_OR_EQ: return VisitAndReturn(op1 <= op2); case TokenID::LESSER_OR_EQ: return SetCurrent(op1 <= op2);
} }
} }
@ -408,7 +408,7 @@ bool ASTInterpreter::ViDeclarative(Cursor iter) {
result.ModifyB().AddElement(child); result.ModifyB().AddElement(child);
} }
} }
return VisitAndReturn(std::move(result)); return SetCurrent(std::move(result));
} }
bool ASTInterpreter::ViImperative(const Cursor iter) { bool ASTInterpreter::ViImperative(const Cursor iter) {
@ -416,7 +416,7 @@ bool ASTInterpreter::ViImperative(const Cursor iter) {
if (!eval.Evaluate()) { if (!eval.Evaluate()) {
return false; return false;
} }
return VisitAndReturn(eval.value); return SetCurrent(eval.value);
} }
bool ASTInterpreter::ViRecursion(Cursor iter) { bool ASTInterpreter::ViRecursion(Cursor iter) {
@ -448,7 +448,7 @@ bool ASTInterpreter::ViRecursion(Cursor iter) {
} }
current = std::get<StructuredData>(curValue); current = std::get<StructuredData>(curValue);
} while (idsData[varID] != current); } while (idsData[varID] != current);
return VisitAndReturn(std::move(current)); return SetCurrent(std::move(current));
} }
bool ASTInterpreter::ViDecart(Cursor iter) { bool ASTInterpreter::ViDecart(Cursor iter) {
@ -486,7 +486,7 @@ bool ASTInterpreter::ViBoolean(Cursor iter) {
); );
return false; return false;
} }
return VisitAndReturn(Factory::Boolean(value)); return SetCurrent(Factory::Boolean(value));
} }
bool ASTInterpreter::ViTuple(Cursor iter) { bool ASTInterpreter::ViTuple(Cursor iter) {
@ -498,7 +498,7 @@ bool ASTInterpreter::ViTuple(Cursor iter) {
} }
args.emplace_back(std::get<StructuredData>(childValue.value())); args.emplace_back(std::get<StructuredData>(childValue.value()));
} }
return VisitAndReturn(Factory::Tuple(args)); return SetCurrent(Factory::Tuple(args));
} }
bool ASTInterpreter::ViSetEnum(Cursor iter) { bool ASTInterpreter::ViSetEnum(Cursor iter) {
@ -510,7 +510,7 @@ bool ASTInterpreter::ViSetEnum(Cursor iter) {
} }
args.emplace_back(std::get<StructuredData>(childValue.value())); args.emplace_back(std::get<StructuredData>(childValue.value()));
} }
return VisitAndReturn(Factory::Set(args)); return SetCurrent(Factory::Set(args));
} }
bool ASTInterpreter::ViBool(Cursor iter) { bool ASTInterpreter::ViBool(Cursor iter) {
@ -518,7 +518,7 @@ bool ASTInterpreter::ViBool(Cursor iter) {
if (!childValue.has_value()) { if (!childValue.has_value()) {
return false; return false;
} }
return VisitAndReturn(Factory::Singleton(std::get<StructuredData>(childValue.value()))); return SetCurrent(Factory::Singleton(std::get<StructuredData>(childValue.value())));
} }
bool ASTInterpreter::ViTypedBinary(Cursor iter) { bool ASTInterpreter::ViTypedBinary(Cursor iter) {
@ -535,16 +535,16 @@ bool ASTInterpreter::ViTypedBinary(Cursor iter) {
const auto& op2 = std::get<StructuredData>(val2.value()); const auto& op2 = std::get<StructuredData>(val2.value());
switch (iter->id) { switch (iter->id) {
default: default:
case TokenID::UNION: return VisitAndReturn(op1.B().Union(op2.B())); case TokenID::UNION: return SetCurrent(op1.B().Union(op2.B()));
case TokenID::INTERSECTION: return VisitAndReturn(op1.B().Intersect(op2.B())); case TokenID::INTERSECTION: return SetCurrent(op1.B().Intersect(op2.B()));
case TokenID::SET_MINUS: return VisitAndReturn(op1.B().Diff(op2.B())); case TokenID::SET_MINUS: return SetCurrent(op1.B().Diff(op2.B()));
case TokenID::SYMMINUS: return VisitAndReturn(op1.B().SymDiff(op2.B())); case TokenID::SYMMINUS: return SetCurrent(op1.B().SymDiff(op2.B()));
case TokenID::IN: return VisitAndReturn(op2.B().Contains(op1)); case TokenID::IN: return SetCurrent(op2.B().Contains(op1));
case TokenID::NOTIN: return VisitAndReturn(!op2.B().Contains(op1)); case TokenID::NOTIN: return SetCurrent(!op2.B().Contains(op1));
case TokenID::SUBSET: return VisitAndReturn(!(op1 == op2) && op1.B().IsSubsetOrEq(op2.B())); case TokenID::SUBSET: return SetCurrent(!(op1 == op2) && op1.B().IsSubsetOrEq(op2.B()));
case TokenID::NOTSUBSET: return VisitAndReturn(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 VisitAndReturn(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()) { if (!childValue.has_value()) {
return false; return false;
} }
return VisitAndReturn(std::get<StructuredData>(childValue.value()).B().Projection(iter->data.ToTuple())); return SetCurrent(std::get<StructuredData>(childValue.value()).B().Projection(iter->data.ToTuple()));
} }
bool ASTInterpreter::ViProjectTuple(Cursor iter) { bool ASTInterpreter::ViProjectTuple(Cursor iter) {
@ -568,7 +568,7 @@ bool ASTInterpreter::ViProjectTuple(Cursor iter) {
for (const auto index : indicies) { for (const auto index : indicies) {
components.emplace_back(std::get<StructuredData>(childValue.value()).T().Component(index)); components.emplace_back(std::get<StructuredData>(childValue.value()).T().Component(index));
} }
return VisitAndReturn(Factory::Tuple(components)); return SetCurrent(Factory::Tuple(components));
} }
bool ASTInterpreter::ViFilter(Cursor iter) { bool ASTInterpreter::ViFilter(Cursor iter) {
@ -578,7 +578,7 @@ bool ASTInterpreter::ViFilter(Cursor iter) {
} }
const auto& argument = std::get<StructuredData>(argumentValue.value()); const auto& argument = std::get<StructuredData>(argumentValue.value());
if (argument.B().IsEmpty()) { if (argument.B().IsEmpty()) {
return VisitAndReturn(Factory::EmptySet()); return SetCurrent(Factory::EmptySet());
} }
const auto& indicies = iter->data.ToTuple(); const auto& indicies = iter->data.ToTuple();
@ -590,7 +590,7 @@ bool ASTInterpreter::ViFilter(Cursor iter) {
return false; return false;
} }
if (const auto val = std::get<StructuredData>(param.value()); val.B().IsEmpty()) { if (const auto val = std::get<StructuredData>(param.value()); val.B().IsEmpty()) {
return VisitAndReturn(Factory::EmptySet()); return SetCurrent(Factory::EmptySet());
} else { } else {
params.emplace_back(val); params.emplace_back(val);
} }
@ -609,7 +609,7 @@ bool ASTInterpreter::ViFilter(Cursor iter) {
result.ModifyB().AddElement(element); result.ModifyB().AddElement(element);
} }
} }
return VisitAndReturn(std::move(result)); return SetCurrent(std::move(result));
} }
bool ASTInterpreter::ViReduce(Cursor iter) { bool ASTInterpreter::ViReduce(Cursor iter) {
@ -617,7 +617,7 @@ bool ASTInterpreter::ViReduce(Cursor iter) {
if (!childValue.has_value()) { if (!childValue.has_value()) {
return false; return false;
} }
return VisitAndReturn(std::get<StructuredData>(childValue.value()).B().Reduce()); return SetCurrent(std::get<StructuredData>(childValue.value()).B().Reduce());
} }
bool ASTInterpreter::ViDebool(Cursor iter) { bool ASTInterpreter::ViDebool(Cursor iter) {
@ -630,7 +630,7 @@ bool ASTInterpreter::ViDebool(Cursor iter) {
OnError(ValueEID::invalidDebool, iter->pos.start); OnError(ValueEID::invalidDebool, iter->pos.start);
return false; return false;
} }
return VisitAndReturn(std::get<StructuredData>(childValue.value()).B().Debool()); return SetCurrent(std::get<StructuredData>(childValue.value()).B().Debool());
} }
std::optional<ExpressionValue> ASTInterpreter::EvaluateChild(Cursor iter, const Index index) { std::optional<ExpressionValue> ASTInterpreter::EvaluateChild(Cursor iter, const Index index) {

View File

@ -50,7 +50,7 @@ bool IsEchelon(SyntaxTree::Cursor iter, const Index index) {
} }
bool IsRadical(const std::string& globalName) { 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) { 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 struct1 = type1.Structure();
const auto struct2 = type2.Structure(); if (struct1 == rslang::StructureType::basic && type1.IsAnyType()) {
if (struct1 == rslang::StructureType::basic && type1.E().baseID == Typification::anyTypificationName) {
return true; 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; return true;
} }
if (struct1 != struct2) { if (struct1 != struct2) {
@ -157,19 +156,18 @@ std::optional<Typification> TypeEnv::Merge(const Typification& type1, const Typi
if (type1 == type2) { if (type1 == type2) {
return type1; return type1;
} }
if (type1.Structure() != type2.Structure()) {
return std::nullopt;
}
const auto struct1 = type1.Structure(); const auto struct1 = type1.Structure();
const auto struct2 = type2.Structure(); if (struct1 == rslang::StructureType::basic && type1.IsAnyType()) {
if (struct1 == rslang::StructureType::basic && type1.E().baseID == Typification::anyTypificationName) {
return type2; 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; return type1;
} }
if (struct1 != struct2) {
return std::nullopt;
}
switch (struct1) { switch (struct1) {
default: default:
@ -218,35 +216,41 @@ bool TypeEnv::CompareTemplated(
if (!substitutes.contains(base)) { if (!substitutes.contains(base)) {
substitutes.insert({ base, value }); substitutes.insert({ base, value });
return true; 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); const auto valueStructure = value.Structure();
if (!mergeType.has_value()) { if (valueStructure == rslang::StructureType::basic && value.IsAnyType()) {
return false;
}
substitutes.at(base) = std::move(mergeType.value());
return true; return true;
} else if (arg.Structure() != value.Structure()) { }
const auto argStructure = arg.Structure();
if (argStructure != valueStructure) {
return false; return false;
} else { }
switch (arg.Structure()) { switch (argStructure) {
default: default:
case rslang::StructureType::basic: case rslang::StructureType::basic:
return CommonType(arg, value) != nullptr; return CommonType(arg, value) != nullptr;
case rslang::StructureType::collection: case rslang::StructureType::collection:
return CompareTemplated(substitutes, arg.B().Base(), value.B().Base()); return CompareTemplated(substitutes, arg.B().Base(), value.B().Base());
case rslang::StructureType::tuple: { case rslang::StructureType::tuple: {
if (arg.T().Arity() != value.T().Arity()) { if (arg.T().Arity() != value.T().Arity()) {
return false;
}
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 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()) { if (!type.IsCollection()) {
return false; return false;
} }
return VisitAndReturn(type.B().Base()); return SetCurrent(type.B().Base());
} else { } else {
assert(iter->id == TokenID::PUNC_DEFINE); assert(iter->id == TokenID::PUNC_DEFINE);
if (childrenCount == 1) { if (childrenCount == 1) {
return VisitAndReturn(Typification{ iter(0).data.ToText() }.ApplyBool()); return SetCurrent(Typification{ iter(0).data.ToText() }.ApplyBool());
} }
const auto type = ChildType(iter, 1); const auto type = ChildType(iter, 1);
if (!type.has_value()) { if (!type.has_value()) {
return false; return false;
} }
return VisitAndReturn(type.value()); return SetCurrent(type.value());
} }
} }
@ -344,7 +348,7 @@ bool TypeAuditor::ViFunctionDefinition(Cursor iter) {
if (!type.has_value()) { if (!type.has_value()) {
return false; return false;
} }
return VisitAndReturn(type.value()); return SetCurrent(type.value());
} }
bool TypeAuditor::ViFunctionCall(Cursor iter) { bool TypeAuditor::ViFunctionCall(Cursor iter) {
@ -363,14 +367,14 @@ bool TypeAuditor::ViFunctionCall(Cursor iter) {
return false; return false;
} }
if (!std::holds_alternative<Typification>(*funcType)) { if (!std::holds_alternative<Typification>(*funcType)) {
return VisitAndReturn(*funcType); return SetCurrent(*funcType);
} else { } else {
Typification fixedType = std::get<Typification>(*funcType); Typification fixedType = std::get<Typification>(*funcType);
MangleRadicals(funcName, fixedType); MangleRadicals(funcName, fixedType);
if (!empty(substitutes.value())) { if (!empty(substitutes.value())) {
fixedType.SubstituteBase(substitutes.value()); fixedType.SubstituteBase(substitutes.value());
} }
return VisitAndReturn(fixedType); return SetCurrent(fixedType);
} }
} }
@ -426,7 +430,7 @@ bool TypeAuditor::ViGlobal(Cursor iter) {
); );
return false; return false;
} }
return VisitAndReturn(Typification(globalName).ApplyBool()); return SetCurrent(Typification(globalName).ApplyBool());
} else { } else {
if (env.context.FunctionArgsFor(globalName) != nullptr) { if (env.context.FunctionArgsFor(globalName) != nullptr) {
OnError( OnError(
@ -445,25 +449,25 @@ bool TypeAuditor::ViGlobal(Cursor iter) {
); );
return false; return false;
} }
return VisitAndReturn(*type); return SetCurrent(*type);
} }
} }
bool TypeAuditor::ViLocal(Cursor iter) { bool TypeAuditor::ViLocal(Cursor iter) {
const auto& localName = iter->data.ToText(); const auto& localName = iter->data.ToText();
if (isLocalDeclaration || isArgDeclaration) { if (isLocalDeclaration || isArgDeclaration) {
return AddLocalVar(localName, std::get<Typification>(currentType), iter->pos.start); return AddLocalVariable(localName, std::get<Typification>(currentType), iter->pos.start);
} else { } else {
const auto* local = GetLocalTypification(localName, iter->pos.start); const auto* local = GetLocalTypification(localName, iter->pos.start);
if (local == nullptr) { if (local == nullptr) {
return false; return false;
} }
return VisitAndReturn(*local); return SetCurrent(*local);
} }
} }
bool TypeAuditor::ViEmptySet(Cursor /*iter*/) { bool TypeAuditor::ViEmptySet(Cursor /*iter*/) {
return VisitAndReturn(Typification::EmptySet()); return SetCurrent(Typification::EmptySet());
} }
bool TypeAuditor::ViLocalBind(Cursor iter) { bool TypeAuditor::ViLocalBind(Cursor iter) {
@ -479,7 +483,7 @@ bool TypeAuditor::ViLocalBind(Cursor iter) {
return false; return false;
} }
} }
return VisitAndReturn(type); return SetCurrent(type);
} }
bool TypeAuditor::ViArgument(Cursor iter) { bool TypeAuditor::ViArgument(Cursor iter) {
@ -489,12 +493,12 @@ bool TypeAuditor::ViArgument(Cursor iter) {
} }
const auto guard{ isArgDeclaration.CreateGuard() }; const auto guard{ isArgDeclaration.CreateGuard() };
currentType = domain.value(); currentType = domain.value();
return VisitChild(iter, 0) && VisitAndReturn(LogicT{}); return VisitChild(iter, 0) && SetCurrent(LogicT{});
} }
bool TypeAuditor::ViCard(Cursor iter) { bool TypeAuditor::ViCard(Cursor iter) {
return ChildTypeDebool(iter, 0, SemanticEID::invalidCard).has_value() return ChildTypeDebool(iter, 0, SemanticEID::invalidCard).has_value()
&& VisitAndReturn(Typification::Integer()); && SetCurrent(Typification::Integer());
} }
bool TypeAuditor::ViArithmetic(Cursor iter) { bool TypeAuditor::ViArithmetic(Cursor iter) {
@ -538,7 +542,7 @@ bool TypeAuditor::ViArithmetic(Cursor iter) {
); );
return false; return false;
} }
return VisitAndReturn(result.value()); return SetCurrent(result.value());
} }
bool TypeAuditor::ViOrdering(Cursor iter) { bool TypeAuditor::ViOrdering(Cursor iter) {
@ -581,7 +585,7 @@ bool TypeAuditor::ViOrdering(Cursor iter) {
); );
return false; return false;
} }
return VisitAndReturn(LogicT{}); return SetCurrent(LogicT{});
} }
bool TypeAuditor::ViQuantifier(Cursor iter) { bool TypeAuditor::ViQuantifier(Cursor iter) {
@ -597,7 +601,7 @@ bool TypeAuditor::ViQuantifier(Cursor iter) {
} }
EndScope(iter->pos.start); EndScope(iter->pos.start);
return VisitAndReturn(LogicT{}); return SetCurrent(LogicT{});
} }
bool TypeAuditor::ViEquals(Cursor iter) { bool TypeAuditor::ViEquals(Cursor iter) {
@ -622,7 +626,7 @@ bool TypeAuditor::ViEquals(Cursor iter) {
); );
return false; return false;
} }
return VisitAndReturn(LogicT{}); return SetCurrent(LogicT{});
} }
bool TypeAuditor::ViTypedPredicate(Cursor iter) { bool TypeAuditor::ViTypedPredicate(Cursor iter) {
@ -656,7 +660,7 @@ bool TypeAuditor::ViTypedPredicate(Cursor iter) {
} }
return false; return false;
} }
return VisitAndReturn(LogicT{}); return SetCurrent(LogicT{});
} }
bool TypeAuditor::ViDeclarative(Cursor iter) { bool TypeAuditor::ViDeclarative(Cursor iter) {
@ -672,7 +676,7 @@ bool TypeAuditor::ViDeclarative(Cursor iter) {
} }
EndScope(iter->pos.start); EndScope(iter->pos.start);
return VisitAndReturn(domain->ApplyBool()); return SetCurrent(domain->ApplyBool());
} }
bool TypeAuditor::ViImperative(Cursor iter) { bool TypeAuditor::ViImperative(Cursor iter) {
@ -690,7 +694,7 @@ bool TypeAuditor::ViImperative(Cursor iter) {
} }
EndScope(iter->pos.start); EndScope(iter->pos.start);
return VisitAndReturn(std::get<Typification>(type.value()).Bool()); return SetCurrent(std::get<Typification>(type.value()).Bool());
} }
bool TypeAuditor::ViImpDeclare(Cursor iter) { bool TypeAuditor::ViImpDeclare(Cursor iter) {
@ -711,22 +715,19 @@ bool TypeAuditor::ViRecursion(Cursor iter) {
auto initType = ChildType(iter, 1); auto initType = ChildType(iter, 1);
if (!initType.has_value()) { if (!initType.has_value()) {
return false; return false;
} else if (!VisitChildDeclaration(iter, 0, std::get<Typification>(initType.value()))) { }
if (!VisitChildDeclaration(iter, 0, std::get<Typification>(initType.value()))) {
return false; return false;
} }
Index iterationIndex{ 2 }; const bool isFull = iter->id == TokenID::NT_RECURSIVE_FULL;
if (iter->id == TokenID::NT_RECURSIVE_FULL) { Index iterationIndex{ isFull ? 3 : 2 };
iterationIndex = 3;
if (!VisitChild(iter, 2)) {
return false;
}
}
const auto iterationType = ChildType(iter, iterationIndex); const auto iterationType = ChildType(iter, iterationIndex);
if (!iterationType.has_value()) { if (!iterationType.has_value()) {
return false; return false;
} else if (!env.AreCompatible(iterationType.value(), initType.value())) { }
if (!env.AreCompatible(iterationType.value(), initType.value())) {
OnError( OnError(
SemanticEID::typesNotEqual, SemanticEID::typesNotEqual,
iter(iterationIndex).pos.start, iter(iterationIndex).pos.start,
@ -736,8 +737,25 @@ bool TypeAuditor::ViRecursion(Cursor iter) {
return false; return false;
} }
{
const auto guard = noWarnings.CreateGuard();
ClearLocalVariables();
if (!VisitChildDeclaration(iter, 0, std::get<Typification>(iterationType.value()))) {
return false;
}
if (!VisitChild(iter, iterationIndex)) {
return false;
}
}
if (isFull) {
if (!VisitChild(iter, 2)) {
return false;
}
}
EndScope(iter->pos.start); EndScope(iter->pos.start);
return VisitAndReturn(iterationType.value()); return SetCurrent(iterationType.value());
} }
bool TypeAuditor::ViDecart(Cursor iter) { bool TypeAuditor::ViDecart(Cursor iter) {
@ -750,7 +768,7 @@ bool TypeAuditor::ViDecart(Cursor iter) {
factors.emplace_back(type.value()); factors.emplace_back(type.value());
} }
} }
return VisitAndReturn(Typification::Tuple(factors).ApplyBool()); return SetCurrent(Typification::Tuple(factors).ApplyBool());
} }
bool TypeAuditor::ViBoolean(Cursor iter) { bool TypeAuditor::ViBoolean(Cursor iter) {
@ -758,7 +776,7 @@ bool TypeAuditor::ViBoolean(Cursor iter) {
if (!type.has_value()) { if (!type.has_value()) {
return false; return false;
} }
return VisitAndReturn(type->ApplyBool().ApplyBool()); return SetCurrent(type->ApplyBool().ApplyBool());
} }
bool TypeAuditor::ViTuple(Cursor iter) { bool TypeAuditor::ViTuple(Cursor iter) {
@ -770,7 +788,7 @@ bool TypeAuditor::ViTuple(Cursor iter) {
} }
components.emplace_back(std::get<Typification>(type.value())); components.emplace_back(std::get<Typification>(type.value()));
} }
return VisitAndReturn(Typification::Tuple(components)); return SetCurrent(Typification::Tuple(components));
} }
bool TypeAuditor::ViSetEnum(Cursor iter) { bool TypeAuditor::ViSetEnum(Cursor iter) {
@ -797,7 +815,7 @@ bool TypeAuditor::ViSetEnum(Cursor iter) {
} }
type = std::move(merge.value()); type = std::move(merge.value());
} }
return VisitAndReturn(type.Bool()); return SetCurrent(type.Bool());
} }
bool TypeAuditor::ViDebool(Cursor iter) { bool TypeAuditor::ViDebool(Cursor iter) {
@ -805,7 +823,7 @@ bool TypeAuditor::ViDebool(Cursor iter) {
if (!type.has_value()) { if (!type.has_value()) {
return false; return false;
} }
return VisitAndReturn(type.value()); return SetCurrent(type.value());
} }
bool TypeAuditor::ViTypedBinary(Cursor iter) { bool TypeAuditor::ViTypedBinary(Cursor iter) {
@ -829,20 +847,24 @@ bool TypeAuditor::ViTypedBinary(Cursor iter) {
); );
return false; return false;
} }
return VisitAndReturn(result.value().Bool()); return SetCurrent(result.value().Bool());
} }
bool TypeAuditor::ViProjectSet(Cursor iter) { bool TypeAuditor::ViProjectSet(Cursor iter) {
// T(Pri(a)) = B(Pi(D(T(a)))) // T(Pri(a)) = B(Pi(D(T(a))))
const auto baseType = ChildTypeDebool(iter, 0, SemanticEID::invalidProjectionSet); const auto maybeArgument = ChildTypeDebool(iter, 0, SemanticEID::invalidProjectionSet);
if (!baseType.has_value()) { if (!maybeArgument.has_value()) {
return false; return false;
} }
if (!baseType->IsTuple()) { const auto& argument = maybeArgument.value();
if (argument.IsAnyType()) {
return SetCurrent(Typification::EmptySet());
}
if (!argument.IsTuple()) {
OnError( OnError(
SemanticEID::invalidProjectionSet, SemanticEID::invalidProjectionSet,
iter(0).pos.start, iter(0).pos.start,
{ iter->ToString(), baseType->ToString() } { iter->ToString(), argument.ToString() }
); );
return false; return false;
} }
@ -851,30 +873,36 @@ bool TypeAuditor::ViProjectSet(Cursor iter) {
std::vector<Typification> components{}; std::vector<Typification> components{};
components.reserve(size(indicies)); components.reserve(size(indicies));
for (const auto index : indicies) { for (const auto index : indicies) {
if (!baseType->T().TestIndex(index)) { if (!argument.T().TestIndex(index)) {
OnError( OnError(
SemanticEID::invalidProjectionSet, SemanticEID::invalidProjectionSet,
iter(0).pos.start, iter(0).pos.start,
{ iter->ToString(), baseType->ToString() } { iter->ToString(), argument.ToString() }
); );
return false; return false;
} else { } else {
components.emplace_back(baseType->T().Component(index)); components.emplace_back(argument.T().Component(index));
} }
} }
currentType = Typification::Tuple(components).ApplyBool(); return SetCurrent(Typification::Tuple(components).ApplyBool());
return true;
} }
bool TypeAuditor::ViProjectTuple(Cursor iter) { bool TypeAuditor::ViProjectTuple(Cursor iter) {
// T(pri(a)) = Pi(T(a)) // T(pri(a)) = Pi(T(a))
const auto baseType = ChildType(iter, 0); const auto maybeArgument = ChildType(iter, 0);
if (!baseType.has_value()) { if (!maybeArgument.has_value()) {
return false; return false;
} }
const auto& base = std::get<Typification>(baseType.value()); const auto& argument = std::get<Typification>(maybeArgument.value());
if (!base.IsTuple()) { if (argument.IsAnyType()) {
OnError(SemanticEID::invalidProjectionTuple, iter(0).pos.start, { iter->ToString(), base.ToString() }); return SetCurrent(argument);
}
if (!argument.IsTuple()) {
OnError(
SemanticEID::invalidProjectionTuple,
iter(0).pos.start,
{ iter->ToString(), argument.ToString() }
);
return false; return false;
} }
@ -882,39 +910,52 @@ bool TypeAuditor::ViProjectTuple(Cursor iter) {
std::vector<Typification> components{}; std::vector<Typification> components{};
components.reserve(size(indicies)); components.reserve(size(indicies));
for (const auto index : indicies) { for (const auto index : indicies) {
if (!base.T().TestIndex(index)) { if (!argument.T().TestIndex(index)) {
OnError(SemanticEID::invalidProjectionTuple, iter(0).pos.start, { iter->ToString(), base.ToString() }); OnError(
SemanticEID::invalidProjectionTuple,
iter(0).pos.start,
{ iter->ToString(), argument.ToString() }
);
return false; return false;
} else { } 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) { bool TypeAuditor::ViFilter(Cursor iter) {
const auto baseType = ChildType(iter, static_cast<Index>(iter.ChildrenCount() - 1));
if (!baseType.has_value()) {
return false;
}
const auto& base = std::get<Typification>(baseType.value());
if (!base.IsCollection() || !base.B().Base().IsTuple()) {
OnError(SemanticEID::invalidFilterArgumentType,
iter(static_cast<Index>(iter.ChildrenCount() - 1)).pos.start,
{ iter->ToString(), base.ToString() });
return false;
}
const auto& indicies = iter->data.ToTuple(); const auto& indicies = iter->data.ToTuple();
if (ssize(indicies) + 1 != iter.ChildrenCount()) { if (ssize(indicies) + 1 != iter.ChildrenCount()) {
OnError(SemanticEID::invalidFilterArity, iter->pos.start); OnError(SemanticEID::invalidFilterArity, iter->pos.start);
return false; return false;
} }
const auto maybeArgument = ChildType(iter, static_cast<Index>(iter.ChildrenCount() - 1));
if (!maybeArgument.has_value()) {
return false;
}
const auto& argument = std::get<Typification>(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<Index>(iter.ChildrenCount() - 1)).pos.start,
{ iter->ToString(), argument.ToString() }
);
return false;
}
Index child{ 0 }; Index child{ 0 };
for (const auto index : indicies) { for (const auto index : indicies) {
if (!base.B().Base().T().TestIndex(index)) { if (!argument.B().Base().T().TestIndex(index)) {
OnError(SemanticEID::invalidFilterArgumentType, iter(static_cast<Index>(iter.ChildrenCount() - 1)).pos.start, OnError(
{ iter->ToString(), base.ToString() }); SemanticEID::invalidFilterArgumentType,
iter(static_cast<Index>(iter.ChildrenCount() - 1)).pos.start,
{ iter->ToString(), argument.ToString() }
);
return false; return false;
} }
const auto param = ChildType(iter, child); const auto param = ChildType(iter, child);
@ -923,50 +964,56 @@ bool TypeAuditor::ViFilter(Cursor iter) {
} }
const auto& paramType = std::get<Typification>(param.value()); const auto& paramType = std::get<Typification>(param.value());
if (!paramType.IsCollection() || if (!paramType.IsCollection() ||
!env.AreCompatible(base.B().Base().T().Component(index), paramType.B().Base())) { !env.AreCompatible(argument.B().Base().T().Component(index), paramType.B().Base())) {
OnError(SemanticEID::typesNotEqual, iter(child).pos.start, OnError(
base.B().Base().T().Component(index).Bool(), paramType); SemanticEID::typesNotEqual,
iter(child).pos.start,
argument.B().Base().T().Component(index).Bool(), paramType
);
return false; return false;
} }
++child; ++child;
} }
return VisitAndReturn(baseType.value()); return SetCurrent(maybeArgument.value());
} }
bool TypeAuditor::ViReduce(Cursor iter) { bool TypeAuditor::ViReduce(Cursor iter) {
// T(red(a)) = B(DD(T(a))) // T(red(a)) = B(DD(T(a)))
const auto baseType = ChildType(iter, 0); const auto maybeArgument = ChildType(iter, 0);
if (!baseType.has_value()) { if (!maybeArgument.has_value()) {
return false; return false;
} }
const auto& base = std::get<Typification>(baseType.value()); const auto& argument = std::get<Typification>(maybeArgument.value());
if (!base.IsCollection() || !base.B().Base().IsCollection()) { if (argument.IsAnyType() || (argument.IsCollection() && argument.B().Base().IsAnyType())) {
return SetCurrent(Typification::EmptySet());
}
if (!argument.IsCollection() || !argument.B().Base().IsCollection()) {
OnError( OnError(
SemanticEID::invalidReduce, SemanticEID::invalidReduce,
iter(0).pos.start + 1, iter(0).pos.start + 1,
base.ToString() argument.ToString()
); );
return false; 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); currentType = std::move(type);
return true; return true;
} }
bool TypeAuditor::VisitAllAndReturn(Cursor iter, const ExpressionType& type) { bool TypeAuditor::VisitAllAndSetCurrent(Cursor iter, const ExpressionType& type) {
return VisitAllChildren(iter) && VisitAndReturn(type); return VisitAllChildren(iter) && SetCurrent(type);
} }
bool TypeAuditor::VisitChildDeclaration(const Cursor& iter, const Index index, const Typification& domain) { bool TypeAuditor::VisitChildDeclaration(const Cursor& iter, const Index index, const Typification& domain) {
currentType = domain; currentType = domain;
if (const auto guard = isLocalDeclaration.CreateGuard(); const auto guard = isLocalDeclaration.CreateGuard();
!VisitChild(iter, index)) { if (!VisitChild(iter, index)) {
return false; return false;
} }
return VisitAndReturn(LogicT{}); return SetCurrent(LogicT{});
} }
std::optional<ExpressionType> TypeAuditor::ChildType(Cursor iter, const Index index) { std::optional<ExpressionType> TypeAuditor::ChildType(Cursor iter, const Index index) {
@ -984,19 +1031,23 @@ std::optional<ExpressionType> TypeAuditor::ChildType(Cursor iter, const Index in
} }
std::optional<Typification> TypeAuditor::ChildTypeDebool(Cursor iter, const Index index, const SemanticEID eid) { std::optional<Typification> TypeAuditor::ChildTypeDebool(Cursor iter, const Index index, const SemanticEID eid) {
const auto result = ChildType(iter, index); const auto maybeResult = ChildType(iter, index);
if (!result.has_value() || !std::holds_alternative<Typification>(result.value())) { if (!maybeResult.has_value() || !std::holds_alternative<Typification>(maybeResult.value())) {
return std::nullopt; return std::nullopt;
} }
if (!std::get<Typification>(result.value()).IsCollection()) { const auto& result = std::get<Typification>(maybeResult.value());
if (result.IsAnyType()) {
return result;
}
if (!result.IsCollection()) {
OnError( OnError(
eid, eid,
iter(index).pos.start, iter(index).pos.start,
ToString(result.value()) ToString(maybeResult.value())
); );
return std::nullopt; return std::nullopt;
} }
return std::get<Typification>(result.value()).B().Base(); return result.B().Base();
} }
const Typification* TypeAuditor::GetLocalTypification(const std::string& name, const StrPos pos) { const Typification* TypeAuditor::GetLocalTypification(const std::string& name, const StrPos pos) {
@ -1030,7 +1081,7 @@ void TypeAuditor::EndScope(const StrPos pos) {
--var.level; --var.level;
if (var.level < 0 && var.enabled) { if (var.level < 0 && var.enabled) {
var.enabled = false; var.enabled = false;
if (var.useCount == 0) { if (var.useCount == 0 && !noWarnings) {
OnError( OnError(
SemanticEID::localNotUsed, SemanticEID::localNotUsed,
pos, pos,
@ -1041,9 +1092,12 @@ void TypeAuditor::EndScope(const StrPos pos) {
} }
} }
bool TypeAuditor::AddLocalVar(const std::string& name, const Typification& type, const StrPos pos) { bool TypeAuditor::AddLocalVariable(const std::string& name, const Typification& type, const StrPos pos) {
auto varIter = std::find_if(begin(localVars), end(localVars), auto varIter = std::find_if(
[&](const auto& data) noexcept { return data.arg.name == name; }); begin(localVars),
end(localVars),
[&](const auto& data) noexcept { return data.arg.name == name; }
);
if (varIter != end(localVars)) { if (varIter != end(localVars)) {
if (varIter->enabled) { if (varIter->enabled) {
OnError( OnError(
@ -1053,16 +1107,17 @@ bool TypeAuditor::AddLocalVar(const std::string& name, const Typification& type,
); );
return false; return false;
} else { } else {
OnError( if (!noWarnings) {
SemanticEID::localDoubleDeclare, OnError(
pos, SemanticEID::localDoubleDeclare,
name pos,
); name
);
}
varIter->arg.type = type; varIter->arg.type = type;
varIter->enabled = true; varIter->enabled = true;
varIter->level = 0; varIter->level = 0;
varIter->useCount = 0; return true;
return true;
} }
} else { } else {
localVars.emplace_back(LocalData{ TypedID{name, type}, 0, 0, true }); 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 } // namespace ccl::rslang

View File

@ -7,6 +7,10 @@
namespace ccl::rslang { namespace ccl::rslang {
bool Typification::IsAnyType() const noexcept {
return IsElement() && E().baseID == anyTypificationName;
}
Typification& Typification::ApplyBool() { Typification& Typification::ApplyBool() {
state = EchelonBool(*this); state = EchelonBool(*this);
return *this; return *this;

View File

@ -37,13 +37,13 @@ void ValueAuditor::Clear() noexcept {
current = ValueClass::invalid; current = ValueClass::invalid;
} }
bool ValueAuditor::VisitAndReturn(const ValueClass type) noexcept { bool ValueAuditor::SetCurrent(const ValueClass type) noexcept {
current = type; current = type;
return true; return true;
} }
bool ValueAuditor::VisitAllAndReturn(Cursor iter, const ValueClass type) { bool ValueAuditor::VisitAllAndSetCurrent(Cursor iter, const ValueClass type) {
return VisitAllChildren(iter) && VisitAndReturn(type); return VisitAllChildren(iter) && SetCurrent(type);
} }
bool ValueAuditor::AssertChildIsValue(Cursor iter, const Index index) { bool ValueAuditor::AssertChildIsValue(Cursor iter, const Index index) {
@ -68,9 +68,9 @@ bool ValueAuditor::AssertAllValues(Cursor iter) {
bool ValueAuditor::ViGlobalDefinition(Cursor iter) { bool ValueAuditor::ViGlobalDefinition(Cursor iter) {
if (iter->id == TokenID::PUNC_STRUCT) { 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) { } else if (iter.ChildrenCount() == 1) {
return VisitAndReturn(ValueClass::value); return SetCurrent(ValueClass::value);
} else { } else {
return VisitChild(iter, 1); return VisitChild(iter, 1);
} }
@ -133,7 +133,7 @@ bool ValueAuditor::RunCheckOnFunc(
bool ValueAuditor::ViGlobal(Cursor iter) { bool ValueAuditor::ViGlobal(Cursor iter) {
const auto& globalName = iter->data.ToText(); const auto& globalName = iter->data.ToText();
if (iter->id == TokenID::ID_RADICAL) { if (iter->id == TokenID::ID_RADICAL) {
return VisitAndReturn(ValueClass::value); return SetCurrent(ValueClass::value);
} else { } else {
const auto type = globalClass(globalName); const auto type = globalClass(globalName);
if (type == ValueClass::invalid) { if (type == ValueClass::invalid) {
@ -148,9 +148,9 @@ bool ValueAuditor::ViGlobal(Cursor iter) {
bool ValueAuditor::ViLocal(Cursor iter) { bool ValueAuditor::ViLocal(Cursor iter) {
const auto& localName = iter->data.ToText(); const auto& localName = iter->data.ToText();
if (std::find(begin(localProps), end(localProps), localName) == end(localProps)) { if (std::find(begin(localProps), end(localProps), localName) == end(localProps)) {
return VisitAndReturn(ValueClass::value); return SetCurrent(ValueClass::value);
} else { } else {
return VisitAndReturn(ValueClass::props); return SetCurrent(ValueClass::props);
} }
} }
@ -195,11 +195,11 @@ bool ValueAuditor::ViDecart(Cursor iter) {
type = current; type = current;
} }
} }
return VisitAndReturn(type); return SetCurrent(type);
} }
bool ValueAuditor::ViBoolean(Cursor iter) { bool ValueAuditor::ViBoolean(Cursor iter) {
return VisitChild(iter, 0) && VisitAndReturn(ValueClass::props); return VisitChild(iter, 0) && SetCurrent(ValueClass::props);
} }
bool ValueAuditor::ViTypedBinary(Cursor iter) { bool ValueAuditor::ViTypedBinary(Cursor iter) {
@ -214,9 +214,9 @@ bool ValueAuditor::ViTypedBinary(Cursor iter) {
const auto secondValue = current == ValueClass::value; const auto secondValue = current == ValueClass::value;
if (CombineOperationValues(iter->id, firstValue, secondValue)) { if (CombineOperationValues(iter->id, firstValue, secondValue)) {
return VisitAndReturn(ValueClass::value); return SetCurrent(ValueClass::value);
} else { } else {
return VisitAndReturn(ValueClass::props); return SetCurrent(ValueClass::props);
} }
} }

View File

@ -227,6 +227,9 @@ TEST_F(UTTypeAuditor, ConstructorsCorrect) {
SetupConstants(); SetupConstants();
ExpectTypification(R"({X1, X1})", "BB(X1)"_t); 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})", "B(Z)"_t);
ExpectTypification(R"({1, card(X1)})", "B(Z)"_t); ExpectTypification(R"({1, card(X1)})", "B(Z)"_t);
ExpectTypification(R"({S4, 1})", "B(C1)"_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 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 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 {} | 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})", "B(X1*X1)"_t);
ExpectTypification(R"(I{(a, b) | a \from X1; b \assign a; 1 \eq 1})", "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 S1 | {a}})", SemanticEID::typesNotEqual, 17);
ExpectError(R"(R{a \assign {} | a \union S4})", SemanticEID::invalidTypeOperation, 26); 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"(\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); 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"(B(X1))", "BB(X1)"_t);
ExpectTypification(R"(X1*X1)", "B(X1*X1)"_t); ExpectTypification(R"(X1*X1)", "B(X1*X1)"_t);
ExpectTypification(R"(Pr1(S1))", "B(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[X1](S1))", "B(X1*X1)"_t);
ExpectTypification(R"(Fi1[{1,2,3}](Z*X1))", "B(Z*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"(Fi1[{1,2,3}](C1*X1))", "B(C1*X1)"_t);
ExpectTypification(R"(Pr1,2(S1))", "B(X1*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"(bool(X1))", "BB(X1)"_t);
ExpectTypification(R"(debool({X1}))", "B(X1)"_t); ExpectTypification(R"(debool({X1}))", "B(X1)"_t);
ExpectTypification(R"(red(S2))", "B(X1)"_t); ExpectTypification(R"(red(S2))", "B(X1)"_t);
@ -365,6 +375,8 @@ TEST_F(UTTypeAuditor, TypedOperationsErrors) {
TEST_F(UTTypeAuditor, TypedFunctions) { TEST_F(UTTypeAuditor, TypedFunctions) {
ExpectTypification(R"(F1[X1, X1])", "B(X1)"_t); 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[X1 \union X1, X1])", "B(X1)"_t);
ExpectTypification(R"(F1[Pr1(S1), Pr2(S1)])", "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; env.data["F2"].arguments = f2Args;
ExpectTypification(R"(F2[B(X1), X1])", "BB(X1)"_t); 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, 1])", "B(Z)"_t);
ExpectTypification(R"(F2[Z, S4])", "B(C1)"_t); ExpectTypification(R"(F2[Z, S4])", "B(C1)"_t);
ExpectTypification(R"(F2[{S4}, 1])", "B(C1)"_t); ExpectTypification(R"(F2[{S4}, 1])", "B(C1)"_t);

View File

@ -30,6 +30,24 @@ TEST_F(UTTypification, Basic) {
EXPECT_TRUE(newBasic.IsElement()); EXPECT_TRUE(newBasic.IsElement());
EXPECT_FALSE(newBasic.IsCollection()); EXPECT_FALSE(newBasic.IsCollection());
EXPECT_FALSE(newBasic.IsTuple()); 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) { TEST_F(UTTypification, Tuple) {
@ -37,6 +55,7 @@ TEST_F(UTTypification, Tuple) {
EXPECT_FALSE(tuple.IsElement()); EXPECT_FALSE(tuple.IsElement());
EXPECT_FALSE(tuple.IsCollection()); EXPECT_FALSE(tuple.IsCollection());
EXPECT_TRUE(tuple.IsTuple()); EXPECT_TRUE(tuple.IsTuple());
EXPECT_FALSE(tuple.IsAnyType());
EXPECT_EQ(tuple.T().Arity(), 2); EXPECT_EQ(tuple.T().Arity(), 2);
tuple = Typification::Tuple({ basic }); tuple = Typification::Tuple({ basic });
@ -74,6 +93,7 @@ TEST_F(UTTypification, Bool) {
EXPECT_FALSE(sBool.IsElement()); EXPECT_FALSE(sBool.IsElement());
EXPECT_TRUE(sBool.IsCollection()); EXPECT_TRUE(sBool.IsCollection());
EXPECT_FALSE(sBool.IsTuple()); EXPECT_FALSE(sBool.IsTuple());
EXPECT_FALSE(sBool.IsAnyType());
} }
TEST_F(UTTypification, ElementTypification) { TEST_F(UTTypification, ElementTypification) {