From 688dba66c0698945f535aaa1554b953b7e01382f Mon Sep 17 00:00:00 2001 From: Peter Matta <mattapet@fit.cvut.cz> Date: Wed, 16 May 2018 11:38:15 +0200 Subject: [PATCH] Added new ASTWalker behavior --- examples/factRec.dusk | 6 +- examples/factor.dusk | 5 +- examples/fibonacci.dusk | 5 +- examples/funcDecl.dusk | 4 - examples/gcd.dusk | 8 +- examples/inOut.dusk | 3 - examples/interpRec.dusk | 5 +- examples/isPrime.dusk | 49 ++--- include/dusk/AST/ASTVisitor.h | 106 ++++++++- include/dusk/AST/ASTWalker.h | 110 +++++++++- include/dusk/AST/Decl.h | 7 +- include/dusk/AST/Expr.h | 20 +- include/dusk/AST/Pattern.h | 5 + include/dusk/AST/Stmt.h | 17 +- include/dusk/AST/TypeRepr.h | 3 + lib/AST/ASTNode.cpp | 14 ++ lib/AST/ASTPrinter.cpp | 80 +++---- lib/AST/ASTWalker.cpp | 403 +++++++++++++++++++++++++++++++--- lib/IRGen/CMakeLists.txt | 2 + lib/IRGen/GenExpr.cpp | 2 +- lib/IRGen/GenFunc.cpp | 12 +- lib/IRGen/IRGenModule.cpp | 29 +-- lib/IRGen/IRGenModule.h | 5 + lib/IRGen/IRGenValue.cpp | 57 +++++ lib/IRGen/IRGenValue.h | 128 +++++++++++ lib/Sema/TypeCheckExpr.cpp | 4 +- 26 files changed, 906 insertions(+), 183 deletions(-) create mode 100644 lib/IRGen/IRGenValue.cpp create mode 100644 lib/IRGen/IRGenValue.h diff --git a/examples/factRec.dusk b/examples/factRec.dusk index 3333913..a35bac6 100644 --- a/examples/factRec.dusk +++ b/examples/factRec.dusk @@ -1,7 +1,3 @@ -extern func println(int: Int) -> Void; -extern func readln() -> Int; - - func fact(n: Int) -> Int { if n == 0 { return 1; @@ -10,7 +6,7 @@ func fact(n: Int) -> Int { } } -func main_() { +func main() { let n = readln(); println(fact(n)); } diff --git a/examples/factor.dusk b/examples/factor.dusk index 67dce84..d4518b7 100644 --- a/examples/factor.dusk +++ b/examples/factor.dusk @@ -1,6 +1,3 @@ -extern func println(int: Int) -> Void; -extern func readln() -> Int; - func factorize(n: Int, fact: Int) -> Int { var ret = n; while ret % fact == 0 { @@ -33,7 +30,7 @@ func factorization(n: Int) { } } -func main_() { +func main() { let n = readln(); factorization(n); } diff --git a/examples/fibonacci.dusk b/examples/fibonacci.dusk index 3dd6c3c..e899778 100644 --- a/examples/fibonacci.dusk +++ b/examples/fibonacci.dusk @@ -1,6 +1,3 @@ -extern func println(int: Int) -> Void; -extern func readln() -> Int; - func fib(n: Int) -> Int { if n < 2 { return n; @@ -9,7 +6,7 @@ func fib(n: Int) -> Int { } } -func main_() { +func main() { let n = readln(); println(fib(n)); } diff --git a/examples/funcDecl.dusk b/examples/funcDecl.dusk index 908c46e..b247d79 100644 --- a/examples/funcDecl.dusk +++ b/examples/funcDecl.dusk @@ -1,7 +1,3 @@ -//extern func test(); -extern func println(output: Int) -> Void; -extern func readln() -> Int; - /*func main(arg1: Int) -> Int { return arg1; }*/ diff --git a/examples/gcd.dusk b/examples/gcd.dusk index 42383f4..2d9f66a 100644 --- a/examples/gcd.dusk +++ b/examples/gcd.dusk @@ -1,6 +1,3 @@ -extern func println(int: Int) -> Void; -extern func readln() -> Int; - func gcdi(a: Int, b: Int) -> Int { while b != 0 { let tmp = b; @@ -11,8 +8,7 @@ func gcdi(a: Int, b: Int) -> Int { } func gcdr(a: Int, b: Int) -> Int { - let tmp = a % b; - if tmp == 0 { + if a % b == 0 { return b; } else { return gcdr(b, tmp); @@ -30,7 +26,7 @@ func gcdrGuessing(a: Int, b: Int) -> Int { return gcdrGuessingInner(a, b, b); } -func main_() { +func main() { println(gcdi(27*2, 27*3)); println(gcdr(27*2, 27*3)); println(gcdrGuessing(27*2, 27*3)); diff --git a/examples/inOut.dusk b/examples/inOut.dusk index 9afe30f..de315f1 100644 --- a/examples/inOut.dusk +++ b/examples/inOut.dusk @@ -1,6 +1,3 @@ -extern func println(int: Int) -> Void; -extern func readln() -> Int; - var n: Int; func main_() { diff --git a/examples/interpRec.dusk b/examples/interpRec.dusk index 140066d..1789cc4 100644 --- a/examples/interpRec.dusk +++ b/examples/interpRec.dusk @@ -1,6 +1,3 @@ -extern func println(int: Int) -> Void; -extern func readln() -> Int; - func isOdd(n: Int) -> Int { if n > 0 { return isEven(n - 1); @@ -15,7 +12,7 @@ func isEven(n: Int) -> Int { return 1; } -func main_() { +func main() { let n = readln(); println(isEven(n)); println(isOdd(n)); diff --git a/examples/isPrime.dusk b/examples/isPrime.dusk index 1d876ae..0d7363d 100644 --- a/examples/isPrime.dusk +++ b/examples/isPrime.dusk @@ -1,6 +1,3 @@ -extern func println(int: Int) -> Void; -extern func readln() -> Int; - func isPrime(n: Int) -> Int { if n < 2 { return 0; @@ -33,29 +30,29 @@ func isPrime(n: Int) -> Int { } } -func main_() { - // println(0); - // println(isPrime(0)); - // println(1); - // println(isPrime(1)); - // println(2); - // println(isPrime(2)); - // println(3); - // println(isPrime(3)); - // println(4); - // println(isPrime(4)); - // println(5); - // println(isPrime(5)); - // println(6); - // println(isPrime(6)); - // println(7); - // println(isPrime(7)); - // println(8); - // println(isPrime(8)); - // println(9); - // println(isPrime(9)); - // println(10); - // println(isPrime(10)); +func main() { + println(0); + println(isPrime(0)); + println(1); + println(isPrime(1)); + println(2); + println(isPrime(2)); + println(3); + println(isPrime(3)); + println(4); + println(isPrime(4)); + println(5); + println(isPrime(5)); + println(6); + println(isPrime(6)); + println(7); + println(isPrime(7)); + println(8); + println(isPrime(8)); + println(9); + println(isPrime(9)); + println(10); + println(isPrime(10)); println(11); println(isPrime(11)); println(12); diff --git a/include/dusk/AST/ASTVisitor.h b/include/dusk/AST/ASTVisitor.h index a83d8e6..7d28973 100644 --- a/include/dusk/AST/ASTVisitor.h +++ b/include/dusk/AST/ASTVisitor.h @@ -39,19 +39,19 @@ public: /// Returns a reference to the derived class. Derived &getDerived() { return *static_cast<Derived *>(this); } - bool visit(ASTNode *N) { + bool visit_(ASTNode *N) { if (auto *D = dynamic_cast<Decl *>(N)) - return visit(D); + return visit_(D); if (auto *E = dynamic_cast<Expr *>(N)) - return visit(E); + return visit_(E); if (auto *S = dynamic_cast<Stmt *>(N)) - return visit(S); + return visit_(S); llvm_unreachable("Unexpected node"); } /// Visit a concrete declaration node. - bool visit(Decl *D) { + bool visit_(Decl *D) { switch (D->getKind()) { case DeclKind::Let: return getDerived().visit(static_cast<LetDecl *>(D)); @@ -67,7 +67,7 @@ public: } /// Visit a conrete expression node. - bool visit(Expr *E) { + bool visit_(Expr *E) { switch (E->getKind()) { case ExprKind::NumberLiteral: return getDerived().visit(static_cast<NumberLiteralExpr *>(E)); @@ -91,7 +91,7 @@ public: } /// Visit a concrete statement node. - bool visit(Stmt *S) { + bool visit_(Stmt *S) { switch (S->getKind()) { case StmtKind::Break: return getDerived().visit(static_cast<BreakStmt *>(S)); @@ -117,7 +117,7 @@ public: } /// Visit a concrete pattern node. - bool visit(Pattern *P) { + bool visit_(Pattern *P) { switch (P->getKind()) { case PatternKind::Expr: return getDerived().visit(static_cast<ExprPattern *>(P)); @@ -127,7 +127,7 @@ public: } /// Visits concrete TypeRepr - bool visit(TypeRepr *T) { + bool visit_(TypeRepr *T) { switch (T->getKind()) { case TypeReprKind::Ident: return getDerived().visit(static_cast<IdentTypeRepr *>(T)); @@ -135,6 +135,94 @@ public: return getDerived().visit(static_cast<ArrayTypeRepr *>(T)); } } + + /// Visit a concrete declaration node. + bool visit(Decl *D) { + switch (D->getKind()) { + case DeclKind::Let: + return getDerived().visitLetDecl(static_cast<LetDecl *>(D)); + case DeclKind::Var: + return getDerived().visitVarDecl(static_cast<VarDecl *>(D)); + case DeclKind::Func: + return getDerived().visitFuncDecl(static_cast<FuncDecl *>(D)); + case DeclKind::Module: + return getDerived().visitModuleDecl(static_cast<ModuleDecl *>(D)); + case DeclKind::Param: + return getDerived().visitParamDecl(static_cast<ParamDecl *>(D)); + } + } + + /// Visit a concrete expression node. + Expr *visit(Expr *E) { + switch (E->getKind()) { + case ExprKind::NumberLiteral: + return getDerived().visitNumberLiteralExpr( + static_cast<NumberLiteralExpr *>(E)); + case ExprKind::ArrayLiteral: + return getDerived().visitArrayLiteralExpr( + static_cast<ArrayLiteralExpr *>(E)); + case ExprKind::Identifier: + return getDerived().visitIdentifierExpr(static_cast<IdentifierExpr *>(E)); + case ExprKind::Paren: + return getDerived().visitParenExpr(static_cast<ParenExpr *>(E)); + case ExprKind::Assign: + return getDerived().visitAssignExpr(static_cast<AssignExpr *>(E)); + case ExprKind::Infix: + return getDerived().visitInfixExpr(static_cast<InfixExpr *>(E)); + case ExprKind::Prefix: + return getDerived().visitPrefixExpr(static_cast<PrefixExpr *>(E)); + case ExprKind::Call: + return getDerived().visitCallExpr(static_cast<CallExpr *>(E)); + case ExprKind::Subscript: + return getDerived().visitSubscriptExpr(static_cast<SubscriptExpr *>(E)); + } + } + + /// Visit a concrete statement node. + bool visit(Stmt *S) { + switch (S->getKind()) { + case StmtKind::Break: + return getDerived().visitBreakStmt(static_cast<BreakStmt *>(S)); + case StmtKind::Return: + return getDerived().visitReturnStmt(static_cast<ReturnStmt *>(S)); + case StmtKind::Range: + return getDerived().visitRangeStmt(static_cast<RangeStmt *>(S)); + case StmtKind::Subscript: + return getDerived().visitSubscriptStmt(static_cast<SubscriptStmt *>(S)); + case StmtKind::Block: + return getDerived().visitBlockStmt(static_cast<BlockStmt *>(S)); + case StmtKind::Extern: + return getDerived().visitExternStmt(static_cast<ExternStmt *>(S)); + case StmtKind::For: + return getDerived().visitForStmt(static_cast<ForStmt *>(S)); + case StmtKind::Func: + return getDerived().visitFuncStmt(static_cast<FuncStmt *>(S)); + case StmtKind::If: + return getDerived().visitIfStmt(static_cast<IfStmt *>(S)); + case StmtKind::While: + return getDerived().visitWhileStmt(static_cast<WhileStmt *>(S)); + } + } + + /// Visit a concrete pattern node. + bool visit(Pattern *P) { + switch (P->getKind()) { + case PatternKind::Expr: + return getDerived().visitExprPattern(static_cast<ExprPattern *>(P)); + case PatternKind::Variable: + return getDerived().visitVarPattern(static_cast<VarPattern *>(P)); + } + } + + /// Visits concrete TypeRepr + bool visit(TypeRepr *T) { + switch (T->getKind()) { + case TypeReprKind::Ident: + return getDerived().visitIdentTypeRepr(static_cast<IdentTypeRepr *>(T)); + case TypeReprKind::Array: + return getDerived().visitArrayTypeRepr(static_cast<ArrayTypeRepr *>(T)); + } + } }; } // namespace dusk diff --git a/include/dusk/AST/ASTWalker.h b/include/dusk/AST/ASTWalker.h index a87ffe5..1250893 100644 --- a/include/dusk/AST/ASTWalker.h +++ b/include/dusk/AST/ASTWalker.h @@ -11,12 +11,14 @@ #define DUSK_AST_WALKER_H #include "dusk/Basic/LLVM.h" +#include <utility> namespace dusk { class Decl; class Expr; class Stmt; class Pattern; +class TypeRepr; /// \brief Base class for all classes, that whish to traverse the AST. /// @@ -42,7 +44,7 @@ public: /// \return \c true if the node should terminate traversal, /// \c false otherwise. virtual bool postWalk(Decl *D) { return true; } - + /// This method is called before a node is being walked. /// /// \param E An expression node that will be walked. @@ -87,6 +89,112 @@ public: /// \return \c true if the node should terminate traversal, /// \c false otherwise. virtual bool postWalk(Pattern *P) { return true; } + + + + /// This method is called before a declaration is being walked. + /// + /// \param D A declaration node that will be walked. + /// + /// \return \c true if the node should be walked, \c false otherwise. + /// + /// Default implementation returns \c true. + virtual bool preWalkDecl(Decl *D) { return true; } + + /// This method is called after declaration children were walked. + /// + /// \param D A declaration node that was walked. + /// + /// \return \c true if the node should continue traversal, + /// \c false otherwise. + /// + /// Default implementation returns \c true. + virtual bool postWalkDecl(Decl *D) { return true; } + + /// This method is called before an expression is being walked. + /// + /// \param E An expression node that will be walked. + /// + /// \return A pair consisting of a \c bool indicating, whether this node + /// should be skipped or not and an expression that should replace this + /// expression in the tree. If \c null is returned, the traversal is + /// terminated. + /// + /// Default implementation returns \c {true, E}. + virtual std::pair<bool, Expr *> preWalkExpr(Expr *E) { return {true, E}; } + + /// This method is called after expression children were walked. + /// + /// \param E An expression node that was walked. + /// + /// \return \c null, in which case the walk is terminater, otherwise the + /// returned expression replaces walked expression in the tree. + /// + /// Default implementation returns its argument. + virtual Expr *postWalkExpr(Expr *E) { return E; } + + + /// This method is called before a statement is being walked. + /// + /// \param S A statement node that will be walked. + /// + /// \return \c true if the node should be walked, \c false otherwise. + /// + /// Default implementation returns \c true. + virtual bool preWalkStmt(Stmt *S) { return true; } + + /// This method is called after statement children were walked. + /// + /// \param S A statement node that was walked. + /// + /// \return \c true if the node should continue traversal, + /// \c false otherwise. + /// + /// Default implementation returns \c true. + virtual bool postWalkStmt(Stmt *S) { return true; } + + + /// This method is called before a pattern is being walked. + /// + /// \param P A pattern node that will be walked. + /// + /// \return \c true if the node should be walked, \c false otherwise. + /// + /// Default implementation returns \c true. + virtual bool preWalkPattern(Pattern *P) { return true; } + + /// This method is called after pattern children were walked. + /// + /// \param P A pattern node that was walked. + /// + /// \return \c true if the node should continue traversal, + /// \c false otherwise. + /// + /// Default implementation returns \c true. + virtual bool postWalkPattern(Pattern *P) { return true; } + + /// This method is called before a type represenation is being walked. + /// + /// \param Tr A type representation node that will be walked. + /// + /// \return \c true if the node should be walked, \c false otherwise. + /// + /// Default implementation returns \c true. + virtual bool preWalkTypeRepr(TypeRepr *Tr) { return true; } + + /// This method is called after type representation children were walked. + /// + /// \param Tr A type representation node that was walked. + /// + /// \return \c true if the node should continue traversal, + /// \c false otherwise. + /// + /// Default implementation returns \c true. + virtual bool postWalkTypeRepr(TypeRepr *Tr) { return true; } + +private: + ASTWalker(const ASTWalker &) = delete; + ASTWalker &operator=(const ASTWalker &) = delete; }; } // namespace dusk diff --git a/include/dusk/AST/Decl.h b/include/dusk/AST/Decl.h index 8fb3506..16f40fa 100644 --- a/include/dusk/AST/Decl.h +++ b/include/dusk/AST/Decl.h @@ -86,7 +86,9 @@ public: /// Returns type representation. TypeRepr *getTypeRepr() const { return TyRepr; } - virtual SMRange getSourceRange() const override; + SMRange getSourceRange() const override; + + bool walk(ASTWalker &Walker) override; }; /// Declaration of value-holdable node @@ -101,9 +103,10 @@ public: ValDecl(DeclKind K, StringRef N, SMLoc NL, Expr *V); ValDecl(DeclKind K, StringRef N, SMLoc NL, Expr *V, TypeRepr *TR); - bool hasValue() const { return Value != nullptr; } SMLoc getValLoc() const { return ValLoc; } + bool hasValue() const { return Value != nullptr; } Expr *getValue() const { return Value; } + void setValue(Expr *V) { Value = V; } }; /// Declaration of a variable diff --git a/include/dusk/AST/Expr.h b/include/dusk/AST/Expr.h index 172593d..7fea43f 100644 --- a/include/dusk/AST/Expr.h +++ b/include/dusk/AST/Expr.h @@ -65,6 +65,8 @@ public: /// Sets declaration type void setType(Type *T) { Ty = T; } + + bool walk(ASTWalker &Walker) override; }; /// Number literal expression encalsulation. @@ -76,7 +78,7 @@ public: NumberLiteralExpr(int64_t V, SMRange ValL); SMRange getValLoc() const { return ValueLoc; } - int getValue() const { return Value; } + int64_t getValue() const { return Value; } SMRange getSourceRange() const override; }; @@ -127,6 +129,7 @@ public: ParenExpr(Expr *E, SMLoc L, SMLoc R); Expr *getExpr() const { return Expression; } + void setExpr(Expr *E) { Expression = E; } SMRange getSourceRange() const override; }; @@ -142,6 +145,8 @@ public: Expr *getLHS() const { return LHS; } Expr *getRHS() const { return RHS; } + void setLHS(Expr *L) { LHS = L; } + void setRHS(Expr *R) { RHS = R; } Token getOp() const { return Op; } SMRange getSourceRange() const override; @@ -152,10 +157,12 @@ class AssignExpr : public Expr { Expr *Source; public: - AssignExpr(Expr *L, Expr *R); + AssignExpr(Expr *D, Expr *S); Expr *getDest() const { return Dest; } Expr *getSource() const { return Source; } + void setDest(Expr *D) { Dest = D; } + void setSource(Expr *S) { Source = S; } SMRange getSourceRange() const override; }; @@ -168,6 +175,7 @@ public: PrefixExpr(Expr *D, Token O); Expr *getDest() const { return Dest; } + void setDest(Expr *D) { Dest = D; } Token getOp() const { return Op; } SMRange getSourceRange() const override; @@ -183,9 +191,10 @@ class CallExpr : public Expr { public: CallExpr(Expr *C, Pattern *A); - Expr *getCalle() const { return Callee; } + Expr *getCallee() const { return Callee; } Pattern *getArgs() { return Args; } - + void setCallee(Expr *C) { Callee = C; } + SMRange getSourceRange() const override; }; @@ -201,7 +210,8 @@ public: Expr *getBase() { return Base; } Stmt *getSubscript() { return Subscript; } - + void setBase(Expr *B) { Base = B; } + SMRange getSourceRange() const override; }; diff --git a/include/dusk/AST/Pattern.h b/include/dusk/AST/Pattern.h index 1ee108a..b61fb07 100644 --- a/include/dusk/AST/Pattern.h +++ b/include/dusk/AST/Pattern.h @@ -22,6 +22,7 @@ class Expr; class Stmt; class Type; class ParamDecl; +class ASTWalker; /// Pattern description. enum struct PatternKind { Expr, Variable }; @@ -45,6 +46,8 @@ public: SMLoc getLocStart() { return getSourceRange().Start; } SMLoc getLocEnd() { return getSourceRange().End; } + + bool walk(ASTWalker &Walker); }; /// Expression pattern @@ -63,6 +66,7 @@ public: ExprPattern(SmallVector<Expr *, 128> &&V, SMLoc L, SMLoc R); ArrayRef<Expr *> getValues() const { return Values; } + SmallVector<Expr *, 128> &getValues() { return Values; } SMLoc getLPar() const { return LPar; } SMLoc getRPar() const { return RPar; } @@ -88,6 +92,7 @@ public: VarPattern(SmallVector<Decl *, 128> &&V, SMLoc L, SMLoc R); ArrayRef<Decl *> getVars() const { return Vars; } + SmallVector<Decl *, 128> &getVars() { return Vars; } SMLoc getLPar() const { return LPar; } SMLoc getRPar() const { return RPar; } diff --git a/include/dusk/AST/Stmt.h b/include/dusk/AST/Stmt.h index ade30dc..9bd3d76 100644 --- a/include/dusk/AST/Stmt.h +++ b/include/dusk/AST/Stmt.h @@ -48,9 +48,11 @@ public: virtual ~Stmt() = default; StmtKind getKind() const { return Kind; } + + bool walk(ASTWalker &Walker) override; }; -/// Represents a `break` statement in a loop. +/// Represents a \c break statement in a loop. class BreakStmt : public Stmt { /// Range of \c break keyword SMRange BreakLoc; @@ -58,10 +60,10 @@ class BreakStmt : public Stmt { public: BreakStmt(SMRange BR); - virtual SMRange getSourceRange() const override; + SMRange getSourceRange() const override; }; -/// Represents a `return` statement. +/// Represents a \c return statement. class ReturnStmt : public Stmt { /// Location of \c return keyword SMLoc RetLoc; @@ -73,6 +75,7 @@ public: ReturnStmt(SMLoc RL, Expr *V); Expr *getValue() const { return Value; } + void setValue(Expr *V) { Value = V; } bool hasValue() const { return Value != nullptr; } virtual SMRange getSourceRange() const override; }; @@ -92,6 +95,7 @@ public: SubscriptStmt(Expr *V, SMLoc L, SMLoc R); Expr *getValue() const { return Value; } + void setValue(Expr *V) { Value = V; } SMLoc getLBracket() const { return LBracket; } SMLoc getRBracket() const { return RBracket; } @@ -114,6 +118,8 @@ public: Expr *getStart() const { return Start; } Expr *getEnd() const { return End; } + void setStart(Expr *S) { Start = S; } + void setEnd(Expr *E) { End = E; } Token getOp() const { return Op; } /// Return \c true, if range is inclusive, \c false otherwise. @@ -136,7 +142,8 @@ class BlockStmt : public Stmt { public: BlockStmt(SMLoc S, SMLoc E, std::vector<ASTNode *> &&N); - ArrayRef<ASTNode *> getNodes() { return Nodes; } + ArrayRef<ASTNode *> getNodes() const { return Nodes; } + std::vector<ASTNode *> &getNodes() { return Nodes; } virtual SMRange getSourceRange() const override; }; @@ -206,6 +213,7 @@ public: WhileStmt(SMLoc WL, Expr *C, Stmt *B); Expr *getCond() const { return Cond; } + void setCond(Expr *C) { Cond = C; } Stmt *getBody() const { return Body; } virtual SMRange getSourceRange() const override; @@ -226,6 +234,7 @@ public: IfStmt(SMLoc IL, Expr *C, Stmt *T, Stmt *E = nullptr); Expr *getCond() const { return Cond; } + void setCond(Expr *C) { Cond = C; } Stmt *getThen() const { return Then; } Stmt *getElse() const { return Else; } bool hasElseBlock() const { return Else != nullptr; } diff --git a/include/dusk/AST/TypeRepr.h b/include/dusk/AST/TypeRepr.h index e0f4fbb..598c8ba 100644 --- a/include/dusk/AST/TypeRepr.h +++ b/include/dusk/AST/TypeRepr.h @@ -18,6 +18,7 @@ namespace dusk { class Expr; class Stmt; +class ASTWalker; enum struct TypeReprKind { Ident, @@ -34,6 +35,8 @@ public: SMLoc getLocStart() const { return getSourceRange().Start; } SMLoc getLocEnd() const { return getSourceRange().End; } virtual SMRange getSourceRange() const = 0; + + bool walk(ASTWalker &Walker); }; /// Simple single identifier type e.g. ': Int' diff --git a/lib/AST/ASTNode.cpp b/lib/AST/ASTNode.cpp index 9ef0649..947f0b8 100644 --- a/lib/AST/ASTNode.cpp +++ b/lib/AST/ASTNode.cpp @@ -14,3 +14,17 @@ #include "dusk/AST/Stmt.h" using namespace dusk; + +bool ASTNode::walk(ASTWalker &Walker) { + if (auto D = dynamic_cast<Decl *>(this)) + return D->walk(Walker); + + else if (auto E = dynamic_cast<Expr *>(this)) + return E->walk(Walker); + + else if (auto S = dynamic_cast<Stmt *>(this)) + return S->walk(Walker); + + else + llvm_unreachable("Unexpected AST node found."); +} diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 1bd709a..41d635c 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -45,7 +45,7 @@ public: if (E) Printer.printNewline(); - super::visit(N); + super::visit_(N); if (E) Printer.printText(";"); @@ -60,12 +60,12 @@ public: if (D->hasTypeRepr()) { Printer << ": "; - super::visit(D->getTypeRepr()); + super::visit_(D->getTypeRepr()); } if (D->hasValue()) { Printer << " " << tok::assign << " "; - super::visit(D->getValue()); + super::visit_(D->getValue()); } Printer.printDeclPost(D); return true; @@ -77,12 +77,12 @@ public: if (D->hasTypeRepr()) { Printer << ": "; - super::visit(D->getTypeRepr()); + super::visit_(D->getTypeRepr()); } if (D->hasValue()) { Printer << " " << tok::assign << " "; - super::visit(D->getValue()); + super::visit_(D->getValue()); } Printer.printDeclPost(D); return true; @@ -91,12 +91,12 @@ public: bool visit(FuncDecl *D) { Printer.printDeclPre(D); Printer << D->getName() << "("; - super::visit(D->getArgs()); + super::visit_(D->getArgs()); Printer << ")"; if (D->hasTypeRepr()) { Printer << " -> "; - super::visit(D->getTypeRepr()); + super::visit_(D->getTypeRepr()); } Printer.printDeclPost(D); @@ -106,7 +106,7 @@ public: bool visit(ParamDecl *D) { Printer.printDeclPost(D); Printer << D->getName() << ": "; - super::visit(D->getTypeRepr()); + super::visit_(D->getTypeRepr()); Printer.printDeclPost(D); return true; } @@ -128,49 +128,49 @@ public: bool visit(ArrayLiteralExpr *E) { Printer << "["; - super::visit(E->getValues()); + super::visit_(E->getValues()); Printer << "]"; return true; } bool visit(ParenExpr *E) { Printer << "("; - super::visit(E->getExpr()); + super::visit_(E->getExpr()); Printer << ")"; return true; } bool visit(AssignExpr *E) { - super::visit(E->getDest()); + super::visit_(E->getDest()); Printer << " " << tok::assign << " "; - super::visit(E->getSource()); + super::visit_(E->getSource()); return true; } bool visit(CallExpr *E) { - super::visit(E->getCalle()); + super::visit_(E->getCallee()); Printer << "("; - super::visit(E->getArgs()); + super::visit_(E->getArgs()); Printer << ")"; return true; } bool visit(InfixExpr *E) { - super::visit(E->getLHS()); + super::visit_(E->getLHS()); Printer << " " << E->getOp().getKind() << " "; - super::visit(E->getRHS()); + super::visit_(E->getRHS()); return true; } bool visit(PrefixExpr *E) { Printer << E->getOp().getKind(); - super::visit(E->getDest()); + super::visit_(E->getDest()); return true; } bool visit(SubscriptExpr *E) { - super::visit(E->getBase()); - super::visit(E->getSubscript()); + super::visit_(E->getBase()); + super::visit_(E->getSubscript()); return true; } @@ -187,7 +187,7 @@ public: Printer.printStmtPre(S); Printer << tok::kwReturn << " "; - super::visit(S->getValue()); + super::visit_(S->getValue()); Printer.printStmtPost(S); return true; @@ -195,18 +195,18 @@ public: bool visit(SubscriptStmt *S) { Printer.printStmtPre(S); - super::visit(S->getValue()); + super::visit_(S->getValue()); Printer.printStmtPost(S); return true; } bool visit(RangeStmt *S) { Printer.printStmtPre(S); - super::visit(S->getStart()); + super::visit_(S->getStart()); Printer << S->getOp().getKind(); - super::visit(S->getEnd()); + super::visit_(S->getEnd()); Printer.printStmtPost(S); return true; } @@ -220,7 +220,7 @@ public: else Printer.printNewline(); - super::visit(N); + super::visit_(N); if (auto E = dynamic_cast<Expr *>(N)) Printer.printText(";"); } @@ -231,16 +231,16 @@ public: bool visit(ExternStmt *S) { Printer.printStmtPre(S); Printer << tok::kwExtern << " "; - super::visit(S->getPrototype()); + super::visit_(S->getPrototype()); Printer.printStmtPost(S); return true; } bool visit(FuncStmt *S) { Printer.printStmtPre(S); - super::visit(S->getPrototype()); + super::visit_(S->getPrototype()); Printer << " "; - super::visit(S->getBody()); + super::visit_(S->getBody()); Printer.printStmtPost(S); return true; } @@ -249,11 +249,11 @@ public: Printer.printStmtPre(S); Printer << tok::kwFor << " "; - super::visit(S->getIter()); + super::visit_(S->getIter()); Printer << " " << tok::kwIn << " "; - super::visit(S->getRange()); + super::visit_(S->getRange()); Printer << " "; - super::visit(S->getBody()); + super::visit_(S->getBody()); Printer.printStmtPost(S); return true; @@ -263,13 +263,13 @@ public: Printer.printStmtPre(S); Printer << tok::kwIf << " "; - super::visit(S->getCond()); + super::visit_(S->getCond()); Printer << " "; - super::visit(S->getThen()); + super::visit_(S->getThen()); if (S->hasElseBlock()) { Printer << " " << tok::kwElse << " "; - super::visit(S->getElse()); + super::visit_(S->getElse()); } Printer.printStmtPost(S); @@ -280,9 +280,9 @@ public: Printer.printStmtPre(S); Printer << tok::kwWhile << " "; - super::visit(S->getCond()); + super::visit_(S->getCond()); Printer << " "; - super::visit(S->getBody()); + super::visit_(S->getBody()); Printer.printStmtPost(S); return true; @@ -294,7 +294,7 @@ public: bool isFirst = true; for (auto V : P->getValues()) { Printer.printSeparator(isFirst, ", "); - super::visit(V); + super::visit_(V); } return true; } @@ -303,7 +303,7 @@ public: bool isFirst = true; for (auto V : P->getVars()) { Printer.printSeparator(isFirst, ", "); - super::visit(V); + super::visit_(V); } return true; } @@ -316,8 +316,8 @@ public: } bool visit(ArrayTypeRepr *T) { - super::visit(T->getBaseTyRepr()); - super::visit(T->getSize()); + super::visit_(T->getBaseTyRepr()); + super::visit_(T->getSize()); return true; } }; @@ -542,6 +542,6 @@ void StreamPrinter::printText(StringRef Text) { OS << Text; } void Formatter::format() { PrettyPrinter pp(OS); PrintAST p(pp); - p.ASTVisitor::visit(Ctx.getRootModule()); + p.ASTVisitor::visit_(Ctx.getRootModule()); } diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index ab7c9e6..d4d747d 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -40,11 +40,323 @@ class Traversal : public ASTVisitor<Traversal> { /// Convenience type alias. typedef ASTVisitor super; - + + friend class ASTVisitor<Traversal>; + + // MARK: - Declarations + + bool visitLetDecl(LetDecl *D) { + if (D->hasTypeRepr()) + if (!traverse(D->getTypeRepr())) + return false; + + if (D->hasValue()) { + auto E = traverse(D->getValue()); + if (!E) + return false; + D->setValue(E); + } + return true; + } + + bool visitVarDecl(VarDecl *D) { + if (D->hasTypeRepr()) + if (!traverse(D->getTypeRepr())) + return false; + + if (D->hasValue()) { + auto E = traverse(D->getValue()); + if (!E) + return false; + D->setValue(E); + } + return true; + } + + bool visitParamDecl(ParamDecl *D) { + return !D->hasTypeRepr() || traverse(D->getTypeRepr()); + } + + bool visitFuncDecl(FuncDecl *D) { + if (!traverse(D->getArgs())) + return false; + return !D->hasTypeRepr() || traverse(D->getTypeRepr()); + } + + bool visitModuleDecl(ModuleDecl *D) { + for (auto &N : D->getContents()) { + if (auto D = dynamic_cast<Decl *>(N)) + if (!traverse(D)) + return false; + + if (auto E = dynamic_cast<Expr *>(N)) + if ((N = traverse(E)) == nullptr) + return false; + + if (auto S = dynamic_cast<Stmt *>(N)) + if (!traverse(S)) + return false; + } + return true; + } + + // MARK: - Expressions + + Expr *visitNumberLiteralExpr(NumberLiteralExpr *E) { + return E; + } + + Expr *visitArrayLiteralExpr(ArrayLiteralExpr *E) { + return E; + } + + Expr *visitIdentifierExpr(IdentifierExpr *E) { + return E; + } + + Expr *visitParenExpr(ParenExpr *E) { + if (auto Ex = traverse(E->getExpr())) + E->setExpr(Ex); + else + return nullptr; + return E; + } + + Expr *visitInfixExpr(InfixExpr *E) { + auto Ex = traverse(E->getLHS()); + if (!Ex) + return nullptr; + E->setLHS(Ex); + Ex = traverse(E->getRHS()); + if (!Ex) + return nullptr; + E->setRHS(Ex); + return E; + } + + Expr *visitAssignExpr(AssignExpr *E) { + auto Ex = traverse(E->getDest()); + if (!Ex) + return nullptr; + E->setDest(Ex); + Ex = traverse(E->getSource()); + if (!Ex) + return nullptr; + E->setSource(Ex); + return E; + } + + Expr *visitPrefixExpr(PrefixExpr *E) { + if (auto Ex = traverse(E->getDest())) + E->setDest(Ex); + else + return nullptr; + return E; + } + + Expr *visitCallExpr(CallExpr *E) { + if (auto Ex = traverse(E->getCallee())) + E->setCallee(Ex); + else + return nullptr; + + if (!traverse(E->getArgs())) + return nullptr; + return E; + } + + Expr *visitSubscriptExpr(SubscriptExpr *E) { + if (auto Ex = traverse(E->getBase())) + E->setBase(Ex); + else + return nullptr; + + if (!traverse(E->getSubscript())) + return nullptr; + return E; + } + + // MAKR: - Statements + + bool visitBreakStmt(BreakStmt *S) { + return true; + } + + bool visitReturnStmt(ReturnStmt *S) { + if (S->hasValue()) { + if (auto Val = traverse(S->getValue())) + S->setValue(Val); + else + return false; + } + return true; + } + + bool visitSubscriptStmt(SubscriptStmt *S) { + if (auto Val = traverse(S->getValue())) + S->setValue(Val); + else + return false; + return true; + } + + bool visitRangeStmt(RangeStmt *S) { + auto Val = traverse(S->getStart()); + if (!Val) + return false; + S->setStart(Val); + + Val = traverse(S->getEnd()); + if (!Val) + return false; + S->setEnd(Val); + return true; + } + + bool visitBlockStmt(BlockStmt *S) { + for (auto &N : S->getNodes()) { + if (auto D = dynamic_cast<Decl *>(N)) { + if (!traverse(D)) + return false; + + } else if (auto E = dynamic_cast<Expr *>(N)) { + if ((N = traverse(E)) == nullptr) + return false; + + } else if (auto S = dynamic_cast<Stmt *>(N)) { + if (!traverse(S)) + return false; + + } else { + llvm_unreachable("Unexpected AST node."); + } + } + return true; + } + + bool visitExternStmt(ExternStmt *S) { + return traverse(S->getPrototype()); + } + + bool visitFuncStmt(FuncStmt *S) { + if (!traverse(S->getPrototype())) + return false; + return traverse(S->getBody()); + } + + bool visitForStmt(ForStmt *S) { + if (!traverse(S->getIter())) + return false; + if (!traverse(S->getRange())) + return false; + return traverse(S->getBody()); + } + + bool visitWhileStmt(WhileStmt *S) { + if (auto C = traverse(S->getCond())) + S->setCond(C); + else + return false; + return traverse(S->getBody()); + } + + bool visitIfStmt(IfStmt *S) { + if (auto C = traverse(S->getCond())) + S->setCond(C); + else + return false; + if (!traverse(S->getThen())) + return false; + return !S->hasElseBlock() || traverse(S->getElse()); + } + + // MARK: - Patterns + + bool visitExprPattern(ExprPattern *P) { + for (auto &E : P->getValues()) { + if (auto Val = traverse(E)) + E = Val; + else + return false; + } + return true; + } + + bool visitVarPattern(VarPattern *P) { + for (auto Var : P->getVars()) + if (!traverse(Var)) + return false; + return false; + } + + // MARK: - Type representations + + bool visitIdentTypeRepr(IdentTypeRepr *TR) { + return true; + } + + bool visitArrayTypeRepr(ArrayTypeRepr *TR) { + if (!traverse(TR->getBaseTyRepr())) + return false; + return traverse(TR->getSize()); + } + public: /// Constructs a basic traversal object. Traversal(ASTWalker &W) : Walker(W) {} - + + bool traverse(Decl *D) { + // Skip current subtree + if (!Walker.preWalkDecl(D)) + return true; + if (!super::visit(D)) + return false; + + return Walker.postWalkDecl(D); + } + + Expr *traverse(Expr *E) { + auto Pre = Walker.preWalkExpr(E); + // Skip current subtree + if (!Pre.first || !Pre.second) + return Pre.second; + + E = super::visit(E); + + if (E) + E = Walker.postWalkExpr(E); + return E; + } + + bool traverse(Stmt *S) { + // Skip current subtree + if (!Walker.preWalkStmt(S)) + return true; + if (!super::visit(S)) + return false; + + return Walker.postWalkStmt(S); + } + + bool traverse(Pattern *P) { + // Skip current subtree + if (!Walker.preWalkPattern(P)) + return true; + if (!super::visit(P)) + return false; + return Walker.postWalkPattern(P); + } + + bool traverse(TypeRepr *TR) { + // Skip current subtree + if (!Walker.preWalkTypeRepr(TR)) + return true; + if (!super::visit(TR)) + return false; + + return Walker.postWalkTypeRepr(TR); + } + // MARK: - Declaration nodes bool visit(LetDecl *D) { @@ -52,7 +364,7 @@ public: if (!Walker.preWalk(D)) return true; - if (!super::visit(D->getValue())) + if (!super::visit_(D->getValue())) return false; return Walker.postWalk(D); } @@ -62,7 +374,7 @@ public: if (!Walker.preWalk(D)) return true; - if (!super::visit(D->getArgs())) + if (!super::visit_(D->getArgs())) return false; return Walker.postWalk(D); } @@ -72,7 +384,7 @@ public: return true; for (auto C : D->getContents()) - if (!super::visit(C)) + if (!super::visit_(C)) return false; return Walker.postWalk(D); } @@ -90,7 +402,7 @@ public: if (!Walker.preWalk(D)) return true; - if (D->hasValue() && !super::visit(D->getValue())) + if (D->hasValue() && !super::visit_(D->getValue())) return false; return Walker.postWalk(D); } @@ -108,7 +420,7 @@ public: // Skip subtree if (!Walker.preWalk(E)) return true; - if (!super::visit(E->getValues())) + if (!super::visit_(E->getValues())) return false; return Walker.postWalk(E); } @@ -126,7 +438,7 @@ public: if (!Walker.preWalk(E)) return true; - if (!super::visit(E->getExpr())) + if (!super::visit_(E->getExpr())) return false; return Walker.postWalk(E); } @@ -136,9 +448,9 @@ public: if (!Walker.preWalk(E)) return true; - if (!super::visit(E->getDest())) + if (!super::visit_(E->getDest())) return false; - if (!super::visit(E->getSource())) + if (!super::visit_(E->getSource())) return false; return Walker.postWalk(E); } @@ -148,9 +460,9 @@ public: if (!Walker.preWalk(E)) return true; - if (!super::visit(E->getLHS())) + if (!super::visit_(E->getLHS())) return false; - if (!super::visit(E->getRHS())) + if (!super::visit_(E->getRHS())) return false; return Walker.postWalk(E); } @@ -160,7 +472,7 @@ public: if (!Walker.preWalk(E)) return true; - if (!super::visit(E->getDest())) + if (!super::visit_(E->getDest())) return false; return Walker.postWalk(E); } @@ -170,9 +482,9 @@ public: if (!Walker.preWalk(E)) return true; - if (!super::visit(E->getCalle())) + if (!super::visit_(E->getCallee())) return false; - if (!super::visit(E->getArgs())) + if (!super::visit_(E->getArgs())) return false; return Walker.postWalk(E); } @@ -182,9 +494,9 @@ public: if (!Walker.preWalk(E)) return true; - if (!super::visit(E->getBase())) + if (!super::visit_(E->getBase())) return false; - if (!super::visit(E->getSubscript())) + if (!super::visit_(E->getSubscript())) return false; return Walker.postWalk(E); } @@ -203,7 +515,7 @@ public: if (!Walker.preWalk(S)) return true; - if (S->hasValue() && !super::visit(S->getValue())) + if (S->hasValue() && !super::visit_(S->getValue())) return false; return Walker.postWalk(S); } @@ -213,9 +525,9 @@ public: if (!Walker.preWalk(S)) return false; - if (!super::visit(S->getStart())) + if (!super::visit_(S->getStart())) return false; - if (!super::visit(S->getEnd())) + if (!super::visit_(S->getEnd())) return false; return Walker.postWalk(S); } @@ -225,7 +537,7 @@ public: if (!Walker.preWalk(S)) return true; - if (!super::visit(S->getValue())) + if (!super::visit_(S->getValue())) return false; return Walker.postWalk(S); } @@ -236,7 +548,7 @@ public: return true; for (auto N : S->getNodes()) - if (!super::visit(N)) + if (!super::visit_(N)) return false; return Walker.postWalk(S); } @@ -246,7 +558,7 @@ public: if (!Walker.preWalk(S)) return true; - if (!super::visit(S->getPrototype())) + if (!super::visit_(S->getPrototype())) return false; return Walker.postWalk(S); } @@ -256,9 +568,9 @@ public: if (!Walker.preWalk(S)) return true; - if (!super::visit(S->getPrototype())) + if (!super::visit_(S->getPrototype())) return false; - if (!super::visit(S->getBody())) + if (!super::visit_(S->getBody())) return false; return Walker.postWalk(S); } @@ -268,9 +580,9 @@ public: if (!Walker.preWalk(S)) return false; - if (!super::visit(S->getRange())) + if (!super::visit_(S->getRange())) return false; - if (!super::visit(S->getBody())) + if (!super::visit_(S->getBody())) return false; return Walker.postWalk(S); } @@ -280,11 +592,11 @@ public: if (!Walker.preWalk(S)) return true; - if (!super::visit(S->getCond())) + if (!super::visit_(S->getCond())) return false; - if (!super::visit(S->getThen())) + if (!super::visit_(S->getThen())) return false; - if (S->hasElseBlock() && !super::visit(S->getElse())) + if (S->hasElseBlock() && !super::visit_(S->getElse())) return false; return Walker.postWalk(S); } @@ -294,9 +606,9 @@ public: if (!Walker.preWalk(S)) return true; - if (!super::visit(S->getCond())) + if (!super::visit_(S->getCond())) return false; - if (!super::visit(S->getBody())) + if (!super::visit_(S->getBody())) return false; return Walker.postWalk(S); } @@ -309,7 +621,7 @@ public: return true; for (auto V : P->getValues()) - if (!super::visit(V)) + if (!super::visit_(V)) return false; return Walker.postWalk(P); } @@ -320,7 +632,7 @@ public: return true; for (auto V : P->getVars()) - if (!super::visit(V)) + if (!super::visit_(V)) return false; return Walker.postWalk(P); } @@ -330,6 +642,25 @@ public: // MARK: - Basic ASTNodes implementations -bool ASTNode::walk(ASTWalker &Walker) { - return Traversal(Walker).ASTVisitor::visit(this); +bool Decl::walk(ASTWalker &Walker) { +// return Traversal(Walker).ASTVisitor::visit_(this); + return Traversal(Walker).traverse(this); +} + +bool Expr::walk(ASTWalker &Walker) { + // return Traversal(Walker).ASTVisitor::visit_(this); + return Traversal(Walker).traverse(this) != nullptr; +} + +bool Stmt::walk(ASTWalker &Walker) { + // return Traversal(Walker).ASTVisitor::visit_(this); + return Traversal(Walker).traverse(this); +} + +bool Pattern::walk(ASTWalker &Walker) { + return Traversal(Walker).traverse(this); +} + +bool TypeRepr::walk(ASTWalker &Walker) { + return Traversal(Walker).traverse(this); } diff --git a/lib/IRGen/CMakeLists.txt b/lib/IRGen/CMakeLists.txt index 9d3d15b..0dd1c35 100644 --- a/lib/IRGen/CMakeLists.txt +++ b/lib/IRGen/CMakeLists.txt @@ -15,6 +15,8 @@ set(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/IRGenFunc.h ${CMAKE_CURRENT_SOURCE_DIR}/IRGenModule.cpp ${CMAKE_CURRENT_SOURCE_DIR}/IRGenModule.h + ${CMAKE_CURRENT_SOURCE_DIR}/IRGenValue.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/IRGenValue.h ${CMAKE_CURRENT_SOURCE_DIR}/LoopInfo.cpp ${CMAKE_CURRENT_SOURCE_DIR}/LoopInfo.h ${SOURCE} diff --git a/lib/IRGen/GenExpr.cpp b/lib/IRGen/GenExpr.cpp index 5622cc5..863f23f 100644 --- a/lib/IRGen/GenExpr.cpp +++ b/lib/IRGen/GenExpr.cpp @@ -170,7 +170,7 @@ llvm::Value *irgen::codegenExpr(IRGenModule &IRGM, AssignExpr *E) { llvm::Value *irgen::codegenExpr(IRGenModule &IRGM, CallExpr *E) { // Get callee as identifier. - auto CalleeID = static_cast<IdentifierExpr *>(E->getCalle()); + auto CalleeID = static_cast<IdentifierExpr *>(E->getCallee()); // Get args auto ArgsPttrn = static_cast<ExprPattern *>(E->getArgs()); diff --git a/lib/IRGen/GenFunc.cpp b/lib/IRGen/GenFunc.cpp index fb3ca65..71f4e5e 100644 --- a/lib/IRGen/GenFunc.cpp +++ b/lib/IRGen/GenFunc.cpp @@ -50,7 +50,7 @@ public: bool visit(BlockStmt *S) { for (auto N : S->getNodes()) - if (!super::visit(N)) + if (!super::visit_(N)) return false; return true; } @@ -90,7 +90,7 @@ public: // Emit Then branch IRGF.Builder.SetInsertPoint(ThenBB); IRGF.IRGM.Lookup.push(); - if (!super::visit(S->getThen())) + if (!super::visit_(S->getThen())) return false; IRGF.IRGM.Lookup.pop(); if (IRGF.Builder.GetInsertBlock()->getTerminator() == nullptr) @@ -100,7 +100,7 @@ public: if (S->hasElseBlock()) { IRGF.Builder.SetInsertPoint(ElseBB); IRGF.IRGM.Lookup.push(); - if (!super::visit(S->getElse())) + if (!super::visit_(S->getElse())) return false; IRGF.IRGM.Lookup.pop(); if (IRGF.Builder.GetInsertBlock()->getTerminator() == nullptr) @@ -136,7 +136,7 @@ public: // Emit loop body IRGF.Builder.SetInsertPoint(BodyBlock); - if (!super::visit(S->getBody())) + if (!super::visit_(S->getBody())) return false; // Jump back to the condition if (IRGF.Builder.GetInsertBlock()->getTerminator() == nullptr) @@ -178,7 +178,7 @@ public: // Emit loop body IRGF.Builder.SetInsertPoint(BodyBlock); - if (!super::visit(S->getBody())) + if (!super::visit_(S->getBody())) return false; // Jump back to the condition auto Ty = llvm::Type::getInt64Ty(IRGF.IRGM.LLVMContext); @@ -235,6 +235,6 @@ public: bool irgen::genFunc(IRGenFunc &IRGF, FuncStmt *F) { GenFunc GF(IRGF); - return GF.ASTVisitor::visit(F->getBody()); + return GF.ASTVisitor::visit_(F->getBody()); } diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index b4ce45c..ac179a1 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -35,25 +35,6 @@ IRGenModule::IRGenModule(ASTContext &Ctx, llvm::LLVMContext &LLVMCtx, Address IRGenModule::declareVal(Decl *D) { return codegenDecl(*this, D); -// auto Ty = codegenType(*this, D->getType()); -// if (Lookup.getDepth() == 0) { -// if (!Lookup.declareVar(D)) -// llvm_unreachable("Redefinition of a variable"); -// -// auto GV = new llvm::GlobalVariable(*Module, Ty, false, -// llvm::GlobalValue::InternalLinkage, -// nullptr, D->getName()); -// auto InitVal = codegenInit(*this, D->getType()); -// GV->setInitializer(InitVal); -// -// return GV; -// } else { -// if (!Lookup.declareVar(D)) -// llvm_unreachable("Redefinition of a variable"); -// auto Addr = codegenAlloca(*this, D->getType()); -// Vals[D] = Addr; -// return Addr; -// } } Address IRGenModule::declareFunc(FuncDecl *D) { @@ -78,6 +59,13 @@ Address IRGenModule::getVal(StringRef N) { return Module->getGlobalVariable(N, true); } +LValue IRGenModule::getValue(StringRef ID) { + if (auto Value = std::move(Values[Lookup.getVal(ID)])) + return Value; + auto Addr = Module->getGlobalVariable(ID, true); + return LValue::getVal(nullptr, Addr); +} + llvm::Function *IRGenModule::getFunc(StringRef N) { return Module->getFunction(N); } @@ -86,7 +74,6 @@ llvm::Value *dusk::getRuntimeFunc(llvm::Module *M, StringRef N, ArrayRef<llvm::Type *> ArgsT, llvm::Type *RetT) { auto Proto = llvm::FunctionType::get(RetT, ArgsT, false); - auto Fn = llvm::Function::Create(Proto, llvm::GlobalValue::ExternalLinkage); - return Fn; + return llvm::Function::Create(Proto, llvm::GlobalValue::ExternalLinkage); } diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index a11ec7e..ccb97d2 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -16,6 +16,7 @@ #include "llvm/IR/IRBuilder.h" #include "Address.h" +#include "IRGenValue.h" namespace llvm { class Constant; @@ -43,6 +44,7 @@ public: NameLookup Lookup; llvm::DenseMap<Decl *, Address> Vals; + llvm::DenseMap<Decl *, LValue> Values; IRGenModule(ASTContext &Ctx, llvm::LLVMContext &LLVMCtx, llvm::Module *M, llvm::IRBuilder<> &B); @@ -56,6 +58,9 @@ public: Address getVal(StringRef N); /// Returns declared function. llvm::Function *getFunc(StringRef N); + + /// Return lvalue for given identifier. + LValue getValue(StringRef ID); }; } // namespace irgen diff --git a/lib/IRGen/IRGenValue.cpp b/lib/IRGen/IRGenValue.cpp new file mode 100644 index 0000000..db1f916 --- /dev/null +++ b/lib/IRGen/IRGenValue.cpp @@ -0,0 +1,57 @@ +//===--- IRGenValue.cpp ---------------------------------------------------===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#include "IRGenValue.h" + +#include "dusk/AST/Type.h" +#include "llvm/IR/Value.h" + +using namespace dusk; +using namespace irgen; + +// MARK: - rvalue + +RValue::RValue() : Value(nullptr), Ty(nullptr) {} + +// MARK: - lvalue + +LValue::LValue() + : Kind(LValue::Simple), Value(nullptr), Ty(nullptr), ArrIdx(nullptr) {} + +LValue::LValue(Type *Ty, Address Addr) + : Kind(LValue::Simple), Value(Addr), Ty(Ty), ArrIdx(nullptr) {} + +LValue::LValue(Type *Ty, Address Addr, llvm::Value *Idx) + : Kind(LValue::ArrayElement), Value(Addr), Ty(Ty), ArrIdx(Idx) {} + +LValue::LValue(LValue &&Other) + : Kind(Other.Kind), Value(Other.Value), Ty(Other.Ty), ArrIdx(Other.ArrIdx) { + assert(isValid() && "Copy of invalid l-value"); +} + +LValue &LValue::operator=(LValue &&Other) { + assert(!isValid() && "Overriding valid value"); + Kind = Other.Kind; + Value = Other.Value; + Ty = Other.Ty; + ArrIdx = Other.ArrIdx; + return *this; +} + +LValue LValue::getVal(Type *Ty, Address Val) { + LValue Ret(Ty, Val); + Ret.Kind = LValue::Simple; + return Ret; +} + +LValue LValue::getArrayElem(Type *Ty, Address Val, llvm::Value *Idx) { + LValue Ret(Ty, Val, Idx); + return Ret; +} + diff --git a/lib/IRGen/IRGenValue.h b/lib/IRGen/IRGenValue.h new file mode 100644 index 0000000..1ea1543 --- /dev/null +++ b/lib/IRGen/IRGenValue.h @@ -0,0 +1,128 @@ +//===--- IRGenValue.h - Value representation --------------------*- C++ -*-===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#ifndef DUSK_IRGEN_IRGEN_VALUE_H +#define DUSK_IRGEN_IRGEN_VALUE_H + +#include "Address.h" + +namespace llvm { +class Value; +} // namespace llvm + +namespace dusk { +class Type; + +namespace irgen { + +/// Represents a single rvalue reference. +class RValue { + llvm::Value *Value; + + Type *Ty; + +public: + RValue(); + + static RValue get(Type *Ty, llvm::Value *V); + +private: + RValue(const RValue &) = delete; + RValue &operator=(const RValue &) = delete; +}; + + +/// Represents a single lvalue refenrece. +class LValue { + enum KindType { Simple, ArrayElement }; + + KindType Kind; + + /// Encapsulated raw value address. + llvm::Value *Value; + + /// Type of value. + Type *Ty; + + /// Index of referenced element in array. + llvm::Value *ArrIdx; + +public: + /// Creates an empty invalid lvalue. + LValue(); + /// Creates a siple lvalue + LValue(Type *Ty, Address Addr); + /// Creates a array access lvalue. + LValue(Type *Ty, Address Addr, llvm::Value *Idx); + /// Moving constructor for copying of lvalues. + LValue(LValue &&); + LValue &operator=(LValue &&); + + operator bool() const { return isValid(); } + + /// Return \c true if type and value are set, \c false otherwise. + bool isValid() const { return Ty != nullptr && Value != nullptr; } + + bool isSimple() const { return Kind == Simple; } + bool isArrayElement() const { return Kind == ArrayElement; } + + /// Sets raw address of referenced value. + void setAddress(Address Addr) { Value = Addr; } + + /// Returns raw address of referenced value. + Address getAddress() const { return Value; } + + /// Sets type of referenced value. + void setType(Type *T) { Ty = T; } + + /// Returns raw address of referenced value. + Type *getType() const { return Ty; } + + /// Returns pointer to the referenced value. + /// + /// \note Referenced value must be a simple value. + llvm::Value *getPointer() const { + assert(isSimple() && "Invalid address access."); + return Value; + } + + /// Returns pointer to the start of the array, which contains referenced + /// element. + /// + /// \note Referened value must be an array element. + llvm::Value *getArrayPtr() const { + assert(isArrayElement() && "Invalid address access."); + return Value; + } + + /// Return index of referenced value as value. + /// + /// \note Referened value must be an array element. + llvm::Value *getElementIndex() const { + assert(isArrayElement() && "Invalid address access."); + return Value; + } + + // MARK: - static construction methods + + /// Creates and returns a simple lvalue. + static LValue getVal(Type *Ty, Address Val); + + /// Creates and returns an array element lvalue. + static LValue getArrayElem(Type *Ty, Address Val, llvm::Value *Idx); + +private: + LValue(const LValue &) = delete; + LValue &operator=(const LValue &) = delete; +}; + +} // namespace irgen +} // namespace dusk + +#endif /* DUSK_IRGEN_IRGEN_VALUE_H */ diff --git a/lib/Sema/TypeCheckExpr.cpp b/lib/Sema/TypeCheckExpr.cpp index 7b32cc9..7f5f8f8 100644 --- a/lib/Sema/TypeCheckExpr.cpp +++ b/lib/Sema/TypeCheckExpr.cpp @@ -85,11 +85,11 @@ bool TypeChecker::postWalkPrefixExpr(PrefixExpr *E) { } bool TypeChecker::postWalkCallExpr(CallExpr *E) { - auto FTy = dynamic_cast<FunctionType *>(E->getCalle()->getType()); + auto FTy = dynamic_cast<FunctionType *>(E->getCallee()->getType()); // Check if references a function if (!FTy) { - diagnose(E->getCalle()->getLocStart(), diag::func_call_non_func_type); + diagnose(E->getCallee()->getLocStart(), diag::func_call_non_func_type); return false; } -- GitLab