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

View file

@ -39,6 +39,11 @@ namespace bolt {
return Kind; return Kind;
} }
virtual Node* getNode() const {
return nullptr;
}
}; };
class UnexpectedTokenDiagnostic : public Diagnostic { class UnexpectedTokenDiagnostic : public Diagnostic {
@ -74,6 +79,10 @@ namespace bolt {
inline BindingNotFoundDiagnostic(ByteString Name, Node* Initiator): inline BindingNotFoundDiagnostic(ByteString Name, Node* Initiator):
Diagnostic(DiagnosticKind::BindingNotFound), Name(Name), Initiator(Initiator) {} Diagnostic(DiagnosticKind::BindingNotFound), Name(Name), Initiator(Initiator) {}
inline Node* getNode() const override {
return Initiator;
}
}; };
class UnificationErrorDiagnostic : public Diagnostic { class UnificationErrorDiagnostic : public Diagnostic {
@ -88,6 +97,10 @@ namespace bolt {
inline UnificationErrorDiagnostic(Type* Left, Type* Right, TypePath LeftPath, TypePath RightPath, Node* Source): 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) {} Diagnostic(DiagnosticKind::UnificationError), Left(Left), Right(Right), LeftPath(LeftPath), RightPath(RightPath), Source(Source) {}
inline Node* getNode() const override {
return Source;
}
}; };
class TypeclassMissingDiagnostic : public Diagnostic { class TypeclassMissingDiagnostic : public Diagnostic {
@ -99,6 +112,10 @@ namespace bolt {
inline TypeclassMissingDiagnostic(TypeclassSignature Sig, LetDeclaration* Decl): inline TypeclassMissingDiagnostic(TypeclassSignature Sig, LetDeclaration* Decl):
Diagnostic(DiagnosticKind::TypeclassMissing), Sig(Sig), Decl(Decl) {} Diagnostic(DiagnosticKind::TypeclassMissing), Sig(Sig), Decl(Decl) {}
inline Node* getNode() const override {
return Decl;
}
}; };
class InstanceNotFoundDiagnostic : public Diagnostic { class InstanceNotFoundDiagnostic : public Diagnostic {
@ -111,6 +128,10 @@ namespace bolt {
inline InstanceNotFoundDiagnostic(ByteString TypeclassName, TCon* Ty, Node* Source): inline InstanceNotFoundDiagnostic(ByteString TypeclassName, TCon* Ty, Node* Source):
Diagnostic(DiagnosticKind::InstanceNotFound), TypeclassName(TypeclassName), Ty(Ty), Source(Source) {} Diagnostic(DiagnosticKind::InstanceNotFound), TypeclassName(TypeclassName), Ty(Ty), Source(Source) {}
inline Node* getNode() const override {
return Source;
}
}; };
class ClassNotFoundDiagnostic : public Diagnostic { class ClassNotFoundDiagnostic : public Diagnostic {
@ -138,29 +159,56 @@ namespace bolt {
public: public:
Type* Actual; Type* Actual;
std::vector<TypeclassId> Classes;
Node* Source;
inline InvalidTypeToTypeclassDiagnostic(Type* Actual): inline InvalidTypeToTypeclassDiagnostic(Type* Actual, std::vector<TypeclassId> Classes, Node* Source):
Diagnostic(DiagnosticKind::InvalidTypeToTypeclass) {} Diagnostic(DiagnosticKind::InvalidTypeToTypeclass), Actual(Actual), Classes(Classes), Source(Source) {}
inline Node* getNode() const override {
return Source;
}
}; };
class DiagnosticEngine { class DiagnosticEngine {
protected:
public: public:
virtual void addDiagnostic(const Diagnostic& Diagnostic) = 0; virtual void addDiagnostic(Diagnostic* Diagnostic) = 0;
template<typename D, typename ...Ts> template<typename D, typename ...Ts>
void add(Ts&&... Args) { void add(Ts&&... Args) {
D Diag { std::forward<Ts>(Args)... }; addDiagnostic(new D { std::forward<Ts>(Args)... });
addDiagnostic(Diag);
} }
virtual ~DiagnosticEngine() {} 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 { enum class Color {
None, None,
Black, Black,
@ -198,12 +246,25 @@ namespace bolt {
); );
void writeExcerpt( void writeExcerpt(
TextFile& File, const TextFile& File,
TextRange ToPrint, TextRange ToPrint,
TextRange ToHighlight, TextRange ToHighlight,
Color HighlightColor 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: public:
unsigned ExcerptLinesPre = 2; unsigned ExcerptLinesPre = 2;
@ -213,9 +274,10 @@ namespace bolt {
bool PrintExcerpts = true; bool PrintExcerpts = true;
bool EnableColors = true; bool EnableColors = true;
void addDiagnostic(const Diagnostic& Diagnostic) override;
ConsoleDiagnostics(std::ostream& Out = std::cerr); ConsoleDiagnostics(std::ostream& Out = std::cerr);
void addDiagnostic(Diagnostic* Diagnostic) override;
}; };
} }

View file

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

View file

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

View file

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

View file

@ -1064,7 +1064,7 @@ namespace bolt {
propagateClassTycon(Class, llvm::cast<TCon>(Ty)); propagateClassTycon(Class, llvm::cast<TCon>(Ty));
} }
} else if (!Classes.empty()) { } 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 <sstream>
#include <cmath> #include <cmath>
#include "bolt/CST.hpp"
#include "zen/config.hpp" #include "zen/config.hpp"
#include "bolt/CST.hpp"
#include "bolt/Type.hpp"
#include "bolt/Diagnostics.hpp" #include "bolt/Diagnostics.hpp"
#include "bolt/Checker.hpp"
#define ANSI_RESET "\u001b[0m" #define ANSI_RESET "\u001b[0m"
#define ANSI_BOLD "\u001b[1m" #define ANSI_BOLD "\u001b[1m"
@ -314,7 +314,7 @@ namespace bolt {
} }
void ConsoleDiagnostics::writeExcerpt( void ConsoleDiagnostics::writeExcerpt(
TextFile& File, const TextFile& File,
TextRange ToPrint, TextRange ToPrint,
TextRange ToHighlight, TextRange ToHighlight,
Color HighlightColor 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: case DiagnosticKind::BindingNotFound:
{ {
auto E = static_cast<const BindingNotFoundDiagnostic&>(D); auto E = static_cast<const BindingNotFoundDiagnostic&>(*D);
Out << ANSI_BOLD ANSI_FG_RED "error: " ANSI_RESET "binding '" << E.Name << "' was not found\n\n"; writePrefix(E);
write("binding '");
writeBinding(E.Name);
write(" was not found\n\n");
if (E.Initiator != nullptr) { if (E.Initiator != nullptr) {
auto Range = E.Initiator->getRange(); auto Range = E.Initiator->getRange();
//std::cerr << Range.Start.Line << ":" << Range.Start.Column << "-" << Range.End.Line << ":" << Range.End.Column << "\n"; //std::cerr << Range.Start.Line << ":" << Range.Start.Column << "-" << Range.End.Line << ":" << Range.End.Column << "\n";
writeExcerpt(E.Initiator->getSourceFile()->getTextFile(), Range, Range, Color::Red); writeExcerpt(E.Initiator->getSourceFile()->getTextFile(), Range, Range, Color::Red);
Out << "\n"; Out << "\n";
} }
return; break;
} }
case DiagnosticKind::UnexpectedToken: case DiagnosticKind::UnexpectedToken:
{ {
auto E = static_cast<const UnexpectedTokenDiagnostic&>(D); auto E = static_cast<const UnexpectedTokenDiagnostic&>(*D);
setForegroundColor(Color::Red); writePrefix(E);
setBold(true); writeLoc(E.File, E.Actual->getStartLoc());
Out << "error: "; write(" expected ");
resetStyles();
setForegroundColor(Color::Yellow);
Out << E.File.getPath() << ":" << E.Actual->getStartLine() << ":" << E.Actual->getStartColumn() << ":";
resetStyles();
Out << " expected ";
switch (E.Expected.size()) { switch (E.Expected.size()) {
case 0: case 0:
Out << "nothing"; write("nothing");
break; break;
case 1: case 1:
Out << describe(E.Expected[0]); write(describe(E.Expected[0]));
break; break;
default: default:
auto Iter = E.Expected.begin(); auto Iter = E.Expected.begin();
Out << describe(*Iter++); Out << describe(*Iter++);
NodeKind Prev = *Iter++; NodeKind Prev = *Iter++;
while (Iter != E.Expected.end()) { while (Iter != E.Expected.end()) {
Out << ", " << describe(Prev); write(", ");
write(describe(Prev));
Prev = *Iter++; Prev = *Iter++;
} }
Out << " or " << describe(Prev); write(" or ");
write(describe(Prev));
break; 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); writeExcerpt(E.File, E.Actual->getRange(), E.Actual->getRange(), Color::Red);
Out << "\n"; write("\n");
return; break;
} }
case DiagnosticKind::UnexpectedString: case DiagnosticKind::UnexpectedString:
{ {
auto E = static_cast<const UnexpectedStringDiagnostic&>(D); auto E = static_cast<const UnexpectedStringDiagnostic&>(*D);
setForegroundColor(Color::Red); writePrefix(E);
setBold(true); writeLoc(E.File, E.Location);
Out << "error: "; write(" unexpected '");
resetStyles();
Out << E.File.getPath() << ":" << E.Location.Line << ":" << E.Location.Column << ": unexpected '";
for (auto Chr: E.Actual) { for (auto Chr: E.Actual) {
switch (Chr) { switch (Chr) {
case '\\': case '\\':
Out << "\\\\"; write("\\\\");
break; break;
case '\'': case '\'':
Out << "\\'"; write("\\'");
break; break;
default: default:
Out << Chr; write(Chr);
break; break;
} }
} }
Out << "'\n\n"; write("'\n\n");
TextRange Range { E.Location, E.Location + E.Actual }; TextRange Range { E.Location, E.Location + E.Actual };
writeExcerpt(E.File, Range, Range, Color::Red); writeExcerpt(E.File, Range, Range, Color::Red);
Out << "\n"; write("\n");
return; break;
} }
case DiagnosticKind::UnificationError: case DiagnosticKind::UnificationError:
{ {
auto E = static_cast<const UnificationErrorDiagnostic&>(D); auto E = static_cast<const UnificationErrorDiagnostic&>(*D);
setForegroundColor(Color::Red); writePrefix(E);
setBold(true);
Out << "error: ";
resetStyles();
auto Left = E.Left->resolve(E.LeftPath); auto Left = E.Left->resolve(E.LeftPath);
auto Right = E.Right->resolve(E.RightPath); auto Right = E.Right->resolve(E.RightPath);
Out << "the types " << ANSI_FG_GREEN << describe(Left) << ANSI_RESET write("the types ");
<< " and " << ANSI_FG_GREEN << describe(Right) << ANSI_RESET << " failed to match\n\n"; writeType(Left);
write(" and ");
writeType(Right);
write(" failed to match\n\n");
if (E.Source) { if (E.Source) {
auto Range = E.Source->getRange(); writeNode(E.Source);
writeExcerpt(E.Source->getSourceFile()->getTextFile(), Range, Range, Color::Red);
Out << "\n"; Out << "\n";
} }
if (!E.LeftPath.empty()) { if (!E.LeftPath.empty()) {
setForegroundColor(Color::Yellow); setForegroundColor(Color::Yellow);
setBold(true); setBold(true);
Out << " info: "; write(" info: ");
resetStyles(); 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()) { if (!E.RightPath.empty()) {
setForegroundColor(Color::Yellow); setForegroundColor(Color::Yellow);
setBold(true); setBold(true);
Out << " info: "; write(" info: ");
resetStyles(); 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: case DiagnosticKind::TypeclassMissing:
{ {
auto E = static_cast<const TypeclassMissingDiagnostic&>(D); auto E = static_cast<const TypeclassMissingDiagnostic&>(*D);
setForegroundColor(Color::Red); writePrefix(E);
setBold(true); write("the type class ");
Out << "error: "; writeTypeclassSignature(E.Sig);
resetStyles(); write(" is missing from the declaration's type signature\n\n");
Out << "the type class " << ANSI_FG_YELLOW << E.Sig.Id; writeNode(E.Decl);
for (auto TV: E.Sig.Params) { write("\n\n");
Out << " " << describe(TV); break;
}
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;
} }
case DiagnosticKind::InstanceNotFound: case DiagnosticKind::InstanceNotFound:
{ {
auto E = static_cast<const InstanceNotFoundDiagnostic&>(D); auto E = static_cast<const InstanceNotFoundDiagnostic&>(*D);
setForegroundColor(Color::Red); writePrefix(E);
setBold(true); write("a type class instance ");
Out << "error: "; writeTypeclassName(E.TypeclassName);
resetStyles(); writeType(E.Ty);
Out << "a type class instance " << ANSI_FG_YELLOW << E.TypeclassName << " " << describe(E.Ty) << ANSI_RESET " was not found.\n\n"; write(" was not found.\n\n");
auto Range = E.Source->getRange(); writeNode(E.Source);
//std::cerr << Range.Start.Line << ":" << Range.Start.Column << "-" << Range.End.Line << ":" << Range.End.Column << "\n"; write("\n");
writeExcerpt(E.Source->getSourceFile()->getTextFile(), Range, Range, Color::Red); break;
Out << "\n";
return;
} }
case DiagnosticKind::ClassNotFound: case DiagnosticKind::ClassNotFound:
{ {
auto E = static_cast<const ClassNotFoundDiagnostic&>(D); auto E = static_cast<const ClassNotFoundDiagnostic&>(*D);
setForegroundColor(Color::Red); writePrefix(E);
setBold(true); write("the type class ");
Out << "error: "; writeTypeclassName(E.Name);
resetStyles(); write(" was not found.\n\n");
Out << "the type class " << ANSI_FG_YELLOW << E.Name << ANSI_RESET " was not found.\n\n"; break;
return; }
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 }); Mapping.emplace(Name, OperatorInfo { Precedence, Flags });
} }
Parser::Parser(TextFile& File, Stream<Token*>& S): Parser::Parser(TextFile& File, Stream<Token*>& S, DiagnosticEngine& DE):
File(File), Tokens(S) { File(File), Tokens(S), DE(DE) {
ExprOperators.add("**", OperatorFlags_InfixR, 10); ExprOperators.add("**", OperatorFlags_InfixR, 10);
ExprOperators.add("*", OperatorFlags_InfixL, 5); ExprOperators.add("*", OperatorFlags_InfixL, 5);
ExprOperators.add("/", OperatorFlags_InfixL, 5); ExprOperators.add("/", OperatorFlags_InfixL, 5);

View file

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

View file

@ -3,6 +3,7 @@
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <algorithm>
#include "zen/config.hpp" #include "zen/config.hpp"
@ -44,22 +45,39 @@ int main(int argc, const char* argv[]) {
VectorStream<ByteString, Char> Chars(Text, EOF); VectorStream<ByteString, Char> Chars(Text, EOF);
Scanner S(File, Chars); Scanner S(File, Chars);
Punctuator PT(S); Punctuator PT(S);
Parser P(File, PT); Parser P(File, PT, DE);
SourceFile* SF; auto SF = P.parseSourceFile();
if (SF == nullptr) {
try {
SF = P.parseSourceFile();
} catch (Diagnostic& D) {
DE.addDiagnostic(D);
return 1; return 1;
} }
SF->setParents(); SF->setParents();
Checker TheChecker { Config, DE }; DiagnosticStore DS;
Checker TheChecker { Config, DS };
TheChecker.check(SF); 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; return 0;
} }