Add more methods to bolt::Node and improve diagnostics

This commit is contained in:
Sam Vervaeck 2022-08-24 12:36:43 +02:00
parent a4a2b4cca5
commit fb69ab745c
10 changed files with 814 additions and 83 deletions

View file

@ -1,6 +1,7 @@
#ifndef BOLT_CST_HPP
#define BOLT_CST_HPP
#include <iterator>
#include <vector>
#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<Expression*> Args): Expression(NodeType::CallExpression), Function(Function), Args(Args) {}
Expression* Function;
std::vector<Expression*> Args;
CallExpression(
Expression* Function,
std::vector<Expression*> 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<Node*> Elements;
LetBlockBody(
BlockStart* BlockStart,
class BlockStart* BlockStart,
std::vector<Node*> Elements
): LetBody(NodeType::LetBlockBody),
BlockStart(BlockStart),
Elements(Elements) {}
BlockStart* BlockStart;
std::vector<Node*> 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<Param*> 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<StructDeclField*> Fields
): Node(NodeType::StructDecl),
StructKeyword(StructKeyword),
Name(Name),
Dot(Dot),
Fields(Fields) {}
PubKeyword* PubKeyword;
StructKeyword* StructKeyword;
Identifier* Name;
Dot* Dot;
BlockStart* BlockStart;
std::vector<StructDeclField*> Fields;
StructDecl(
class PubKeyword* PubKeyword,
class StructKeyword* StructKeyword,
Identifier* Name,
class BlockStart* BlockStart,
std::vector<StructDeclField*> 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<Node*> Elements):
Node(NodeType::SourceFile), Elements(Elements) {}
public:
TextFile& File;
std::vector<Node*> Elements;
SourceFile(TextFile& File, std::vector<Node*> Elements):
Node(NodeType::SourceFile), File(File), Elements(Elements) {}
inline TextFile& getTextFile() {
return File;
}
void setParents() override;
Token* getFirstToken() override;
Token* getLastToken() override;
~SourceFile();
};

View file

@ -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);

View file

@ -60,6 +60,8 @@ namespace bolt {
class Parser {
TextFile& File;
Stream<Token*>& Tokens;
OperatorTable ExprOperators;
@ -70,7 +72,7 @@ namespace bolt {
public:
Parser(Stream<Token*>& S);
Parser(TextFile& File, Stream<Token*>& S);
QualifiedName* parseQualifiedName();

View file

@ -7,6 +7,7 @@
#include <string>
#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<size_t> 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;
};

View file

@ -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<SourceFile*>(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 "=";
}

View file

@ -181,9 +181,10 @@ namespace bolt {
case NodeType::ReferenceExpression:
{
auto Y = static_cast<ReferenceExpression*>(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<BindingNotFoundDiagnostic>(Y->Name->Text, Y->Name);
DE.add<BindingNotFoundDiagnostic>(Y->Name->Name->Text, Y->Name);
return new TAny();
}
return instantiate(*Scm);

View file

@ -1,5 +1,6 @@
#include <sstream>
#include <cmath>
#include "zen/config.hpp"
@ -31,6 +32,14 @@
namespace bolt {
template<typename T>
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<std::size_t>(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;
}

View file

@ -34,8 +34,8 @@ namespace bolt {
Mapping.emplace(Name, OperatorInfo { Precedence, Flags });
}
Parser::Parser(Stream<Token*>& S):
Tokens(S) {
Parser::Parser(TextFile& File, Stream<Token*>& 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<Identifier*>(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);
}
}

View file

@ -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;
}

View file

@ -39,10 +39,11 @@ int main(int argc, const char* argv[]) {
ConsoleDiagnostics DE;
auto Text = readFile(argv[1]);
TextFile File { argv[1], Text };
VectorStream<String> 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);