From f63d892662d02c92591119e0800847276d93634f Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Sat, 3 Jun 2023 14:35:02 +0200 Subject: [PATCH] Re-introduce let declarations Closes #42 --- include/bolt/CST.hpp | 121 ++++++++++++++----------------- include/bolt/CSTVisitor.hpp | 43 ++++------- include/bolt/Checker.hpp | 4 +- include/bolt/Parser.hpp | 4 +- include/bolt/Type.hpp | 1 - src/CST.cc | 47 ++++-------- src/Checker.cc | 108 +++++++++++++++------------- src/Diagnostics.cc | 10 ++- src/Parser.cc | 138 +++++++----------------------------- src/Scanner.cc | 6 +- 10 files changed, 173 insertions(+), 309 deletions(-) diff --git a/include/bolt/CST.hpp b/include/bolt/CST.hpp index 8f3582a79..ef94e9179 100644 --- a/include/bolt/CST.hpp +++ b/include/bolt/CST.hpp @@ -104,9 +104,9 @@ namespace bolt { RArrow, RArrowAlt, LetKeyword, - FnKeyword, MutKeyword, PubKeyword, + ForeignKeyword, TypeKeyword, ReturnKeyword, ModKeyword, @@ -164,8 +164,7 @@ namespace bolt { Parameter, LetBlockBody, LetExprBody, - FunctionDeclaration, - VariableDeclaration, + LetDeclaration, RecordDeclarationField, RecordDeclaration, VariantDeclaration, @@ -549,20 +548,6 @@ namespace bolt { }; - class FnKeyword : public Token { - public: - - inline FnKeyword(TextLoc StartLoc): - Token(NodeKind::FnKeyword, StartLoc) {} - - std::string getText() const override; - - static bool classof(const Node* N) { - return N->getKind() == NodeKind::FnKeyword; - } - - }; - class MutKeyword : public Token { public: @@ -591,6 +576,20 @@ namespace bolt { }; + class ForeignKeyword : public Token { + public: + + inline ForeignKeyword(TextLoc StartLoc): + Token(NodeKind::ForeignKeyword, StartLoc) {} + + std::string getText() const override; + + static bool classof(const Node* N) { + return N->getKind() == NodeKind::ForeignKeyword; + } + + }; + class TypeKeyword : public Token { public: @@ -1718,7 +1717,7 @@ namespace bolt { }; - class FunctionDeclaration : public Node { + class LetDeclaration : public TypedNode { Scope* TheScope = nullptr; @@ -1726,26 +1725,31 @@ namespace bolt { bool IsCycleActive = false; InferContext* Ctx; - class Type* Ty; class PubKeyword* PubKeyword; - class FnKeyword* FnKeyword; - class Identifier* Name; + class ForeignKeyword* ForeignKeyword; + class LetKeyword* LetKeyword; + class MutKeyword* MutKeyword; + class Pattern* Pattern; std::vector Params; class TypeAssert* TypeAssert; LetBody* Body; - FunctionDeclaration( + LetDeclaration( class PubKeyword* PubKeyword, - class FnKeyword* FnKeyword, - class Identifier* Name, + class ForeignKeyword* ForeignKeyword, + class LetKeyword* LetKeyword, + class MutKeyword* MutKeyword, + class Pattern* Pattern, std::vector Params, class TypeAssert* TypeAssert, LetBody* Body - ): Node(NodeKind::FunctionDeclaration), + ): TypedNode(NodeKind::LetDeclaration), PubKeyword(PubKeyword), - FnKeyword(FnKeyword), - Name(Name), + ForeignKeyword(ForeignKeyword), + LetKeyword(LetKeyword), + MutKeyword(MutKeyword), + Pattern(Pattern), Params(Params), TypeAssert(TypeAssert), Body(Body) {} @@ -1766,54 +1770,36 @@ namespace bolt { } bool isSignature() const noexcept { - return !Body; + return ForeignKeyword; + } + + bool isVariable() const noexcept { + // Variables in classes and instances are never possible, so we reflect this by excluding them here. + return !isSignature() && !isClass() && !isInstance() && (Pattern->getKind() != NodeKind::BindPattern || !Body); + } + + bool isFunction() const noexcept { + return !isSignature() && !isVariable(); + } + + Identifier* getName() const noexcept { + ZEN_ASSERT(Pattern->getKind() == NodeKind::BindPattern); + return static_cast(Pattern)->Name; + } + + ByteString getNameAsString() const noexcept { + return getName()->getCanonicalText(); } Token* getFirstToken() const override; Token* getLastToken() const override; static bool classof(const Node* N) { - return N->getKind() == NodeKind::FunctionDeclaration; + return N->getKind() == NodeKind::LetDeclaration; } }; - class VariableDeclaration : public TypedNode { - - Scope* TheScope = nullptr; - - public: - - bool IsCycleActive = false; - - class PubKeyword* PubKeyword; - class LetKeyword* LetKeyword; - class MutKeyword* MutKeyword; - class Pattern* Pattern; - std::vector Params; - class TypeAssert* TypeAssert; - LetBody* Body; - - VariableDeclaration( - class PubKeyword* PubKeyword, - class LetKeyword* LetKeyword, - class MutKeyword* MutKeyword, - class Pattern* Pattern, - class TypeAssert* TypeAssert, - LetBody* Body - ): TypedNode(NodeKind::VariableDeclaration), - PubKeyword(PubKeyword), - LetKeyword(LetKeyword), - MutKeyword(MutKeyword), - Pattern(Pattern), - TypeAssert(TypeAssert), - Body(Body) {} - - Token* getFirstToken() const override; - Token* getLastToken() const override; - - }; - class InstanceDeclaration : public Node { public: @@ -2063,7 +2049,7 @@ namespace bolt { template<> inline NodeKind getNodeType() { return NodeKind::RArrow; } template<> inline NodeKind getNodeType() { return NodeKind::RArrowAlt; } template<> inline NodeKind getNodeType() { return NodeKind::LetKeyword; } - template<> inline NodeKind getNodeType() { return NodeKind::FnKeyword; } + template<> inline NodeKind getNodeType() { return NodeKind::ForeignKeyword; } template<> inline NodeKind getNodeType() { return NodeKind::MutKeyword; } template<> inline NodeKind getNodeType() { return NodeKind::PubKeyword; } template<> inline NodeKind getNodeType() { return NodeKind::TypeKeyword; } @@ -2106,8 +2092,7 @@ namespace bolt { template<> inline NodeKind getNodeType() { return NodeKind::Parameter; } template<> inline NodeKind getNodeType() { return NodeKind::LetBlockBody; } template<> inline NodeKind getNodeType() { return NodeKind::LetExprBody; } - template<> inline NodeKind getNodeType() { return NodeKind::FunctionDeclaration; } - template<> inline NodeKind getNodeType() { return NodeKind::VariableDeclaration; } + template<> inline NodeKind getNodeType() { return NodeKind::LetDeclaration; } template<> inline NodeKind getNodeType() { return NodeKind::RecordDeclarationField; } template<> inline NodeKind getNodeType() { return NodeKind::RecordDeclaration; } template<> inline NodeKind getNodeType() { return NodeKind::ClassDeclaration; } diff --git a/include/bolt/CSTVisitor.hpp b/include/bolt/CSTVisitor.hpp index c45015643..feee600d0 100644 --- a/include/bolt/CSTVisitor.hpp +++ b/include/bolt/CSTVisitor.hpp @@ -33,7 +33,7 @@ namespace bolt { BOLT_GEN_CASE(RArrow) BOLT_GEN_CASE(RArrowAlt) BOLT_GEN_CASE(LetKeyword) - BOLT_GEN_CASE(FnKeyword) + BOLT_GEN_CASE(ForeignKeyword) BOLT_GEN_CASE(MutKeyword) BOLT_GEN_CASE(PubKeyword) BOLT_GEN_CASE(TypeKeyword) @@ -93,8 +93,7 @@ namespace bolt { BOLT_GEN_CASE(Parameter) BOLT_GEN_CASE(LetBlockBody) BOLT_GEN_CASE(LetExprBody) - BOLT_GEN_CASE(FunctionDeclaration) - BOLT_GEN_CASE(VariableDeclaration) + BOLT_GEN_CASE(LetDeclaration) BOLT_GEN_CASE(RecordDeclaration) BOLT_GEN_CASE(RecordDeclarationField) BOLT_GEN_CASE(VariantDeclaration) @@ -176,7 +175,7 @@ namespace bolt { visitToken(N); } - void visitFnKeyword(FnKeyword* N) { + void visitForeignKeyword(ForeignKeyword* N) { visitToken(N); } @@ -440,11 +439,7 @@ namespace bolt { visitLetBody(N); } - void visitFunctionDeclaration(FunctionDeclaration* N) { - visitNode(N); - } - - void visitVariableDeclaration(VariableDeclaration* N) { + void visitLetDeclaration(LetDeclaration* N) { visitNode(N); } @@ -509,7 +504,7 @@ namespace bolt { BOLT_GEN_CHILD_CASE(RArrow) BOLT_GEN_CHILD_CASE(RArrowAlt) BOLT_GEN_CHILD_CASE(LetKeyword) - BOLT_GEN_CHILD_CASE(FnKeyword) + BOLT_GEN_CHILD_CASE(ForeignKeyword) BOLT_GEN_CHILD_CASE(MutKeyword) BOLT_GEN_CHILD_CASE(PubKeyword) BOLT_GEN_CHILD_CASE(TypeKeyword) @@ -569,8 +564,7 @@ namespace bolt { BOLT_GEN_CHILD_CASE(Parameter) BOLT_GEN_CHILD_CASE(LetBlockBody) BOLT_GEN_CHILD_CASE(LetExprBody) - BOLT_GEN_CHILD_CASE(FunctionDeclaration) - BOLT_GEN_CHILD_CASE(VariableDeclaration) + BOLT_GEN_CHILD_CASE(LetDeclaration) BOLT_GEN_CHILD_CASE(RecordDeclaration) BOLT_GEN_CHILD_CASE(RecordDeclarationField) BOLT_GEN_CHILD_CASE(VariantDeclaration) @@ -629,7 +623,7 @@ namespace bolt { void visitEachChild(LetKeyword* N) { } - void visitEachChild(FnKeyword* N) { + void visitEachChild(ForeignKeyword* N) { } void visitEachChild(MutKeyword* N) { @@ -951,29 +945,18 @@ namespace bolt { BOLT_VISIT(N->Expression); } - void visitEachChild(FunctionDeclaration* N) { + void visitEachChild(LetDeclaration* N) { if (N->PubKeyword) { BOLT_VISIT(N->PubKeyword); } - BOLT_VISIT(N->FnKeyword); - BOLT_VISIT(N->Name); - for (auto Param: N->Params) { - BOLT_VISIT(Param); - } - if (N->TypeAssert) { - BOLT_VISIT(N->TypeAssert); - } - if (N->Body) { - BOLT_VISIT(N->Body); - } - } - - void visitEachChild(VariableDeclaration* N) { - if (N->PubKeyword) { - BOLT_VISIT(N->PubKeyword); + if (N->ForeignKeyword) { + BOLT_VISIT(N->ForeignKeyword); } BOLT_VISIT(N->LetKeyword); BOLT_VISIT(N->Pattern); + for (auto Param: N->Params) { + BOLT_VISIT(Param); + } if (N->TypeAssert) { BOLT_VISIT(N->TypeAssert); } diff --git a/include/bolt/Checker.hpp b/include/bolt/Checker.hpp index f310b7ed9..4eec0104f 100644 --- a/include/bolt/Checker.hpp +++ b/include/bolt/Checker.hpp @@ -192,7 +192,7 @@ namespace bolt { /// Type inference void forwardDeclare(Node* Node); - void forwardDeclareFunctionDeclaration(FunctionDeclaration* N, TVSet* TVs, ConstraintSet* Constraints); + void forwardDeclareFunctionDeclaration(LetDeclaration* N, TVSet* TVs, ConstraintSet* Constraints); Type* inferExpression(Expression* Expression); Type* inferTypeExpression(TypeExpression* TE, bool IsPoly = true); @@ -200,7 +200,7 @@ namespace bolt { Type* inferPattern(Pattern* Pattern, ConstraintSet* Constraints = new ConstraintSet, TVSet* TVs = new TVSet); void infer(Node* node); - void inferFunctionDeclaration(FunctionDeclaration* N); + void inferFunctionDeclaration(LetDeclaration* N); void inferConstraintExpression(ConstraintExpression* C); /// Factory methods diff --git a/include/bolt/Parser.hpp b/include/bolt/Parser.hpp index 86b26555f..e28f2e5a5 100644 --- a/include/bolt/Parser.hpp +++ b/include/bolt/Parser.hpp @@ -126,9 +126,7 @@ namespace bolt { Node* parseLetBodyElement(); - FunctionDeclaration* parseFunctionDeclaration(); - - VariableDeclaration* parseVariableDeclaration(); + LetDeclaration* parseLetDeclaration(); Node* parseClassElement(); diff --git a/include/bolt/Type.hpp b/include/bolt/Type.hpp index e15a873b6..ab5ae8b71 100644 --- a/include/bolt/Type.hpp +++ b/include/bolt/Type.hpp @@ -321,7 +321,6 @@ namespace bolt { return Curr; } - static bool classof(const Type* Ty) { return Ty->getKind() == TypeKind::Arrow; } diff --git a/src/CST.cc b/src/CST.cc index 2d223ed31..dc5a6705e 100644 --- a/src/CST.cc +++ b/src/CST.cc @@ -78,9 +78,10 @@ namespace bolt { } break; } - case NodeKind::FunctionDeclaration: + case NodeKind::LetDeclaration: { - auto Decl = static_cast(X); + auto Decl = static_cast(X); + ZEN_ASSERT(Decl->isFunction()); for (auto Param: Decl->Params) { visitPattern(Param->Pattern, Param); } @@ -121,18 +122,14 @@ namespace bolt { } break; } - case NodeKind::VariableDeclaration: + case NodeKind::LetDeclaration: { - auto Decl = static_cast(X); + auto Decl = static_cast(X); + // No matter if it is a function or a variable, by visiting the pattern + // we add all relevant bindings to the current scope. visitPattern(Decl->Pattern, Decl); break; } - case NodeKind::FunctionDeclaration: - { - auto Decl = static_cast(X); - addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Var); - break; - } case NodeKind::RecordDeclaration: { auto Decl = static_cast(X); @@ -651,14 +648,17 @@ namespace bolt { return Expression->getLastToken(); } - Token* FunctionDeclaration::getFirstToken() const { + Token* LetDeclaration::getFirstToken() const { if (PubKeyword) { return PubKeyword; } - return FnKeyword; + if (ForeignKeyword) { + return ForeignKeyword; + } + return LetKeyword; } - Token* FunctionDeclaration::getLastToken() const { + Token* LetDeclaration::getLastToken() const { if (Body) { return Body->getLastToken(); } @@ -668,23 +668,6 @@ namespace bolt { if (Params.size()) { return Params.back()->getLastToken(); } - return Name; - } - - Token* VariableDeclaration::getFirstToken() const { - if (PubKeyword) { - return PubKeyword; - } - return LetKeyword; - } - - Token* VariableDeclaration::getLastToken() const { - if (Body) { - return Body->getLastToken(); - } - if (TypeAssert) { - return TypeAssert->getLastToken(); - } return Pattern->getLastToken(); } @@ -837,8 +820,8 @@ namespace bolt { return "let"; } - std::string FnKeyword::getText() const { - return "fn"; + std::string ForeignKeyword::getText() const { + return "foreign"; } std::string MutKeyword::getText() const { diff --git a/src/Checker.cc b/src/Checker.cc index 1b0652c03..4fbce7c40 100644 --- a/src/Checker.cc +++ b/src/Checker.cc @@ -274,13 +274,22 @@ namespace bolt { break; } - case NodeKind::FunctionDeclaration: - // These declarations will be handled separately in check() - break; - - case NodeKind::VariableDeclaration: - // All of this node's semantics will be handled in infer() + case NodeKind::LetDeclaration: + { + // Function declarations are handled separately in forwardDeclareLetDeclaration() + auto Decl = static_cast(X); + if (!Decl->isVariable()) { + break; + } + Type* Ty; + if (Decl->TypeAssert) { + Ty = inferTypeExpression(Decl->TypeAssert->TypeExpression, false); + } else { + Ty = createTypeVar(); + } + Decl->setType(Ty); break; + } case NodeKind::VariantDeclaration: { @@ -405,11 +414,13 @@ namespace bolt { Contexts.pop(); } - void visitFunctionDeclaration(FunctionDeclaration* Let) { - Let->Ctx = createDerivedContext(); - Contexts.push(Let->Ctx); - visitEachChild(Let); - Contexts.pop(); + void visitLetDeclaration(LetDeclaration* Let) { + if (Let->isFunction()) { + Let->Ctx = createDerivedContext(); + Contexts.push(Let->Ctx); + visitEachChild(Let); + Contexts.pop(); + } } // void visitVariableDeclaration(VariableDeclaration* Var) { @@ -424,7 +435,11 @@ namespace bolt { } - void Checker::forwardDeclareFunctionDeclaration(FunctionDeclaration* Let, TVSet* TVs, ConstraintSet* Constraints) { + void Checker::forwardDeclareFunctionDeclaration(LetDeclaration* Let, TVSet* TVs, ConstraintSet* Constraints) { + + if (!Let->isFunction()) { + return; + } setContext(Let->Ctx); @@ -460,7 +475,7 @@ namespace bolt { } else { Ty = createTypeVar(); } - Let->Ty = Ty; + Let->setType(Ty); // If declaring a let-declaration inside a type instance declaration, // we need to perform some work to make sure the type asserts of the @@ -470,7 +485,7 @@ namespace bolt { auto Instance = static_cast(Let->Parent); auto Class = llvm::cast(Instance->getScope()->lookup({ {}, Instance->Name->getCanonicalText() }, SymbolKind::Class)); - auto SigLet = llvm::cast(Class->getScope()->lookupDirect({ {}, Let->Name->getCanonicalText() }, SymbolKind::Var)); + auto SigLet = llvm::cast(Class->getScope()->lookupDirect({ {}, Let->getNameAsString() }, SymbolKind::Var)); auto Params = addClassVars(Class, false); @@ -526,14 +541,14 @@ namespace bolt { } if (!Let->isInstance()) { - Let->Ctx->Parent->Env.emplace(Let->Name->getCanonicalText(), new Forall(Let->Ctx->TVs, Let->Ctx->Constraints, Ty)); + Let->Ctx->Parent->Env.emplace(Let->getNameAsString(), new Forall(Let->Ctx->TVs, Let->Ctx->Constraints, Ty)); } } - void Checker::inferFunctionDeclaration(FunctionDeclaration* Decl) { + void Checker::inferFunctionDeclaration(LetDeclaration* Decl) { - if (Decl->isSignature()) { + if (!Decl->isFunction()) { return; } @@ -570,7 +585,7 @@ namespace bolt { RetType = createTypeVar(); } - makeEqual(Decl->Ty, TArrow::build(ParamTypes, RetType), Decl); + makeEqual(Decl->getType(), TArrow::build(ParamTypes, RetType), Decl); } @@ -624,9 +639,6 @@ namespace bolt { break; } - case NodeKind::FunctionDeclaration: - break; - case NodeKind::ReturnStatement: { auto RetStmt = static_cast(N); @@ -640,30 +652,22 @@ namespace bolt { break; } - case NodeKind::VariableDeclaration: + case NodeKind::LetDeclaration: { - auto Decl = static_cast(N); - Type* Ty = nullptr; - if (Decl->TypeAssert) { - Ty = inferTypeExpression(Decl->TypeAssert->TypeExpression, false); + // Function declarations are handled separately in inferLetDeclaration() + auto Decl = static_cast(N); + if (!Decl->isVariable()) { + break; } + auto Ty = Decl->getType(); if (Decl->Body) { ZEN_ASSERT(Decl->Body->getKind() == NodeKind::LetExprBody); auto E = static_cast(Decl->Body); auto Ty2 = inferExpression(E->Expression); - if (Ty) { - makeEqual(Ty, Ty2, Decl); - } else { - Ty = Ty2; - } + makeEqual(Ty, Ty2, Decl); } auto Ty3 = inferPattern(Decl->Pattern); - if (Ty) { - makeEqual(Ty, Ty3, Decl); - } else { - Ty = Ty3; - } - Decl->setType(Ty); + makeEqual(Ty, Ty3, Decl); break; } @@ -759,7 +763,9 @@ namespace bolt { auto D = static_cast(C); std::vector Types; for (auto TE: D->TEs) { - auto TV = static_cast(inferTypeExpression(TE)); + auto Ty = inferTypeExpression(TE); + ZEN_ASSERT(Ty->getKind() == TypeKind::Var && static_cast(Ty)->isRigid()); + auto TV = static_cast(Ty); TV->Provided.emplace(D->Name->getCanonicalText()); Types.push_back(TV); } @@ -938,10 +944,10 @@ namespace bolt { auto Ref = static_cast(X); ZEN_ASSERT(Ref->ModulePath.empty()); auto Target = Ref->getScope()->lookup(Ref->getSymbolPath()); - if (Target && llvm::isa(Target)) { - auto Let = static_cast(Target); + if (Target && llvm::isa(Target)) { + auto Let = static_cast(Target); if (Let->IsCycleActive) { - return Let->Ty; + return Let->getType(); } } auto Scm = lookup(Ref->Name->getCanonicalText()); @@ -1133,7 +1139,7 @@ namespace bolt { std::stack Stack; - void visitFunctionDeclaration(FunctionDeclaration* N) { + void visitLetDeclaration(LetDeclaration* N) { RefGraph.addVertex(N); Stack.push(N); visitEachChild(N); @@ -1154,7 +1160,7 @@ namespace bolt { RefGraph.addEdge(Stack.top(), Def->Parent); return; } - ZEN_ASSERT(Def->getKind() == NodeKind::FunctionDeclaration || Def->getKind() == NodeKind::VariableDeclaration); + ZEN_ASSERT(Def->getKind() == NodeKind::LetDeclaration); if (!Stack.empty()) { RefGraph.addEdge(Def, Stack.top()); } @@ -1193,33 +1199,33 @@ namespace bolt { auto TVs = new TVSet; auto Constraints = new ConstraintSet; for (auto N: Nodes) { - if (N->getKind() != NodeKind::FunctionDeclaration) { + if (N->getKind() != NodeKind::LetDeclaration) { continue; } - auto Decl = static_cast(N); + auto Decl = static_cast(N); forwardDeclareFunctionDeclaration(Decl, TVs, Constraints); } } for (auto Nodes: SCCs) { for (auto N: Nodes) { - if (N->getKind() != NodeKind::FunctionDeclaration) { + if (N->getKind() != NodeKind::LetDeclaration) { continue; } - auto Decl = static_cast(N); + auto Decl = static_cast(N); Decl->IsCycleActive = true; } for (auto N: Nodes) { - if (N->getKind() != NodeKind::FunctionDeclaration) { + if (N->getKind() != NodeKind::LetDeclaration) { continue; } - auto Decl = static_cast(N); + auto Decl = static_cast(N); inferFunctionDeclaration(Decl); } for (auto N: Nodes) { - if (N->getKind() != NodeKind::FunctionDeclaration) { + if (N->getKind() != NodeKind::LetDeclaration) { continue; } - auto Decl = static_cast(N); + auto Decl = static_cast(N); Decl->IsCycleActive = false; } } diff --git a/src/Diagnostics.cc b/src/Diagnostics.cc index 30569f8a4..6740f1f6e 100644 --- a/src/Diagnostics.cc +++ b/src/Diagnostics.cc @@ -100,8 +100,8 @@ namespace bolt { return "'pub'"; case NodeKind::LetKeyword: return "'let'"; - case NodeKind::FnKeyword: - return "'fn'"; + case NodeKind::ForeignKeyword: + return "'foreign'"; case NodeKind::MutKeyword: return "'mut'"; case NodeKind::MatchKeyword: @@ -112,10 +112,8 @@ namespace bolt { return "'type'"; case NodeKind::ReferenceTypeExpression: return "a type reference"; - case NodeKind::FunctionDeclaration: - return "a function declaration"; - case NodeKind::VariableDeclaration: - return "a variable declaration"; + case NodeKind::LetDeclaration: + return "a let-declaration"; case NodeKind::CallExpression: return "a call-expression"; case NodeKind::InfixExpression: diff --git a/src/Parser.cc b/src/Parser.cc index 2e57f8b16..56e2d08b5 100644 --- a/src/Parser.cc +++ b/src/Parser.cc @@ -919,9 +919,10 @@ finish: return new IfStatement(Parts); } -VariableDeclaration* Parser::parseVariableDeclaration() { + LetDeclaration* Parser::parseLetDeclaration() { PubKeyword* Pub = nullptr; + ForeignKeyword* Foreign = nullptr; LetKeyword* Let; MutKeyword* Mut = nullptr; TypeAssert* TA = nullptr; @@ -932,26 +933,36 @@ VariableDeclaration* Parser::parseVariableDeclaration() { Pub = static_cast(T0); T0 = Tokens.get(); } + if (T0->getKind() == NodeKind::ForeignKeyword) { + Foreign = static_cast(T0); + T0 = Tokens.get(); + } if (T0->getKind() != NodeKind::LetKeyword) { DE.add(File, T0, std::vector { NodeKind::LetKeyword }); if (Pub) { Pub->unref(); } + if (Foreign) { + Foreign->unref(); + } skipToLineFoldEnd(); return nullptr; } Let = static_cast(T0); auto T1 = Tokens.peek(); if (T1->getKind() == NodeKind::MutKeyword) { - Mut = static_cast(T1); Tokens.get(); + Mut = static_cast(T1); } - auto P = parseWidePattern(); - if (!P) { + auto Pattern = parseNarrowPattern(); + if (!Pattern) { if (Pub) { Pub->unref(); } + if (Foreign) { + Foreign->unref(); + } Let->unref(); if (Mut) { Mut->unref(); @@ -960,103 +971,6 @@ VariableDeclaration* Parser::parseVariableDeclaration() { return nullptr; } - auto T2 = Tokens.peek(); - if (T2->getKind() == NodeKind::Colon) { - Tokens.get(); - auto TE = parseTypeExpression(); - if (TE) { - TA = new TypeAssert(static_cast(T2), TE); - } else { - skipToLineFoldEnd(); - goto finish; - } - T2 = Tokens.peek(); - } - - switch (T2->getKind()) { - case NodeKind::BlockStart: - { - Tokens.get(); - std::vector Elements; - for (;;) { - auto T3 = Tokens.peek(); - if (T3->getKind() == NodeKind::BlockEnd) { - break; - } - auto Element = parseLetBodyElement(); - if (Element) { - Elements.push_back(Element); - } - } - Tokens.get()->unref(); // Always a BlockEnd - Body = new LetBlockBody(static_cast(T2), Elements); - break; - } - case NodeKind::Equals: - { - Tokens.get(); - auto E = parseExpression(); - if (E == nullptr) { - skipToLineFoldEnd(); - goto finish; - } - if (E) { - Body = new LetExprBody(static_cast(T2), E); - } - break; - } - case NodeKind::LineFoldEnd: - break; - default: - std::vector Expected { NodeKind::BlockStart, NodeKind::LineFoldEnd, NodeKind::Equals }; - if (TA == nullptr) { - // First tokens of TypeAssert - Expected.push_back(NodeKind::Colon); - // First tokens of Pattern - Expected.push_back(NodeKind::Identifier); - } - DE.add(File, T2, Expected); - } - - checkLineFoldEnd(); - -finish: - - return new VariableDeclaration { Pub, Let, Mut, P, TA, Body }; - } - - FunctionDeclaration* Parser::parseFunctionDeclaration() { - - PubKeyword* Pub = nullptr; - FnKeyword* Fn; - TypeAssert* TA = nullptr; - LetBody* Body = nullptr; - - auto T0 = Tokens.get(); - if (T0->getKind() == NodeKind::PubKeyword) { - Pub = static_cast(T0); - T0 = Tokens.get(); - } - if (T0->getKind() != NodeKind::FnKeyword) { - DE.add(File, T0, std::vector { NodeKind::FnKeyword }); - if (Pub) { - Pub->unref(); - } - skipToLineFoldEnd(); - return nullptr; - } - Fn = static_cast(T0); - - auto Name = expectToken(); - if (!Name) { - if (Pub) { - Pub->unref(); - } - Fn->unref(); - skipToLineFoldEnd(); - return nullptr; - } - std::vector Params; Token* T2; for (;;) { @@ -1138,10 +1052,12 @@ after_params: finish: - return new FunctionDeclaration( + return new LetDeclaration( Pub, - Fn, - Name, + Foreign, + Let, + Mut, + Pattern, Params, TA, Body @@ -1152,9 +1068,7 @@ finish: auto T0 = peekFirstTokenAfterModifiers(); switch (T0->getKind()) { case NodeKind::LetKeyword: - return parseVariableDeclaration(); - case NodeKind::FnKeyword: - return parseFunctionDeclaration(); + return parseLetDeclaration(); case NodeKind::ReturnKeyword: return parseReturnStatement(); case NodeKind::IfKeyword: @@ -1558,12 +1472,12 @@ next_member: Node* Parser::parseClassElement() { auto T0 = Tokens.peek(); switch (T0->getKind()) { - case NodeKind::FnKeyword: - return parseFunctionDeclaration(); + case NodeKind::LetKeyword: + return parseLetDeclaration(); case NodeKind::TypeKeyword: // TODO default: - DE.add(File, T0, std::vector { NodeKind::FnKeyword, NodeKind::TypeKeyword }); + DE.add(File, T0, std::vector { NodeKind::LetKeyword, NodeKind::TypeKeyword }); skipToLineFoldEnd(); return nullptr; } @@ -1573,9 +1487,7 @@ next_member: auto T0 = peekFirstTokenAfterModifiers(); switch (T0->getKind()) { case NodeKind::LetKeyword: - return parseVariableDeclaration(); - case NodeKind::FnKeyword: - return parseFunctionDeclaration(); + return parseLetDeclaration(); case NodeKind::IfKeyword: return parseIfStatement(); case NodeKind::ClassKeyword: diff --git a/src/Scanner.cc b/src/Scanner.cc index 505fe8364..f6f3ab461 100644 --- a/src/Scanner.cc +++ b/src/Scanner.cc @@ -62,7 +62,7 @@ namespace bolt { std::unordered_map Keywords = { { "pub", NodeKind::PubKeyword }, { "let", NodeKind::LetKeyword }, - { "fn", NodeKind::FnKeyword }, + { "foreign", NodeKind::ForeignKeyword }, { "mut", NodeKind::MutKeyword }, { "return", NodeKind::ReturnKeyword }, { "type", NodeKind::TypeKeyword }, @@ -227,8 +227,8 @@ digit_finish: return new PubKeyword(StartLoc); case NodeKind::LetKeyword: return new LetKeyword(StartLoc); - case NodeKind::FnKeyword: - return new FnKeyword(StartLoc); + case NodeKind::ForeignKeyword: + return new ForeignKeyword(StartLoc); case NodeKind::MutKeyword: return new MutKeyword(StartLoc); case NodeKind::TypeKeyword: