Make compile on GCC and add support for infix let-declarations
This commit is contained in:
parent
449cda8fc4
commit
9f5de2987a
10 changed files with 330 additions and 164 deletions
|
@ -13,6 +13,10 @@ set(ICU_INCLUDE_DIRS "${ICU_DIR}/include")
|
||||||
set(ICU_LIBRARY_DIRS "${ICU_DIR}/lib")
|
set(ICU_LIBRARY_DIRS "${ICU_DIR}/lib")
|
||||||
set(ICU_LIBRARIES icuuc)
|
set(ICU_LIBRARIES icuuc)
|
||||||
|
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
set(BOLT_DEBUG ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(
|
add_library(
|
||||||
BoltCore
|
BoltCore
|
||||||
#src/Text.cc
|
#src/Text.cc
|
||||||
|
@ -33,10 +37,17 @@ target_link_directories(
|
||||||
target_compile_options(
|
target_compile_options(
|
||||||
BoltCore
|
BoltCore
|
||||||
PUBLIC
|
PUBLIC
|
||||||
-fstandalone-debug
|
|
||||||
-Werror
|
-Werror
|
||||||
${ICU_CFLAGS}
|
${ICU_CFLAGS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND BOLT_DEBUG)
|
||||||
|
target_compile_options(
|
||||||
|
BoltCore
|
||||||
|
PUBLIC
|
||||||
|
-fstandalone-debug
|
||||||
|
)
|
||||||
|
endif()
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
BoltCore
|
BoltCore
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|
|
@ -125,10 +125,11 @@ namespace bolt {
|
||||||
LineFoldEnd,
|
LineFoldEnd,
|
||||||
CustomOperator,
|
CustomOperator,
|
||||||
Assignment,
|
Assignment,
|
||||||
Identifier,
|
|
||||||
IdentifierAlt,
|
|
||||||
StringLiteral,
|
StringLiteral,
|
||||||
IntegerLiteral,
|
IntegerLiteral,
|
||||||
|
Identifier,
|
||||||
|
IdentifierAlt,
|
||||||
|
WrappedOperator,
|
||||||
ExpressionAnnotation,
|
ExpressionAnnotation,
|
||||||
TypeAssertAnnotation,
|
TypeAssertAnnotation,
|
||||||
TypeclassConstraintExpression,
|
TypeclassConstraintExpression,
|
||||||
|
@ -196,6 +197,11 @@ namespace bolt {
|
||||||
|
|
||||||
using NodeFlagsMask = unsigned;
|
using NodeFlagsMask = unsigned;
|
||||||
|
|
||||||
|
class Node;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool _is_helper(const Node* N) noexcept;
|
||||||
|
|
||||||
class Node {
|
class Node {
|
||||||
|
|
||||||
unsigned RefCount = 1;
|
unsigned RefCount = 1;
|
||||||
|
@ -229,17 +235,7 @@ namespace bolt {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool is() const noexcept {
|
bool is() const noexcept {
|
||||||
return Kind == getNodeType<T>();
|
return _is_helper<T>(this);
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
bool is<Expression>() const noexcept {
|
|
||||||
return Kind == NodeKind::ReferenceExpression
|
|
||||||
|| Kind == NodeKind::LiteralExpression
|
|
||||||
|| Kind == NodeKind::PrefixExpression
|
|
||||||
|| Kind == NodeKind::InfixExpression
|
|
||||||
|| Kind == NodeKind::CallExpression
|
|
||||||
|| Kind == NodeKind::NestedExpression;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -262,6 +258,21 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool _is_helper(const Node* N) noexcept {
|
||||||
|
return N->getKind() == getNodeType<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool _is_helper<Expression>(const Node* N) noexcept {
|
||||||
|
return N->getKind() == NodeKind::ReferenceExpression
|
||||||
|
|| N->getKind() == NodeKind::LiteralExpression
|
||||||
|
|| N->getKind() == NodeKind::PrefixExpression
|
||||||
|
|| N->getKind() == NodeKind::InfixExpression
|
||||||
|
|| N->getKind() == NodeKind::CallExpression
|
||||||
|
|| N->getKind() == NodeKind::NestedExpression;
|
||||||
|
}
|
||||||
|
|
||||||
enum class SymbolKind {
|
enum class SymbolKind {
|
||||||
Var,
|
Var,
|
||||||
Class,
|
Class,
|
||||||
|
@ -353,6 +364,31 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Any node that can be used as an operator
|
||||||
|
///
|
||||||
|
/// This includes the following nodes:
|
||||||
|
/// - VBar
|
||||||
|
/// - CustomOperator
|
||||||
|
using Operator = Token;
|
||||||
|
|
||||||
|
/// Any node that can be used as a kind of identifier.
|
||||||
|
///
|
||||||
|
/// This includes the following nodes:
|
||||||
|
/// - Identifier
|
||||||
|
/// - IdentifierAlt
|
||||||
|
/// - WrappedOperator
|
||||||
|
using Symbol = Node;
|
||||||
|
|
||||||
|
inline bool isSymbol(const Node* N) {
|
||||||
|
return N->getKind() == NodeKind::Identifier
|
||||||
|
|| N->getKind() == NodeKind::IdentifierAlt
|
||||||
|
|| N->getKind() == NodeKind::WrappedOperator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the text that is actually represented by a symbol, without all the
|
||||||
|
/// syntactic sugar.
|
||||||
|
ByteString getCanonicalText(const Symbol* N);
|
||||||
|
|
||||||
class Equals : public Token {
|
class Equals : public Token {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -889,30 +925,13 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Symbol : public Token {
|
class Identifier : public Token {
|
||||||
public:
|
|
||||||
|
|
||||||
inline Symbol(NodeKind Kind, TextLoc StartLoc):
|
|
||||||
Token(Kind, StartLoc) {}
|
|
||||||
|
|
||||||
virtual ByteString getCanonicalText() = 0;
|
|
||||||
|
|
||||||
static bool classof(const Node* N) {
|
|
||||||
return N->getKind() == NodeKind::Identifier
|
|
||||||
|| N->getKind() == NodeKind::IdentifierAlt;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class Identifier : public Symbol {
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ByteString Text;
|
ByteString Text;
|
||||||
|
|
||||||
Identifier(ByteString Text, TextLoc StartLoc = TextLoc::empty()):
|
Identifier(ByteString Text, TextLoc StartLoc = TextLoc::empty()):
|
||||||
Symbol(NodeKind::Identifier, StartLoc), Text(Text) {}
|
Token(NodeKind::Identifier, StartLoc), Text(Text) {}
|
||||||
|
|
||||||
ByteString getCanonicalText() override;
|
|
||||||
|
|
||||||
std::string getText() const override;
|
std::string getText() const override;
|
||||||
|
|
||||||
|
@ -924,15 +943,13 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IdentifierAlt : public Symbol {
|
class IdentifierAlt : public Token {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ByteString Text;
|
ByteString Text;
|
||||||
|
|
||||||
IdentifierAlt(ByteString Text, TextLoc StartLoc):
|
IdentifierAlt(ByteString Text, TextLoc StartLoc):
|
||||||
Symbol(NodeKind::IdentifierAlt, StartLoc), Text(Text) {}
|
Token(NodeKind::IdentifierAlt, StartLoc), Text(Text) {}
|
||||||
|
|
||||||
ByteString getCanonicalText() override;
|
|
||||||
|
|
||||||
std::string getText() const override;
|
std::string getText() const override;
|
||||||
|
|
||||||
|
@ -1020,8 +1037,8 @@ namespace bolt {
|
||||||
class ExpressionAnnotation : public Annotation {
|
class ExpressionAnnotation : public Annotation {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
At* At;
|
class At* At;
|
||||||
Expression* Expression;
|
class Expression* Expression;
|
||||||
|
|
||||||
inline ExpressionAnnotation(
|
inline ExpressionAnnotation(
|
||||||
class At* At,
|
class At* At,
|
||||||
|
@ -1044,8 +1061,8 @@ namespace bolt {
|
||||||
class TypeAssertAnnotation : public Annotation {
|
class TypeAssertAnnotation : public Annotation {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
At* At;
|
class At* At;
|
||||||
Colon* Colon;
|
class Colon* Colon;
|
||||||
TypeExpression* TE;
|
TypeExpression* TE;
|
||||||
|
|
||||||
inline TypeAssertAnnotation(
|
inline TypeAssertAnnotation(
|
||||||
|
@ -1107,7 +1124,7 @@ namespace bolt {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Identifier* Name;
|
Identifier* Name;
|
||||||
Colon* Colon;
|
class Colon* Colon;
|
||||||
TypeExpression* TE;
|
TypeExpression* TE;
|
||||||
|
|
||||||
inline RecordTypeExpressionField(
|
inline RecordTypeExpressionField(
|
||||||
|
@ -1127,11 +1144,11 @@ namespace bolt {
|
||||||
class RecordTypeExpression : public TypeExpression {
|
class RecordTypeExpression : public TypeExpression {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LBrace* LBrace;
|
class LBrace* LBrace;
|
||||||
std::vector<std::tuple<RecordTypeExpressionField*, Comma*>> Fields;
|
std::vector<std::tuple<RecordTypeExpressionField*, Comma*>> Fields;
|
||||||
VBar* VBar;
|
class VBar* VBar;
|
||||||
TypeExpression* Rest;
|
TypeExpression* Rest;
|
||||||
RBrace* RBrace;
|
class RBrace* RBrace;
|
||||||
|
|
||||||
inline RecordTypeExpression(
|
inline RecordTypeExpression(
|
||||||
class LBrace* LBrace,
|
class LBrace* LBrace,
|
||||||
|
@ -1183,9 +1200,9 @@ namespace bolt {
|
||||||
TypeExpression* Right;
|
TypeExpression* Right;
|
||||||
|
|
||||||
inline EqualityConstraintExpression(
|
inline EqualityConstraintExpression(
|
||||||
TypeExpression* Left,
|
TypeExpression* Left,
|
||||||
class Tilde* Tilde,
|
class Tilde* Tilde,
|
||||||
TypeExpression* Right
|
TypeExpression* Right
|
||||||
): ConstraintExpression(NodeKind::EqualityConstraintExpression),
|
): ConstraintExpression(NodeKind::EqualityConstraintExpression),
|
||||||
Left(Left),
|
Left(Left),
|
||||||
Tilde(Tilde),
|
Tilde(Tilde),
|
||||||
|
@ -1297,9 +1314,9 @@ namespace bolt {
|
||||||
class NestedTypeExpression : public TypeExpression {
|
class NestedTypeExpression : public TypeExpression {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LParen* LParen;
|
class LParen* LParen;
|
||||||
TypeExpression* TE;
|
TypeExpression* TE;
|
||||||
RParen* RParen;
|
class RParen* RParen;
|
||||||
|
|
||||||
inline NestedTypeExpression(
|
inline NestedTypeExpression(
|
||||||
class LParen* LParen,
|
class LParen* LParen,
|
||||||
|
@ -1318,9 +1335,9 @@ namespace bolt {
|
||||||
class TupleTypeExpression : public TypeExpression {
|
class TupleTypeExpression : public TypeExpression {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LParen* LParen;
|
class LParen* LParen;
|
||||||
std::vector<std::tuple<TypeExpression*, Comma*>> Elements;
|
std::vector<std::tuple<TypeExpression*, Comma*>> Elements;
|
||||||
RParen* RParen;
|
class RParen* RParen;
|
||||||
|
|
||||||
inline TupleTypeExpression(
|
inline TupleTypeExpression(
|
||||||
class LParen* LParen,
|
class LParen* LParen,
|
||||||
|
@ -1336,6 +1353,32 @@ namespace bolt {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WrappedOperator : public Symbol {
|
||||||
|
public:
|
||||||
|
|
||||||
|
class LParen* LParen;
|
||||||
|
Token* Op;
|
||||||
|
class RParen* RParen;
|
||||||
|
|
||||||
|
WrappedOperator(
|
||||||
|
class LParen* LParen,
|
||||||
|
Token* Operator,
|
||||||
|
class RParen* RParen
|
||||||
|
): Symbol(NodeKind::WrappedOperator),
|
||||||
|
LParen(LParen),
|
||||||
|
Op(Operator),
|
||||||
|
RParen(RParen) {}
|
||||||
|
|
||||||
|
inline Token* getOperator() const {
|
||||||
|
return Op;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* getFirstToken() const override;
|
||||||
|
Token* getLastToken() const override;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Pattern : public Node {
|
class Pattern : public Node {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -1347,10 +1390,10 @@ namespace bolt {
|
||||||
class BindPattern : public Pattern {
|
class BindPattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Identifier* Name;
|
Symbol* Name;
|
||||||
|
|
||||||
BindPattern(
|
BindPattern(
|
||||||
Identifier* Name
|
Symbol* Name
|
||||||
): Pattern(NodeKind::BindPattern),
|
): Pattern(NodeKind::BindPattern),
|
||||||
Name(Name) {}
|
Name(Name) {}
|
||||||
|
|
||||||
|
@ -1384,10 +1427,10 @@ namespace bolt {
|
||||||
class RecordPatternField : public Node {
|
class RecordPatternField : public Node {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DotDot* DotDot;
|
class DotDot* DotDot;
|
||||||
Identifier* Name;
|
Identifier* Name;
|
||||||
Equals* Equals;
|
class Equals* Equals;
|
||||||
Pattern* Pattern;
|
class Pattern* Pattern;
|
||||||
|
|
||||||
inline RecordPatternField(
|
inline RecordPatternField(
|
||||||
class DotDot* DotDot,
|
class DotDot* DotDot,
|
||||||
|
@ -1427,9 +1470,9 @@ namespace bolt {
|
||||||
class RecordPattern : public Pattern {
|
class RecordPattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LBrace* LBrace;
|
class LBrace* LBrace;
|
||||||
std::vector<std::tuple<RecordPatternField*, Comma*>> Fields;
|
std::vector<std::tuple<RecordPatternField*, Comma*>> Fields;
|
||||||
RBrace* RBrace;
|
class RBrace* RBrace;
|
||||||
|
|
||||||
inline RecordPattern(
|
inline RecordPattern(
|
||||||
class LBrace* LBrace,
|
class LBrace* LBrace,
|
||||||
|
@ -1450,9 +1493,9 @@ namespace bolt {
|
||||||
|
|
||||||
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath;
|
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath;
|
||||||
IdentifierAlt* Name;
|
IdentifierAlt* Name;
|
||||||
LBrace* LBrace;
|
class LBrace* LBrace;
|
||||||
std::vector<std::tuple<RecordPatternField*, Comma*>> Fields;
|
std::vector<std::tuple<RecordPatternField*, Comma*>> Fields;
|
||||||
RBrace* RBrace;
|
class RBrace* RBrace;
|
||||||
|
|
||||||
inline NamedRecordPattern(
|
inline NamedRecordPattern(
|
||||||
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath,
|
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath,
|
||||||
|
@ -1493,9 +1536,9 @@ namespace bolt {
|
||||||
class TuplePattern : public Pattern {
|
class TuplePattern : public Pattern {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LParen* LParen;
|
class LParen* LParen;
|
||||||
std::vector<std::tuple<Pattern*, Comma*>> Elements;
|
std::vector<std::tuple<Pattern*, Comma*>> Elements;
|
||||||
RParen* RParen;
|
class RParen* RParen;
|
||||||
|
|
||||||
inline TuplePattern(
|
inline TuplePattern(
|
||||||
class LParen* LParen,
|
class LParen* LParen,
|
||||||
|
@ -1583,7 +1626,7 @@ namespace bolt {
|
||||||
Name(Name) {}
|
Name(Name) {}
|
||||||
|
|
||||||
inline ByteString getNameAsString() const noexcept {
|
inline ByteString getNameAsString() const noexcept {
|
||||||
return Name->getCanonicalText();
|
return getCanonicalText(Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* getFirstToken() const override;
|
Token* getFirstToken() const override;
|
||||||
|
@ -1656,11 +1699,11 @@ namespace bolt {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Expression* E;
|
Expression* E;
|
||||||
Dot* Dot;
|
class Dot* Dot;
|
||||||
Token* Name;
|
Token* Name;
|
||||||
|
|
||||||
inline MemberExpression(
|
inline MemberExpression(
|
||||||
class Expression* E,
|
Expression* E,
|
||||||
class Dot* Dot,
|
class Dot* Dot,
|
||||||
Token* Name
|
Token* Name
|
||||||
): Expression(NodeKind::MemberExpression),
|
): Expression(NodeKind::MemberExpression),
|
||||||
|
@ -1867,7 +1910,7 @@ namespace bolt {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Identifier* Name;
|
Identifier* Name;
|
||||||
Equals* Equals;
|
class Equals* Equals;
|
||||||
Expression* E;
|
Expression* E;
|
||||||
|
|
||||||
inline RecordExpressionField(
|
inline RecordExpressionField(
|
||||||
|
@ -1891,9 +1934,9 @@ namespace bolt {
|
||||||
class RecordExpression : public Expression {
|
class RecordExpression : public Expression {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LBrace* LBrace;
|
class LBrace* LBrace;
|
||||||
std::vector<std::tuple<RecordExpressionField*, Comma*>> Fields;
|
std::vector<std::tuple<RecordExpressionField*, Comma*>> Fields;
|
||||||
RBrace* RBrace;
|
class RBrace* RBrace;
|
||||||
|
|
||||||
inline RecordExpression(
|
inline RecordExpression(
|
||||||
class LBrace* LBrace,
|
class LBrace* LBrace,
|
||||||
|
@ -2191,13 +2234,13 @@ namespace bolt {
|
||||||
return !isSignature() && !isVariable();
|
return !isSignature() && !isVariable();
|
||||||
}
|
}
|
||||||
|
|
||||||
Identifier* getName() const noexcept {
|
Symbol* getName() const noexcept {
|
||||||
ZEN_ASSERT(Pattern->getKind() == NodeKind::BindPattern);
|
ZEN_ASSERT(Pattern->getKind() == NodeKind::BindPattern);
|
||||||
return static_cast<BindPattern*>(Pattern)->Name;
|
return static_cast<BindPattern*>(Pattern)->Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteString getNameAsString() const noexcept {
|
ByteString getNameAsString() const noexcept {
|
||||||
return getName()->getCanonicalText();
|
return getCanonicalText(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* getFirstToken() const override;
|
Token* getFirstToken() const override;
|
||||||
|
@ -2357,7 +2400,7 @@ namespace bolt {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
IdentifierAlt* Name;
|
IdentifierAlt* Name;
|
||||||
BlockStart* BlockStart;
|
class BlockStart* BlockStart;
|
||||||
std::vector<RecordDeclarationField*> Fields;
|
std::vector<RecordDeclarationField*> Fields;
|
||||||
|
|
||||||
inline RecordVariantDeclarationMember(
|
inline RecordVariantDeclarationMember(
|
||||||
|
|
|
@ -59,6 +59,7 @@ namespace bolt {
|
||||||
BOLT_GEN_CASE(Assignment)
|
BOLT_GEN_CASE(Assignment)
|
||||||
BOLT_GEN_CASE(Identifier)
|
BOLT_GEN_CASE(Identifier)
|
||||||
BOLT_GEN_CASE(IdentifierAlt)
|
BOLT_GEN_CASE(IdentifierAlt)
|
||||||
|
BOLT_GEN_CASE(WrappedOperator)
|
||||||
BOLT_GEN_CASE(StringLiteral)
|
BOLT_GEN_CASE(StringLiteral)
|
||||||
BOLT_GEN_CASE(IntegerLiteral)
|
BOLT_GEN_CASE(IntegerLiteral)
|
||||||
BOLT_GEN_CASE(ExpressionAnnotation)
|
BOLT_GEN_CASE(ExpressionAnnotation)
|
||||||
|
@ -357,6 +358,10 @@ namespace bolt {
|
||||||
static_cast<D*>(this)->visitTypeExpression(N);
|
static_cast<D*>(this)->visitTypeExpression(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitWrappedOperator(WrappedOperator* N) {
|
||||||
|
static_cast<D*>(this)->visitNode(N);
|
||||||
|
}
|
||||||
|
|
||||||
void visitPattern(Pattern* N) {
|
void visitPattern(Pattern* N) {
|
||||||
static_cast<D*>(this)->visitNode(N);
|
static_cast<D*>(this)->visitNode(N);
|
||||||
}
|
}
|
||||||
|
@ -579,6 +584,7 @@ namespace bolt {
|
||||||
BOLT_GEN_CHILD_CASE(Assignment)
|
BOLT_GEN_CHILD_CASE(Assignment)
|
||||||
BOLT_GEN_CHILD_CASE(Identifier)
|
BOLT_GEN_CHILD_CASE(Identifier)
|
||||||
BOLT_GEN_CHILD_CASE(IdentifierAlt)
|
BOLT_GEN_CHILD_CASE(IdentifierAlt)
|
||||||
|
BOLT_GEN_CHILD_CASE(WrappedOperator)
|
||||||
BOLT_GEN_CHILD_CASE(StringLiteral)
|
BOLT_GEN_CHILD_CASE(StringLiteral)
|
||||||
BOLT_GEN_CHILD_CASE(IntegerLiteral)
|
BOLT_GEN_CHILD_CASE(IntegerLiteral)
|
||||||
BOLT_GEN_CHILD_CASE(ExpressionAnnotation)
|
BOLT_GEN_CHILD_CASE(ExpressionAnnotation)
|
||||||
|
@ -763,6 +769,12 @@ namespace bolt {
|
||||||
void visitEachChild(IntegerLiteral* N) {
|
void visitEachChild(IntegerLiteral* N) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitEachChild(WrappedOperator* N) {
|
||||||
|
BOLT_VISIT(N->LParen);
|
||||||
|
BOLT_VISIT(N->Op);
|
||||||
|
BOLT_VISIT(N->RParen);
|
||||||
|
}
|
||||||
|
|
||||||
void visitEachChild(ExpressionAnnotation* N) {
|
void visitEachChild(ExpressionAnnotation* N) {
|
||||||
BOLT_VISIT(N->At);
|
BOLT_VISIT(N->At);
|
||||||
BOLT_VISIT(N->Expression);
|
BOLT_VISIT(N->Expression);
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include "bolt/CST.hpp"
|
#include "bolt/CST.hpp"
|
||||||
#include "bolt/CSTVisitor.hpp"
|
#include "bolt/CSTVisitor.hpp"
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
namespace bolt {
|
namespace bolt {
|
||||||
|
|
||||||
|
@ -117,7 +116,7 @@ namespace bolt {
|
||||||
case NodeKind::ClassDeclaration:
|
case NodeKind::ClassDeclaration:
|
||||||
{
|
{
|
||||||
auto Decl = static_cast<ClassDeclaration*>(X);
|
auto Decl = static_cast<ClassDeclaration*>(X);
|
||||||
addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Class);
|
addSymbol(getCanonicalText(Decl->Name), Decl, SymbolKind::Class);
|
||||||
for (auto Element: Decl->Elements) {
|
for (auto Element: Decl->Elements) {
|
||||||
scanChild(Element);
|
scanChild(Element);
|
||||||
}
|
}
|
||||||
|
@ -134,25 +133,25 @@ namespace bolt {
|
||||||
case NodeKind::RecordDeclaration:
|
case NodeKind::RecordDeclaration:
|
||||||
{
|
{
|
||||||
auto Decl = static_cast<RecordDeclaration*>(X);
|
auto Decl = static_cast<RecordDeclaration*>(X);
|
||||||
addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Type);
|
addSymbol(getCanonicalText(Decl->Name), Decl, SymbolKind::Type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind::VariantDeclaration:
|
case NodeKind::VariantDeclaration:
|
||||||
{
|
{
|
||||||
auto Decl = static_cast<VariantDeclaration*>(X);
|
auto Decl = static_cast<VariantDeclaration*>(X);
|
||||||
addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Type);
|
addSymbol(getCanonicalText(Decl->Name), Decl, SymbolKind::Type);
|
||||||
for (auto Member: Decl->Members) {
|
for (auto Member: Decl->Members) {
|
||||||
switch (Member->getKind()) {
|
switch (Member->getKind()) {
|
||||||
case NodeKind::TupleVariantDeclarationMember:
|
case NodeKind::TupleVariantDeclarationMember:
|
||||||
{
|
{
|
||||||
auto T = static_cast<TupleVariantDeclarationMember*>(Member);
|
auto T = static_cast<TupleVariantDeclarationMember*>(Member);
|
||||||
addSymbol(T->Name->getCanonicalText(), Decl, SymbolKind::Constructor);
|
addSymbol(getCanonicalText(T->Name), Decl, SymbolKind::Constructor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind::RecordVariantDeclarationMember:
|
case NodeKind::RecordVariantDeclarationMember:
|
||||||
{
|
{
|
||||||
auto R = static_cast<RecordVariantDeclarationMember*>(Member);
|
auto R = static_cast<RecordVariantDeclarationMember*>(Member);
|
||||||
addSymbol(R->Name->getCanonicalText(), Decl, SymbolKind::Constructor);
|
addSymbol(getCanonicalText(R->Name), Decl, SymbolKind::Constructor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -171,7 +170,7 @@ namespace bolt {
|
||||||
case NodeKind::BindPattern:
|
case NodeKind::BindPattern:
|
||||||
{
|
{
|
||||||
auto Y = static_cast<BindPattern*>(X);
|
auto Y = static_cast<BindPattern*>(X);
|
||||||
addSymbol(Y->Name->Text, Decl, SymbolKind::Var);
|
addSymbol(getCanonicalText(Y->Name), Decl, SymbolKind::Var);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind::RecordPattern:
|
case NodeKind::RecordPattern:
|
||||||
|
@ -489,12 +488,38 @@ namespace bolt {
|
||||||
return RParen;
|
return RParen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token* WrappedOperator::getFirstToken() const {
|
||||||
|
return LParen;
|
||||||
|
}
|
||||||
|
|
||||||
|
Token* WrappedOperator::getLastToken() const {
|
||||||
|
return RParen;
|
||||||
|
}
|
||||||
|
|
||||||
Token* BindPattern::getFirstToken() const {
|
Token* BindPattern::getFirstToken() const {
|
||||||
return Name;
|
switch (Name->getKind()) {
|
||||||
|
case NodeKind::Identifier:
|
||||||
|
return static_cast<Identifier*>(Name);
|
||||||
|
case NodeKind::IdentifierAlt:
|
||||||
|
return static_cast<IdentifierAlt*>(Name);
|
||||||
|
case NodeKind::WrappedOperator:
|
||||||
|
return static_cast<WrappedOperator*>(Name)->LParen;
|
||||||
|
default:
|
||||||
|
ZEN_UNREACHABLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* BindPattern::getLastToken() const {
|
Token* BindPattern::getLastToken() const {
|
||||||
return Name;
|
switch (Name->getKind()) {
|
||||||
|
case NodeKind::Identifier:
|
||||||
|
return static_cast<Identifier*>(Name);
|
||||||
|
case NodeKind::IdentifierAlt:
|
||||||
|
return static_cast<IdentifierAlt*>(Name);
|
||||||
|
case NodeKind::WrappedOperator:
|
||||||
|
return static_cast<WrappedOperator*>(Name)->RParen;
|
||||||
|
default:
|
||||||
|
ZEN_UNREACHABLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* LiteralPattern::getFirstToken() const {
|
Token* LiteralPattern::getFirstToken() const {
|
||||||
|
@ -577,11 +602,29 @@ namespace bolt {
|
||||||
if (!ModulePath.empty()) {
|
if (!ModulePath.empty()) {
|
||||||
return std::get<0>(ModulePath.front());
|
return std::get<0>(ModulePath.front());
|
||||||
}
|
}
|
||||||
return Name;
|
switch (Name->getKind()) {
|
||||||
|
case NodeKind::Identifier:
|
||||||
|
return static_cast<Identifier*>(Name);
|
||||||
|
case NodeKind::IdentifierAlt:
|
||||||
|
return static_cast<IdentifierAlt*>(Name);
|
||||||
|
case NodeKind::WrappedOperator:
|
||||||
|
return static_cast<WrappedOperator*>(Name)->LParen;
|
||||||
|
default:
|
||||||
|
ZEN_UNREACHABLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* ReferenceExpression::getLastToken() const {
|
Token* ReferenceExpression::getLastToken() const {
|
||||||
return Name;
|
switch (Name->getKind()) {
|
||||||
|
case NodeKind::Identifier:
|
||||||
|
return static_cast<Identifier*>(Name);
|
||||||
|
case NodeKind::IdentifierAlt:
|
||||||
|
return static_cast<IdentifierAlt*>(Name);
|
||||||
|
case NodeKind::WrappedOperator:
|
||||||
|
return static_cast<WrappedOperator*>(Name)->RParen;
|
||||||
|
default:
|
||||||
|
ZEN_UNREACHABLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Token* MatchCase::getFirstToken() const {
|
Token* MatchCase::getFirstToken() const {
|
||||||
|
@ -1044,12 +1087,21 @@ namespace bolt {
|
||||||
return "instance";
|
return "instance";
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteString Identifier::getCanonicalText() {
|
ByteString getCanonicalText(const Symbol* N) {
|
||||||
return Text;
|
switch (N->getKind()) {
|
||||||
}
|
case NodeKind::Identifier:
|
||||||
|
return static_cast<const Identifier*>(N)->Text;
|
||||||
ByteString IdentifierAlt::getCanonicalText() {
|
case NodeKind::IdentifierAlt:
|
||||||
return Text;
|
return static_cast<const IdentifierAlt*>(N)->Text;
|
||||||
|
case NodeKind::CustomOperator:
|
||||||
|
return static_cast<const CustomOperator*>(N)->Text;
|
||||||
|
case NodeKind::VBar:
|
||||||
|
return static_cast<const VBar*>(N)->getText();
|
||||||
|
case NodeKind::WrappedOperator:
|
||||||
|
return static_cast<const WrappedOperator*>(N)->getOperator()->getText();
|
||||||
|
default:
|
||||||
|
ZEN_UNREACHABLE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LiteralValue StringLiteral::getValue() {
|
LiteralValue StringLiteral::getValue() {
|
||||||
|
@ -1063,9 +1115,9 @@ namespace bolt {
|
||||||
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) {
|
||||||
ModuleNames.push_back(Name->getCanonicalText());
|
ModuleNames.push_back(getCanonicalText(Name));
|
||||||
}
|
}
|
||||||
return SymbolPath { ModuleNames, Name->getCanonicalText() };
|
return SymbolPath { ModuleNames, getCanonicalText(Name) };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace bolt {
|
||||||
case ConstraintKind::Empty:
|
case ConstraintKind::Empty:
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
ZEN_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
Type* Checker::solveType(Type* Ty) {
|
Type* Checker::solveType(Type* Ty) {
|
||||||
|
@ -250,9 +251,9 @@ namespace bolt {
|
||||||
inferTypeExpression(TE);
|
inferTypeExpression(TE);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Match = InstanceMap.find(Decl->Name->getCanonicalText());
|
auto Match = InstanceMap.find(getCanonicalText(Decl->Name));
|
||||||
if (Match == InstanceMap.end()) {
|
if (Match == InstanceMap.end()) {
|
||||||
InstanceMap.emplace(Decl->Name->getCanonicalText(), std::vector { Decl });
|
InstanceMap.emplace(getCanonicalText(Decl->Name), std::vector { Decl });
|
||||||
} else {
|
} else {
|
||||||
Match->second.push_back(Decl);
|
Match->second.push_back(Decl);
|
||||||
}
|
}
|
||||||
|
@ -289,13 +290,13 @@ namespace bolt {
|
||||||
|
|
||||||
std::vector<Type*> Vars;
|
std::vector<Type*> Vars;
|
||||||
for (auto TE: Decl->TVs) {
|
for (auto TE: Decl->TVs) {
|
||||||
auto TV = createRigidVar(TE->Name->getCanonicalText());
|
auto TV = createRigidVar(getCanonicalText(TE->Name));
|
||||||
Decl->Ctx->TVs->emplace(TV);
|
Decl->Ctx->TVs->emplace(TV);
|
||||||
Decl->Ctx->Env.add(TE->Name->getCanonicalText(), new Forall(TV), SymKind::Type);
|
Decl->Ctx->Env.add(getCanonicalText(TE->Name), new Forall(TV), SymKind::Type);
|
||||||
Vars.push_back(TV);
|
Vars.push_back(TV);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type* Ty = createConType(Decl->Name->getCanonicalText());
|
Type* Ty = createConType(getCanonicalText(Decl->Name));
|
||||||
|
|
||||||
// Build the type that is actually returned by constructor functions
|
// Build the type that is actually returned by constructor functions
|
||||||
auto RetTy = Ty;
|
auto RetTy = Ty;
|
||||||
|
@ -304,7 +305,7 @@ namespace bolt {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must be added early so we can create recursive types
|
// Must be added early so we can create recursive types
|
||||||
Decl->Ctx->Parent->Env.add(Decl->Name->getCanonicalText(), new Forall(Ty), SymKind::Type);
|
Decl->Ctx->Parent->Env.add(getCanonicalText(Decl->Name), new Forall(Ty), SymKind::Type);
|
||||||
|
|
||||||
for (auto Member: Decl->Members) {
|
for (auto Member: Decl->Members) {
|
||||||
switch (Member->getKind()) {
|
switch (Member->getKind()) {
|
||||||
|
@ -317,7 +318,7 @@ namespace bolt {
|
||||||
ParamTypes.push_back(inferTypeExpression(Element, false));
|
ParamTypes.push_back(inferTypeExpression(Element, false));
|
||||||
}
|
}
|
||||||
Decl->Ctx->Parent->Env.add(
|
Decl->Ctx->Parent->Env.add(
|
||||||
TupleMember->Name->getCanonicalText(),
|
getCanonicalText(TupleMember->Name),
|
||||||
new Forall(
|
new Forall(
|
||||||
Decl->Ctx->TVs,
|
Decl->Ctx->TVs,
|
||||||
Decl->Ctx->Constraints,
|
Decl->Ctx->Constraints,
|
||||||
|
@ -350,13 +351,13 @@ namespace bolt {
|
||||||
|
|
||||||
std::vector<Type*> Vars;
|
std::vector<Type*> Vars;
|
||||||
for (auto TE: Decl->Vars) {
|
for (auto TE: Decl->Vars) {
|
||||||
auto TV = createRigidVar(TE->Name->getCanonicalText());
|
auto TV = createRigidVar(getCanonicalText(TE->Name));
|
||||||
Decl->Ctx->TVs->emplace(TV);
|
Decl->Ctx->TVs->emplace(TV);
|
||||||
Decl->Ctx->Env.add(TE->Name->getCanonicalText(), new Forall(TV), SymKind::Type);
|
Decl->Ctx->Env.add(getCanonicalText(TE->Name), new Forall(TV), SymKind::Type);
|
||||||
Vars.push_back(TV);
|
Vars.push_back(TV);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Name = Decl->Name->getCanonicalText();
|
auto Name = getCanonicalText(Decl->Name);
|
||||||
auto Ty = createConType(Name);
|
auto Ty = createConType(Name);
|
||||||
|
|
||||||
// Must be added early so we can create recursive types
|
// Must be added early so we can create recursive types
|
||||||
|
@ -372,7 +373,7 @@ namespace bolt {
|
||||||
for (auto Field: Decl->Fields) {
|
for (auto Field: Decl->Fields) {
|
||||||
FieldsTy = new Type(
|
FieldsTy = new Type(
|
||||||
TField(
|
TField(
|
||||||
Field->Name->getCanonicalText(),
|
getCanonicalText(Field->Name),
|
||||||
new Type(TPresent(inferTypeExpression(Field->TypeExpression, false))),
|
new Type(TPresent(inferTypeExpression(Field->TypeExpression, false))),
|
||||||
FieldsTy
|
FieldsTy
|
||||||
)
|
)
|
||||||
|
@ -466,11 +467,11 @@ namespace bolt {
|
||||||
setContext(Let->Ctx);
|
setContext(Let->Ctx);
|
||||||
|
|
||||||
auto addClassVars = [&](ClassDeclaration* Class, bool IsRigid) {
|
auto addClassVars = [&](ClassDeclaration* Class, bool IsRigid) {
|
||||||
auto Id = Class->Name->getCanonicalText();
|
auto Id = getCanonicalText(Class->Name);
|
||||||
auto Ctx = &getContext();
|
auto Ctx = &getContext();
|
||||||
std::vector<Type*> Out;
|
std::vector<Type*> Out;
|
||||||
for (auto TE: Class->TypeVars) {
|
for (auto TE: Class->TypeVars) {
|
||||||
auto Name = TE->Name->getCanonicalText();
|
auto Name = getCanonicalText(TE->Name);
|
||||||
auto TV = IsRigid ? createRigidVar(Name) : createTypeVar();
|
auto TV = IsRigid ? createRigidVar(Name) : createTypeVar();
|
||||||
TV->asVar().Context.emplace(Id);
|
TV->asVar().Context.emplace(Id);
|
||||||
Ctx->Env.add(Name, new Forall(TV), SymKind::Type);
|
Ctx->Env.add(Name, new Forall(TV), SymKind::Type);
|
||||||
|
@ -506,7 +507,7 @@ namespace bolt {
|
||||||
if (Let->isInstance()) {
|
if (Let->isInstance()) {
|
||||||
|
|
||||||
auto Instance = static_cast<InstanceDeclaration*>(Let->Parent);
|
auto Instance = static_cast<InstanceDeclaration*>(Let->Parent);
|
||||||
auto Class = cast<ClassDeclaration>(Instance->getScope()->lookup({ {}, Instance->Name->getCanonicalText() }, SymbolKind::Class));
|
auto Class = cast<ClassDeclaration>(Instance->getScope()->lookup({ {}, getCanonicalText(Instance->Name) }, SymbolKind::Class));
|
||||||
auto SigLet = cast<LetDeclaration>(Class->getScope()->lookupDirect({ {}, Let->getNameAsString() }, SymbolKind::Var));
|
auto SigLet = cast<LetDeclaration>(Class->getScope()->lookupDirect({ {}, Let->getNameAsString() }, SymbolKind::Var));
|
||||||
|
|
||||||
auto Params = addClassVars(Class, false);
|
auto Params = addClassVars(Class, false);
|
||||||
|
@ -788,6 +789,7 @@ namespace bolt {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZEN_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Checker::inferConstraintExpression(ConstraintExpression* C) {
|
void Checker::inferConstraintExpression(ConstraintExpression* C) {
|
||||||
|
@ -798,7 +800,7 @@ namespace bolt {
|
||||||
std::vector<Type*> Types;
|
std::vector<Type*> Types;
|
||||||
for (auto TE: D->TEs) {
|
for (auto TE: D->TEs) {
|
||||||
auto Ty = inferTypeExpression(TE);
|
auto Ty = inferTypeExpression(TE);
|
||||||
Ty->asVar().Provided->emplace(D->Name->getCanonicalText());
|
Ty->asVar().Provided->emplace(getCanonicalText(D->Name));
|
||||||
Types.push_back(Ty);
|
Types.push_back(Ty);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -821,10 +823,10 @@ namespace bolt {
|
||||||
case NodeKind::ReferenceTypeExpression:
|
case NodeKind::ReferenceTypeExpression:
|
||||||
{
|
{
|
||||||
auto RefTE = static_cast<ReferenceTypeExpression*>(N);
|
auto RefTE = static_cast<ReferenceTypeExpression*>(N);
|
||||||
auto Scm = lookup(RefTE->Name->getCanonicalText(), SymKind::Type);
|
auto Scm = lookup(getCanonicalText(RefTE->Name), SymKind::Type);
|
||||||
Type* Ty;
|
Type* Ty;
|
||||||
if (Scm == nullptr) {
|
if (Scm == nullptr) {
|
||||||
DE.add<BindingNotFoundDiagnostic>(RefTE->Name->getCanonicalText(), RefTE->Name);
|
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(RefTE->Name), RefTE->Name);
|
||||||
Ty = createTypeVar();
|
Ty = createTypeVar();
|
||||||
} else {
|
} else {
|
||||||
Ty = instantiate(Scm, RefTE);
|
Ty = instantiate(Scm, RefTE);
|
||||||
|
@ -847,13 +849,13 @@ namespace bolt {
|
||||||
case NodeKind::VarTypeExpression:
|
case NodeKind::VarTypeExpression:
|
||||||
{
|
{
|
||||||
auto VarTE = static_cast<VarTypeExpression*>(N);
|
auto VarTE = static_cast<VarTypeExpression*>(N);
|
||||||
auto Ty = lookupMono(VarTE->Name->getCanonicalText(), SymKind::Type);
|
auto Ty = lookupMono(getCanonicalText(VarTE->Name), SymKind::Type);
|
||||||
if (Ty == nullptr) {
|
if (Ty == nullptr) {
|
||||||
if (!AutoVars || Config.typeVarsRequireForall()) {
|
if (!AutoVars || Config.typeVarsRequireForall()) {
|
||||||
DE.add<BindingNotFoundDiagnostic>(VarTE->Name->getCanonicalText(), VarTE->Name);
|
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(VarTE->Name), VarTE->Name);
|
||||||
}
|
}
|
||||||
Ty = createRigidVar(VarTE->Name->getCanonicalText());
|
Ty = createRigidVar(getCanonicalText(VarTE->Name));
|
||||||
addBinding(VarTE->Name->getCanonicalText(), new Forall(Ty), SymKind::Type);
|
addBinding(getCanonicalText(VarTE->Name), new Forall(Ty), SymKind::Type);
|
||||||
}
|
}
|
||||||
ZEN_ASSERT(Ty->isVar());
|
ZEN_ASSERT(Ty->isVar());
|
||||||
N->setType(Ty);
|
N->setType(Ty);
|
||||||
|
@ -865,7 +867,7 @@ namespace bolt {
|
||||||
auto RecTE = static_cast<RecordTypeExpression*>(N);
|
auto RecTE = static_cast<RecordTypeExpression*>(N);
|
||||||
auto Ty = RecTE->Rest ? inferTypeExpression(RecTE->Rest, AutoVars) : new Type(TNil());
|
auto Ty = RecTE->Rest ? inferTypeExpression(RecTE->Rest, AutoVars) : new Type(TNil());
|
||||||
for (auto [Field, Comma]: RecTE->Fields) {
|
for (auto [Field, Comma]: RecTE->Fields) {
|
||||||
Ty = new Type(TField(Field->Name->getCanonicalText(), new Type(TPresent(inferTypeExpression(Field->TE, AutoVars))), Ty));
|
Ty = new Type(TField(getCanonicalText(Field->Name), new Type(TPresent(inferTypeExpression(Field->TE, AutoVars))), Ty));
|
||||||
}
|
}
|
||||||
N->setType(Ty);
|
N->setType(Ty);
|
||||||
return Ty;
|
return Ty;
|
||||||
|
@ -977,7 +979,7 @@ namespace bolt {
|
||||||
Ty = new Type(TNil());
|
Ty = new Type(TNil());
|
||||||
for (auto [Field, Comma]: Record->Fields) {
|
for (auto [Field, Comma]: Record->Fields) {
|
||||||
Ty = new Type(TField(
|
Ty = new Type(TField(
|
||||||
Field->Name->getCanonicalText(),
|
getCanonicalText(Field->Name),
|
||||||
new Type(TPresent(inferExpression(Field->getExpression()))),
|
new Type(TPresent(inferExpression(Field->getExpression()))),
|
||||||
Ty
|
Ty
|
||||||
));
|
));
|
||||||
|
@ -998,9 +1000,9 @@ namespace bolt {
|
||||||
auto Ref = static_cast<ReferenceExpression*>(X);
|
auto Ref = static_cast<ReferenceExpression*>(X);
|
||||||
ZEN_ASSERT(Ref->ModulePath.empty());
|
ZEN_ASSERT(Ref->ModulePath.empty());
|
||||||
if (Ref->Name->is<IdentifierAlt>()) {
|
if (Ref->Name->is<IdentifierAlt>()) {
|
||||||
auto Scm = lookup(Ref->Name->getCanonicalText(), SymKind::Var);
|
auto Scm = lookup(getCanonicalText(Ref->Name), SymKind::Var);
|
||||||
if (!Scm) {
|
if (!Scm) {
|
||||||
DE.add<BindingNotFoundDiagnostic>(Ref->Name->getCanonicalText(), Ref->Name);
|
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(Ref->Name), Ref->Name);
|
||||||
Ty = createTypeVar();
|
Ty = createTypeVar();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1009,7 +1011,7 @@ namespace bolt {
|
||||||
}
|
}
|
||||||
auto Target = Ref->getScope()->lookup(Ref->getSymbolPath());
|
auto Target = Ref->getScope()->lookup(Ref->getSymbolPath());
|
||||||
if (!Target) {
|
if (!Target) {
|
||||||
DE.add<BindingNotFoundDiagnostic>(Ref->Name->getCanonicalText(), Ref->Name);
|
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(Ref->Name), Ref->Name);
|
||||||
Ty = createTypeVar();
|
Ty = createTypeVar();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1023,7 +1025,7 @@ namespace bolt {
|
||||||
infer(Let);
|
infer(Let);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto Scm = lookup(Ref->Name->getCanonicalText(), SymKind::Var);
|
auto Scm = lookup(getCanonicalText(Ref->Name), SymKind::Var);
|
||||||
ZEN_ASSERT(Scm);
|
ZEN_ASSERT(Scm);
|
||||||
Ty = instantiate(Scm, X);
|
Ty = instantiate(Scm, X);
|
||||||
break;
|
break;
|
||||||
|
@ -1088,7 +1090,7 @@ namespace bolt {
|
||||||
auto K = static_cast<Identifier*>(Member->Name);
|
auto K = static_cast<Identifier*>(Member->Name);
|
||||||
Ty = createTypeVar();
|
Ty = createTypeVar();
|
||||||
auto RestTy = createTypeVar();
|
auto RestTy = createTypeVar();
|
||||||
makeEqual(new Type(TField(K->getCanonicalText(), Ty, RestTy)), ExprTy, Member);
|
makeEqual(new Type(TField(getCanonicalText(K), Ty, RestTy)), ExprTy, Member);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -1135,20 +1137,20 @@ namespace bolt {
|
||||||
{
|
{
|
||||||
auto P = static_cast<BindPattern*>(Pattern);
|
auto P = static_cast<BindPattern*>(Pattern);
|
||||||
auto Ty = createTypeVar();
|
auto Ty = createTypeVar();
|
||||||
addBinding(P->Name->getCanonicalText(), new Forall(TVs, Constraints, Ty), SymKind::Var);
|
addBinding(getCanonicalText(P->Name), new Forall(TVs, Constraints, Ty), SymKind::Var);
|
||||||
return Ty;
|
return Ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
case NodeKind::NamedTuplePattern:
|
case NodeKind::NamedTuplePattern:
|
||||||
{
|
{
|
||||||
auto P = static_cast<NamedTuplePattern*>(Pattern);
|
auto P = static_cast<NamedTuplePattern*>(Pattern);
|
||||||
auto Scm = lookup(P->Name->getCanonicalText(), SymKind::Var);
|
auto Scm = lookup(getCanonicalText(P->Name), SymKind::Var);
|
||||||
std::vector<Type*> ElementTypes;
|
std::vector<Type*> ElementTypes;
|
||||||
for (auto P2: P->Patterns) {
|
for (auto P2: P->Patterns) {
|
||||||
ElementTypes.push_back(inferPattern(P2, Constraints, TVs));
|
ElementTypes.push_back(inferPattern(P2, Constraints, TVs));
|
||||||
}
|
}
|
||||||
if (!Scm) {
|
if (!Scm) {
|
||||||
DE.add<BindingNotFoundDiagnostic>(P->Name->getCanonicalText(), P->Name);
|
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(P->Name), P->Name);
|
||||||
return createTypeVar();
|
return createTypeVar();
|
||||||
}
|
}
|
||||||
auto Ty = instantiate(Scm, P);
|
auto Ty = instantiate(Scm, P);
|
||||||
|
@ -1178,9 +1180,9 @@ namespace bolt {
|
||||||
FieldTy = inferPattern(Field->Pattern, Constraints, TVs);
|
FieldTy = inferPattern(Field->Pattern, Constraints, TVs);
|
||||||
} else {
|
} else {
|
||||||
FieldTy = createTypeVar();
|
FieldTy = createTypeVar();
|
||||||
addBinding(Field->Name->getCanonicalText(), new Forall(TVs, Constraints, FieldTy), SymKind::Var);
|
addBinding(getCanonicalText(Field->Name), new Forall(TVs, Constraints, FieldTy), SymKind::Var);
|
||||||
}
|
}
|
||||||
RecordTy = new Type(TField(Field->Name->getCanonicalText(), new Type(TPresent(FieldTy)), RecordTy));
|
RecordTy = new Type(TField(getCanonicalText(Field->Name), new Type(TPresent(FieldTy)), RecordTy));
|
||||||
}
|
}
|
||||||
return RecordTy;
|
return RecordTy;
|
||||||
}
|
}
|
||||||
|
@ -1188,9 +1190,9 @@ namespace bolt {
|
||||||
case NodeKind::NamedRecordPattern:
|
case NodeKind::NamedRecordPattern:
|
||||||
{
|
{
|
||||||
auto P = static_cast<NamedRecordPattern*>(Pattern);
|
auto P = static_cast<NamedRecordPattern*>(Pattern);
|
||||||
auto Scm = lookup(P->Name->getCanonicalText(), SymKind::Var);
|
auto Scm = lookup(getCanonicalText(P->Name), SymKind::Var);
|
||||||
if (Scm == nullptr) {
|
if (Scm == nullptr) {
|
||||||
DE.add<BindingNotFoundDiagnostic>(P->Name->getCanonicalText(), P->Name);
|
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(P->Name), P->Name);
|
||||||
return createTypeVar();
|
return createTypeVar();
|
||||||
}
|
}
|
||||||
auto RestField = getRestField(P->Fields);
|
auto RestField = getRestField(P->Fields);
|
||||||
|
@ -1211,9 +1213,9 @@ namespace bolt {
|
||||||
FieldTy = inferPattern(Field->Pattern, Constraints, TVs);
|
FieldTy = inferPattern(Field->Pattern, Constraints, TVs);
|
||||||
} else {
|
} else {
|
||||||
FieldTy = createTypeVar();
|
FieldTy = createTypeVar();
|
||||||
addBinding(Field->Name->getCanonicalText(), new Forall(TVs, Constraints, FieldTy), SymKind::Var);
|
addBinding(getCanonicalText(Field->Name), new Forall(TVs, Constraints, FieldTy), SymKind::Var);
|
||||||
}
|
}
|
||||||
RecordTy = new Type(TField(Field->Name->getCanonicalText(), new Type(TPresent(FieldTy)), RecordTy));
|
RecordTy = new Type(TField(getCanonicalText(Field->Name), new Type(TPresent(FieldTy)), RecordTy));
|
||||||
}
|
}
|
||||||
auto Ty = instantiate(Scm, P);
|
auto Ty = instantiate(Scm, P);
|
||||||
auto RetTy = createTypeVar();
|
auto RetTy = createTypeVar();
|
||||||
|
|
|
@ -175,6 +175,8 @@ namespace bolt {
|
||||||
return "a branch of an if-statement";
|
return "a branch of an if-statement";
|
||||||
case NodeKind::VariantDeclaration:
|
case NodeKind::VariantDeclaration:
|
||||||
return "a variant";
|
return "a variant";
|
||||||
|
case NodeKind::MatchCase:
|
||||||
|
return "a match-arm";
|
||||||
default:
|
default:
|
||||||
ZEN_UNREACHABLE
|
ZEN_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
@ -262,6 +264,7 @@ namespace bolt {
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ZEN_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeForegroundANSI(Color C, std::ostream& Out) {
|
void writeForegroundANSI(Color C, std::ostream& Out) {
|
||||||
|
@ -925,6 +928,8 @@ namespace bolt {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZEN_UNREACHABLE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
|
|
||||||
namespace bolt {
|
namespace bolt {
|
||||||
|
|
||||||
Value Evaluator::evaluateExpression(Expression* X, Env& E) {
|
Value Evaluator::evaluateExpression(Expression* X, Env& Env) {
|
||||||
switch (X->getKind()) {
|
switch (X->getKind()) {
|
||||||
case NodeKind::ReferenceExpression:
|
case NodeKind::ReferenceExpression:
|
||||||
{
|
{
|
||||||
auto RE = static_cast<ReferenceExpression*>(X);
|
auto RE = static_cast<ReferenceExpression*>(X);
|
||||||
return E.lookup(RE->Name->getCanonicalText());
|
return Env.lookup(getCanonicalText(RE->Name));
|
||||||
// auto Decl = RE->getScope()->lookup(RE->getSymbolPath());
|
// auto Decl = RE->getScope()->lookup(RE->getSymbolPath());
|
||||||
// ZEN_ASSERT(Decl && Decl->getKind() == NodeKind::FunctionDeclaration);
|
// ZEN_ASSERT(Decl && Decl->getKind() == NodeKind::FunctionDeclaration);
|
||||||
// return static_cast<FunctionDeclaration*>(Decl);
|
// return static_cast<FunctionDeclaration*>(Decl);
|
||||||
|
@ -31,10 +31,10 @@ namespace bolt {
|
||||||
case NodeKind::CallExpression:
|
case NodeKind::CallExpression:
|
||||||
{
|
{
|
||||||
auto CE = static_cast<CallExpression*>(X);
|
auto CE = static_cast<CallExpression*>(X);
|
||||||
auto Op = evaluateExpression(CE->Function, E);
|
auto Op = evaluateExpression(CE->Function, Env);
|
||||||
std::vector<Value> Args;
|
std::vector<Value> Args;
|
||||||
for (auto Arg: CE->Args) {
|
for (auto Arg: CE->Args) {
|
||||||
Args.push_back(evaluateExpression(Arg, E));
|
Args.push_back(evaluateExpression(Arg, Env));
|
||||||
}
|
}
|
||||||
return apply(Op, Args);
|
return apply(Op, Args);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ namespace bolt {
|
||||||
case NodeKind::BindPattern:
|
case NodeKind::BindPattern:
|
||||||
{
|
{
|
||||||
auto BP = static_cast<BindPattern*>(P);
|
auto BP = static_cast<BindPattern*>(P);
|
||||||
E.add(BP->Name->getCanonicalText(), V);
|
E.add(getCanonicalText(BP->Name), V);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -32,6 +32,16 @@
|
||||||
|
|
||||||
namespace bolt {
|
namespace bolt {
|
||||||
|
|
||||||
|
bool isOperator(Token* T) {
|
||||||
|
switch (T->getKind()) {
|
||||||
|
case NodeKind::VBar:
|
||||||
|
case NodeKind::CustomOperator:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<OperatorInfo> OperatorTable::getInfix(Token* T) {
|
std::optional<OperatorInfo> OperatorTable::getInfix(Token* T) {
|
||||||
auto Match = Mapping.find(T->getText());
|
auto Match = Mapping.find(T->getText());
|
||||||
if (Match == Mapping.end() || !Match->second.isInfix()) {
|
if (Match == Mapping.end() || !Match->second.isInfix()) {
|
||||||
|
@ -810,7 +820,7 @@ after_tuple_element:
|
||||||
ModulePath.push_back(std::make_tuple(static_cast<IdentifierAlt*>(T1), static_cast<class Dot*>(T2)));
|
ModulePath.push_back(std::make_tuple(static_cast<IdentifierAlt*>(T1), static_cast<class Dot*>(T2)));
|
||||||
}
|
}
|
||||||
auto T3 = Tokens.get();
|
auto T3 = Tokens.get();
|
||||||
if (!isa<Symbol>(T3)) {
|
if (!T3->is<Identifier>() && !T3->is<IdentifierAlt>()) {
|
||||||
for (auto [Name, Dot]: ModulePath) {
|
for (auto [Name, Dot]: ModulePath) {
|
||||||
Name->unref();
|
Name->unref();
|
||||||
Dot->unref();
|
Dot->unref();
|
||||||
|
@ -938,13 +948,14 @@ finish:
|
||||||
auto T1 = Tokens.peek();
|
auto T1 = Tokens.peek();
|
||||||
if (T1->getKind() == NodeKind::LineFoldEnd
|
if (T1->getKind() == NodeKind::LineFoldEnd
|
||||||
|| T1->getKind() == NodeKind::RParen
|
|| T1->getKind() == NodeKind::RParen
|
||||||
|
|| T1->getKind() == NodeKind::RBracket
|
||||||
|| T1->getKind() == NodeKind::RBrace
|
|| T1->getKind() == NodeKind::RBrace
|
||||||
|| T1->getKind() == NodeKind::BlockStart
|
|| T1->getKind() == NodeKind::BlockStart
|
||||||
|| T1->getKind() == NodeKind::Comma
|
|| T1->getKind() == NodeKind::Comma
|
||||||
|| ExprOperators.isInfix(T1)) {
|
|| ExprOperators.isInfix(T1)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto Arg = parsePrimitiveExpression();
|
auto Arg = parseMemberExpression();
|
||||||
if (!Arg) {
|
if (!Arg) {
|
||||||
Operator->unref();
|
Operator->unref();
|
||||||
for (auto Arg: Args) {
|
for (auto Arg: Args) {
|
||||||
|
@ -1137,6 +1148,8 @@ finish:
|
||||||
ForeignKeyword* Foreign = nullptr;
|
ForeignKeyword* Foreign = nullptr;
|
||||||
LetKeyword* Let;
|
LetKeyword* Let;
|
||||||
MutKeyword* Mut = nullptr;
|
MutKeyword* Mut = nullptr;
|
||||||
|
Pattern* Name;
|
||||||
|
std::vector<Parameter*> Params;
|
||||||
TypeAssert* TA = nullptr;
|
TypeAssert* TA = nullptr;
|
||||||
LetBody* Body = nullptr;
|
LetBody* Body = nullptr;
|
||||||
|
|
||||||
|
@ -1167,27 +1180,49 @@ finish:
|
||||||
Mut = static_cast<MutKeyword*>(T1);
|
Mut = static_cast<MutKeyword*>(T1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Pattern = parseNarrowPattern();
|
auto T2 = Tokens.peek(0);
|
||||||
if (!Pattern) {
|
auto T3 = Tokens.peek(1);
|
||||||
if (Pub) {
|
auto T4 = Tokens.peek(2);
|
||||||
Pub->unref();
|
if (T2->getKind() == NodeKind::LParen && isOperator(T3) && T4->getKind() == NodeKind::RParen) {
|
||||||
|
Tokens.get();
|
||||||
|
Tokens.get();
|
||||||
|
Tokens.get();
|
||||||
|
Name = new BindPattern(
|
||||||
|
new WrappedOperator(
|
||||||
|
static_cast<class LParen*>(T2),
|
||||||
|
T3,
|
||||||
|
static_cast<class RParen*>(T3)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else if (isOperator(T3)) {
|
||||||
|
auto P1 = parseNarrowPattern();
|
||||||
|
Params.push_back(new Parameter(P1, nullptr));
|
||||||
|
Tokens.get();
|
||||||
|
auto P2 = parseNarrowPattern();
|
||||||
|
Params.push_back(new Parameter(P2, nullptr));
|
||||||
|
Name = new BindPattern(T3);
|
||||||
|
goto after_params;
|
||||||
|
} else {
|
||||||
|
Name = parseNarrowPattern();
|
||||||
|
if (!Name) {
|
||||||
|
if (Pub) {
|
||||||
|
Pub->unref();
|
||||||
|
}
|
||||||
|
if (Foreign) {
|
||||||
|
Foreign->unref();
|
||||||
|
}
|
||||||
|
Let->unref();
|
||||||
|
if (Mut) {
|
||||||
|
Mut->unref();
|
||||||
|
}
|
||||||
|
skipPastLineFoldEnd();
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (Foreign) {
|
|
||||||
Foreign->unref();
|
|
||||||
}
|
|
||||||
Let->unref();
|
|
||||||
if (Mut) {
|
|
||||||
Mut->unref();
|
|
||||||
}
|
|
||||||
skipPastLineFoldEnd();
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Parameter*> Params;
|
|
||||||
Token* T2;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
T2 = Tokens.peek();
|
auto T5 = Tokens.peek();
|
||||||
switch (T2->getKind()) {
|
switch (T5->getKind()) {
|
||||||
case NodeKind::LineFoldEnd:
|
case NodeKind::LineFoldEnd:
|
||||||
case NodeKind::BlockStart:
|
case NodeKind::BlockStart:
|
||||||
case NodeKind::Equals:
|
case NodeKind::Equals:
|
||||||
|
@ -1205,26 +1240,28 @@ finish:
|
||||||
|
|
||||||
after_params:
|
after_params:
|
||||||
|
|
||||||
if (T2->getKind() == NodeKind::Colon) {
|
auto T5 = Tokens.peek();
|
||||||
|
|
||||||
|
if (T5->getKind() == NodeKind::Colon) {
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
auto TE = parseTypeExpression();
|
auto TE = parseTypeExpression();
|
||||||
if (TE) {
|
if (TE) {
|
||||||
TA = new TypeAssert(static_cast<Colon*>(T2), TE);
|
TA = new TypeAssert(static_cast<Colon*>(T5), TE);
|
||||||
} else {
|
} else {
|
||||||
skipPastLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
T2 = Tokens.peek();
|
T5 = Tokens.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (T2->getKind()) {
|
switch (T5->getKind()) {
|
||||||
case NodeKind::BlockStart:
|
case NodeKind::BlockStart:
|
||||||
{
|
{
|
||||||
Tokens.get();
|
Tokens.get();
|
||||||
std::vector<Node*> Elements;
|
std::vector<Node*> Elements;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto T3 = Tokens.peek();
|
auto T6 = Tokens.peek();
|
||||||
if (T3->getKind() == NodeKind::BlockEnd) {
|
if (T6->getKind() == NodeKind::BlockEnd) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto Element = parseLetBodyElement();
|
auto Element = parseLetBodyElement();
|
||||||
|
@ -1233,7 +1270,7 @@ after_params:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tokens.get()->unref(); // Always a BlockEnd
|
Tokens.get()->unref(); // Always a BlockEnd
|
||||||
Body = new LetBlockBody(static_cast<BlockStart*>(T2), Elements);
|
Body = new LetBlockBody(static_cast<BlockStart*>(T5), Elements);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind::Equals:
|
case NodeKind::Equals:
|
||||||
|
@ -1244,7 +1281,7 @@ after_params:
|
||||||
skipPastLineFoldEnd();
|
skipPastLineFoldEnd();
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
Body = new LetExprBody(static_cast<Equals*>(T2), E);
|
Body = new LetExprBody(static_cast<Equals*>(T5), E);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeKind::LineFoldEnd:
|
case NodeKind::LineFoldEnd:
|
||||||
|
@ -1257,7 +1294,7 @@ after_params:
|
||||||
// First tokens of Pattern
|
// First tokens of Pattern
|
||||||
Expected.push_back(NodeKind::Identifier);
|
Expected.push_back(NodeKind::Identifier);
|
||||||
}
|
}
|
||||||
DE.add<UnexpectedTokenDiagnostic>(File, T2, Expected);
|
DE.add<UnexpectedTokenDiagnostic>(File, T5, Expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkLineFoldEnd();
|
checkLineFoldEnd();
|
||||||
|
@ -1270,7 +1307,7 @@ finish:
|
||||||
Foreign,
|
Foreign,
|
||||||
Let,
|
Let,
|
||||||
Mut,
|
Mut,
|
||||||
Pattern,
|
Name,
|
||||||
Params,
|
Params,
|
||||||
TA,
|
TA,
|
||||||
Body
|
Body
|
||||||
|
|
|
@ -500,7 +500,8 @@ after_string_contents:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZEN_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ namespace bolt {
|
||||||
case TypeKind::App:
|
case TypeKind::App:
|
||||||
return App == Other.App;
|
return App == Other.App;
|
||||||
}
|
}
|
||||||
|
ZEN_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
void Type::visitEachChild(std::function<void(Type*)> Proc) {
|
void Type::visitEachChild(std::function<void(Type*)> Proc) {
|
||||||
|
@ -223,6 +224,7 @@ namespace bolt {
|
||||||
return new Type(TPresent(NewTy));
|
return new Type(TPresent(NewTy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ZEN_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
Type* Type::substitute(const TVSub &Sub) {
|
Type* Type::substitute(const TVSub &Sub) {
|
||||||
|
@ -326,6 +328,7 @@ namespace bolt {
|
||||||
case TypeKind::Present:
|
case TypeKind::Present:
|
||||||
return Present.Ty->hasTypeVar(TV);
|
return Present.Ty->hasTypeVar(TV);
|
||||||
}
|
}
|
||||||
|
ZEN_UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue