Add support for literal patterns
This commit is contained in:
parent
17d21d234b
commit
56cbfc6fbe
6 changed files with 108 additions and 23 deletions
|
@ -5,6 +5,7 @@
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "zen/config.hpp"
|
#include "zen/config.hpp"
|
||||||
|
@ -70,6 +71,7 @@ namespace bolt {
|
||||||
ArrowTypeExpression,
|
ArrowTypeExpression,
|
||||||
VarTypeExpression,
|
VarTypeExpression,
|
||||||
BindPattern,
|
BindPattern,
|
||||||
|
LiteralPattern,
|
||||||
ReferenceExpression,
|
ReferenceExpression,
|
||||||
MatchCase,
|
MatchCase,
|
||||||
MatchExpression,
|
MatchExpression,
|
||||||
|
@ -760,32 +762,53 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringLiteral : public Token {
|
using Value = std::variant<ByteString, Integer>;
|
||||||
|
|
||||||
|
class Literal : public Token {
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline Literal(NodeKind Kind, TextLoc StartLoc):
|
||||||
|
Token(Kind, StartLoc) {}
|
||||||
|
|
||||||
|
virtual Value getValue() = 0;
|
||||||
|
|
||||||
|
static bool classof(const Node* N) {
|
||||||
|
return N->getKind() == NodeKind::StringLiteral
|
||||||
|
|| N->getKind() == NodeKind::IntegerLiteral;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class StringLiteral : public Literal {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ByteString Text;
|
ByteString Text;
|
||||||
|
|
||||||
StringLiteral(ByteString Text, TextLoc StartLoc):
|
StringLiteral(ByteString Text, TextLoc StartLoc):
|
||||||
Token(NodeKind::StringLiteral, StartLoc), Text(Text) {}
|
Literal(NodeKind::StringLiteral, StartLoc), Text(Text) {}
|
||||||
|
|
||||||
std::string getText() const override;
|
std::string getText() const override;
|
||||||
|
|
||||||
|
Value getValue() override;
|
||||||
|
|
||||||
static bool classof(const Node* N) {
|
static bool classof(const Node* N) {
|
||||||
return N->getKind() == NodeKind::StringLiteral;
|
return N->getKind() == NodeKind::StringLiteral;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IntegerLiteral : public Token {
|
class IntegerLiteral : public Literal {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Integer Value;
|
Integer V;
|
||||||
|
|
||||||
IntegerLiteral(Integer Value, TextLoc StartLoc):
|
IntegerLiteral(Integer Value, TextLoc StartLoc):
|
||||||
Token(NodeKind::IntegerLiteral, StartLoc), Value(Value) {}
|
Literal(NodeKind::IntegerLiteral, StartLoc), V(Value) {}
|
||||||
|
|
||||||
std::string getText() const override;
|
std::string getText() const override;
|
||||||
|
|
||||||
|
Value getValue() override;
|
||||||
|
|
||||||
static bool classof(const Node* N) {
|
static bool classof(const Node* N) {
|
||||||
return N->getKind() == NodeKind::IntegerLiteral;
|
return N->getKind() == NodeKind::IntegerLiteral;
|
||||||
}
|
}
|
||||||
|
@ -977,6 +1000,20 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LiteralPattern : public Pattern {
|
||||||
|
public:
|
||||||
|
|
||||||
|
class Literal* Literal;
|
||||||
|
|
||||||
|
LiteralPattern(class Literal* Literal):
|
||||||
|
Pattern(NodeKind::LiteralPattern),
|
||||||
|
Literal(Literal) {}
|
||||||
|
|
||||||
|
Token* getFirstToken() override;
|
||||||
|
Token* getLastToken() override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class Expression : public TypedNode {
|
class Expression : public TypedNode {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -1074,10 +1111,10 @@ namespace bolt {
|
||||||
class ConstantExpression : public Expression {
|
class ConstantExpression : public Expression {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Token* Token;
|
class Literal* Token;
|
||||||
|
|
||||||
ConstantExpression(
|
ConstantExpression(
|
||||||
class Token* Token
|
class Literal* Token
|
||||||
): Expression(NodeKind::ConstantExpression),
|
): Expression(NodeKind::ConstantExpression),
|
||||||
Token(Token) {}
|
Token(Token) {}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,8 @@ namespace bolt {
|
||||||
return static_cast<D*>(this)->visitVarTypeExpression(static_cast<VarTypeExpression*>(N));
|
return static_cast<D*>(this)->visitVarTypeExpression(static_cast<VarTypeExpression*>(N));
|
||||||
case NodeKind::BindPattern:
|
case NodeKind::BindPattern:
|
||||||
return static_cast<D*>(this)->visitBindPattern(static_cast<BindPattern*>(N));
|
return static_cast<D*>(this)->visitBindPattern(static_cast<BindPattern*>(N));
|
||||||
|
case NodeKind::LiteralPattern:
|
||||||
|
return static_cast<D*>(this)->visitLiteralPattern(static_cast<LiteralPattern*>(N));
|
||||||
case NodeKind::ReferenceExpression:
|
case NodeKind::ReferenceExpression:
|
||||||
return static_cast<D*>(this)->visitReferenceExpression(static_cast<ReferenceExpression*>(N));
|
return static_cast<D*>(this)->visitReferenceExpression(static_cast<ReferenceExpression*>(N));
|
||||||
case NodeKind::MatchCase:
|
case NodeKind::MatchCase:
|
||||||
|
@ -350,6 +352,10 @@ namespace bolt {
|
||||||
visitPattern(N);
|
visitPattern(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitLiteralPattern(LiteralPattern* N) {
|
||||||
|
visitPattern(N);
|
||||||
|
}
|
||||||
|
|
||||||
void visitExpression(Expression* N) {
|
void visitExpression(Expression* N) {
|
||||||
visitNode(N);
|
visitNode(N);
|
||||||
}
|
}
|
||||||
|
@ -589,6 +595,9 @@ namespace bolt {
|
||||||
case NodeKind::BindPattern:
|
case NodeKind::BindPattern:
|
||||||
visitEachChild(static_cast<BindPattern*>(N));
|
visitEachChild(static_cast<BindPattern*>(N));
|
||||||
break;
|
break;
|
||||||
|
case NodeKind::LiteralPattern:
|
||||||
|
visitEachChild(static_cast<LiteralPattern*>(N));
|
||||||
|
break;
|
||||||
case NodeKind::ReferenceExpression:
|
case NodeKind::ReferenceExpression:
|
||||||
visitEachChild(static_cast<ReferenceExpression*>(N));
|
visitEachChild(static_cast<ReferenceExpression*>(N));
|
||||||
break;
|
break;
|
||||||
|
@ -823,6 +832,10 @@ namespace bolt {
|
||||||
BOLT_VISIT(N->Name);
|
BOLT_VISIT(N->Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitEachChild(LiteralPattern* N) {
|
||||||
|
BOLT_VISIT(N->Literal);
|
||||||
|
}
|
||||||
|
|
||||||
void visitEachChild(ReferenceExpression* N) {
|
void visitEachChild(ReferenceExpression* N) {
|
||||||
for (auto [Name, Dot]: N->ModulePath) {
|
for (auto [Name, Dot]: N->ModulePath) {
|
||||||
BOLT_VISIT(Name);
|
BOLT_VISIT(Name);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "zen/config.hpp"
|
#include "zen/config.hpp"
|
||||||
|
@ -355,6 +356,7 @@ namespace bolt {
|
||||||
|
|
||||||
Type* inferExpression(Expression* Expression);
|
Type* inferExpression(Expression* Expression);
|
||||||
Type* inferTypeExpression(TypeExpression* TE);
|
Type* inferTypeExpression(TypeExpression* TE);
|
||||||
|
Type* inferLiteral(Literal* Lit);
|
||||||
|
|
||||||
void inferBindings(Pattern* Pattern, Type* T, ConstraintSet* Constraints, TVSet* TVs);
|
void inferBindings(Pattern* Pattern, Type* T, ConstraintSet* Constraints, TVSet* TVs);
|
||||||
void inferBindings(Pattern* Pattern, Type* T);
|
void inferBindings(Pattern* Pattern, Type* T);
|
||||||
|
|
18
src/CST.cc
18
src/CST.cc
|
@ -221,6 +221,14 @@ namespace bolt {
|
||||||
return Name;
|
return Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token* LiteralPattern::getFirstToken() {
|
||||||
|
return Literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* LiteralPattern::getLastToken() {
|
||||||
|
return Literal;
|
||||||
|
}
|
||||||
|
|
||||||
Token* ReferenceExpression::getFirstToken() {
|
Token* ReferenceExpression::getFirstToken() {
|
||||||
if (!ModulePath.empty()) {
|
if (!ModulePath.empty()) {
|
||||||
return std::get<0>(ModulePath.front());
|
return std::get<0>(ModulePath.front());
|
||||||
|
@ -586,7 +594,7 @@ namespace bolt {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string IntegerLiteral::getText() const {
|
std::string IntegerLiteral::getText() const {
|
||||||
return std::to_string(Value);
|
return std::to_string(V);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DotDot::getText() const {
|
std::string DotDot::getText() const {
|
||||||
|
@ -613,6 +621,14 @@ namespace bolt {
|
||||||
return Text;
|
return Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value StringLiteral::getValue() {
|
||||||
|
return Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value IntegerLiteral::getValue() {
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
SymbolPath ReferenceExpression::getSymbolPath() const {
|
SymbolPath ReferenceExpression::getSymbolPath() const {
|
||||||
std::vector<ByteString> ModuleNames;
|
std::vector<ByteString> ModuleNames;
|
||||||
for (auto [Name, Dot]: ModulePath) {
|
for (auto [Name, Dot]: ModulePath) {
|
||||||
|
|
|
@ -723,18 +723,7 @@ namespace bolt {
|
||||||
case NodeKind::ConstantExpression:
|
case NodeKind::ConstantExpression:
|
||||||
{
|
{
|
||||||
auto Const = static_cast<ConstantExpression*>(X);
|
auto Const = static_cast<ConstantExpression*>(X);
|
||||||
Type* Ty = nullptr;
|
auto Ty = inferLiteral(Const->Token);
|
||||||
switch (Const->Token->getKind()) {
|
|
||||||
case NodeKind::IntegerLiteral:
|
|
||||||
Ty = lookupMono("Int");
|
|
||||||
break;
|
|
||||||
case NodeKind::StringLiteral:
|
|
||||||
Ty = lookupMono("String");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ZEN_UNREACHABLE
|
|
||||||
}
|
|
||||||
ZEN_ASSERT(Ty != nullptr);
|
|
||||||
X->setType(Ty);
|
X->setType(Ty);
|
||||||
return Ty;
|
return Ty;
|
||||||
}
|
}
|
||||||
|
@ -815,7 +804,15 @@ namespace bolt {
|
||||||
|
|
||||||
case NodeKind::BindPattern:
|
case NodeKind::BindPattern:
|
||||||
{
|
{
|
||||||
addBinding(static_cast<BindPattern*>(Pattern)->Name->getCanonicalText(), new Forall(TVs, Constraints, Type));
|
auto P = static_cast<BindPattern*>(Pattern);
|
||||||
|
addBinding(P->Name->getCanonicalText(), new Forall(TVs, Constraints, Type));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case NodeKind::LiteralPattern:
|
||||||
|
{
|
||||||
|
auto P = static_cast<LiteralPattern*>(Pattern);
|
||||||
|
addConstraint(new CEqual(inferLiteral(P->Literal), Type, P));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,6 +827,22 @@ namespace bolt {
|
||||||
inferBindings(Pattern, Type, new ConstraintSet, new TVSet);
|
inferBindings(Pattern, Type, new ConstraintSet, new TVSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type* Checker::inferLiteral(Literal* L) {
|
||||||
|
Type* Ty;
|
||||||
|
switch (L->getKind()) {
|
||||||
|
case NodeKind::IntegerLiteral:
|
||||||
|
Ty = lookupMono("Int");
|
||||||
|
break;
|
||||||
|
case NodeKind::StringLiteral:
|
||||||
|
Ty = lookupMono("String");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ZEN_UNREACHABLE
|
||||||
|
}
|
||||||
|
ZEN_ASSERT(Ty != nullptr);
|
||||||
|
return Ty;
|
||||||
|
}
|
||||||
|
|
||||||
void collectTypeclasses(LetDeclaration* Decl, std::vector<TypeclassSignature>& Out) {
|
void collectTypeclasses(LetDeclaration* Decl, std::vector<TypeclassSignature>& Out) {
|
||||||
if (llvm::isa<ClassDeclaration>(Decl->Parent)) {
|
if (llvm::isa<ClassDeclaration>(Decl->Parent)) {
|
||||||
auto Class = llvm::cast<ClassDeclaration>(Decl->Parent);
|
auto Class = llvm::cast<ClassDeclaration>(Decl->Parent);
|
||||||
|
|
|
@ -89,11 +89,15 @@ namespace bolt {
|
||||||
Pattern* Parser::parsePattern() {
|
Pattern* Parser::parsePattern() {
|
||||||
auto T0 = Tokens.peek();
|
auto T0 = Tokens.peek();
|
||||||
switch (T0->getKind()) {
|
switch (T0->getKind()) {
|
||||||
|
case NodeKind::StringLiteral:
|
||||||
|
case NodeKind::IntegerLiteral:
|
||||||
|
Tokens.get();
|
||||||
|
return new LiteralPattern(static_cast<Literal*>(T0));
|
||||||
case NodeKind::Identifier:
|
case NodeKind::Identifier:
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
return new BindPattern(static_cast<Identifier*>(T0));
|
return new BindPattern(static_cast<Identifier*>(T0));
|
||||||
default:
|
default:
|
||||||
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeKind::Identifier });
|
throw UnexpectedTokenDiagnostic(File, T0, std::vector { NodeKind::Identifier, NodeKind::StringLiteral, NodeKind::IntegerLiteral });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +273,7 @@ after_constraints:
|
||||||
case NodeKind::IntegerLiteral:
|
case NodeKind::IntegerLiteral:
|
||||||
case NodeKind::StringLiteral:
|
case NodeKind::StringLiteral:
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
return new ConstantExpression(T0);
|
return new ConstantExpression(static_cast<Literal*>(T0));
|
||||||
default:
|
default:
|
||||||
throw UnexpectedTokenDiagnostic(File, T0, { NodeKind::MatchKeyword, NodeKind::Identifier, NodeKind::IdentifierAlt, NodeKind::IntegerLiteral, NodeKind::StringLiteral });
|
throw UnexpectedTokenDiagnostic(File, T0, { NodeKind::MatchKeyword, NodeKind::Identifier, NodeKind::IdentifierAlt, NodeKind::IntegerLiteral, NodeKind::StringLiteral });
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue