From 9f5de2987a49fd9442aefc95d35f1e64ed5d2e61 Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Sun, 4 Feb 2024 16:44:58 +0000 Subject: [PATCH] Make compile on GCC and add support for infix let-declarations --- bootstrap/cxx/CMakeLists.txt | 13 +- bootstrap/cxx/include/bolt/CST.hpp | 187 +++++++++++++--------- bootstrap/cxx/include/bolt/CSTVisitor.hpp | 12 ++ bootstrap/cxx/src/CST.cc | 90 ++++++++--- bootstrap/cxx/src/Checker.cc | 76 ++++----- bootstrap/cxx/src/ConsolePrinter.cc | 5 + bootstrap/cxx/src/Evaluator.cc | 10 +- bootstrap/cxx/src/Parser.cc | 95 +++++++---- bootstrap/cxx/src/Scanner.cc | 3 +- bootstrap/cxx/src/Types.cc | 3 + 10 files changed, 330 insertions(+), 164 deletions(-) diff --git a/bootstrap/cxx/CMakeLists.txt b/bootstrap/cxx/CMakeLists.txt index cacbe99b3..5ae4b36ed 100644 --- a/bootstrap/cxx/CMakeLists.txt +++ b/bootstrap/cxx/CMakeLists.txt @@ -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 diff --git a/bootstrap/cxx/include/bolt/CST.hpp b/bootstrap/cxx/include/bolt/CST.hpp index 0555658e6..ad0c0e02d 100644 --- a/bootstrap/cxx/include/bolt/CST.hpp +++ b/bootstrap/cxx/include/bolt/CST.hpp @@ -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 + bool _is_helper(const Node* N) noexcept; + class Node { unsigned RefCount = 1; @@ -229,17 +235,7 @@ namespace bolt { template bool is() const noexcept { - return Kind == getNodeType(); - } - - template<> - bool is() const noexcept { - return Kind == NodeKind::ReferenceExpression - || Kind == NodeKind::LiteralExpression - || Kind == NodeKind::PrefixExpression - || Kind == NodeKind::InfixExpression - || Kind == NodeKind::CallExpression - || Kind == NodeKind::NestedExpression; + return _is_helper(this); } template @@ -262,6 +258,21 @@ namespace bolt { }; + template + bool _is_helper(const Node* N) noexcept { + return N->getKind() == getNodeType(); + } + + template<> + inline bool _is_helper(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> 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> 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> Fields; - RBrace* RBrace; + class RBrace* RBrace; inline RecordPattern( class LBrace* LBrace, @@ -1450,9 +1493,9 @@ namespace bolt { std::vector> ModulePath; IdentifierAlt* Name; - LBrace* LBrace; + class LBrace* LBrace; std::vector> Fields; - RBrace* RBrace; + class RBrace* RBrace; inline NamedRecordPattern( std::vector> ModulePath, @@ -1493,10 +1536,10 @@ namespace bolt { class TuplePattern : public Pattern { public: - LParen* LParen; + class LParen* LParen; std::vector> Elements; - RParen* RParen; - + class RParen* RParen; + inline TuplePattern( class LParen* LParen, std::vector> 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> 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(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 Fields; inline RecordVariantDeclarationMember( diff --git a/bootstrap/cxx/include/bolt/CSTVisitor.hpp b/bootstrap/cxx/include/bolt/CSTVisitor.hpp index 15353c007..133fc83fd 100644 --- a/bootstrap/cxx/include/bolt/CSTVisitor.hpp +++ b/bootstrap/cxx/include/bolt/CSTVisitor.hpp @@ -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(this)->visitTypeExpression(N); } + void visitWrappedOperator(WrappedOperator* N) { + static_cast(this)->visitNode(N); + } + void visitPattern(Pattern* N) { static_cast(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); diff --git a/bootstrap/cxx/src/CST.cc b/bootstrap/cxx/src/CST.cc index 43fea60b7..ffaa0f5cb 100644 --- a/bootstrap/cxx/src/CST.cc +++ b/bootstrap/cxx/src/CST.cc @@ -3,7 +3,6 @@ #include "bolt/CST.hpp" #include "bolt/CSTVisitor.hpp" -#include namespace bolt { @@ -117,7 +116,7 @@ namespace bolt { case NodeKind::ClassDeclaration: { auto Decl = static_cast(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(X); - addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Type); + addSymbol(getCanonicalText(Decl->Name), Decl, SymbolKind::Type); break; } case NodeKind::VariantDeclaration: { auto Decl = static_cast(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(Member); - addSymbol(T->Name->getCanonicalText(), Decl, SymbolKind::Constructor); + addSymbol(getCanonicalText(T->Name), Decl, SymbolKind::Constructor); break; } case NodeKind::RecordVariantDeclarationMember: { auto R = static_cast(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(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(Name); + case NodeKind::IdentifierAlt: + return static_cast(Name); + case NodeKind::WrappedOperator: + return static_cast(Name)->LParen; + default: + ZEN_UNREACHABLE + } } Token* BindPattern::getLastToken() const { - return Name; + switch (Name->getKind()) { + case NodeKind::Identifier: + return static_cast(Name); + case NodeKind::IdentifierAlt: + return static_cast(Name); + case NodeKind::WrappedOperator: + return static_cast(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(Name); + case NodeKind::IdentifierAlt: + return static_cast(Name); + case NodeKind::WrappedOperator: + return static_cast(Name)->LParen; + default: + ZEN_UNREACHABLE + } } Token* ReferenceExpression::getLastToken() const { - return Name; + switch (Name->getKind()) { + case NodeKind::Identifier: + return static_cast(Name); + case NodeKind::IdentifierAlt: + return static_cast(Name); + case NodeKind::WrappedOperator: + return static_cast(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(N)->Text; + case NodeKind::IdentifierAlt: + return static_cast(N)->Text; + case NodeKind::CustomOperator: + return static_cast(N)->Text; + case NodeKind::VBar: + return static_cast(N)->getText(); + case NodeKind::WrappedOperator: + return static_cast(N)->getOperator()->getText(); + default: + ZEN_UNREACHABLE + } } LiteralValue StringLiteral::getValue() { @@ -1063,9 +1115,9 @@ namespace bolt { SymbolPath ReferenceExpression::getSymbolPath() const { std::vector 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) }; } } diff --git a/bootstrap/cxx/src/Checker.cc b/bootstrap/cxx/src/Checker.cc index 511c4e67f..eee54574c 100644 --- a/bootstrap/cxx/src/Checker.cc +++ b/bootstrap/cxx/src/Checker.cc @@ -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 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 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 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(Let->Parent); - auto Class = cast(Instance->getScope()->lookup({ {}, Instance->Name->getCanonicalText() }, SymbolKind::Class)); + auto Class = cast(Instance->getScope()->lookup({ {}, getCanonicalText(Instance->Name) }, SymbolKind::Class)); auto SigLet = cast(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 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(N); - auto Scm = lookup(RefTE->Name->getCanonicalText(), SymKind::Type); + auto Scm = lookup(getCanonicalText(RefTE->Name), SymKind::Type); Type* Ty; if (Scm == nullptr) { - DE.add(RefTE->Name->getCanonicalText(), RefTE->Name); + DE.add(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(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(VarTE->Name->getCanonicalText(), VarTE->Name); + DE.add(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(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(X); ZEN_ASSERT(Ref->ModulePath.empty()); if (Ref->Name->is()) { - auto Scm = lookup(Ref->Name->getCanonicalText(), SymKind::Var); + auto Scm = lookup(getCanonicalText(Ref->Name), SymKind::Var); if (!Scm) { - DE.add(Ref->Name->getCanonicalText(), Ref->Name); + DE.add(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(Ref->Name->getCanonicalText(), Ref->Name); + DE.add(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(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(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(Pattern); - auto Scm = lookup(P->Name->getCanonicalText(), SymKind::Var); + auto Scm = lookup(getCanonicalText(P->Name), SymKind::Var); std::vector ElementTypes; for (auto P2: P->Patterns) { ElementTypes.push_back(inferPattern(P2, Constraints, TVs)); } if (!Scm) { - DE.add(P->Name->getCanonicalText(), P->Name); + DE.add(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(Pattern); - auto Scm = lookup(P->Name->getCanonicalText(), SymKind::Var); + auto Scm = lookup(getCanonicalText(P->Name), SymKind::Var); if (Scm == nullptr) { - DE.add(P->Name->getCanonicalText(), P->Name); + DE.add(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(); diff --git a/bootstrap/cxx/src/ConsolePrinter.cc b/bootstrap/cxx/src/ConsolePrinter.cc index 243ece772..9e0e82e15 100644 --- a/bootstrap/cxx/src/ConsolePrinter.cc +++ b/bootstrap/cxx/src/ConsolePrinter.cc @@ -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 + } } diff --git a/bootstrap/cxx/src/Evaluator.cc b/bootstrap/cxx/src/Evaluator.cc index a63312a2b..a36156bbe 100644 --- a/bootstrap/cxx/src/Evaluator.cc +++ b/bootstrap/cxx/src/Evaluator.cc @@ -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(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(Decl); @@ -31,10 +31,10 @@ namespace bolt { case NodeKind::CallExpression: { auto CE = static_cast(X); - auto Op = evaluateExpression(CE->Function, E); + auto Op = evaluateExpression(CE->Function, Env); std::vector 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(P); - E.add(BP->Name->getCanonicalText(), V); + E.add(getCanonicalText(BP->Name), V); break; } default: diff --git a/bootstrap/cxx/src/Parser.cc b/bootstrap/cxx/src/Parser.cc index 0083b92c6..400d98f9c 100644 --- a/bootstrap/cxx/src/Parser.cc +++ b/bootstrap/cxx/src/Parser.cc @@ -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 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(T1), static_cast(T2))); } auto T3 = Tokens.get(); - if (!isa(T3)) { + if (!T3->is() && !T3->is()) { 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 Params; TypeAssert* TA = nullptr; LetBody* Body = nullptr; @@ -1167,27 +1180,49 @@ finish: Mut = static_cast(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(T2), + T3, + static_cast(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 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(T2), TE); + TA = new TypeAssert(static_cast(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 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(T2), Elements); + Body = new LetBlockBody(static_cast(T5), Elements); break; } case NodeKind::Equals: @@ -1244,7 +1281,7 @@ after_params: skipPastLineFoldEnd(); goto finish; } - Body = new LetExprBody(static_cast(T2), E); + Body = new LetExprBody(static_cast(T5), E); break; } case NodeKind::LineFoldEnd: @@ -1257,7 +1294,7 @@ after_params: // First tokens of Pattern Expected.push_back(NodeKind::Identifier); } - DE.add(File, T2, Expected); + DE.add(File, T5, Expected); } checkLineFoldEnd(); @@ -1270,7 +1307,7 @@ finish: Foreign, Let, Mut, - Pattern, + Name, Params, TA, Body diff --git a/bootstrap/cxx/src/Scanner.cc b/bootstrap/cxx/src/Scanner.cc index f404b2d05..b69b1ec98 100644 --- a/bootstrap/cxx/src/Scanner.cc +++ b/bootstrap/cxx/src/Scanner.cc @@ -500,7 +500,8 @@ after_string_contents: } } - + ZEN_UNREACHABLE } + } diff --git a/bootstrap/cxx/src/Types.cc b/bootstrap/cxx/src/Types.cc index 14602079b..9429af865 100644 --- a/bootstrap/cxx/src/Types.cc +++ b/bootstrap/cxx/src/Types.cc @@ -102,6 +102,7 @@ namespace bolt { case TypeKind::App: return App == Other.App; } + ZEN_UNREACHABLE } void Type::visitEachChild(std::function 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 } }