From bce5bffa857ed9c047b491bfe33e11e7a24a3003 Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Mon, 22 May 2023 11:54:52 +0200 Subject: [PATCH] Add support for parsing member expressions --- include/bolt/CST.hpp | 26 ++++++++++++++++++++++++++ include/bolt/CSTVisitor.hpp | 15 +++++++++++++++ include/bolt/Checker.hpp | 1 - include/bolt/Parser.hpp | 1 + src/CST.cc | 8 ++++++++ src/Checker.cc | 7 +++---- src/Parser.cc | 25 ++++++++++++++++++++++++- 7 files changed, 77 insertions(+), 6 deletions(-) diff --git a/include/bolt/CST.hpp b/include/bolt/CST.hpp index 00ca31a8d..1cae3f3c0 100644 --- a/include/bolt/CST.hpp +++ b/include/bolt/CST.hpp @@ -75,6 +75,7 @@ namespace bolt { ReferenceExpression, MatchCase, MatchExpression, + MemberExpression, NestedExpression, ConstantExpression, CallExpression, @@ -1117,6 +1118,31 @@ namespace bolt { }; + class MemberExpression : public Expression { + public: + + Expression* E; + Dot* Dot; + Token* Name; + + inline MemberExpression( + class Expression* E, + class Dot* Dot, + Token* Name + ): Expression(NodeKind::MemberExpression), + E(E), + Dot(Dot), + Name(Name) {} + + Token* getFirstToken() override; + Token* getLastToken() override; + + inline Expression* getExpression() const { + return E; + } + + }; + class NestedExpression : public Expression { public: diff --git a/include/bolt/CSTVisitor.hpp b/include/bolt/CSTVisitor.hpp index e6fb99ec4..4d29db89c 100644 --- a/include/bolt/CSTVisitor.hpp +++ b/include/bolt/CSTVisitor.hpp @@ -109,6 +109,8 @@ namespace bolt { return static_cast(this)->visitMatchCase(static_cast(N)); case NodeKind::MatchExpression: return static_cast(this)->visitMatchExpression(static_cast(N)); + case NodeKind::MemberExpression: + return static_cast(this)->visitMemberExpression(static_cast(N)); case NodeKind::NestedExpression: return static_cast(this)->visitNestedExpression(static_cast(N)); case NodeKind::ConstantExpression: @@ -372,6 +374,10 @@ namespace bolt { visitExpression(N); } + void visitMemberExpression(MemberExpression* N) { + visitExpression(N); + } + void visitNestedExpression(NestedExpression* N) { visitExpression(N); } @@ -607,6 +613,9 @@ namespace bolt { case NodeKind::MatchExpression: visitEachChild(static_cast(N)); break; + case NodeKind::MemberExpression: + visitEachChild(static_cast(N)); + break; case NodeKind::NestedExpression: visitEachChild(static_cast(N)); break; @@ -861,6 +870,12 @@ namespace bolt { } } + void visitEachChild(MemberExpression* N) { + BOLT_VISIT(N->getExpression()); + BOLT_VISIT(N->Dot); + BOLT_VISIT(N->Name); + } + void visitEachChild(NestedExpression* N) { BOLT_VISIT(N->LParen); BOLT_VISIT(N->Inner); diff --git a/include/bolt/Checker.hpp b/include/bolt/Checker.hpp index e6a6a4df5..ecae3c3fc 100644 --- a/include/bolt/Checker.hpp +++ b/include/bolt/Checker.hpp @@ -1,5 +1,4 @@ - #pragma once #include "zen/config.hpp" diff --git a/include/bolt/Parser.hpp b/include/bolt/Parser.hpp index e42eb8071..7aaeadfd8 100644 --- a/include/bolt/Parser.hpp +++ b/include/bolt/Parser.hpp @@ -78,6 +78,7 @@ namespace bolt { Expression* parseInfixOperatorAfterExpression(Expression* LHS, int MinPrecedence); + Expression* parseMemberExpression(); Expression* parsePrimitiveExpression(); ConstraintExpression* parseConstraintExpression(); diff --git a/src/CST.cc b/src/CST.cc index e933c43bb..ecd346060 100644 --- a/src/CST.cc +++ b/src/CST.cc @@ -275,6 +275,14 @@ namespace bolt { return BlockStart; } + Token* MemberExpression::getFirstToken() { + return E->getFirstToken(); + } + + Token* MemberExpression::getLastToken() { + return Name; + } + Token* NestedExpression::getFirstToken() { return LParen; } diff --git a/src/Checker.cc b/src/Checker.cc index 212390b34..af1f431dc 100644 --- a/src/Checker.cc +++ b/src/Checker.cc @@ -1,9 +1,7 @@ // TODO Add list of CST variable names to TVar and unify them so that e.g. the typeclass checker may pick one when displaying a diagnostic -// TODO make sure that if we have Eq Int, Eq a ~ Eq Int such that an instance binding eq has the correct type - -// TODO make unficiation work like union-find in find() +// TODO (maybe) make unficiation work like union-find in find() #include #include @@ -1184,7 +1182,8 @@ namespace bolt { bool Checker::unify(Type* A, Type* B, Node* Source) { - auto find = [&](auto Ty) { + auto find = [&](auto OrigTy) { + auto Ty = OrigTy; while (Ty->getKind() == TypeKind::Var) { auto Match = Solution.find(static_cast(Ty)); if (Match == Solution.end()) { diff --git a/src/Parser.cc b/src/Parser.cc index ad58cfb46..507321ff5 100644 --- a/src/Parser.cc +++ b/src/Parser.cc @@ -279,8 +279,31 @@ after_constraints: } } + Expression* Parser::parseMemberExpression() { + auto E = parsePrimitiveExpression(); + for (;;) { + auto T1 = Tokens.peek(0); + auto T2 = Tokens.peek(1); + if (!llvm::isa(T1)) { + break; + } + switch (T2->getKind()) { + case NodeKind::IntegerLiteral: + case NodeKind::Identifier: + Tokens.get(); + Tokens.get(); + E = new MemberExpression { E, static_cast(T1), T2 }; + break; + default: + goto finish; + } + } +finish: + return E; + } + Expression* Parser::parseCallExpression() { - auto Operator = parsePrimitiveExpression(); + auto Operator = parseMemberExpression(); std::vector Args; for (;;) { auto T1 = Tokens.peek();