diff --git a/docs/imgs/ast.svg b/docs/imgs/ast.svg new file mode 100644 index 0000000..4a8a742 --- /dev/null +++ b/docs/imgs/ast.svg @@ -0,0 +1,439 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + List + + + + List + + + + Symbol + def + + + + Symbol + main + + + + Symbol + fn + + + + Number + 4 + + + Symbol + prn + + + Symbol + main + + + + List + + + + List + + + + List + + + + + + + + + + + + + diff --git a/docs/videos.org b/docs/videos.org index a8d108e..e002655 100644 --- a/docs/videos.org +++ b/docs/videos.org @@ -84,7 +84,8 @@ Deducted from https://www.aosabook.org/en/llvm.html - Finally we fully lower =lir= to =LLVM IR= and pass it to the object generator to generate object files. - Call the default =c compiler= to link the object files and generate the machine code. -* Episode 4 - The reader +* DONE Episode 4 - The reader +CLOSED: [2021-07-27 Tue 22:50] ** What is a Parser ? To put it simply, Parser converts the source code to an [[https://en.wikipedia.org/wiki/Abstract_syntax_tree][AST]] *** Algorithms @@ -110,3 +111,21 @@ Read More: #+END_SRC - LL(1.5)? - O(n) +* Episode 5 - The Abstract Syntax Tree +** What is an AST? +Ast is a tree representation of the abstract syntactic structure of source code. It's just a tree made of nodes that each node is +a data structure describing the syntax. + +#+BEGIN_SRC lisp + ;; pseudo code + (def main (fn () 4)) + (prn (main)) +#+END_SRC + + +[[./imgs/ast.svg]] +** The =Expression= abstract class +*** Expressions +- Expressions vs Statements +- Serene(Lisp) and expressions +** Node & AST diff --git a/include/serene/exprs/expression.h b/include/serene/exprs/expression.h index 9817653..1da3e19 100644 --- a/include/serene/exprs/expression.h +++ b/include/serene/exprs/expression.h @@ -44,7 +44,7 @@ class Expression; using Node = std::shared_ptr; using ErrorPtr = std::shared_ptr; -// tree? Yupe, Errors can be stackable which makes +// tree? Yupe, Errors can be stackable which makes a vector of them a tree using ErrorTree = std::vector; using MaybeNode = Result; @@ -53,6 +53,7 @@ using Ast = std::vector; using MaybeAst = Result; static auto EmptyNode = MaybeNode::success(nullptr); + /// The base class of the expressions which provides the common interface for /// the expressions to implement. class Expression { @@ -80,6 +81,10 @@ public: /// \param ctx is the context object of the semantic analyzer. virtual MaybeNode analyze(SereneContext &ctx) = 0; + /// Genenates the correspondig SLIR of the expressoin and attach it to the + /// module of the given namespace. + /// + /// \param ns The namespace that current expression is in it. virtual void generateIR(serene::Namespace &ns) = 0; }; @@ -97,7 +102,6 @@ template Node make(Args &&...args) { return std::make_shared(std::forward(args)...); }; - /// Create a new `node` of type `T` and forwards any given parameter /// to the constructor of type `T`. This is the **official way** to create /// a new `Expression`. Here is an example: diff --git a/include/serene/exprs/list.h b/include/serene/exprs/list.h index bc4a6e6..de90514 100644 --- a/include/serene/exprs/list.h +++ b/include/serene/exprs/list.h @@ -28,8 +28,7 @@ #include "serene/context.h" #include "serene/exprs/expression.h" -#include "llvm/ADT/Optional.h" - +#include #include namespace serene { @@ -59,21 +58,31 @@ public: size_t count() const; Ast from(uint begin); - // llvm::MutableArrayRef from(uint begin); llvm::Optional at(uint index); + /// Return an iterator to be used with the `for` loop. It's implicitly called + /// by the for loop. std::vector::const_iterator cbegin(); + + /// Return an iterator to be used with the `for` loop. It's implicitly called + /// by the for loop. std::vector::const_iterator cend(); + + /// Return an iterator to be used with the `for` loop. It's implicitly called + /// by the for loop. std::vector::iterator begin(); + + /// Return an iterator to be used with the `for` loop. It's implicitly called + /// by the for loop. std::vector::iterator end(); MaybeNode analyze(SereneContext &); void generateIR(serene::Namespace &){}; - static bool classof(const Expression *e); - ~List() = default; + + static bool classof(const Expression *e); }; } // namespace exprs diff --git a/include/serene/exprs/number.h b/include/serene/exprs/number.h index bb9af82..bc6fb91 100644 --- a/include/serene/exprs/number.h +++ b/include/serene/exprs/number.h @@ -29,10 +29,9 @@ #include "serene/exprs/expression.h" #include "serene/namespace.h" -#include "llvm/Support/FormatVariadic.h" +#include namespace serene { - namespace exprs { /// This data structure represent a number. I handles float points, integers, @@ -40,7 +39,8 @@ namespace exprs { /// So it won't cast to actual numeric types and it has a string container /// to hold the parsed value. struct Number : public Expression { - // TODO: Use a variant here instead + + // TODO: Use a variant here instead to store different number types std::string value; bool isNeg; @@ -52,15 +52,16 @@ struct Number : public Expression { ExprType getType() const; std::string toString() const; - MaybeNode analyze(SereneContext &ctx); - static bool classof(const Expression *e); + MaybeNode analyze(SereneContext &ctx); + void generateIR(serene::Namespace &); // TODO: This is horrible, we need to fix it after the mvp int toI64(); - void generateIR(serene::Namespace &); ~Number() = default; + + static bool classof(const Expression *e); }; } // namespace exprs diff --git a/include/serene/exprs/symbol.h b/include/serene/exprs/symbol.h index 18f7594..372556f 100644 --- a/include/serene/exprs/symbol.h +++ b/include/serene/exprs/symbol.h @@ -28,8 +28,7 @@ #include "serene/context.h" #include "serene/exprs/expression.h" -#include "llvm/ADT/StringRef.h" - +#include #include namespace serene { @@ -51,12 +50,12 @@ public: ExprType getType() const; std::string toString() const; - static bool classof(const Expression *e); - MaybeNode analyze(SereneContext &); void generateIR(serene::Namespace &){}; ~Symbol() = default; + + static bool classof(const Expression *e); }; } // namespace exprs diff --git a/src/serene/exprs/list.cpp b/src/serene/exprs/list.cpp index 1026c15..c2e953b 100644 --- a/src/serene/exprs/list.cpp +++ b/src/serene/exprs/list.cpp @@ -31,11 +31,10 @@ #include "serene/exprs/fn.h" #include "serene/exprs/symbol.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormatVariadic.h" - #include +#include +#include +#include namespace serene { namespace exprs { @@ -91,20 +90,12 @@ bool List::classof(const Expression *e) { return e->getType() == ExprType::List; }; -/// Return an iterator to be used with the `for` loop. It's implicitly called by -/// the for loop. std::vector::const_iterator List::cbegin() { return elements.begin(); } -/// Return an iterator to be used with the `for` loop. It's implicitly called by -/// the for loop. std::vector::const_iterator List::cend() { return elements.end(); } -/// Return an iterator to be used with the `for` loop. It's implicitly called by -/// the for loop. std::vector::iterator List::begin() { return elements.begin(); } -/// Return an iterator to be used with the `for` loop. It's implicitly called by -/// the for loop. std::vector::iterator List::end() { return elements.end(); } size_t List::count() const { return elements.size(); } @@ -118,7 +109,6 @@ llvm::Optional List::at(uint index) { } Ast List::from(uint index) { - if (index < elements.size()) { return Ast(elements.begin() + index, elements.end()); } diff --git a/src/serene/exprs/symbol.cpp b/src/serene/exprs/symbol.cpp index 4f2b393..d0d7f39 100644 --- a/src/serene/exprs/symbol.cpp +++ b/src/serene/exprs/symbol.cpp @@ -24,7 +24,9 @@ #include "serene/exprs/symbol.h" -#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/Casting.h" + +#include namespace serene { namespace exprs {