diff --git a/include/bolt/CST.hpp b/include/bolt/CST.hpp index ee4d71a6c..5dff45223 100644 --- a/include/bolt/CST.hpp +++ b/include/bolt/CST.hpp @@ -1,6 +1,7 @@ #ifndef BOLT_CST_HPP #define BOLT_CST_HPP +#include #include #include "bolt/Text.hpp" @@ -57,29 +58,41 @@ namespace bolt { SourceFile, }; + class Token; + class SourceFile; class Node { - unsigned refcount = 0; + unsigned RefCount = 0; public: + Node* Parent = nullptr; + inline void ref() { - ++refcount; + ++RefCount; } inline void unref() { - --refcount; - if (refcount == 0) { + --RefCount; + if (RefCount == 0) { delete this; } } + virtual void setParents() = 0; + + virtual Token* getFirstToken() = 0; + virtual Token* getLastToken() = 0; + + TextRange getRange(); + const NodeType Type; inline Node(NodeType Type): Type(Type) {} + SourceFile* getSourceFile(); virtual ~Node(); @@ -95,6 +108,16 @@ namespace bolt { virtual std::string getText() const = 0; + void setParents() override; + + inline Token* getFirstToken() override { + return this; + } + + inline Token* getLastToken() override { + return this; + } + inline TextLoc getStartLoc() { return StartLoc; } @@ -128,7 +151,8 @@ namespace bolt { class Equals : public Token { public: - Equals(TextLoc StartLoc): Token(NodeType::Equals, StartLoc) {} + Equals(TextLoc StartLoc): + Token(NodeType::Equals, StartLoc) {} std::string getText() const override; @@ -139,7 +163,8 @@ namespace bolt { class Colon : public Token { public: - Colon(TextLoc StartLoc): Token(NodeType::Colon, StartLoc) {} + Colon(TextLoc StartLoc): + Token(NodeType::Colon, StartLoc) {} std::string getText() const override; @@ -150,7 +175,8 @@ namespace bolt { class Dot : public Token { public: - Dot(TextLoc StartLoc): Token(NodeType::Dot, StartLoc) {} + Dot(TextLoc StartLoc): + Token(NodeType::Dot, StartLoc) {} std::string getText() const override; @@ -161,7 +187,8 @@ namespace bolt { class DotDot : public Token { public: - DotDot(TextLoc StartLoc): Token(NodeType::DotDot, StartLoc) {} + DotDot(TextLoc StartLoc): + Token(NodeType::DotDot, StartLoc) {} std::string getText() const override; @@ -172,7 +199,8 @@ namespace bolt { class LParen : public Token { public: - LParen(TextLoc StartLoc): Token(NodeType::LParen, StartLoc) {} + LParen(TextLoc StartLoc): + Token(NodeType::LParen, StartLoc) {} std::string getText() const override; @@ -183,7 +211,8 @@ namespace bolt { class RParen : public Token { public: - RParen(TextLoc StartLoc): Token(NodeType::RParen, StartLoc) {} + RParen(TextLoc StartLoc): + Token(NodeType::RParen, StartLoc) {} std::string getText() const override; @@ -194,7 +223,8 @@ namespace bolt { class LBracket : public Token { public: - LBracket(TextLoc StartLoc): Token(NodeType::LBracket, StartLoc) {} + LBracket(TextLoc StartLoc): + Token(NodeType::LBracket, StartLoc) {} std::string getText() const override; @@ -205,7 +235,8 @@ namespace bolt { class RBracket : public Token { public: - RBracket(TextLoc StartLoc): Token(NodeType::RBracket, StartLoc) {} + RBracket(TextLoc StartLoc): + Token(NodeType::RBracket, StartLoc) {} std::string getText() const override; @@ -216,7 +247,8 @@ namespace bolt { class LBrace : public Token { public: - LBrace(TextLoc StartLoc): Token(NodeType::LBrace, StartLoc) {} + LBrace(TextLoc StartLoc): + Token(NodeType::LBrace, StartLoc) {} std::string getText() const override; @@ -227,7 +259,8 @@ namespace bolt { class RBrace : public Token { public: - RBrace(TextLoc StartLoc): Token(NodeType::RBrace, StartLoc) {} + RBrace(TextLoc StartLoc): + Token(NodeType::RBrace, StartLoc) {} std::string getText() const override; @@ -238,7 +271,8 @@ namespace bolt { class LetKeyword : public Token { public: - LetKeyword(TextLoc StartLoc): Token(NodeType::LetKeyword, StartLoc) {} + LetKeyword(TextLoc StartLoc): + Token(NodeType::LetKeyword, StartLoc) {} std::string getText() const override; @@ -249,7 +283,8 @@ namespace bolt { class MutKeyword : public Token { public: - MutKeyword(TextLoc StartLoc): Token(NodeType::MutKeyword, StartLoc) {} + MutKeyword(TextLoc StartLoc): + Token(NodeType::MutKeyword, StartLoc) {} std::string getText() const override; @@ -260,7 +295,8 @@ namespace bolt { class PubKeyword : public Token { public: - PubKeyword(TextLoc StartLoc): Token(NodeType::PubKeyword, StartLoc) {} + PubKeyword(TextLoc StartLoc): + Token(NodeType::PubKeyword, StartLoc) {} std::string getText() const override; @@ -271,7 +307,8 @@ namespace bolt { class TypeKeyword : public Token { public: - TypeKeyword(TextLoc StartLoc): Token(NodeType::TypeKeyword, StartLoc) {} + TypeKeyword(TextLoc StartLoc): + Token(NodeType::TypeKeyword, StartLoc) {} std::string getText() const override; @@ -282,7 +319,8 @@ namespace bolt { class ReturnKeyword : public Token { public: - ReturnKeyword(TextLoc StartLoc): Token(NodeType::ReturnKeyword, StartLoc) {} + ReturnKeyword(TextLoc StartLoc): + Token(NodeType::ReturnKeyword, StartLoc) {} std::string getText() const override; @@ -293,7 +331,8 @@ namespace bolt { class ModKeyword : public Token { public: - ModKeyword(TextLoc StartLoc): Token(NodeType::ModKeyword, StartLoc) {} + ModKeyword(TextLoc StartLoc): + Token(NodeType::ModKeyword, StartLoc) {} std::string getText() const override; @@ -304,7 +343,8 @@ namespace bolt { class StructKeyword : public Token { public: - StructKeyword(TextLoc StartLoc): Token(NodeType::StructKeyword, StartLoc) {} + StructKeyword(TextLoc StartLoc): + Token(NodeType::StructKeyword, StartLoc) {} std::string getText() const override; @@ -315,7 +355,8 @@ namespace bolt { class Invalid : public Token { public: - Invalid(TextLoc StartLoc): Token(NodeType::Invalid, StartLoc) {} + Invalid(TextLoc StartLoc): + Token(NodeType::Invalid, StartLoc) {} std::string getText() const override; @@ -326,7 +367,8 @@ namespace bolt { class EndOfFile : public Token { public: - EndOfFile(TextLoc StartLoc): Token(NodeType::EndOfFile, StartLoc) {} + EndOfFile(TextLoc StartLoc): + Token(NodeType::EndOfFile, StartLoc) {} std::string getText() const override; @@ -337,7 +379,8 @@ namespace bolt { class BlockStart : public Token { public: - BlockStart(TextLoc StartLoc): Token(NodeType::BlockStart, StartLoc) {} + BlockStart(TextLoc StartLoc): + Token(NodeType::BlockStart, StartLoc) {} std::string getText() const override; @@ -348,7 +391,8 @@ namespace bolt { class BlockEnd : public Token { public: - BlockEnd(TextLoc StartLoc): Token(NodeType::BlockEnd, StartLoc) {} + BlockEnd(TextLoc StartLoc): + Token(NodeType::BlockEnd, StartLoc) {} std::string getText() const override; @@ -359,7 +403,8 @@ namespace bolt { class LineFoldEnd : public Token { public: - LineFoldEnd(TextLoc StartLoc): Token(NodeType::LineFoldEnd, StartLoc) {} + LineFoldEnd(TextLoc StartLoc): + Token(NodeType::LineFoldEnd, StartLoc) {} std::string getText() const override; @@ -372,7 +417,8 @@ namespace bolt { ByteString Text; - CustomOperator(ByteString Text, TextLoc StartLoc): Token(NodeType::CustomOperator, StartLoc), Text(Text) {} + CustomOperator(ByteString Text, TextLoc StartLoc): + Token(NodeType::CustomOperator, StartLoc), Text(Text) {} std::string getText() const override; @@ -385,7 +431,8 @@ namespace bolt { ByteString Text; - Assignment(ByteString Text, TextLoc StartLoc): Token(NodeType::Assignment, StartLoc), Text(Text) {} + Assignment(ByteString Text, TextLoc StartLoc): + Token(NodeType::Assignment, StartLoc), Text(Text) {} std::string getText() const override; @@ -398,7 +445,8 @@ namespace bolt { ByteString Text; - Identifier(ByteString Text, TextLoc StartLoc): Token(NodeType::Identifier, StartLoc), Text(Text) {} + Identifier(ByteString Text, TextLoc StartLoc): + Token(NodeType::Identifier, StartLoc), Text(Text) {} std::string getText() const override; @@ -411,7 +459,8 @@ namespace bolt { ByteString Text; - StringLiteral(ByteString Text, TextLoc StartLoc): Token(NodeType::StringLiteral, StartLoc), Text(Text) {} + StringLiteral(ByteString Text, TextLoc StartLoc): + Token(NodeType::StringLiteral, StartLoc), Text(Text) {} std::string getText() const override; @@ -424,7 +473,8 @@ namespace bolt { Integer Value; - IntegerLiteral(Integer Value, TextLoc StartLoc): Token(NodeType::IntegerLiteral, StartLoc), Value(Value) {} + IntegerLiteral(Integer Value, TextLoc StartLoc): + Token(NodeType::IntegerLiteral, StartLoc), Value(Value) {} std::string getText() const override; @@ -445,6 +495,11 @@ namespace bolt { ModulePath(ModulePath), Name(Name) {} + Token* getFirstToken() override; + Token* getLastToken() override; + + void setParents() override; + ~QualifiedName(); }; @@ -468,6 +523,11 @@ namespace bolt { ): TypeExpression(NodeType::ReferenceTypeExpression), Name(Name) {} + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~ReferenceTypeExpression(); }; @@ -491,6 +551,11 @@ namespace bolt { ): Pattern(NodeType::BindPattern), Name(Name) {} + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~BindPattern(); }; @@ -507,13 +572,18 @@ namespace bolt { class ReferenceExpression : public Expression { public: - Identifier* Name; + QualifiedName* Name; ReferenceExpression( - Identifier* Name + QualifiedName* Name ): Expression(NodeType::ReferenceExpression), Name(Name) {} + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~ReferenceExpression(); }; @@ -528,6 +598,11 @@ namespace bolt { ): Expression(NodeType::ConstantExpression), Token(Token) {} + void setParents() override; + + class Token* getFirstToken() override; + class Token* getLastToken() override; + ~ConstantExpression(); }; @@ -535,11 +610,21 @@ namespace bolt { class CallExpression : public Expression { public: - CallExpression(Expression* Function, std::vector Args): Expression(NodeType::CallExpression), Function(Function), Args(Args) {} - Expression* Function; std::vector Args; + CallExpression( + Expression* Function, + std::vector Args + ): Expression(NodeType::CallExpression), + Function(Function), + Args(Args) {} + + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~CallExpression(); }; @@ -557,6 +642,11 @@ namespace bolt { Operator(Operator), RHS(RHS) {} + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~InfixExpression(); }; @@ -574,6 +664,11 @@ namespace bolt { Operator(Operator), Argument(Argument) {} + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~UnaryExpression(); }; @@ -590,10 +685,15 @@ namespace bolt { class ExpressionStatement : public Statement { public: - ExpressionStatement(Expression* Expression): + Expression* Expression; + + ExpressionStatement(class Expression* Expression): Statement(NodeType::ExpressionStatement), Expression(Expression) {} - Expression* Expression; + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; ~ExpressionStatement(); @@ -602,24 +702,43 @@ namespace bolt { class ReturnStatement : public Statement { public: - ReturnStatement(ReturnKeyword* ReturnKeyword, Expression* Expression): Statement(NodeType::ReturnStatement), ReturnKeyword(ReturnKeyword), Expression(Expression) {} - ReturnKeyword* ReturnKeyword; Expression* Expression; + ReturnStatement( + class ReturnKeyword* ReturnKeyword, + class Expression* Expression + ): Statement(NodeType::ReturnStatement), + ReturnKeyword(ReturnKeyword), + Expression(Expression) {} + + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~ReturnStatement(); }; class TypeAssert : public Node { - - public: - - TypeAssert(Colon* Colon, TypeExpression* TypeExpression): Node(NodeType::TypeAssert), Colon(Colon), TypeExpression(TypeExpression) {} + public: Colon* Colon; TypeExpression* TypeExpression; + TypeAssert( + class Colon* Colon, + class TypeExpression* TypeExpression + ): Node(NodeType::TypeAssert), + Colon(Colon), + TypeExpression(TypeExpression) {} + + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~TypeAssert(); }; @@ -632,6 +751,11 @@ namespace bolt { Pattern* Pattern; TypeAssert* TypeAssert; + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~Param(); }; @@ -648,15 +772,20 @@ namespace bolt { class LetBlockBody : public LetBody { public: + BlockStart* BlockStart; + std::vector Elements; + LetBlockBody( - BlockStart* BlockStart, + class BlockStart* BlockStart, std::vector Elements ): LetBody(NodeType::LetBlockBody), BlockStart(BlockStart), Elements(Elements) {} - BlockStart* BlockStart; - std::vector Elements; + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; ~LetBlockBody(); @@ -675,6 +804,11 @@ namespace bolt { Equals(Equals), Expression(Expression) {} + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~LetExprBody(); }; @@ -683,7 +817,7 @@ namespace bolt { public: PubKeyword* PubKeyword; - LetKeyword* LetKeywod; + LetKeyword* LetKeyword; MutKeyword* MutKeyword; Pattern* Pattern; std::vector Params; @@ -700,13 +834,18 @@ namespace bolt { LetBody* Body ): Node(NodeType::LetDeclaration), PubKeyword(PubKeyword), - LetKeywod(LetKeywod), + LetKeyword(LetKeywod), MutKeyword(MutKeyword), Pattern(Pattern), Params(Params), TypeAssert(TypeAssert), Body(Body) {} + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~LetDeclaration(); }; @@ -727,6 +866,11 @@ namespace bolt { Colon* Colon; TypeExpression* TypeExpression; + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~StructDeclField(); }; @@ -734,35 +878,53 @@ namespace bolt { class StructDecl : public Node { public: - StructDecl( - StructKeyword* StructKeyword, - Identifier* Name, - Dot* Dot, - std::vector Fields - ): Node(NodeType::StructDecl), - StructKeyword(StructKeyword), - Name(Name), - Dot(Dot), - Fields(Fields) {} - + PubKeyword* PubKeyword; StructKeyword* StructKeyword; Identifier* Name; - Dot* Dot; + BlockStart* BlockStart; std::vector Fields; + StructDecl( + class PubKeyword* PubKeyword, + class StructKeyword* StructKeyword, + Identifier* Name, + class BlockStart* BlockStart, + std::vector Fields + ): Node(NodeType::StructDecl), + PubKeyword(PubKeyword), + StructKeyword(StructKeyword), + Name(Name), + BlockStart(BlockStart), + Fields(Fields) {} + + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~StructDecl(); }; class SourceFile : public Node { - - public: - - SourceFile(std::vector Elements): - Node(NodeType::SourceFile), Elements(Elements) {} + public: + + TextFile& File; std::vector Elements; + SourceFile(TextFile& File, std::vector Elements): + Node(NodeType::SourceFile), File(File), Elements(Elements) {} + + inline TextFile& getTextFile() { + return File; + } + + void setParents() override; + + Token* getFirstToken() override; + Token* getLastToken() override; + ~SourceFile(); }; diff --git a/include/bolt/Diagnostics.hpp b/include/bolt/Diagnostics.hpp index 4c50f5c76..eac875f05 100644 --- a/include/bolt/Diagnostics.hpp +++ b/include/bolt/Diagnostics.hpp @@ -98,12 +98,55 @@ namespace bolt { }; + enum class Color { + None, + Black, + White, + Red, + Yellow, + Green, + Blue, + Cyan, + Magenta, + }; + class ConsoleDiagnostics : public DiagnosticEngine { std::ostream& Out; + void setForegroundColor(Color C); + void setBackgroundColor(Color C); + void resetStyles(); + + void writeGutter( + std::size_t GutterWidth, + std::size_t Line + ); + + void writeHighlight( + std::size_t GutterWidth, + TextRange Range, + Color HighlightColor, + std::size_t Line, + std::size_t LineLength + ); + + void writeExcerpt( + TextFile& File, + TextRange ToPrint, + TextRange ToHighlight, + Color HighlightColor + ); + public: + unsigned ExcerptLinesPre = 2; + unsigned ExcerptLinesPost = 2; + std::size_t MaxTypeSubsitutionCount = 0; + bool PrintFilePosition = true; + bool PrintExcerpts = true; + bool EnableColors = true; + void addDiagnostic(const Diagnostic& Diagnostic) override; ConsoleDiagnostics(std::ostream& Out = std::cerr); diff --git a/include/bolt/Parser.hpp b/include/bolt/Parser.hpp index 7ac68eb51..1cbaa1752 100644 --- a/include/bolt/Parser.hpp +++ b/include/bolt/Parser.hpp @@ -60,6 +60,8 @@ namespace bolt { class Parser { + TextFile& File; + Stream& Tokens; OperatorTable ExprOperators; @@ -70,7 +72,7 @@ namespace bolt { public: - Parser(Stream& S); + Parser(TextFile& File, Stream& S); QualifiedName* parseQualifiedName(); diff --git a/include/bolt/Text.hpp b/include/bolt/Text.hpp index 7e27759ef..a576a618a 100644 --- a/include/bolt/Text.hpp +++ b/include/bolt/Text.hpp @@ -7,6 +7,7 @@ #include #include "bolt/ByteString.hpp" +#include "bolt/String.hpp" namespace bolt { @@ -38,21 +39,23 @@ namespace bolt { class TextFile { ByteString Path; - ByteString Text; + String Text; std::vector LineOffsets; public: - TextFile(ByteString Path, ByteString Text); + TextFile(ByteString Path, String Text); size_t getLine(size_t Offset); size_t getColumn(size_t Offset); size_t getStartOffset(size_t Line); + size_t getLineCount() const; + ByteString getPath() const; - ByteString getText() const; + String getText() const; }; diff --git a/src/CST.cc b/src/CST.cc index c780feb51..46a5ce149 100644 --- a/src/CST.cc +++ b/src/CST.cc @@ -1,9 +1,168 @@ +#include "zen/config.hpp" + #include "bolt/CST.hpp" namespace bolt { - Node::~Node() { } + SourceFile* Node::getSourceFile() { + auto CurrNode = this; + for (;;) { + if (CurrNode->Type == NodeType::SourceFile) { + return static_cast(this); + } + CurrNode = CurrNode->Parent; + ZEN_ASSERT(CurrNode != nullptr); + } + } + + TextRange Node::getRange() { + return TextRange { + getFirstToken()->getStartLoc(), + getLastToken()->getEndLoc(), + }; + } + + void Token::setParents() { + } + + void QualifiedName::setParents() { + for (auto Name: ModulePath) { + Name->Parent = this; + } + Name->Parent = this; + } + + void ReferenceTypeExpression::setParents() { + Name->Parent = this; + Name->setParents(); + } + + void BindPattern::setParents() { + Name->Parent = this; + } + + void ReferenceExpression::setParents() { + Name->Parent = this; + } + + void ConstantExpression::setParents() { + Token->Parent = this; + } + + void CallExpression::setParents() { + Function->Parent = this; + Function->setParents(); + for (auto Arg: Args) { + Arg->Parent = this; + Arg->setParents(); + } + } + + void InfixExpression::setParents() { + LHS->Parent = this; + LHS->setParents(); + Operator->Parent = this; + RHS->Parent = this; + RHS->setParents(); + } + + void UnaryExpression::setParents() { + Operator->Parent = this; + Argument->Parent = this; + Argument->setParents(); + } + + void ExpressionStatement::setParents() { + Expression->Parent = this; + Expression->setParents(); + } + + void ReturnStatement::setParents() { + ReturnKeyword->Parent = this; + Expression->Parent = this; + Expression->setParents(); + } + + void TypeAssert::setParents() { + Colon->Parent = this; + TypeExpression->Parent = this; + TypeExpression->setParents(); + } + + void LetBlockBody::setParents() { + BlockStart->Parent = this; + for (auto Element: Elements) { + Element->Parent = this; + Element->setParents(); + } + } + + void LetExprBody::setParents() { + Equals->Parent = this; + Expression->Parent = this; + Expression->setParents(); + } + + void Param::setParents() { + Pattern->Parent = this; + Pattern->setParents(); + if (TypeAssert) { + TypeAssert->Parent = this; + TypeAssert->setParents(); + } + } + + void LetDeclaration::setParents() { + if (PubKeyword) { + PubKeyword->Parent = this; + } + LetKeyword->Parent = this; + if (MutKeyword) { + MutKeyword->Parent = this; + } + Pattern->Parent = this; + Pattern->setParents(); + for (auto Param: Params) { + Param->Parent = this; + Param->setParents(); + } + if (TypeAssert) { + TypeAssert->Parent = this; + TypeAssert->setParents(); + } + if (Body) { + Body->Parent = this; + Body->setParents(); + } + } + + void StructDeclField::setParents() { + Name->Parent = this; + Colon->Parent = this; + TypeExpression->Parent = this; + TypeExpression->setParents(); + } + + void StructDecl::setParents() { + StructKeyword->Parent = this; + Name->Parent = this; + BlockStart->Parent = this; + for (auto Field: Fields) { + Field->Parent = this; + Field->setParents(); + } + } + + void SourceFile::setParents() { + for (auto Element: Elements) { + Element->Parent = this; + Element->setParents(); + } + } + + Node::~Node() { + } Token::~Token() { } @@ -180,7 +339,7 @@ namespace bolt { if (PubKeyword) { PubKeyword->unref(); } - LetKeywod->unref(); + LetKeyword->unref(); if (MutKeyword) { MutKeyword->unref(); } @@ -205,7 +364,7 @@ namespace bolt { StructDecl::~StructDecl() { StructKeyword->unref(); Name->unref(); - Dot->unref(); + BlockStart->unref(); for (auto& Element: Fields){ Element->unref(); } @@ -217,6 +376,189 @@ namespace bolt { } } + Token* QualifiedName::getFirstToken() { + if (ModulePath.size()) { + return ModulePath.front(); + } + return Name; + } + + Token* QualifiedName::getLastToken() { + return Name; + } + + Token* ReferenceTypeExpression::getFirstToken() { + return Name->getFirstToken(); + } + + Token* ReferenceTypeExpression::getLastToken() { + return Name->getFirstToken(); + } + + Token* BindPattern::getFirstToken() { + return Name; + } + + Token* BindPattern::getLastToken() { + return Name; + } + + Token* ReferenceExpression::getFirstToken() { + return Name->getFirstToken(); + } + + Token* ReferenceExpression::getLastToken() { + return Name->getLastToken(); + } + + Token* ConstantExpression::getFirstToken() { + return Token; + } + + Token* ConstantExpression::getLastToken() { + return Token; + } + + Token* CallExpression::getFirstToken() { + return Function->getFirstToken(); + } + + Token* CallExpression::getLastToken() { + if (Args.size()) { + return Args.back()->getLastToken(); + } + return Function->getLastToken(); + } + + Token* InfixExpression::getFirstToken() { + return LHS->getFirstToken(); + } + + Token* InfixExpression::getLastToken() { + return RHS->getLastToken(); + } + + Token* UnaryExpression::getFirstToken() { + return Operator; + } + + Token* UnaryExpression::getLastToken() { + return Argument->getLastToken(); + } + + Token* ExpressionStatement::getFirstToken() { + return Expression->getFirstToken(); + } + + Token* ExpressionStatement::getLastToken() { + return Expression->getLastToken(); + } + + Token* ReturnStatement::getFirstToken() { + return ReturnKeyword; + } + + Token* ReturnStatement::getLastToken() { + if (Expression) { + return Expression->getLastToken(); + } + return ReturnKeyword; + } + + Token* TypeAssert::getFirstToken() { + return Colon; + } + + Token* TypeAssert::getLastToken() { + return TypeExpression->getLastToken(); + } + + Token* Param::getFirstToken() { + return Pattern->getFirstToken(); + } + + Token* Param::getLastToken() { + if (TypeAssert) { + return TypeAssert->getLastToken(); + } + return Pattern->getLastToken(); + } + + Token* LetBlockBody::getFirstToken() { + return BlockStart; + } + + Token* LetBlockBody::getLastToken() { + if (Elements.size()) { + return Elements.back()->getLastToken(); + } + return BlockStart; + } + + Token* LetExprBody::getFirstToken() { + return Equals; + } + + Token* LetExprBody::getLastToken() { + return Expression->getLastToken(); + } + + Token* LetDeclaration::getFirstToken() { + if (PubKeyword) { + return PubKeyword; + } + return LetKeyword; + } + + Token* LetDeclaration::getLastToken() { + if (Body) { + return Body->getLastToken(); + } + if (TypeAssert) { + return TypeAssert->getLastToken(); + } + if (Params.size()) { + return Params.back()->getLastToken(); + } + return Pattern->getLastToken(); + } + + Token* StructDeclField::getFirstToken() { + return Name; + } + + Token* StructDeclField::getLastToken() { + return TypeExpression->getLastToken(); + } + + Token* StructDecl::getFirstToken() { + if (PubKeyword) { + return PubKeyword; + } + return StructKeyword; + } + + Token* StructDecl::getLastToken() { + if (Fields.size()) { + Fields.back()->getLastToken(); + } + return BlockStart; + } + + Token* SourceFile::getFirstToken() { + if (Elements.size()) { + return Elements.front()->getFirstToken(); + } + return nullptr; + } + + Token* SourceFile::getLastToken() { + if (Elements.size()) { + return Elements.back()->getLastToken(); + } + return nullptr; + } + std::string Equals::getText() const { return "="; } diff --git a/src/Checker.cc b/src/Checker.cc index 32b58fc70..1bc0e80e3 100644 --- a/src/Checker.cc +++ b/src/Checker.cc @@ -181,9 +181,10 @@ namespace bolt { case NodeType::ReferenceExpression: { auto Y = static_cast(X); - auto Scm = Ctx.Env.lookup(Y->Name->Text); + ZEN_ASSERT(Y->Name->ModulePath.empty()); + auto Scm = Ctx.Env.lookup(Y->Name->Name->Text); if (Scm == nullptr) { - DE.add(Y->Name->Text, Y->Name); + DE.add(Y->Name->Name->Text, Y->Name); return new TAny(); } return instantiate(*Scm); diff --git a/src/Diagnostics.cc b/src/Diagnostics.cc index c4fe3c6da..df1417bc9 100644 --- a/src/Diagnostics.cc +++ b/src/Diagnostics.cc @@ -1,5 +1,6 @@ #include +#include #include "zen/config.hpp" @@ -31,6 +32,14 @@ namespace bolt { + template + T countDigits(T number) { + if (number == 0) { + return 1; + } + return std::ceil(std::log10(number+1)); + } + Diagnostic::Diagnostic(DiagnosticKind Kind): std::runtime_error("a compiler error occurred without being caught"), Kind(Kind) {} @@ -122,10 +131,169 @@ namespace bolt { } } - ConsoleDiagnostics::ConsoleDiagnostics(std::ostream& Out): Out(Out) {} + void ConsoleDiagnostics::setForegroundColor(Color C) { + if (EnableColors) { + switch (C) { + case Color::None: + break; + case Color::Black: + Out << ANSI_FG_BLACK; + break; + case Color::White: + Out << ANSI_FG_WHITE; + break; + case Color::Red: + Out << ANSI_FG_RED; + break; + case Color::Yellow: + Out << ANSI_FG_YELLOW; + break; + case Color::Green: + Out << ANSI_FG_GREEN; + break; + case Color::Blue: + Out << ANSI_FG_BLUE; + break; + case Color::Cyan: + Out << ANSI_FG_CYAN; + break; + case Color::Magenta: + Out << ANSI_FG_MAGENTA; + break; + } + } + } + + + void ConsoleDiagnostics::setBackgroundColor(Color C) { + if (EnableColors) { + switch (C) { + case Color::None: + break; + case Color::Black: + Out << ANSI_BG_BLACK; + break; + case Color::White: + Out << ANSI_BG_WHITE; + break; + case Color::Red: + Out << ANSI_BG_RED; + break; + case Color::Yellow: + Out << ANSI_BG_YELLOW; + break; + case Color::Green: + Out << ANSI_BG_GREEN; + break; + case Color::Blue: + Out << ANSI_BG_BLUE; + break; + case Color::Cyan: + Out << ANSI_BG_CYAN; + break; + case Color::Magenta: + Out << ANSI_BG_MAGENTA; + break; + } + } + } + + void ConsoleDiagnostics::resetStyles() { + if (EnableColors) { + Out << ANSI_RESET; + } + } + + void ConsoleDiagnostics::writeGutter( + std::size_t GutterWidth, + std::size_t Line + ) { + auto LineNumberDigitCount = countDigits(Line); + auto LeadingSpaces = GutterWidth - LineNumberDigitCount; + Out << " "; + setForegroundColor(Color::Black); + setBackgroundColor(Color::White); + for (std::size_t i = 0; i < LeadingSpaces; i++) { + Out << ' '; + } + Out << Line; + resetStyles(); + Out << " "; + } + + void ConsoleDiagnostics::writeHighlight( + std::size_t GutterWidth, + TextRange Range, + Color HighlightColor, + std::size_t Line, + std::size_t LineLength + ) { + if (Line < Range.Start.Line || Range.End.Line < Line) { + return; + } + Out << " "; + setBackgroundColor(Color::White); + for (std::size_t i = 0; i < GutterWidth; i++) { + Out << ' '; + } + resetStyles(); + Out << ' '; + std::size_t start_column = Range.Start.Line == Line ? Range.Start.Column : 1; + std::size_t end_column = Range.End.Line == Line ? Range.End.Column : LineLength+1; + for (std::size_t i = 1; i < start_column; i++) { + Out << ' '; + } + setForegroundColor(HighlightColor); + for (std::size_t i = start_column; i < end_column; i++) { + Out << '~'; + } + resetStyles(); + Out << '\n'; + } + + void ConsoleDiagnostics::writeExcerpt( + TextFile& File, + TextRange ToPrint, + TextRange ToHighlight, + Color HighlightColor + ) { + + auto Text = File.getText(); + auto StartPos = ToPrint.Start; + auto EndPos = ToPrint.End; + auto StartLine = StartPos.Line-1 > ExcerptLinesPre ? StartPos.Line - ExcerptLinesPost : 1; + auto StartOffset = File.getStartOffset(StartLine); + auto EndLine = std::min(File.getLineCount(), EndPos.Line + ExcerptLinesPost); + auto EndOffset = File.getStartOffset(EndLine+1); + auto GutterWidth = std::max(2, countDigits(EndLine+1)); + auto HighlightStart = ToHighlight.Start; + auto HighlightEnd = ToHighlight.End; + auto HighlightRange = TextRange { HighlightStart, HighlightEnd }; + + std::size_t CurrColumn = 1; + std::size_t CurrLine = StartLine; + writeGutter(GutterWidth, CurrLine); + for (std::size_t i = StartOffset; i < EndOffset; i++) { + auto C = Text[i]; + Out << C; + if (C == '\n') { + writeHighlight(GutterWidth, HighlightRange, HighlightColor, CurrLine, CurrColumn); + if (CurrLine == EndLine && C == '\n') { + break; + } + CurrLine++; + writeGutter(GutterWidth, CurrLine); + CurrColumn = 1; + } else { + CurrColumn++; + } + } + + } + void ConsoleDiagnostics::addDiagnostic(const Diagnostic& D) { switch (D.getKind()) { @@ -163,6 +331,7 @@ namespace bolt { break; } Out << " but instead got '" << E.Actual->getText() << "'\n"; + writeExcerpt(E.Actual->getSourceFile()->getTextFile(), E.Actual->getRange(), E.Actual->getRange(), Color::Red); break; } diff --git a/src/Parser.cc b/src/Parser.cc index baf426aeb..08615b7af 100644 --- a/src/Parser.cc +++ b/src/Parser.cc @@ -34,8 +34,8 @@ namespace bolt { Mapping.emplace(Name, OperatorInfo { Precedence, Flags }); } - Parser::Parser(Stream& S): - Tokens(S) { + Parser::Parser(TextFile& File, Stream& S): + File(File), Tokens(S) { ExprOperators.add("**", OperatorFlags_InfixR, 10); ExprOperators.add("*", OperatorFlags_InfixL, 5); ExprOperators.add("/", OperatorFlags_InfixL, 5); @@ -120,8 +120,10 @@ namespace bolt { auto T0 = Tokens.peek(); switch (T0->Type) { case NodeType::Identifier: - Tokens.get(); - return new ReferenceExpression(static_cast(T0)); + { + auto Name = parseQualifiedName(); + return new ReferenceExpression(Name); + } case NodeType::IntegerLiteral: case NodeType::StringLiteral: Tokens.get(); @@ -320,7 +322,7 @@ after_params: } Elements.push_back(parseSourceElement()); } - return new SourceFile(Elements); + return new SourceFile(File, Elements); } } diff --git a/src/Text.cc b/src/Text.cc index 17b2f05ba..ce1d0233e 100644 --- a/src/Text.cc +++ b/src/Text.cc @@ -6,7 +6,7 @@ namespace bolt { - TextFile::TextFile(ByteString Path, ByteString Text): + TextFile::TextFile(ByteString Path, String Text): Path(Path), Text(Text) { LineOffsets.push_back(0); for (size_t I = 0; I < Text.size(); I++) { @@ -18,6 +18,10 @@ namespace bolt { LineOffsets.push_back(Text.size()); } + size_t TextFile::getLineCount() const { + return LineOffsets.size(); + } + size_t TextFile::getStartOffset(size_t Line) { return LineOffsets[Line-1]; } @@ -42,7 +46,7 @@ namespace bolt { return Path; } - ByteString TextFile::getText() const { + String TextFile::getText() const { return Text; } diff --git a/src/main.cc b/src/main.cc index 652eae794..1ba875f52 100644 --- a/src/main.cc +++ b/src/main.cc @@ -39,10 +39,11 @@ int main(int argc, const char* argv[]) { ConsoleDiagnostics DE; auto Text = readFile(argv[1]); + TextFile File { argv[1], Text }; VectorStream Chars(Text, EOF); Scanner S(Chars); Punctuator PT(S); - Parser P(PT); + Parser P(File, PT); SourceFile* SF; @@ -56,6 +57,8 @@ int main(int argc, const char* argv[]) { SF = P.parseSourceFile(); #endif + SF->setParents(); + Checker TheChecker { DE }; TheChecker.check(SF);