diff --git a/bootstrap/cxx/include/bolt/Checker.hpp b/bootstrap/cxx/include/bolt/Checker.hpp index 2c750d670..71f596a11 100644 --- a/bootstrap/cxx/include/bolt/Checker.hpp +++ b/bootstrap/cxx/include/bolt/Checker.hpp @@ -1,8 +1,6 @@ #pragma once -#include "zen/config.hpp" - #include "bolt/ByteString.hpp" #include "bolt/Common.hpp" #include "bolt/CST.hpp" @@ -11,7 +9,6 @@ #include #include -#include #include #include @@ -77,6 +74,7 @@ namespace bolt { enum class ConstraintKind { Equal, + Field, Many, Empty, }; @@ -112,6 +110,19 @@ namespace bolt { }; + class CField : public Constraint { + public: + + Type* TupleTy; + size_t I; + Type* FieldTy; + Node* Source; + + inline CField(Type* TupleTy, size_t I, Type* FieldTy, Node* Source = nullptr): + Constraint(ConstraintKind::Field), TupleTy(TupleTy), I(I), FieldTy(FieldTy), Source(Source) {} + + }; + class CMany : public Constraint { public: @@ -254,7 +265,7 @@ namespace bolt { */ std::deque Queue; - void solveEqual(CEqual* C); + void unify(Type* Left, Type* Right, Node* Source); void solve(Constraint* Constraint); @@ -276,11 +287,6 @@ namespace bolt { Checker(const LanguageConfig& Config, DiagnosticEngine& DE); - /** - * \internal - */ - Type* simplifyType(Type* Ty); - /** * \internal */ diff --git a/bootstrap/cxx/include/bolt/Diagnostics.hpp b/bootstrap/cxx/include/bolt/Diagnostics.hpp index 3d44ace13..c301f8739 100644 --- a/bootstrap/cxx/include/bolt/Diagnostics.hpp +++ b/bootstrap/cxx/include/bolt/Diagnostics.hpp @@ -170,9 +170,14 @@ namespace bolt { Type* Tuple; std::size_t I; + Node* Source; - inline TupleIndexOutOfRangeDiagnostic(Type* Tuple, std::size_t I): - Diagnostic(DiagnosticKind::TupleIndexOutOfRange), Tuple(Tuple), I(I) {} + inline TupleIndexOutOfRangeDiagnostic(Type* Tuple, std::size_t I, Node* Source): + Diagnostic(DiagnosticKind::TupleIndexOutOfRange), Tuple(Tuple), I(I), Source(Source) {} + + inline Node * getNode() const override { + return Source; + } unsigned getCode() const noexcept override { return 2015; @@ -221,9 +226,14 @@ namespace bolt { public: Type* Ty; + Node* Source; - inline NotATupleDiagnostic(Type* Ty): - Diagnostic(DiagnosticKind::NotATuple), Ty(Ty) {} + inline NotATupleDiagnostic(Type* Ty, Node* Source): + Diagnostic(DiagnosticKind::NotATuple), Ty(Ty), Source(Source) {} + + inline Node * getNode() const override { + return Source; + } unsigned getCode() const noexcept override { return 2016; diff --git a/bootstrap/cxx/include/bolt/Type.hpp b/bootstrap/cxx/include/bolt/Type.hpp index a123ce30f..091cbff16 100644 --- a/bootstrap/cxx/include/bolt/Type.hpp +++ b/bootstrap/cxx/include/bolt/Type.hpp @@ -9,7 +9,6 @@ #include #include "zen/config.hpp" -#include "zen/range.hpp" #include "bolt/CST.hpp" #include "bolt/ByteString.hpp" @@ -48,7 +47,6 @@ namespace bolt { TupleElement, FieldType, FieldRestType, - TupleIndexType, PresentType, End, }; @@ -105,10 +103,6 @@ namespace bolt { return { TypeIndexKind::AppArgType }; } - static TypeIndex forTupleIndexType() { - return { TypeIndexKind::TupleIndexType }; - } - static TypeIndex forPresentType() { return { TypeIndexKind::PresentType }; } @@ -157,7 +151,6 @@ namespace bolt { App, Arrow, Tuple, - TupleIndex, Field, Nil, Absent, @@ -225,15 +218,6 @@ namespace bolt { }; - struct TTupleIndex { - - Type* Ty; - std::size_t I; - - bool operator==(const TTupleIndex& Other) const; - - }; - struct TNil { bool operator==(const TNil& Other) const; }; @@ -266,7 +250,6 @@ namespace bolt { TVar Var; TArrow Arrow; TTuple Tuple; - TTupleIndex TupleIndex; TNil Nil; TField Field; TAbsent Absent; @@ -288,9 +271,6 @@ namespace bolt { Type(TTuple&& Tuple): Kind(TypeKind::Tuple), Tuple(std::move(Tuple)) {}; - Type(TTupleIndex&& TupleIndex): - Kind(TypeKind::TupleIndex), TupleIndex(std::move(TupleIndex)) {}; - Type(TNil&& Nil): Kind(TypeKind::Nil), Nil(std::move(Nil)) {}; @@ -303,46 +283,6 @@ namespace bolt { Type(TPresent&& Present): Kind(TypeKind::Present), Present(std::move(Present)) {}; -// Type(TCon Con): Kind(TypeKind::Con) { -// new (&Con)TCon(Con); -// } - -// Type(TApp App): Kind(TypeKind::App) { -// new (&App)TApp(App); -// } - -// Type(TVar Var): Kind(TypeKind::Var) { -// new (&Var)TVar(Var); -// } - -// Type(TArrow Arrow): Kind(TypeKind::Arrow) { -// new (&Arrow)TArrow(Arrow); -// } - -// Type(TTuple Tuple): Kind(TypeKind::Tuple) { -// new (&Tuple)TTuple(Tuple); -// } - -// Type(TTupleIndex TupleIndex): Kind(TypeKind::TupleIndex) { -// new (&TupleIndex)TTupleIndex(TupleIndex); -// } - -// Type(TNil Nil): Kind(TypeKind::Nil) { -// new (&Nil)TNil(Nil); -// } - -// Type(TField Field): Kind(TypeKind::Field) { -// new (&Field)TField(Field); -// } - -// Type(TAbsent Absent): Kind(TypeKind::Absent) { -// new (&Absent)TAbsent(Absent); -// } - -// Type(TPresent Present): Kind(TypeKind::Present) { -// new (&Present)TPresent(Present); -// } - Type(const Type& Other): Kind(Other.Kind) { switch (Kind) { case TypeKind::Con: @@ -360,9 +300,6 @@ namespace bolt { case TypeKind::Tuple: new (&Tuple)TTuple(Other.Tuple); break; - case TypeKind::TupleIndex: - new (&TupleIndex)TTupleIndex(Other.TupleIndex); - break; case TypeKind::Nil: new (&Nil)TNil(Other.Nil); break; @@ -395,9 +332,6 @@ namespace bolt { case TypeKind::Tuple: new (&Tuple)TTuple(std::move(Other.Tuple)); break; - case TypeKind::TupleIndex: - new (&TupleIndex)TTupleIndex(std::move(Other.TupleIndex)); - break; case TypeKind::Nil: new (&Nil)TNil(std::move(Other.Nil)); break; @@ -492,20 +426,6 @@ namespace bolt { return Tuple; } - bool isTupleIndex() const { - return Kind == TypeKind::TupleIndex; - } - - TTupleIndex& asTupleIndex() { - ZEN_ASSERT(Kind == TypeKind::TupleIndex); - return TupleIndex; - } - - const TTupleIndex& asTupleIndex() const { - ZEN_ASSERT(Kind == TypeKind::TupleIndex); - return TupleIndex; - } - bool isField() const { return Kind == TypeKind::Field; } @@ -611,9 +531,6 @@ namespace bolt { case TypeKind::Tuple: Tuple.~TTuple(); break; - case TypeKind::TupleIndex: - TupleIndex.~TTupleIndex(); - break; case TypeKind::Nil: Nil.~TNil(); break; @@ -648,9 +565,6 @@ namespace bolt { case TypeKind::Tuple: Tuple = Other.Tuple; break; - case TypeKind::TupleIndex: - TupleIndex = Other.TupleIndex; - break; case TypeKind::Nil: Nil = Other.Nil; break; @@ -735,10 +649,6 @@ namespace bolt { } } - virtual void visitTupleIndexType(C& Ty) { - visit(Ty.Ty); - } - virtual void visitAbsentType(C& Ty) { } @@ -794,12 +704,6 @@ namespace bolt { visit(Present->Ty); break; } - case TypeKind::TupleIndex: - { - auto& Index = Ty->asTupleIndex(); - visit(Index->Ty); - break; - } } } @@ -837,9 +741,6 @@ namespace bolt { case TypeKind::App: visitAppType(Ty->asApp()); break; - case TypeKind::TupleIndex: - visitTupleIndexType(Ty->asTupleIndex()); - break; } exitType(Ty); } diff --git a/bootstrap/cxx/src/Checker.cc b/bootstrap/cxx/src/Checker.cc index 8980d7ea7..7dcb71844 100644 --- a/bootstrap/cxx/src/Checker.cc +++ b/bootstrap/cxx/src/Checker.cc @@ -30,37 +30,20 @@ namespace bolt { } return new CMany(*NewConstraints); } + case ConstraintKind::Field: + { + auto Field = static_cast(this); + auto NewTupleTy = Field->TupleTy->substitute(Sub); + auto NewFieldTy = Field->FieldTy->substitute(Sub); + return new CField(NewTupleTy, Field->I, NewFieldTy); + } case ConstraintKind::Empty: return this; } } - Type* Checker::simplifyType(Type* Ty) { - - Ty = Ty->find(); - - if (Ty->isTupleIndex()) { - auto& Index = Ty->asTupleIndex(); - auto MaybeTuple = simplifyType(Index.Ty); - if (MaybeTuple->isTuple()) { - auto& Tuple = MaybeTuple->asTuple(); - if (Index.I >= Tuple.ElementTypes.size()) { - DE.add(MaybeTuple, Index.I); - } else { - auto ElementTy = simplifyType(Tuple.ElementTypes[Index.I]); - Ty->set(ElementTy); - Ty = ElementTy; - } - } else if (!MaybeTuple->isVar()) { - DE.add(MaybeTuple); - } - } - - return Ty; - } - Type* Checker::solveType(Type* Ty) { - return Ty->rewrite([this](auto Ty) { return simplifyType(Ty); }, true); + return Ty->rewrite([this](auto Ty) { return Ty->find(); }, true); } Checker::Checker(const LanguageConfig& Config, DiagnosticEngine& DE): @@ -135,7 +118,14 @@ namespace bolt { } void Checker::addConstraint(Constraint* C) { + switch (C->getKind()) { + + case ConstraintKind::Field: + // FIXME Check if this is all that needs to be done + getContext().Constraints->push_back(C); + break; + case ConstraintKind::Equal: { auto Y = static_cast(C); @@ -195,13 +185,14 @@ namespace bolt { } if (UpperLevel == LowerLevel || MaxLevelLeft == Global || MaxLevelRight == Global) { - solveEqual(Y); + unify(Y->Left, Y->Right, Y->Source); } else { Contexts[UpperLevel]->Constraints->push_back(C); } break; } + case ConstraintKind::Many: { auto Y = static_cast(C); @@ -210,9 +201,12 @@ namespace bolt { } break; } + case ConstraintKind::Empty: break; + } + } void Checker::forwardDeclare(Node* X) { @@ -1061,7 +1055,8 @@ namespace bolt { case NodeKind::IntegerLiteral: { auto I = static_cast(Member->Name); - Ty = new Type(TTupleIndex(ExprTy, I->getInteger())); + Ty = createTypeVar(); + addConstraint(new CField(ExprTy, I->asInt(), Ty, Member)); break; } case NodeKind::Identifier: @@ -1310,6 +1305,26 @@ namespace bolt { case ConstraintKind::Empty: break; + case ConstraintKind::Field: + { + auto Field = static_cast(Constraint); + auto MaybeTuple = Field->TupleTy->find(); + if (MaybeTuple->isTuple()) { + auto& Tuple = MaybeTuple->asTuple(); + if (Field->I >= Tuple.ElementTypes.size()) { + DE.add(MaybeTuple, Field->I, Field->Source); + } else { + auto ElementTy = Tuple.ElementTypes[Field->I]; + unify(ElementTy, Field->FieldTy, Field->Source); + } + } else if (MaybeTuple->isVar()) { + // TODO Add logic for when tuple is a var + } else { + DE.add(MaybeTuple, Field->Source); + } + break; + } + case ConstraintKind::Many: { auto Many = static_cast(Constraint); @@ -1321,7 +1336,8 @@ namespace bolt { case ConstraintKind::Equal: { - solveEqual(static_cast(Constraint)); + auto Equal = static_cast(Constraint); + unify(Equal->Left, Equal->Right, Equal->Source); break; } @@ -1392,7 +1408,11 @@ namespace bolt { struct Unifier { Checker& C; - CEqual* Constraint; + // CEqual* Constraint; + Type* Left; + Type* Right; + Node* Source; + // Internal state used by the unifier ByteString CurrentFieldName; @@ -1400,15 +1420,15 @@ namespace bolt { TypePath RightPath; Type* getLeft() const { - return Constraint->Left; + return Left; } Type* getRight() const { - return Constraint->Right; + return Right; } Node* getSource() const { - return Constraint->Source; + return Source; } bool unifyField(Type* A, Type* B, bool DidSwap); @@ -1416,7 +1436,7 @@ namespace bolt { bool unify(Type* A, Type* B, bool DidSwap); bool unify() { - return unify(Constraint->Left, Constraint->Right, false); + return unify(Left, Right, false); } std::vector findInstanceContext(const TypeSig& Ty, TypeclassId& Class) { @@ -1548,16 +1568,16 @@ namespace bolt { bool Unifier::unify(Type* A, Type* B, bool DidSwap) { - A = C.simplifyType(A); - B = C.simplifyType(B); + A = A->find(); + B = B->find(); auto unifyError = [&]() { C.DE.add( - Constraint->Left, - Constraint->Right, + Left, + Right, LeftPath, RightPath, - Constraint->Source + Source ); }; @@ -1717,12 +1737,12 @@ namespace bolt { return Success; } - if (A->isTupleIndex() || B->isTupleIndex()) { - // Type(s) could not be simplified at the beginning of this function, - // so we have to re-visit the constraint when there is more information. - C.Queue.push_back(Constraint); - return true; - } + // if (A->isTupleIndex() || B->isTupleIndex()) { + // // Type(s) could not be simplified at the beginning of this function, + // // so we have to re-visit the constraint when there is more information. + // C.Queue.push_back(Constraint); + // return true; + // } // This does not work because it ignores the indices // if (A->isTupleIndex() && B->isTupleIndex()) { @@ -1806,9 +1826,9 @@ namespace bolt { return false; } - void Checker::solveEqual(CEqual* C) { + void Checker::unify(Type* Left, Type* Right, Node* Source) { // std::cerr << describe(C->Left) << " ~ " << describe(C->Right) << std::endl; - Unifier A { *this, C }; + Unifier A { *this, Left, Right, Source }; A.unify(); } diff --git a/bootstrap/cxx/src/ConsolePrinter.cc b/bootstrap/cxx/src/ConsolePrinter.cc index 8b8f98a90..860852db7 100644 --- a/bootstrap/cxx/src/ConsolePrinter.cc +++ b/bootstrap/cxx/src/ConsolePrinter.cc @@ -235,11 +235,6 @@ namespace bolt { Out << ")"; return Out.str(); } - case TypeKind::TupleIndex: - { - auto Y = Ty->asTupleIndex(); - return describe(Y.Ty) + "." + std::to_string(Y.I); - } case TypeKind::Nil: return "{}"; case TypeKind::Absent: @@ -617,14 +612,6 @@ namespace bolt { W.write(")"); } - void visitTupleIndexType(const TTupleIndex& Ty) override { - Path.push_back(TypeIndex::forTupleIndexType()); - visit(Ty.Ty); - Path.pop_back(); - W.write("."); - W.write(Ty.I); - } - void visitNilType(const TNil& Ty) override { W.write("{}"); } @@ -889,6 +876,9 @@ namespace bolt { writeType(E.I); write(" is out of range for tuple "); writeType(E.Tuple); + write("\n\n"); + writeNode(E.Source); + write("\n"); break; } @@ -927,7 +917,9 @@ namespace bolt { writePrefix(E); write("the type "); writeType(E.Ty); - write(" is not a tuple.\n"); + write(" is not a tuple.\n\n"); + writeNode(E.Source); + write("\n"); break; } diff --git a/bootstrap/cxx/src/Types.cc b/bootstrap/cxx/src/Types.cc index 60dce6f7e..14602079b 100644 --- a/bootstrap/cxx/src/Types.cc +++ b/bootstrap/cxx/src/Types.cc @@ -4,6 +4,8 @@ #include #include +#include "zen/range.hpp" + namespace bolt { bool TypeclassSignature::operator<(const TypeclassSignature& Other) const { @@ -60,10 +62,6 @@ namespace bolt { return true; } - bool TTupleIndex::operator==(const TTupleIndex& Other) const { - return *Ty == *Other.Ty && I == Other.I; - } - bool TNil::operator==(const TNil& Other) const { return true; } @@ -101,8 +99,6 @@ namespace bolt { return Nil == Other.Nil; case TypeKind::Tuple: return Tuple == Other.Tuple; - case TypeKind::TupleIndex: - return TupleIndex == Other.TupleIndex; case TypeKind::App: return App == Other.App; } @@ -145,11 +141,6 @@ namespace bolt { Proc(Present.Ty); break; } - case TypeKind::TupleIndex: - { - Proc(TupleIndex.Ty); - break; - } } } @@ -190,12 +181,6 @@ namespace bolt { } return new Type(TApp(NewOp, NewArg)); } - case TypeKind::TupleIndex: - { - auto Tuple = Ty2->asTupleIndex(); - auto NewTy = Tuple.Ty->rewrite(Fn, Recursive); - return NewTy != Tuple.Ty ? new Type(TTupleIndex(NewTy, Tuple.I)) : Ty2; - } case TypeKind::Tuple: { auto Tuple = Ty2->asTuple(); @@ -258,8 +243,6 @@ namespace bolt { return this->asApp().Op; case TypeIndexKind::AppArgType: return this->asApp().Arg; - case TypeIndexKind::TupleIndexType: - return this->asTupleIndex().Ty; case TypeIndexKind::TupleElement: return this->asTuple().ElementTypes[Index.I]; case TypeIndexKind::ArrowParamType: @@ -336,8 +319,6 @@ namespace bolt { } } return false; - case TypeKind::TupleIndex: - return TupleIndex.Ty->hasTypeVar(TV); case TypeKind::Field: return Field.Ty->hasTypeVar(TV) || Field.RestTy->hasTypeVar(TV); case TypeKind::Arrow: