Make compile on GCC and add support for infix let-declarations

This commit is contained in:
Sam Vervaeck 2024-02-04 16:44:58 +00:00
parent 449cda8fc4
commit 9f5de2987a
10 changed files with 330 additions and 164 deletions

View file

@ -13,6 +13,10 @@ set(ICU_INCLUDE_DIRS "${ICU_DIR}/include")
set(ICU_LIBRARY_DIRS "${ICU_DIR}/lib")
set(ICU_LIBRARIES icuuc)
if (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "Debug")
set(BOLT_DEBUG ON)
endif()
add_library(
BoltCore
#src/Text.cc
@ -33,10 +37,17 @@ target_link_directories(
target_compile_options(
BoltCore
PUBLIC
-fstandalone-debug
-Werror
${ICU_CFLAGS}
)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND BOLT_DEBUG)
target_compile_options(
BoltCore
PUBLIC
-fstandalone-debug
)
endif()
target_include_directories(
BoltCore
PUBLIC

View file

@ -125,10 +125,11 @@ namespace bolt {
LineFoldEnd,
CustomOperator,
Assignment,
Identifier,
IdentifierAlt,
StringLiteral,
IntegerLiteral,
Identifier,
IdentifierAlt,
WrappedOperator,
ExpressionAnnotation,
TypeAssertAnnotation,
TypeclassConstraintExpression,
@ -196,6 +197,11 @@ namespace bolt {
using NodeFlagsMask = unsigned;
class Node;
template<typename T>
bool _is_helper(const Node* N) noexcept;
class Node {
unsigned RefCount = 1;
@ -229,17 +235,7 @@ namespace bolt {
template<typename T>
bool is() const noexcept {
return Kind == getNodeType<T>();
}
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;
return _is_helper<T>(this);
}
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 {
Var,
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 {
public:
@ -889,30 +925,13 @@ namespace bolt {
};
class Symbol : 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 {
class Identifier : public Token {
public:
ByteString Text;
Identifier(ByteString Text, TextLoc StartLoc = TextLoc::empty()):
Symbol(NodeKind::Identifier, StartLoc), Text(Text) {}
ByteString getCanonicalText() override;
Token(NodeKind::Identifier, StartLoc), Text(Text) {}
std::string getText() const override;
@ -924,15 +943,13 @@ namespace bolt {
};
class IdentifierAlt : public Symbol {
class IdentifierAlt : public Token {
public:
ByteString Text;
IdentifierAlt(ByteString Text, TextLoc StartLoc):
Symbol(NodeKind::IdentifierAlt, StartLoc), Text(Text) {}
ByteString getCanonicalText() override;
Token(NodeKind::IdentifierAlt, StartLoc), Text(Text) {}
std::string getText() const override;
@ -1020,8 +1037,8 @@ namespace bolt {
class ExpressionAnnotation : public Annotation {
public:
At* At;
Expression* Expression;
class At* At;
class Expression* Expression;
inline ExpressionAnnotation(
class At* At,
@ -1044,8 +1061,8 @@ namespace bolt {
class TypeAssertAnnotation : public Annotation {
public:
At* At;
Colon* Colon;
class At* At;
class Colon* Colon;
TypeExpression* TE;
inline TypeAssertAnnotation(
@ -1107,7 +1124,7 @@ namespace bolt {
public:
Identifier* Name;
Colon* Colon;
class Colon* Colon;
TypeExpression* TE;
inline RecordTypeExpressionField(
@ -1127,11 +1144,11 @@ namespace bolt {
class RecordTypeExpression : public TypeExpression {
public:
LBrace* LBrace;
class LBrace* LBrace;
std::vector<std::tuple<RecordTypeExpressionField*, Comma*>> Fields;
VBar* VBar;
class VBar* VBar;
TypeExpression* Rest;
RBrace* RBrace;
class RBrace* RBrace;
inline RecordTypeExpression(
class LBrace* LBrace,
@ -1183,9 +1200,9 @@ namespace bolt {
TypeExpression* Right;
inline EqualityConstraintExpression(
TypeExpression* Left,
class Tilde* Tilde,
TypeExpression* Right
TypeExpression* Left,
class Tilde* Tilde,
TypeExpression* Right
): ConstraintExpression(NodeKind::EqualityConstraintExpression),
Left(Left),
Tilde(Tilde),
@ -1297,9 +1314,9 @@ namespace bolt {
class NestedTypeExpression : public TypeExpression {
public:
LParen* LParen;
class LParen* LParen;
TypeExpression* TE;
RParen* RParen;
class RParen* RParen;
inline NestedTypeExpression(
class LParen* LParen,
@ -1318,9 +1335,9 @@ namespace bolt {
class TupleTypeExpression : public TypeExpression {
public:
LParen* LParen;
class LParen* LParen;
std::vector<std::tuple<TypeExpression*, Comma*>> Elements;
RParen* RParen;
class RParen* RParen;
inline TupleTypeExpression(
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 {
protected:
@ -1347,10 +1390,10 @@ namespace bolt {
class BindPattern : public Pattern {
public:
Identifier* Name;
Symbol* Name;
BindPattern(
Identifier* Name
Symbol* Name
): Pattern(NodeKind::BindPattern),
Name(Name) {}
@ -1384,10 +1427,10 @@ namespace bolt {
class RecordPatternField : public Node {
public:
DotDot* DotDot;
class DotDot* DotDot;
Identifier* Name;
Equals* Equals;
Pattern* Pattern;
class Equals* Equals;
class Pattern* Pattern;
inline RecordPatternField(
class DotDot* DotDot,
@ -1427,9 +1470,9 @@ namespace bolt {
class RecordPattern : public Pattern {
public:
LBrace* LBrace;
class LBrace* LBrace;
std::vector<std::tuple<RecordPatternField*, Comma*>> Fields;
RBrace* RBrace;
class RBrace* RBrace;
inline RecordPattern(
class LBrace* LBrace,
@ -1450,9 +1493,9 @@ namespace bolt {
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath;
IdentifierAlt* Name;
LBrace* LBrace;
class LBrace* LBrace;
std::vector<std::tuple<RecordPatternField*, Comma*>> Fields;
RBrace* RBrace;
class RBrace* RBrace;
inline NamedRecordPattern(
std::vector<std::tuple<IdentifierAlt*, Dot*>> ModulePath,
@ -1493,10 +1536,10 @@ namespace bolt {
class TuplePattern : public Pattern {
public:
LParen* LParen;
class LParen* LParen;
std::vector<std::tuple<Pattern*, Comma*>> Elements;
RParen* RParen;
class RParen* RParen;
inline TuplePattern(
class LParen* LParen,
std::vector<std::tuple<Pattern*, Comma*>> Elements,
@ -1583,7 +1626,7 @@ namespace bolt {
Name(Name) {}
inline ByteString getNameAsString() const noexcept {
return Name->getCanonicalText();
return getCanonicalText(Name);
}
Token* getFirstToken() const override;
@ -1656,11 +1699,11 @@ namespace bolt {
public:
Expression* E;
Dot* Dot;
class Dot* Dot;
Token* Name;
inline MemberExpression(
class Expression* E,
Expression* E,
class Dot* Dot,
Token* Name
): Expression(NodeKind::MemberExpression),
@ -1867,7 +1910,7 @@ namespace bolt {
public:
Identifier* Name;
Equals* Equals;
class Equals* Equals;
Expression* E;
inline RecordExpressionField(
@ -1891,9 +1934,9 @@ namespace bolt {
class RecordExpression : public Expression {
public:
LBrace* LBrace;
class LBrace* LBrace;
std::vector<std::tuple<RecordExpressionField*, Comma*>> Fields;
RBrace* RBrace;
class RBrace* RBrace;
inline RecordExpression(
class LBrace* LBrace,
@ -2191,13 +2234,13 @@ namespace bolt {
return !isSignature() && !isVariable();
}
Identifier* getName() const noexcept {
Symbol* getName() const noexcept {
ZEN_ASSERT(Pattern->getKind() == NodeKind::BindPattern);
return static_cast<BindPattern*>(Pattern)->Name;
}
ByteString getNameAsString() const noexcept {
return getName()->getCanonicalText();
return getCanonicalText(getName());
}
Token* getFirstToken() const override;
@ -2357,7 +2400,7 @@ namespace bolt {
public:
IdentifierAlt* Name;
BlockStart* BlockStart;
class BlockStart* BlockStart;
std::vector<RecordDeclarationField*> Fields;
inline RecordVariantDeclarationMember(

View file

@ -59,6 +59,7 @@ namespace bolt {
BOLT_GEN_CASE(Assignment)
BOLT_GEN_CASE(Identifier)
BOLT_GEN_CASE(IdentifierAlt)
BOLT_GEN_CASE(WrappedOperator)
BOLT_GEN_CASE(StringLiteral)
BOLT_GEN_CASE(IntegerLiteral)
BOLT_GEN_CASE(ExpressionAnnotation)
@ -357,6 +358,10 @@ namespace bolt {
static_cast<D*>(this)->visitTypeExpression(N);
}
void visitWrappedOperator(WrappedOperator* N) {
static_cast<D*>(this)->visitNode(N);
}
void visitPattern(Pattern* N) {
static_cast<D*>(this)->visitNode(N);
}
@ -579,6 +584,7 @@ namespace bolt {
BOLT_GEN_CHILD_CASE(Assignment)
BOLT_GEN_CHILD_CASE(Identifier)
BOLT_GEN_CHILD_CASE(IdentifierAlt)
BOLT_GEN_CHILD_CASE(WrappedOperator)
BOLT_GEN_CHILD_CASE(StringLiteral)
BOLT_GEN_CHILD_CASE(IntegerLiteral)
BOLT_GEN_CHILD_CASE(ExpressionAnnotation)
@ -763,6 +769,12 @@ namespace bolt {
void visitEachChild(IntegerLiteral* N) {
}
void visitEachChild(WrappedOperator* N) {
BOLT_VISIT(N->LParen);
BOLT_VISIT(N->Op);
BOLT_VISIT(N->RParen);
}
void visitEachChild(ExpressionAnnotation* N) {
BOLT_VISIT(N->At);
BOLT_VISIT(N->Expression);

View file

@ -3,7 +3,6 @@
#include "bolt/CST.hpp"
#include "bolt/CSTVisitor.hpp"
#include <variant>
namespace bolt {
@ -117,7 +116,7 @@ namespace bolt {
case NodeKind::ClassDeclaration:
{
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) {
scanChild(Element);
}
@ -134,25 +133,25 @@ namespace bolt {
case NodeKind::RecordDeclaration:
{
auto Decl = static_cast<RecordDeclaration*>(X);
addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Type);
addSymbol(getCanonicalText(Decl->Name), Decl, SymbolKind::Type);
break;
}
case NodeKind::VariantDeclaration:
{
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) {
switch (Member->getKind()) {
case NodeKind::TupleVariantDeclarationMember:
{
auto T = static_cast<TupleVariantDeclarationMember*>(Member);
addSymbol(T->Name->getCanonicalText(), Decl, SymbolKind::Constructor);
addSymbol(getCanonicalText(T->Name), Decl, SymbolKind::Constructor);
break;
}
case NodeKind::RecordVariantDeclarationMember:
{
auto R = static_cast<RecordVariantDeclarationMember*>(Member);
addSymbol(R->Name->getCanonicalText(), Decl, SymbolKind::Constructor);
addSymbol(getCanonicalText(R->Name), Decl, SymbolKind::Constructor);
break;
}
default:
@ -171,7 +170,7 @@ namespace bolt {
case NodeKind::BindPattern:
{
auto Y = static_cast<BindPattern*>(X);
addSymbol(Y->Name->Text, Decl, SymbolKind::Var);
addSymbol(getCanonicalText(Y->Name), Decl, SymbolKind::Var);
break;
}
case NodeKind::RecordPattern:
@ -489,12 +488,38 @@ namespace bolt {
return RParen;
}
Token* WrappedOperator::getFirstToken() const {
return LParen;
}
Token* WrappedOperator::getLastToken() const {
return RParen;
}
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 {
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 {
@ -577,11 +602,29 @@ namespace bolt {
if (!ModulePath.empty()) {
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 {
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 {
@ -1044,12 +1087,21 @@ namespace bolt {
return "instance";
}
ByteString Identifier::getCanonicalText() {
return Text;
}
ByteString IdentifierAlt::getCanonicalText() {
return Text;
ByteString getCanonicalText(const Symbol* N) {
switch (N->getKind()) {
case NodeKind::Identifier:
return static_cast<const Identifier*>(N)->Text;
case NodeKind::IdentifierAlt:
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() {
@ -1063,9 +1115,9 @@ namespace bolt {
SymbolPath ReferenceExpression::getSymbolPath() const {
std::vector<ByteString> ModuleNames;
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) };
}
}

View file

@ -40,6 +40,7 @@ namespace bolt {
case ConstraintKind::Empty:
return this;
}
ZEN_UNREACHABLE
}
Type* Checker::solveType(Type* Ty) {
@ -250,9 +251,9 @@ namespace bolt {
inferTypeExpression(TE);
}
auto Match = InstanceMap.find(Decl->Name->getCanonicalText());
auto Match = InstanceMap.find(getCanonicalText(Decl->Name));
if (Match == InstanceMap.end()) {
InstanceMap.emplace(Decl->Name->getCanonicalText(), std::vector { Decl });
InstanceMap.emplace(getCanonicalText(Decl->Name), std::vector { Decl });
} else {
Match->second.push_back(Decl);
}
@ -289,13 +290,13 @@ namespace bolt {
std::vector<Type*> Vars;
for (auto TE: Decl->TVs) {
auto TV = createRigidVar(TE->Name->getCanonicalText());
auto TV = createRigidVar(getCanonicalText(TE->Name));
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);
}
Type* Ty = createConType(Decl->Name->getCanonicalText());
Type* Ty = createConType(getCanonicalText(Decl->Name));
// Build the type that is actually returned by constructor functions
auto RetTy = Ty;
@ -304,7 +305,7 @@ namespace bolt {
}
// 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) {
switch (Member->getKind()) {
@ -317,7 +318,7 @@ namespace bolt {
ParamTypes.push_back(inferTypeExpression(Element, false));
}
Decl->Ctx->Parent->Env.add(
TupleMember->Name->getCanonicalText(),
getCanonicalText(TupleMember->Name),
new Forall(
Decl->Ctx->TVs,
Decl->Ctx->Constraints,
@ -350,13 +351,13 @@ namespace bolt {
std::vector<Type*> 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->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);
}
auto Name = Decl->Name->getCanonicalText();
auto Name = getCanonicalText(Decl->Name);
auto Ty = createConType(Name);
// Must be added early so we can create recursive types
@ -372,7 +373,7 @@ namespace bolt {
for (auto Field: Decl->Fields) {
FieldsTy = new Type(
TField(
Field->Name->getCanonicalText(),
getCanonicalText(Field->Name),
new Type(TPresent(inferTypeExpression(Field->TypeExpression, false))),
FieldsTy
)
@ -466,11 +467,11 @@ namespace bolt {
setContext(Let->Ctx);
auto addClassVars = [&](ClassDeclaration* Class, bool IsRigid) {
auto Id = Class->Name->getCanonicalText();
auto Id = getCanonicalText(Class->Name);
auto Ctx = &getContext();
std::vector<Type*> Out;
for (auto TE: Class->TypeVars) {
auto Name = TE->Name->getCanonicalText();
auto Name = getCanonicalText(TE->Name);
auto TV = IsRigid ? createRigidVar(Name) : createTypeVar();
TV->asVar().Context.emplace(Id);
Ctx->Env.add(Name, new Forall(TV), SymKind::Type);
@ -506,7 +507,7 @@ namespace bolt {
if (Let->isInstance()) {
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 Params = addClassVars(Class, false);
@ -788,6 +789,7 @@ namespace bolt {
}
ZEN_UNREACHABLE
}
void Checker::inferConstraintExpression(ConstraintExpression* C) {
@ -798,7 +800,7 @@ namespace bolt {
std::vector<Type*> Types;
for (auto TE: D->TEs) {
auto Ty = inferTypeExpression(TE);
Ty->asVar().Provided->emplace(D->Name->getCanonicalText());
Ty->asVar().Provided->emplace(getCanonicalText(D->Name));
Types.push_back(Ty);
}
break;
@ -821,10 +823,10 @@ namespace bolt {
case NodeKind::ReferenceTypeExpression:
{
auto RefTE = static_cast<ReferenceTypeExpression*>(N);
auto Scm = lookup(RefTE->Name->getCanonicalText(), SymKind::Type);
auto Scm = lookup(getCanonicalText(RefTE->Name), SymKind::Type);
Type* Ty;
if (Scm == nullptr) {
DE.add<BindingNotFoundDiagnostic>(RefTE->Name->getCanonicalText(), RefTE->Name);
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(RefTE->Name), RefTE->Name);
Ty = createTypeVar();
} else {
Ty = instantiate(Scm, RefTE);
@ -847,13 +849,13 @@ namespace bolt {
case NodeKind::VarTypeExpression:
{
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 (!AutoVars || Config.typeVarsRequireForall()) {
DE.add<BindingNotFoundDiagnostic>(VarTE->Name->getCanonicalText(), VarTE->Name);
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(VarTE->Name), VarTE->Name);
}
Ty = createRigidVar(VarTE->Name->getCanonicalText());
addBinding(VarTE->Name->getCanonicalText(), new Forall(Ty), SymKind::Type);
Ty = createRigidVar(getCanonicalText(VarTE->Name));
addBinding(getCanonicalText(VarTE->Name), new Forall(Ty), SymKind::Type);
}
ZEN_ASSERT(Ty->isVar());
N->setType(Ty);
@ -865,7 +867,7 @@ namespace bolt {
auto RecTE = static_cast<RecordTypeExpression*>(N);
auto Ty = RecTE->Rest ? inferTypeExpression(RecTE->Rest, AutoVars) : new Type(TNil());
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);
return Ty;
@ -977,7 +979,7 @@ namespace bolt {
Ty = new Type(TNil());
for (auto [Field, Comma]: Record->Fields) {
Ty = new Type(TField(
Field->Name->getCanonicalText(),
getCanonicalText(Field->Name),
new Type(TPresent(inferExpression(Field->getExpression()))),
Ty
));
@ -998,9 +1000,9 @@ namespace bolt {
auto Ref = static_cast<ReferenceExpression*>(X);
ZEN_ASSERT(Ref->ModulePath.empty());
if (Ref->Name->is<IdentifierAlt>()) {
auto Scm = lookup(Ref->Name->getCanonicalText(), SymKind::Var);
auto Scm = lookup(getCanonicalText(Ref->Name), SymKind::Var);
if (!Scm) {
DE.add<BindingNotFoundDiagnostic>(Ref->Name->getCanonicalText(), Ref->Name);
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(Ref->Name), Ref->Name);
Ty = createTypeVar();
break;
}
@ -1009,7 +1011,7 @@ namespace bolt {
}
auto Target = Ref->getScope()->lookup(Ref->getSymbolPath());
if (!Target) {
DE.add<BindingNotFoundDiagnostic>(Ref->Name->getCanonicalText(), Ref->Name);
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(Ref->Name), Ref->Name);
Ty = createTypeVar();
break;
}
@ -1023,7 +1025,7 @@ namespace bolt {
infer(Let);
}
}
auto Scm = lookup(Ref->Name->getCanonicalText(), SymKind::Var);
auto Scm = lookup(getCanonicalText(Ref->Name), SymKind::Var);
ZEN_ASSERT(Scm);
Ty = instantiate(Scm, X);
break;
@ -1088,7 +1090,7 @@ namespace bolt {
auto K = static_cast<Identifier*>(Member->Name);
Ty = 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;
}
default:
@ -1135,20 +1137,20 @@ namespace bolt {
{
auto P = static_cast<BindPattern*>(Pattern);
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;
}
case NodeKind::NamedTuplePattern:
{
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;
for (auto P2: P->Patterns) {
ElementTypes.push_back(inferPattern(P2, Constraints, TVs));
}
if (!Scm) {
DE.add<BindingNotFoundDiagnostic>(P->Name->getCanonicalText(), P->Name);
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(P->Name), P->Name);
return createTypeVar();
}
auto Ty = instantiate(Scm, P);
@ -1178,9 +1180,9 @@ namespace bolt {
FieldTy = inferPattern(Field->Pattern, Constraints, TVs);
} else {
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;
}
@ -1188,9 +1190,9 @@ namespace bolt {
case NodeKind::NamedRecordPattern:
{
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) {
DE.add<BindingNotFoundDiagnostic>(P->Name->getCanonicalText(), P->Name);
DE.add<BindingNotFoundDiagnostic>(getCanonicalText(P->Name), P->Name);
return createTypeVar();
}
auto RestField = getRestField(P->Fields);
@ -1211,9 +1213,9 @@ namespace bolt {
FieldTy = inferPattern(Field->Pattern, Constraints, TVs);
} else {
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 RetTy = createTypeVar();

View file

@ -175,6 +175,8 @@ namespace bolt {
return "a branch of an if-statement";
case NodeKind::VariantDeclaration:
return "a variant";
case NodeKind::MatchCase:
return "a match-arm";
default:
ZEN_UNREACHABLE
}
@ -262,6 +264,7 @@ namespace bolt {
return out.str();
}
}
ZEN_UNREACHABLE
}
void writeForegroundANSI(Color C, std::ostream& Out) {
@ -925,6 +928,8 @@ namespace bolt {
}
ZEN_UNREACHABLE
}
}

View file

@ -6,12 +6,12 @@
namespace bolt {
Value Evaluator::evaluateExpression(Expression* X, Env& E) {
Value Evaluator::evaluateExpression(Expression* X, Env& Env) {
switch (X->getKind()) {
case NodeKind::ReferenceExpression:
{
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());
// ZEN_ASSERT(Decl && Decl->getKind() == NodeKind::FunctionDeclaration);
// return static_cast<FunctionDeclaration*>(Decl);
@ -31,10 +31,10 @@ namespace bolt {
case NodeKind::CallExpression:
{
auto CE = static_cast<CallExpression*>(X);
auto Op = evaluateExpression(CE->Function, E);
auto Op = evaluateExpression(CE->Function, Env);
std::vector<Value> Args;
for (auto Arg: CE->Args) {
Args.push_back(evaluateExpression(Arg, E));
Args.push_back(evaluateExpression(Arg, Env));
}
return apply(Op, Args);
}
@ -48,7 +48,7 @@ namespace bolt {
case NodeKind::BindPattern:
{
auto BP = static_cast<BindPattern*>(P);
E.add(BP->Name->getCanonicalText(), V);
E.add(getCanonicalText(BP->Name), V);
break;
}
default:

View file

@ -32,6 +32,16 @@
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) {
auto Match = Mapping.find(T->getText());
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)));
}
auto T3 = Tokens.get();
if (!isa<Symbol>(T3)) {
if (!T3->is<Identifier>() && !T3->is<IdentifierAlt>()) {
for (auto [Name, Dot]: ModulePath) {
Name->unref();
Dot->unref();
@ -938,13 +948,14 @@ finish:
auto T1 = Tokens.peek();
if (T1->getKind() == NodeKind::LineFoldEnd
|| T1->getKind() == NodeKind::RParen
|| T1->getKind() == NodeKind::RBracket
|| T1->getKind() == NodeKind::RBrace
|| T1->getKind() == NodeKind::BlockStart
|| T1->getKind() == NodeKind::Comma
|| ExprOperators.isInfix(T1)) {
break;
}
auto Arg = parsePrimitiveExpression();
auto Arg = parseMemberExpression();
if (!Arg) {
Operator->unref();
for (auto Arg: Args) {
@ -1137,6 +1148,8 @@ finish:
ForeignKeyword* Foreign = nullptr;
LetKeyword* Let;
MutKeyword* Mut = nullptr;
Pattern* Name;
std::vector<Parameter*> Params;
TypeAssert* TA = nullptr;
LetBody* Body = nullptr;
@ -1167,27 +1180,49 @@ finish:
Mut = static_cast<MutKeyword*>(T1);
}
auto Pattern = parseNarrowPattern();
if (!Pattern) {
if (Pub) {
Pub->unref();
auto T2 = Tokens.peek(0);
auto T3 = Tokens.peek(1);
auto T4 = Tokens.peek(2);
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 (;;) {
T2 = Tokens.peek();
switch (T2->getKind()) {
auto T5 = Tokens.peek();
switch (T5->getKind()) {
case NodeKind::LineFoldEnd:
case NodeKind::BlockStart:
case NodeKind::Equals:
@ -1205,26 +1240,28 @@ finish:
after_params:
if (T2->getKind() == NodeKind::Colon) {
auto T5 = Tokens.peek();
if (T5->getKind() == NodeKind::Colon) {
Tokens.get();
auto TE = parseTypeExpression();
if (TE) {
TA = new TypeAssert(static_cast<Colon*>(T2), TE);
TA = new TypeAssert(static_cast<Colon*>(T5), TE);
} else {
skipPastLineFoldEnd();
goto finish;
}
T2 = Tokens.peek();
T5 = Tokens.peek();
}
switch (T2->getKind()) {
switch (T5->getKind()) {
case NodeKind::BlockStart:
{
Tokens.get();
std::vector<Node*> Elements;
for (;;) {
auto T3 = Tokens.peek();
if (T3->getKind() == NodeKind::BlockEnd) {
auto T6 = Tokens.peek();
if (T6->getKind() == NodeKind::BlockEnd) {
break;
}
auto Element = parseLetBodyElement();
@ -1233,7 +1270,7 @@ after_params:
}
}
Tokens.get()->unref(); // Always a BlockEnd
Body = new LetBlockBody(static_cast<BlockStart*>(T2), Elements);
Body = new LetBlockBody(static_cast<BlockStart*>(T5), Elements);
break;
}
case NodeKind::Equals:
@ -1244,7 +1281,7 @@ after_params:
skipPastLineFoldEnd();
goto finish;
}
Body = new LetExprBody(static_cast<Equals*>(T2), E);
Body = new LetExprBody(static_cast<Equals*>(T5), E);
break;
}
case NodeKind::LineFoldEnd:
@ -1257,7 +1294,7 @@ after_params:
// First tokens of Pattern
Expected.push_back(NodeKind::Identifier);
}
DE.add<UnexpectedTokenDiagnostic>(File, T2, Expected);
DE.add<UnexpectedTokenDiagnostic>(File, T5, Expected);
}
checkLineFoldEnd();
@ -1270,7 +1307,7 @@ finish:
Foreign,
Let,
Mut,
Pattern,
Name,
Params,
TA,
Body

View file

@ -500,7 +500,8 @@ after_string_contents:
}
}
ZEN_UNREACHABLE
}
}

View file

@ -102,6 +102,7 @@ namespace bolt {
case TypeKind::App:
return App == Other.App;
}
ZEN_UNREACHABLE
}
void Type::visitEachChild(std::function<void(Type*)> Proc) {
@ -223,6 +224,7 @@ namespace bolt {
return new Type(TPresent(NewTy));
}
}
ZEN_UNREACHABLE
}
Type* Type::substitute(const TVSub &Sub) {
@ -326,6 +328,7 @@ namespace bolt {
case TypeKind::Present:
return Present.Ty->hasTypeVar(TV);
}
ZEN_UNREACHABLE
}
}