Sort diangostics by node and refactor ConsoleDiagnostics

This commit is contained in:
Sam Vervaeck 2023-05-24 14:11:59 +02:00
parent 5ac162cd72
commit 6967f9a060
Signed by: samvv
SSH key fingerprint: SHA256:dIg0ywU1OP+ZYifrYxy8c5esO72cIKB+4/9wkZj1VaY
10 changed files with 468 additions and 257 deletions

View file

@ -131,8 +131,13 @@ namespace bolt {
void setParents();
virtual Token* getFirstToken() = 0;
virtual Token* getLastToken() = 0;
virtual Token* getFirstToken() const = 0;
virtual Token* getLastToken() const = 0;
virtual std::size_t getStartLine() const;
virtual std::size_t getStartColumn() const;
virtual std::size_t getEndLine() const;
virtual std::size_t getEndColumn() const;
inline NodeKind getKind() const noexcept {
return Kind;
@ -159,11 +164,12 @@ namespace bolt {
return static_cast<T*>(this);
}
TextRange getRange();
TextRange getRange() const;
inline Node(NodeKind Type):
Kind(Type) {}
const SourceFile* getSourceFile() const;
SourceFile* getSourceFile();
virtual Scope* getScope();
@ -223,12 +229,12 @@ namespace bolt {
virtual std::string getText() const = 0;
inline Token* getFirstToken() override {
return this;
inline Token* getFirstToken() const override {
ZEN_UNREACHABLE
}
inline Token* getLastToken() override {
return this;
inline Token* getLastToken() const override {
ZEN_UNREACHABLE
}
inline TextLoc getStartLoc() {
@ -897,8 +903,8 @@ namespace bolt {
Name(Name),
TEs(TEs) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::TypeclassConstraintExpression;
@ -922,8 +928,8 @@ namespace bolt {
Tilde(Tilde),
Right(Right) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::EqualityConstraintExpression;
@ -947,8 +953,8 @@ namespace bolt {
RArrowAlt(RArrowAlt),
TE(TE) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::QualifiedTypeExpression;
@ -969,8 +975,8 @@ namespace bolt {
ModulePath(ModulePath),
Name(Name) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
SymbolPath getSymbolPath() const;
@ -989,8 +995,8 @@ namespace bolt {
ParamTypes(ParamTypes),
ReturnType(ReturnType) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1002,8 +1008,8 @@ namespace bolt {
inline VarTypeExpression(Identifier* Name):
TypeExpression(NodeKind::VarTypeExpression), Name(Name) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1023,8 +1029,8 @@ namespace bolt {
TE(TE),
RParen(RParen) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1044,8 +1050,8 @@ namespace bolt {
Elements(Elements),
RParen(RParen) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1067,8 +1073,8 @@ namespace bolt {
): Pattern(NodeKind::BindPattern),
Name(Name) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::BindPattern;
@ -1085,8 +1091,8 @@ namespace bolt {
Pattern(NodeKind::LiteralPattern),
Literal(Literal) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::LiteralPattern;
@ -1115,8 +1121,8 @@ namespace bolt {
ModulePath(ModulePath),
Name(Name) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
SymbolPath getSymbolPath() const;
@ -1138,8 +1144,8 @@ namespace bolt {
RArrowAlt(RArrowAlt),
Expression(Expression) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1162,8 +1168,8 @@ namespace bolt {
BlockStart(BlockStart),
Cases(Cases) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1183,8 +1189,8 @@ namespace bolt {
Dot(Dot),
Name(Name) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
inline Expression* getExpression() const {
return E;
@ -1208,8 +1214,8 @@ namespace bolt {
Elements(Elements),
RParen(RParen) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1229,8 +1235,8 @@ namespace bolt {
Inner(Inner),
RParen(RParen) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1244,8 +1250,8 @@ namespace bolt {
): Expression(NodeKind::ConstantExpression),
Token(Token) {}
class Token* getFirstToken() override;
class Token* getLastToken() override;
class Token* getFirstToken() const override;
class Token* getLastToken() const override;
};
@ -1262,8 +1268,8 @@ namespace bolt {
Function(Function),
Args(Args) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1280,8 +1286,8 @@ namespace bolt {
Operator(Operator),
RHS(RHS) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1298,8 +1304,8 @@ namespace bolt {
Operator(Operator),
Argument(Argument) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1319,8 +1325,8 @@ namespace bolt {
ExpressionStatement(class Expression* Expression):
Statement(NodeKind::ExpressionStatement), Expression(Expression) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1343,8 +1349,8 @@ namespace bolt {
BlockStart(BlockStart),
Elements(Elements) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1356,8 +1362,8 @@ namespace bolt {
inline IfStatement(std::vector<IfStatementPart*> Parts):
Statement(NodeKind::IfStatement), Parts(Parts) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1374,8 +1380,8 @@ namespace bolt {
ReturnKeyword(ReturnKeyword),
Expression(Expression) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1392,8 +1398,8 @@ namespace bolt {
Colon(Colon),
TypeExpression(TypeExpression) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1410,8 +1416,8 @@ namespace bolt {
class Pattern* Pattern;
class TypeAssert* TypeAssert;
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1435,8 +1441,8 @@ namespace bolt {
BlockStart(BlockStart),
Elements(Elements) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1453,8 +1459,8 @@ namespace bolt {
Equals(Equals),
Expression(Expression) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1502,8 +1508,8 @@ namespace bolt {
return TheScope;
}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::LetDeclaration;
@ -1533,8 +1539,8 @@ namespace bolt {
BlockStart(BlockStart),
Elements(Elements) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::InstanceDeclaration;
@ -1567,8 +1573,8 @@ namespace bolt {
BlockStart(BlockStart),
Elements(Elements) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::ClassDeclaration;
@ -1592,8 +1598,8 @@ namespace bolt {
class Colon* Colon;
class TypeExpression* TypeExpression;
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1619,8 +1625,8 @@ namespace bolt {
BlockStart(BlockStart),
Fields(Fields) {}
Token* getFirstToken() override;
Token* getLastToken() override;
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
@ -1641,8 +1647,12 @@ namespace bolt {
return File;
}
Token* getFirstToken() override;
Token* getLastToken() override;
inline const TextFile& getTextFile() const {
return File;
}
Token* getFirstToken() const override;
Token* getLastToken() const override;
inline Scope* getScope() override {
if (TheScope == nullptr) {

View file

@ -39,6 +39,11 @@ namespace bolt {
return Kind;
}
virtual Node* getNode() const {
return nullptr;
}
};
class UnexpectedTokenDiagnostic : public Diagnostic {
@ -74,6 +79,10 @@ namespace bolt {
inline BindingNotFoundDiagnostic(ByteString Name, Node* Initiator):
Diagnostic(DiagnosticKind::BindingNotFound), Name(Name), Initiator(Initiator) {}
inline Node* getNode() const override {
return Initiator;
}
};
class UnificationErrorDiagnostic : public Diagnostic {
@ -88,6 +97,10 @@ namespace bolt {
inline UnificationErrorDiagnostic(Type* Left, Type* Right, TypePath LeftPath, TypePath RightPath, Node* Source):
Diagnostic(DiagnosticKind::UnificationError), Left(Left), Right(Right), LeftPath(LeftPath), RightPath(RightPath), Source(Source) {}
inline Node* getNode() const override {
return Source;
}
};
class TypeclassMissingDiagnostic : public Diagnostic {
@ -99,6 +112,10 @@ namespace bolt {
inline TypeclassMissingDiagnostic(TypeclassSignature Sig, LetDeclaration* Decl):
Diagnostic(DiagnosticKind::TypeclassMissing), Sig(Sig), Decl(Decl) {}
inline Node* getNode() const override {
return Decl;
}
};
class InstanceNotFoundDiagnostic : public Diagnostic {
@ -111,6 +128,10 @@ namespace bolt {
inline InstanceNotFoundDiagnostic(ByteString TypeclassName, TCon* Ty, Node* Source):
Diagnostic(DiagnosticKind::InstanceNotFound), TypeclassName(TypeclassName), Ty(Ty), Source(Source) {}
inline Node* getNode() const override {
return Source;
}
};
class ClassNotFoundDiagnostic : public Diagnostic {
@ -138,29 +159,56 @@ namespace bolt {
public:
Type* Actual;
std::vector<TypeclassId> Classes;
Node* Source;
inline InvalidTypeToTypeclassDiagnostic(Type* Actual):
Diagnostic(DiagnosticKind::InvalidTypeToTypeclass) {}
inline InvalidTypeToTypeclassDiagnostic(Type* Actual, std::vector<TypeclassId> Classes, Node* Source):
Diagnostic(DiagnosticKind::InvalidTypeToTypeclass), Actual(Actual), Classes(Classes), Source(Source) {}
inline Node* getNode() const override {
return Source;
}
};
class DiagnosticEngine {
protected:
public:
virtual void addDiagnostic(const Diagnostic& Diagnostic) = 0;
virtual void addDiagnostic(Diagnostic* Diagnostic) = 0;
template<typename D, typename ...Ts>
void add(Ts&&... Args) {
D Diag { std::forward<Ts>(Args)... };
addDiagnostic(Diag);
addDiagnostic(new D { std::forward<Ts>(Args)... });
}
virtual ~DiagnosticEngine() {}
};
/**
* Keeps diagnostics alive in-memory until a seperate procedure processes them.
*/
class DiagnosticStore : public DiagnosticEngine {
public:
std::vector<Diagnostic*> Diagnostics;
void addDiagnostic(Diagnostic* Diagnostic) {
Diagnostics.push_back(Diagnostic);
}
void clear() {
Diagnostics.clear();
}
~DiagnosticStore() {
for (auto D: Diagnostics) {
delete D;
}
}
};
enum class Color {
None,
Black,
@ -198,12 +246,25 @@ namespace bolt {
);
void writeExcerpt(
TextFile& File,
const TextFile& File,
TextRange ToPrint,
TextRange ToHighlight,
Color HighlightColor
);
void writeNode(const Node* N);
void writePrefix(const Diagnostic& D);
void writeBinding(const ByteString& Name);
void writeType(std::size_t I);
void writeType(const Type* Ty);
void writeLoc(const TextFile& File, const TextLoc& Loc);
void writeTypeclassName(const ByteString& Name);
void writeTypeclassSignature(const TypeclassSignature& Sig);
void write(const std::string_view& S);
void write(std::size_t N);
public:
unsigned ExcerptLinesPre = 2;
@ -213,9 +274,10 @@ namespace bolt {
bool PrintExcerpts = true;
bool EnableColors = true;
void addDiagnostic(const Diagnostic& Diagnostic) override;
ConsoleDiagnostics(std::ostream& Out = std::cerr);
void addDiagnostic(Diagnostic* Diagnostic) override;
};
}

View file

@ -9,6 +9,7 @@
namespace bolt {
class DiagnosticEngine;
class Scanner;
enum OperatorFlags {
@ -62,6 +63,7 @@ namespace bolt {
class Parser {
TextFile& File;
DiagnosticEngine& DE;
Stream<Token*>& Tokens;
@ -90,7 +92,7 @@ namespace bolt {
public:
Parser(TextFile& File, Stream<Token*>& S);
Parser(TextFile& File, Stream<Token*>& S, DiagnosticEngine& DE);
TypeExpression* parseTypeExpression();

View file

@ -52,9 +52,9 @@ namespace bolt {
TextFile(ByteString Path, ByteString Text);
size_t getLine(size_t Offset);
size_t getColumn(size_t Offset);
size_t getStartOffset(size_t Line);
size_t getLine(size_t Offset) const;
size_t getColumn(size_t Offset) const;
size_t getStartOffset(size_t Line) const;
size_t getLineCount() const;

View file

@ -92,18 +92,44 @@ namespace bolt {
return Source->Parent->getScope();
}
const SourceFile* Node::getSourceFile() const {
const Node* CurrNode = this;
for (;;) {
if (CurrNode->Kind == NodeKind::SourceFile) {
return static_cast<const SourceFile*>(CurrNode);
}
CurrNode = CurrNode->Parent;
ZEN_ASSERT(CurrNode != nullptr);
}
}
SourceFile* Node::getSourceFile() {
auto CurrNode = this;
Node* CurrNode = this;
for (;;) {
if (CurrNode->Kind == NodeKind::SourceFile) {
return static_cast<SourceFile*>(CurrNode);
}
CurrNode = CurrNode->Parent;
ZEN_ASSERT(CurrNode != nullptr);
}
}
}
TextRange Node::getRange() {
std::size_t Node::getStartLine() const {
return getFirstToken()->getStartLine();
}
std::size_t Node::getStartColumn() const {
return getFirstToken()->getStartColumn();
}
std::size_t Node::getEndLine() const {
return getLastToken()->getEndLine();
}
std::size_t Node::getEndColumn() const {
return getLastToken()->getEndColumn();
}
TextRange Node::getRange() const {
return TextRange {
getFirstToken()->getStartLoc(),
getLastToken()->getEndLoc(),
@ -169,273 +195,273 @@ namespace bolt {
return true;
}
Token* TypeclassConstraintExpression::getFirstToken() {
Token* TypeclassConstraintExpression::getFirstToken() const {
return Name;
}
Token* TypeclassConstraintExpression::getLastToken() {
Token* TypeclassConstraintExpression::getLastToken() const {
if (!TEs.empty()) {
return TEs.back()->getLastToken();
}
return Name;
}
Token* EqualityConstraintExpression::getFirstToken() {
Token* EqualityConstraintExpression::getFirstToken() const {
return Left->getFirstToken();
}
Token* EqualityConstraintExpression::getLastToken() {
Token* EqualityConstraintExpression::getLastToken() const {
return Left->getLastToken();
}
Token* QualifiedTypeExpression::getFirstToken() {
Token* QualifiedTypeExpression::getFirstToken() const {
if (!Constraints.empty()) {
return std::get<0>(Constraints.front())->getFirstToken();
}
return TE->getFirstToken();
}
Token* QualifiedTypeExpression::getLastToken() {
Token* QualifiedTypeExpression::getLastToken() const {
return TE->getLastToken();
}
Token* ReferenceTypeExpression::getFirstToken() {
Token* ReferenceTypeExpression::getFirstToken() const {
if (!ModulePath.empty()) {
return std::get<0>(ModulePath.front());
}
return Name;
}
Token* ReferenceTypeExpression::getLastToken() {
Token* ReferenceTypeExpression::getLastToken() const {
return Name;
}
Token* ArrowTypeExpression::getFirstToken() {
Token* ArrowTypeExpression::getFirstToken() const {
if (ParamTypes.size()) {
return ParamTypes.front()->getFirstToken();
}
return ReturnType->getFirstToken();
}
Token* ArrowTypeExpression::getLastToken() {
Token* ArrowTypeExpression::getLastToken() const {
return ReturnType->getLastToken();
}
Token* VarTypeExpression::getLastToken() {
Token* VarTypeExpression::getLastToken() const {
return Name;
}
Token* VarTypeExpression::getFirstToken() {
Token* VarTypeExpression::getFirstToken() const {
return Name;
}
Token* NestedTypeExpression::getLastToken() {
Token* NestedTypeExpression::getLastToken() const {
return LParen;
}
Token* NestedTypeExpression::getFirstToken() {
Token* NestedTypeExpression::getFirstToken() const {
return RParen;
}
Token* TupleTypeExpression::getLastToken() {
Token* TupleTypeExpression::getLastToken() const {
return LParen;
}
Token* TupleTypeExpression::getFirstToken() {
Token* TupleTypeExpression::getFirstToken() const {
return RParen;
}
Token* BindPattern::getFirstToken() {
Token* BindPattern::getFirstToken() const {
return Name;
}
Token* BindPattern::getLastToken() {
Token* BindPattern::getLastToken() const {
return Name;
}
Token* LiteralPattern::getFirstToken() {
Token* LiteralPattern::getFirstToken() const {
return Literal;
}
Token* LiteralPattern::getLastToken() {
Token* LiteralPattern::getLastToken() const {
return Literal;
}
Token* ReferenceExpression::getFirstToken() {
Token* ReferenceExpression::getFirstToken() const {
if (!ModulePath.empty()) {
return std::get<0>(ModulePath.front());
}
return Name;
}
Token* ReferenceExpression::getLastToken() {
Token* ReferenceExpression::getLastToken() const {
return Name;
}
Token* MatchCase::getFirstToken() {
Token* MatchCase::getFirstToken() const {
return Pattern->getFirstToken();
}
Token* MatchCase::getLastToken() {
Token* MatchCase::getLastToken() const {
return Expression->getLastToken();
}
Token* MatchExpression::getFirstToken() {
Token* MatchExpression::getFirstToken() const {
return MatchKeyword;
}
Token* MatchExpression::getLastToken() {
Token* MatchExpression::getLastToken() const {
if (!Cases.empty()) {
return Cases.back()->getLastToken();
}
return BlockStart;
}
Token* MemberExpression::getFirstToken() {
Token* MemberExpression::getFirstToken() const {
return E->getFirstToken();
}
Token* MemberExpression::getLastToken() {
Token* MemberExpression::getLastToken() const {
return Name;
}
Token* TupleExpression::getFirstToken() {
Token* TupleExpression::getFirstToken() const {
return LParen;
}
Token* TupleExpression::getLastToken() {
Token* TupleExpression::getLastToken() const {
return RParen;
}
Token* NestedExpression::getFirstToken() {
Token* NestedExpression::getFirstToken() const {
return LParen;
}
Token* NestedExpression::getLastToken() {
Token* NestedExpression::getLastToken() const {
return RParen;
}
Token* ConstantExpression::getFirstToken() {
Token* ConstantExpression::getFirstToken() const {
return Token;
}
Token* ConstantExpression::getLastToken() {
Token* ConstantExpression::getLastToken() const {
return Token;
}
Token* CallExpression::getFirstToken() {
Token* CallExpression::getFirstToken() const {
return Function->getFirstToken();
}
Token* CallExpression::getLastToken() {
Token* CallExpression::getLastToken() const {
if (Args.size()) {
return Args.back()->getLastToken();
}
return Function->getLastToken();
}
Token* InfixExpression::getFirstToken() {
Token* InfixExpression::getFirstToken() const {
return LHS->getFirstToken();
}
Token* InfixExpression::getLastToken() {
Token* InfixExpression::getLastToken() const {
return RHS->getLastToken();
}
Token* PrefixExpression::getFirstToken() {
Token* PrefixExpression::getFirstToken() const {
return Operator;
}
Token* PrefixExpression::getLastToken() {
Token* PrefixExpression::getLastToken() const {
return Argument->getLastToken();
}
Token* ExpressionStatement::getFirstToken() {
Token* ExpressionStatement::getFirstToken() const {
return Expression->getFirstToken();
}
Token* ExpressionStatement::getLastToken() {
Token* ExpressionStatement::getLastToken() const {
return Expression->getLastToken();
}
Token* ReturnStatement::getFirstToken() {
Token* ReturnStatement::getFirstToken() const {
return ReturnKeyword;
}
Token* ReturnStatement::getLastToken() {
Token* ReturnStatement::getLastToken() const {
if (Expression) {
return Expression->getLastToken();
}
return ReturnKeyword;
}
Token* IfStatementPart::getFirstToken() {
Token* IfStatementPart::getFirstToken() const {
return Keyword;
}
Token* IfStatementPart::getLastToken() {
Token* IfStatementPart::getLastToken() const {
if (Elements.size()) {
return Elements.back()->getLastToken();
}
return BlockStart;
}
Token* IfStatement::getFirstToken() {
Token* IfStatement::getFirstToken() const {
ZEN_ASSERT(Parts.size());
return Parts.front()->getFirstToken();
}
Token* IfStatement::getLastToken() {
Token* IfStatement::getLastToken() const {
ZEN_ASSERT(Parts.size());
return Parts.back()->getLastToken();
}
Token* TypeAssert::getFirstToken() {
Token* TypeAssert::getFirstToken() const {
return Colon;
}
Token* TypeAssert::getLastToken() {
Token* TypeAssert::getLastToken() const {
return TypeExpression->getLastToken();
}
Token* Parameter::getFirstToken() {
Token* Parameter::getFirstToken() const {
return Pattern->getFirstToken();
}
Token* Parameter::getLastToken() {
Token* Parameter::getLastToken() const {
if (TypeAssert) {
return TypeAssert->getLastToken();
}
return Pattern->getLastToken();
}
Token* LetBlockBody::getFirstToken() {
Token* LetBlockBody::getFirstToken() const {
return BlockStart;
}
Token* LetBlockBody::getLastToken() {
Token* LetBlockBody::getLastToken() const {
if (Elements.size()) {
return Elements.back()->getLastToken();
}
return BlockStart;
}
Token* LetExprBody::getFirstToken() {
Token* LetExprBody::getFirstToken() const {
return Equals;
}
Token* LetExprBody::getLastToken() {
Token* LetExprBody::getLastToken() const {
return Expression->getLastToken();
}
Token* LetDeclaration::getFirstToken() {
Token* LetDeclaration::getFirstToken() const {
if (PubKeyword) {
return PubKeyword;
}
return LetKeyword;
}
Token* LetDeclaration::getLastToken() {
Token* LetDeclaration::getLastToken() const {
if (Body) {
return Body->getLastToken();
}
@ -448,61 +474,61 @@ namespace bolt {
return Pattern->getLastToken();
}
Token* StructDeclarationField::getFirstToken() {
Token* StructDeclarationField::getFirstToken() const {
return Name;
}
Token* StructDeclarationField::getLastToken() {
Token* StructDeclarationField::getLastToken() const {
return TypeExpression->getLastToken();
}
Token* StructDeclaration::getFirstToken() {
Token* StructDeclaration::getFirstToken() const {
if (PubKeyword) {
return PubKeyword;
}
return StructKeyword;
}
Token* StructDeclaration::getLastToken() {
Token* StructDeclaration::getLastToken() const {
if (Fields.size()) {
Fields.back()->getLastToken();
}
return BlockStart;
}
Token* InstanceDeclaration::getFirstToken() {
Token* InstanceDeclaration::getFirstToken() const {
return InstanceKeyword;
}
Token* InstanceDeclaration::getLastToken() {
Token* InstanceDeclaration::getLastToken() const {
if (!Elements.empty()) {
return Elements.back()->getLastToken();
}
return BlockStart;
}
Token* ClassDeclaration::getFirstToken() {
Token* ClassDeclaration::getFirstToken() const {
if (PubKeyword != nullptr) {
return PubKeyword;
}
return ClassKeyword;
}
Token* ClassDeclaration::getLastToken() {
Token* ClassDeclaration::getLastToken() const {
if (!Elements.empty()) {
return Elements.back()->getLastToken();
}
return BlockStart;
}
Token* SourceFile::getFirstToken() {
Token* SourceFile::getFirstToken() const {
if (Elements.size()) {
return Elements.front()->getFirstToken();
}
return nullptr;
}
Token* SourceFile::getLastToken() {
Token* SourceFile::getLastToken() const {
if (Elements.size()) {
return Elements.back()->getLastToken();
}

View file

@ -1064,7 +1064,7 @@ namespace bolt {
propagateClassTycon(Class, llvm::cast<TCon>(Ty));
}
} else if (!Classes.empty()) {
DE.add<InvalidTypeToTypeclassDiagnostic>(Ty);
DE.add<InvalidTypeToTypeclassDiagnostic>(Ty, std::vector(Classes.begin(), Classes.end()), Source);
}
};

View file

@ -4,11 +4,11 @@
#include <sstream>
#include <cmath>
#include "bolt/CST.hpp"
#include "zen/config.hpp"
#include "bolt/CST.hpp"
#include "bolt/Type.hpp"
#include "bolt/Diagnostics.hpp"
#include "bolt/Checker.hpp"
#define ANSI_RESET "\u001b[0m"
#define ANSI_BOLD "\u001b[1m"
@ -314,7 +314,7 @@ namespace bolt {
}
void ConsoleDiagnostics::writeExcerpt(
TextFile& File,
const TextFile& File,
TextRange ToPrint,
TextRange ToHighlight,
Color HighlightColor
@ -353,166 +353,259 @@ namespace bolt {
}
void ConsoleDiagnostics::addDiagnostic(const Diagnostic& D) {
void ConsoleDiagnostics::write(const std::string_view& S) {
Out << S;
}
switch (D.getKind()) {
void ConsoleDiagnostics::write(std::size_t I) {
Out << I;
}
void ConsoleDiagnostics::writeBinding(const ByteString& Name) {
write("'");
write(Name);
write("'");
}
void ConsoleDiagnostics::writeType(const Type* Ty) {
setForegroundColor(Color::Green);
write(describe(Ty));
resetStyles();
}
void ConsoleDiagnostics::writeType(std::size_t I) {
setForegroundColor(Color::Green);
write(I);
resetStyles();
}
void ConsoleDiagnostics::writeNode(const Node* N) {
auto Range = N->getRange();
writeExcerpt(N->getSourceFile()->getTextFile(), Range, Range, Color::Red);
}
void ConsoleDiagnostics::writeLoc(const TextFile& File, const TextLoc& Loc) {
setForegroundColor(Color::Yellow);
write(File.getPath());
write(":");
write(Loc.Line);
write(":");
write(Loc.Column);
write(":");
resetStyles();
}
void ConsoleDiagnostics::writePrefix(const Diagnostic& D) {
setForegroundColor(Color::Red);
setBold(true);
write("error: ");
resetStyles();
}
void ConsoleDiagnostics::writeTypeclassName(const ByteString& Name) {
setForegroundColor(Color::Magenta);
write(Name);
resetStyles();
}
void ConsoleDiagnostics::writeTypeclassSignature(const TypeclassSignature& Sig) {
setForegroundColor(Color::Magenta);
write(Sig.Id);
for (auto TV: Sig.Params) {
write(" ");
write(describe(TV));
}
resetStyles();
}
void ConsoleDiagnostics::addDiagnostic(Diagnostic* D) {
switch (D->getKind()) {
case DiagnosticKind::BindingNotFound:
{
auto E = static_cast<const BindingNotFoundDiagnostic&>(D);
Out << ANSI_BOLD ANSI_FG_RED "error: " ANSI_RESET "binding '" << E.Name << "' was not found\n\n";
auto E = static_cast<const BindingNotFoundDiagnostic&>(*D);
writePrefix(E);
write("binding '");
writeBinding(E.Name);
write(" was not found\n\n");
if (E.Initiator != nullptr) {
auto Range = E.Initiator->getRange();
//std::cerr << Range.Start.Line << ":" << Range.Start.Column << "-" << Range.End.Line << ":" << Range.End.Column << "\n";
writeExcerpt(E.Initiator->getSourceFile()->getTextFile(), Range, Range, Color::Red);
Out << "\n";
}
return;
break;
}
case DiagnosticKind::UnexpectedToken:
{
auto E = static_cast<const UnexpectedTokenDiagnostic&>(D);
setForegroundColor(Color::Red);
setBold(true);
Out << "error: ";
resetStyles();
setForegroundColor(Color::Yellow);
Out << E.File.getPath() << ":" << E.Actual->getStartLine() << ":" << E.Actual->getStartColumn() << ":";
resetStyles();
Out << " expected ";
auto E = static_cast<const UnexpectedTokenDiagnostic&>(*D);
writePrefix(E);
writeLoc(E.File, E.Actual->getStartLoc());
write(" expected ");
switch (E.Expected.size()) {
case 0:
Out << "nothing";
write("nothing");
break;
case 1:
Out << describe(E.Expected[0]);
write(describe(E.Expected[0]));
break;
default:
auto Iter = E.Expected.begin();
Out << describe(*Iter++);
NodeKind Prev = *Iter++;
while (Iter != E.Expected.end()) {
Out << ", " << describe(Prev);
write(", ");
write(describe(Prev));
Prev = *Iter++;
}
Out << " or " << describe(Prev);
write(" or ");
write(describe(Prev));
break;
}
Out << " but instead got '" << E.Actual->getText() << "'\n\n";
write(" but instead got '");
write(E.Actual->getText());
write("'\n\n");
writeExcerpt(E.File, E.Actual->getRange(), E.Actual->getRange(), Color::Red);
Out << "\n";
return;
write("\n");
break;
}
case DiagnosticKind::UnexpectedString:
{
auto E = static_cast<const UnexpectedStringDiagnostic&>(D);
setForegroundColor(Color::Red);
setBold(true);
Out << "error: ";
resetStyles();
Out << E.File.getPath() << ":" << E.Location.Line << ":" << E.Location.Column << ": unexpected '";
auto E = static_cast<const UnexpectedStringDiagnostic&>(*D);
writePrefix(E);
writeLoc(E.File, E.Location);
write(" unexpected '");
for (auto Chr: E.Actual) {
switch (Chr) {
case '\\':
Out << "\\\\";
write("\\\\");
break;
case '\'':
Out << "\\'";
write("\\'");
break;
default:
Out << Chr;
write(Chr);
break;
}
}
Out << "'\n\n";
write("'\n\n");
TextRange Range { E.Location, E.Location + E.Actual };
writeExcerpt(E.File, Range, Range, Color::Red);
Out << "\n";
return;
write("\n");
break;
}
case DiagnosticKind::UnificationError:
{
auto E = static_cast<const UnificationErrorDiagnostic&>(D);
setForegroundColor(Color::Red);
setBold(true);
Out << "error: ";
resetStyles();
auto E = static_cast<const UnificationErrorDiagnostic&>(*D);
writePrefix(E);
auto Left = E.Left->resolve(E.LeftPath);
auto Right = E.Right->resolve(E.RightPath);
Out << "the types " << ANSI_FG_GREEN << describe(Left) << ANSI_RESET
<< " and " << ANSI_FG_GREEN << describe(Right) << ANSI_RESET << " failed to match\n\n";
write("the types ");
writeType(Left);
write(" and ");
writeType(Right);
write(" failed to match\n\n");
if (E.Source) {
auto Range = E.Source->getRange();
writeExcerpt(E.Source->getSourceFile()->getTextFile(), Range, Range, Color::Red);
writeNode(E.Source);
Out << "\n";
}
if (!E.LeftPath.empty()) {
setForegroundColor(Color::Yellow);
setBold(true);
Out << " info: ";
write(" info: ");
resetStyles();
Out << "type " << ANSI_FG_GREEN << describe(Left) << ANSI_RESET << " occurs in the full type " << ANSI_FG_GREEN << describe(E.Left) << ANSI_RESET << "\n\n";
write("the type ");
writeType(Left);
write(" occurs in the full type ");
writeType(E.Left);
write("\n\n");
}
if (!E.RightPath.empty()) {
setForegroundColor(Color::Yellow);
setBold(true);
Out << " info: ";
write(" info: ");
resetStyles();
Out << "type " << ANSI_FG_GREEN << describe(Right) << ANSI_RESET << " occurs in the full type " << ANSI_FG_GREEN << describe(E.Right) << ANSI_RESET << "\n\n";
write("the type ");
writeType(Right);
write(" occurs in the full type ");
writeType(E.Right);
write("\n\n");
}
return;
break;
}
case DiagnosticKind::TypeclassMissing:
{
auto E = static_cast<const TypeclassMissingDiagnostic&>(D);
setForegroundColor(Color::Red);
setBold(true);
Out << "error: ";
resetStyles();
Out << "the type class " << ANSI_FG_YELLOW << E.Sig.Id;
for (auto TV: E.Sig.Params) {
Out << " " << describe(TV);
}
Out << ANSI_RESET << " is missing from the declaration's type signature\n\n";
auto Range = E.Decl->getRange();
writeExcerpt(E.Decl->getSourceFile()->getTextFile(), Range, Range, Color::Yellow);
Out << "\n\n";
return;
auto E = static_cast<const TypeclassMissingDiagnostic&>(*D);
writePrefix(E);
write("the type class ");
writeTypeclassSignature(E.Sig);
write(" is missing from the declaration's type signature\n\n");
writeNode(E.Decl);
write("\n\n");
break;
}
case DiagnosticKind::InstanceNotFound:
{
auto E = static_cast<const InstanceNotFoundDiagnostic&>(D);
setForegroundColor(Color::Red);
setBold(true);
Out << "error: ";
resetStyles();
Out << "a type class instance " << ANSI_FG_YELLOW << E.TypeclassName << " " << describe(E.Ty) << ANSI_RESET " was not found.\n\n";
auto Range = E.Source->getRange();
//std::cerr << Range.Start.Line << ":" << Range.Start.Column << "-" << Range.End.Line << ":" << Range.End.Column << "\n";
writeExcerpt(E.Source->getSourceFile()->getTextFile(), Range, Range, Color::Red);
Out << "\n";
return;
auto E = static_cast<const InstanceNotFoundDiagnostic&>(*D);
writePrefix(E);
write("a type class instance ");
writeTypeclassName(E.TypeclassName);
writeType(E.Ty);
write(" was not found.\n\n");
writeNode(E.Source);
write("\n");
break;
}
case DiagnosticKind::ClassNotFound:
{
auto E = static_cast<const ClassNotFoundDiagnostic&>(D);
setForegroundColor(Color::Red);
setBold(true);
Out << "error: ";
resetStyles();
Out << "the type class " << ANSI_FG_YELLOW << E.Name << ANSI_RESET " was not found.\n\n";
return;
auto E = static_cast<const ClassNotFoundDiagnostic&>(*D);
writePrefix(E);
write("the type class ");
writeTypeclassName(E.Name);
write(" was not found.\n\n");
break;
}
case DiagnosticKind::TupleIndexOutOfRange:
{
auto E = static_cast<const TupleIndexOutOfRangeDiagnostic&>(*D);
writePrefix(E);
write("the index ");
writeType(E.I);
write(" is out of range for tuple ");
writeType(E.Tuple);
break;
}
case DiagnosticKind::InvalidTypeToTypeclass:
{
auto E = static_cast<const InvalidTypeToTypeclassDiagnostic&>(*D);
writePrefix(E);
write("the type ");
writeType(E.Actual);
write(" was applied to type class names ");
bool First = true;
for (auto Class: E.Classes) {
if (First) First = false;
else write(", ");
writeTypeclassName(Class);
}
write(" but this is invalid\n\n");
break;
}
}
ZEN_UNREACHABLE
// Since this DiagnosticEngine is expected to own the diagnostic, we simply
// destroy the processed diagnostic so that there are no memory leaks.
delete D;
}
}

View file

@ -38,8 +38,8 @@ namespace bolt {
Mapping.emplace(Name, OperatorInfo { Precedence, Flags });
}
Parser::Parser(TextFile& File, Stream<Token*>& S):
File(File), Tokens(S) {
Parser::Parser(TextFile& File, Stream<Token*>& S, DiagnosticEngine& DE):
File(File), Tokens(S), DE(DE) {
ExprOperators.add("**", OperatorFlags_InfixR, 10);
ExprOperators.add("*", OperatorFlags_InfixL, 5);
ExprOperators.add("/", OperatorFlags_InfixL, 5);

View file

@ -22,11 +22,11 @@ namespace bolt {
return LineOffsets.size();
}
size_t TextFile::getStartOffset(size_t Line) {
size_t TextFile::getStartOffset(size_t Line) const {
return LineOffsets[Line-1];
}
size_t TextFile::getLine(size_t Offset) {
size_t TextFile::getLine(size_t Offset) const {
ZEN_ASSERT(Offset < Text.size());
for (size_t I = 0; I < LineOffsets.size(); ++I) {
if (LineOffsets[I] > Offset) {
@ -36,7 +36,7 @@ namespace bolt {
ZEN_UNREACHABLE
}
size_t TextFile::getColumn(size_t Offset) {
size_t TextFile::getColumn(size_t Offset) const {
auto Line = getLine(Offset);
auto StartOffset = getStartOffset(Line);
return Offset - StartOffset + 1 ;

View file

@ -3,6 +3,7 @@
#include <iostream>
#include <fstream>
#include <algorithm>
#include "zen/config.hpp"
@ -44,22 +45,39 @@ int main(int argc, const char* argv[]) {
VectorStream<ByteString, Char> Chars(Text, EOF);
Scanner S(File, Chars);
Punctuator PT(S);
Parser P(File, PT);
Parser P(File, PT, DE);
SourceFile* SF;
try {
SF = P.parseSourceFile();
} catch (Diagnostic& D) {
DE.addDiagnostic(D);
auto SF = P.parseSourceFile();
if (SF == nullptr) {
return 1;
}
SF->setParents();
Checker TheChecker { Config, DE };
DiagnosticStore DS;
Checker TheChecker { Config, DS };
TheChecker.check(SF);
auto LT = [](const Diagnostic* L, const Diagnostic* R) {
auto N1 = L->getNode();
auto N2 = R->getNode();
if (N1 == nullptr && N2 == nullptr) {
return false;
}
if (N1 == nullptr) {
return true;
}
if (N2 == nullptr) {
return false;
}
return N1->getStartLine() < N2->getStartLine() || N1->getStartColumn() < N2->getStartColumn();
};
std::sort(DS.Diagnostics.begin(), DS.Diagnostics.end(), LT);
for (auto D: DS.Diagnostics) {
DE.addDiagnostic(D);
}
return 0;
}