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