diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
| commit | 967be9e750221ab2ab783f95df79bb26d290a45e (patch) | |
| tree | 6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/src/ast | |
Diffstat (limited to 'tiger-compiler/src/ast')
151 files changed, 6826 insertions, 0 deletions
diff --git a/tiger-compiler/src/ast/README.txt b/tiger-compiler/src/ast/README.txt new file mode 100644 index 0000000..4291b24 --- /dev/null +++ b/tiger-compiler/src/ast/README.txt @@ -0,0 +1,66 @@ +* README + +Tiger Abstract Syntax Tree nodes with their principal members. +Incomplete classes are tagged with a `*'. + +/Ast/ (Location location) + /Dec/ (symbol name) + FunctionDec (VarChunk formals, NameTy result, Exp body) + MethodDec () + TypeDec (Ty ty) + VarDec (NameTy type_name, Exp init) + + /Exp/ () + /Var/ () + FieldVar (Var var, symbol name) + SimpleVar (symbol name) + SubscriptVar (Var var, Exp index) + + ArrayExp (NameTy type_name, Exp size, Exp init) + AssertExp (Exp exp) + AssignExp (Var var, Exp exp) + BreakExp () + CallExp (symbol name, exps_type args) + MethodCallExp (Var object) + CastExp (Exp exp, Ty ty) + ForExp (VarDec vardec, Exp hi, Exp body) + IfExp (Exp test, Exp thenclause, Exp elseclause) + IntExp (int value) + LetExp (ChunkList chunks, Exp body) + NilExp () + ObjectExp (NameTy type_name) + OpExp (Exp left, Oper oper, Exp right) + RecordExp (NameTy type_name, fieldinits_type fields) + SeqExp (exps_type exps) + StringExp (string value) + WhileExp (Exp test, Exp body) + + /Ty/ () + ArrayTy (NameTy base_type) + ClassTy (NameTy super, ChunkList chunks) + NameTy (symbol name) + RecordTy (fields_type fields) + + ChunkList (list_type chunks) + + Field (symbol name, NameTy type_name) + + FieldInit (symbol name, Exp init) + + +Some of these classes also inherit from other classes. + +/Escapable/ + VarDec (NameTy type_name, Exp init) + +/Typable/ + /Dec/ (symbol name) + /Exp/ () + /Ty/ () + +/TypeConstructor/ + /Ty/ () + FunctionDec (VarChunk formals, NameTy result, Exp body) + NilExp () + TypeDec (Ty ty) + diff --git a/tiger-compiler/src/ast/all.hh b/tiger-compiler/src/ast/all.hh new file mode 100644 index 0000000..c55c3eb --- /dev/null +++ b/tiger-compiler/src/ast/all.hh @@ -0,0 +1,51 @@ +/** + ** \file ast/all.hh + ** \brief Include all the exported headers. + */ + +#pragma once + +#include <ast/fwd.hh> + +#include <ast/chunk.hh> + +#include <ast/array-exp.hh> +#include <ast/array-ty.hh> +#include <ast/assert-exp.hh> +#include <ast/assign-exp.hh> +#include <ast/ast.hh> +#include <ast/break-exp.hh> +#include <ast/call-exp.hh> +#include <ast/cast-exp.hh> +#include <ast/chunk-list.hh> +#include <ast/class-ty.hh> +#include <ast/dec.hh> +#include <ast/escapable.hh> +#include <ast/exp.hh> +#include <ast/field-init.hh> +#include <ast/field-var.hh> +#include <ast/field.hh> +#include <ast/for-exp.hh> +#include <ast/function-dec.hh> +#include <ast/if-exp.hh> +#include <ast/int-exp.hh> +#include <ast/let-exp.hh> +#include <ast/method-call-exp.hh> +#include <ast/method-dec.hh> +#include <ast/name-ty.hh> +#include <ast/nil-exp.hh> +#include <ast/object-exp.hh> +#include <ast/op-exp.hh> +#include <ast/record-exp.hh> +#include <ast/record-ty.hh> +#include <ast/seq-exp.hh> +#include <ast/simple-var.hh> +#include <ast/string-exp.hh> +#include <ast/subscript-var.hh> +#include <ast/ty.hh> +#include <ast/typable.hh> +#include <ast/type-constructor.hh> +#include <ast/type-dec.hh> +#include <ast/var-dec.hh> +#include <ast/var.hh> +#include <ast/while-exp.hh> diff --git a/tiger-compiler/src/ast/array-exp.cc b/tiger-compiler/src/ast/array-exp.cc new file mode 100644 index 0000000..8c0f241 --- /dev/null +++ b/tiger-compiler/src/ast/array-exp.cc @@ -0,0 +1,31 @@ +/** + ** \file ast/array-exp.cc + ** \brief Implementation of ast::ArrayExp. + */ + +#include <ast/array-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + ArrayExp::ArrayExp(const Location& location, + NameTy* type_name, + Exp* size, + Exp* init) + : Exp(location) + , type_name_(type_name) + , size_(size) + , init_(init) + {} + + ArrayExp::~ArrayExp() + { + delete type_name_; + delete size_; + delete init_; + } + + void ArrayExp::accept(ConstVisitor& v) const { v(*this); } + + void ArrayExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/array-exp.hh b/tiger-compiler/src/ast/array-exp.hh new file mode 100644 index 0000000..ceab385 --- /dev/null +++ b/tiger-compiler/src/ast/array-exp.hh @@ -0,0 +1,60 @@ +/** + ** \file ast/array-exp.hh + ** \brief Declaration of ast::ArrayExp. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/name-ty.hh> + +namespace ast +{ + /// ArrayExp. + class ArrayExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct an ArrayExp node. + ArrayExp(const Location& location, NameTy* type_name, Exp* size, Exp* init); + ArrayExp(const ArrayExp&) = delete; + ArrayExp& operator=(const ArrayExp&) = delete; + /// Destroy an ArrayExp node. + ~ArrayExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return identifier of the stored elements type. + const NameTy& type_name_get() const; + /// Return identifier of the stored elements type. + NameTy& type_name_get(); + /// Return size of the array. + const Exp& size_get() const; + /// Return size of the array. + Exp& size_get(); + /// Return initial value assigned to all elements of the array. + const Exp& init_get() const; + /// Return initial value assigned to all elements of the array. + Exp& init_get(); + /** \} */ + + protected: + /// Identifier of the stored elements type. + NameTy* type_name_; + /// Size of the array. + Exp* size_; + /// Initial value assigned to all elements of the array. + Exp* init_; + }; +} // namespace ast +#include <ast/array-exp.hxx> diff --git a/tiger-compiler/src/ast/array-exp.hxx b/tiger-compiler/src/ast/array-exp.hxx new file mode 100644 index 0000000..cab3e8b --- /dev/null +++ b/tiger-compiler/src/ast/array-exp.hxx @@ -0,0 +1,22 @@ +/** + ** \file ast/array-exp.hxx + ** \brief Inline methods of ast::ArrayExp. + */ + +#pragma once + +#include <ast/array-exp.hh> + +namespace ast +{ + + inline const NameTy& ArrayExp::type_name_get() const { return *type_name_; } + inline NameTy& ArrayExp::type_name_get() { return *type_name_; } + + inline const Exp& ArrayExp::size_get() const { return *size_; } + inline Exp& ArrayExp::size_get() { return *size_; } + + inline const Exp& ArrayExp::init_get() const { return *init_; } + inline Exp& ArrayExp::init_get() { return *init_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/array-ty.cc b/tiger-compiler/src/ast/array-ty.cc new file mode 100644 index 0000000..d7af8b4 --- /dev/null +++ b/tiger-compiler/src/ast/array-ty.cc @@ -0,0 +1,21 @@ +/** + ** \file ast/array-ty.cc + ** \brief Implementation of ast::ArrayTy. + */ + +#include <ast/array-ty.hh> +#include <ast/visitor.hh> + +namespace ast +{ + ArrayTy::ArrayTy(const Location& location, NameTy* base_type) + : Ty(location) + , base_type_(base_type) + {} + + ArrayTy::~ArrayTy() { delete base_type_; } + + void ArrayTy::accept(ConstVisitor& v) const { v(*this); } + + void ArrayTy::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/array-ty.hh b/tiger-compiler/src/ast/array-ty.hh new file mode 100644 index 0000000..73bb956 --- /dev/null +++ b/tiger-compiler/src/ast/array-ty.hh @@ -0,0 +1,48 @@ +/** + ** \file ast/array-ty.hh + ** \brief Declaration of ast::ArrayTy. + */ + +#pragma once + +#include <ast/name-ty.hh> +#include <ast/ty.hh> + +namespace ast +{ + /// ArrayTy. + class ArrayTy : public Ty + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct an ArrayTy node. + ArrayTy(const Location& location, NameTy* base_type); + ArrayTy(const ArrayTy&) = delete; + ArrayTy& operator=(const ArrayTy&) = delete; + /// Destroy an ArrayTy node. + ~ArrayTy() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return name of the base type. + const NameTy& base_type_get() const; + /// Return name of the base type. + NameTy& base_type_get(); + /** \} */ + + protected: + /// Name of the base type. + NameTy* base_type_; + }; +} // namespace ast +#include <ast/array-ty.hxx> diff --git a/tiger-compiler/src/ast/array-ty.hxx b/tiger-compiler/src/ast/array-ty.hxx new file mode 100644 index 0000000..c679b1c --- /dev/null +++ b/tiger-compiler/src/ast/array-ty.hxx @@ -0,0 +1,16 @@ +/** + ** \file ast/array-ty.hxx + ** \brief Inline methods of ast::ArrayTy. + */ + +#pragma once + +#include <ast/array-ty.hh> + +namespace ast +{ + + inline const NameTy& ArrayTy::base_type_get() const { return *base_type_; } + inline NameTy& ArrayTy::base_type_get() { return *base_type_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/assert-exp.cc b/tiger-compiler/src/ast/assert-exp.cc new file mode 100644 index 0000000..251f776 --- /dev/null +++ b/tiger-compiler/src/ast/assert-exp.cc @@ -0,0 +1,24 @@ +/** + ** \file ast/assert-exp.cc + ** \brief Implementation of ast::AssertExp. + */ + +#include <ast/assert-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + AssertExp::AssertExp(const Location& location, Exp* condition) + : Exp(location) + , cond_{condition} + {} + + AssertExp::~AssertExp() + { + delete cond_; + } + + void AssertExp::accept(ConstVisitor& v) const { v(*this); } + + void AssertExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/assert-exp.hh b/tiger-compiler/src/ast/assert-exp.hh new file mode 100644 index 0000000..6650ca4 --- /dev/null +++ b/tiger-compiler/src/ast/assert-exp.hh @@ -0,0 +1,42 @@ +/** + ** \file ast/assert-exp.hh + ** \brief Declaration of ast::AssertExp. + */ + +#pragma once + +#include <ast/exp.hh> + +namespace ast +{ + // AssertExp + class AssertExp : public Exp + { + public: + /// Construct an AssertExp node. + AssertExp(const Location& location, Exp* cond); + AssertExp(const AssertExp&) = delete; + AssertExp& operator=(const AssertExp&) = delete; + + /// Destroy an AssertExp node. + ~AssertExp() override; + + + // Here are the visitor methods + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + + // Some basic getters + // Return the asserted condition in const form + const Exp& cond_get() const; + // Return the asserted condition + Exp& cond_get(); + + protected: + // The condition that the assertion will evaluate + Exp* cond_; + }; +} // namespace ast +#include <ast/assert-exp.hxx> diff --git a/tiger-compiler/src/ast/assert-exp.hxx b/tiger-compiler/src/ast/assert-exp.hxx new file mode 100644 index 0000000..d5f8af8 --- /dev/null +++ b/tiger-compiler/src/ast/assert-exp.hxx @@ -0,0 +1,14 @@ +/** + ** \file ast/assert-exp.hxx + ** \brief Inline methods of ast::AssertExp. + */ + +#pragma once + +#include <ast/assert-exp.hh> + +namespace ast +{ + inline const Exp& AssertExp::cond_get() const { return *cond_; } + inline Exp& AssertExp::cond_get() { return *cond_; } +} // namespace ast diff --git a/tiger-compiler/src/ast/assert-visitor.hh b/tiger-compiler/src/ast/assert-visitor.hh new file mode 100644 index 0000000..0488c1c --- /dev/null +++ b/tiger-compiler/src/ast/assert-visitor.hh @@ -0,0 +1,51 @@ +/** + ** \file ast/object-visitor.hh + ** \brief Provide default visits for assertion nodes. + */ + +#pragma once + +#include <ast/visitor.hh> + +namespace ast +{ + template <template <typename> class Const> + class GenAssertVisitor : virtual public GenVisitor<Const> + { + public: + /// Super class type. + using super_type = GenVisitor<Const>; + + // Import overloaded virtual functions. + using super_type::operator(); + + /// Convenient abbreviation. + template <typename Type> using const_t = typename Const<Type>::type; + + /** \name Ctor & dtor. + ** \{ */ + /// Construct an object visitor. + GenAssertVisitor(); + /// Destroy an object visitor. + virtual ~GenAssertVisitor(); + /** \} */ + + /// \name Object-related visits. + /// \{ + void operator()(const_t<AssertExp>& e) override; + /// \} + }; + + /// Shorthand for a const visitor. + using AssertConstVisitor = GenAssertVisitor<misc::constify_traits>; + /// Shorthand for a non const visitor. + using AssertVisitor = GenAssertVisitor<misc::id_traits>; + +#ifdef SWIG + %template(AssertConstVisitor) GenAssertVisitor<misc::constify_traits>; + %template(AssertVisitor) GenAssertVisitor<misc::id_traits>; +#endif + +} // namespace ast + +#include <ast/assert-visitor.hxx> diff --git a/tiger-compiler/src/ast/assert-visitor.hxx b/tiger-compiler/src/ast/assert-visitor.hxx new file mode 100644 index 0000000..c55bb43 --- /dev/null +++ b/tiger-compiler/src/ast/assert-visitor.hxx @@ -0,0 +1,32 @@ +/** + ** \file ast/assert-visitor.hxx + ** \brief Implementation for ast/assert-visitor.hh. + */ + +#pragma once + +#include <ast/assert-exp.hh> +#include <ast/assert-visitor.hh> + +namespace ast +{ + template <template <typename> class Const> + GenAssertVisitor<Const>::GenAssertVisitor() + : GenVisitor<Const>() + {} + + template <template <typename> class Const> + GenAssertVisitor<Const>::~GenAssertVisitor() + {} + + /*-------------------------------. + | Assert-related visit method. | + `-------------------------------*/ + + template <template <typename> class Const> + void GenAssertVisitor<Const>::operator()(const_t<AssertExp>& e) + { + e.cond_get().accept(*this); + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/assign-exp.cc b/tiger-compiler/src/ast/assign-exp.cc new file mode 100644 index 0000000..d61b5c2 --- /dev/null +++ b/tiger-compiler/src/ast/assign-exp.cc @@ -0,0 +1,26 @@ +/** + ** \file ast/assign-exp.cc + ** \brief Implementation of ast::AssignExp. + */ + +#include <ast/assign-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + AssignExp::AssignExp(const Location& location, Var* var, Exp* exp) + : Exp(location) + , var_(var) + , exp_(exp) + {} + + AssignExp::~AssignExp() + { + delete var_; + delete exp_; + } + + void AssignExp::accept(ConstVisitor& v) const { v(*this); } + + void AssignExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/assign-exp.hh b/tiger-compiler/src/ast/assign-exp.hh new file mode 100644 index 0000000..ca575ec --- /dev/null +++ b/tiger-compiler/src/ast/assign-exp.hh @@ -0,0 +1,54 @@ +/** + ** \file ast/assign-exp.hh + ** \brief Declaration of ast::AssignExp. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/var.hh> + +namespace ast +{ + /// AssignExp. + class AssignExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct an AssignExp node. + AssignExp(const Location& location, Var* var, Exp* exp); + AssignExp(const AssignExp&) = delete; + AssignExp& operator=(const AssignExp&) = delete; + /// Destroy an AssignExp node. + ~AssignExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return reference to the affected variable. + const Var& var_get() const; + /// Return reference to the affected variable. + Var& var_get(); + /// Return assigned value. + const Exp& exp_get() const; + /// Return assigned value. + Exp& exp_get(); + /** \} */ + + protected: + /// Reference to the affected variable. + Var* var_; + /// Assigned value. + Exp* exp_; + }; +} // namespace ast +#include <ast/assign-exp.hxx> diff --git a/tiger-compiler/src/ast/assign-exp.hxx b/tiger-compiler/src/ast/assign-exp.hxx new file mode 100644 index 0000000..afd96ff --- /dev/null +++ b/tiger-compiler/src/ast/assign-exp.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/assign-exp.hxx + ** \brief Inline methods of ast::AssignExp. + */ + +#pragma once + +#include <ast/assign-exp.hh> + +namespace ast +{ + + inline const Var& AssignExp::var_get() const { return *var_; } + inline Var& AssignExp::var_get() { return *var_; } + + inline const Exp& AssignExp::exp_get() const { return *exp_; } + inline Exp& AssignExp::exp_get() { return *exp_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/ast-nodes.mk b/tiger-compiler/src/ast/ast-nodes.mk new file mode 100644 index 0000000..ab35724 --- /dev/null +++ b/tiger-compiler/src/ast/ast-nodes.mk @@ -0,0 +1,41 @@ +AST_NODES = \ + src/ast/array-exp.hh src/ast/array-exp.hxx src/ast/array-exp.cc \ + src/ast/array-ty.hh src/ast/array-ty.hxx src/ast/array-ty.cc \ + src/ast/assert-exp.hh src/ast/assert-exp.hxx src/ast/assert-exp.cc \ + src/ast/assign-exp.hh src/ast/assign-exp.hxx src/ast/assign-exp.cc \ + src/ast/ast.hh src/ast/ast.hxx src/ast/ast.cc \ + src/ast/break-exp.hh src/ast/break-exp.hxx src/ast/break-exp.cc \ + src/ast/call-exp.hh src/ast/call-exp.hxx src/ast/call-exp.cc \ + src/ast/cast-exp.hh src/ast/cast-exp.hxx src/ast/cast-exp.cc \ + src/ast/chunk-list.hh src/ast/chunk-list.hxx src/ast/chunk-list.cc \ + src/ast/class-ty.hh src/ast/class-ty.hxx src/ast/class-ty.cc \ + src/ast/dec.hh src/ast/dec.hxx src/ast/dec.cc \ + src/ast/escapable.hh src/ast/escapable.hxx src/ast/escapable.cc \ + src/ast/exp.hh src/ast/exp.hxx src/ast/exp.cc \ + src/ast/field.hh src/ast/field.hxx src/ast/field.cc \ + src/ast/field-init.hh src/ast/field-init.hxx src/ast/field-init.cc \ + src/ast/field-var.hh src/ast/field-var.hxx src/ast/field-var.cc \ + src/ast/for-exp.hh src/ast/for-exp.hxx src/ast/for-exp.cc \ + src/ast/function-dec.hh src/ast/function-dec.hxx src/ast/function-dec.cc \ + src/ast/if-exp.hh src/ast/if-exp.hxx src/ast/if-exp.cc \ + src/ast/int-exp.hh src/ast/int-exp.hxx src/ast/int-exp.cc \ + src/ast/let-exp.hh src/ast/let-exp.hxx src/ast/let-exp.cc \ + src/ast/method-call-exp.hh src/ast/method-call-exp.hxx src/ast/method-call-exp.cc \ + src/ast/method-dec.hh src/ast/method-dec.hxx src/ast/method-dec.cc \ + src/ast/name-ty.hh src/ast/name-ty.hxx src/ast/name-ty.cc \ + src/ast/nil-exp.hh src/ast/nil-exp.hxx src/ast/nil-exp.cc \ + src/ast/object-exp.hh src/ast/object-exp.hxx src/ast/object-exp.cc \ + src/ast/op-exp.hh src/ast/op-exp.hxx src/ast/op-exp.cc \ + src/ast/record-exp.hh src/ast/record-exp.hxx src/ast/record-exp.cc \ + src/ast/record-ty.hh src/ast/record-ty.hxx src/ast/record-ty.cc \ + src/ast/seq-exp.hh src/ast/seq-exp.hxx src/ast/seq-exp.cc \ + src/ast/simple-var.hh src/ast/simple-var.hxx src/ast/simple-var.cc \ + src/ast/string-exp.hh src/ast/string-exp.hxx src/ast/string-exp.cc \ + src/ast/subscript-var.hh src/ast/subscript-var.hxx src/ast/subscript-var.cc \ + src/ast/ty.hh src/ast/ty.hxx src/ast/ty.cc \ + src/ast/typable.hh src/ast/typable.hxx src/ast/typable.cc \ + src/ast/type-constructor.hh src/ast/type-constructor.hxx src/ast/type-constructor.cc \ + src/ast/type-dec.hh src/ast/type-dec.hxx src/ast/type-dec.cc \ + src/ast/var.hh src/ast/var.hxx src/ast/var.cc \ + src/ast/var-dec.hh src/ast/var-dec.hxx src/ast/var-dec.cc \ + src/ast/while-exp.hh src/ast/while-exp.hxx src/ast/while-exp.cc diff --git a/tiger-compiler/src/ast/ast.cc b/tiger-compiler/src/ast/ast.cc new file mode 100644 index 0000000..136262f --- /dev/null +++ b/tiger-compiler/src/ast/ast.cc @@ -0,0 +1,15 @@ +/** + ** \file ast/ast.cc + ** \brief Implementation of ast::Ast. + */ + +#include <ast/ast.hh> +#include <ast/visitor.hh> + +namespace ast +{ + Ast::Ast(const Location& location) + : location_(location) + {} + +} // namespace ast diff --git a/tiger-compiler/src/ast/ast.hh b/tiger-compiler/src/ast/ast.hh new file mode 100644 index 0000000..1c3037c --- /dev/null +++ b/tiger-compiler/src/ast/ast.hh @@ -0,0 +1,48 @@ +/** + ** \file ast/ast.hh + ** \brief Declaration of ast::Ast. + */ + +#pragma once + +#include <ast/fwd.hh> +#include <ast/location.hh> + +namespace ast +{ + /// Ast. + class Ast + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct an Ast node. + explicit Ast(const Location& location); + Ast(const Ast&) = delete; + Ast& operator=(const Ast&) = delete; + /// Destroy an Ast node. + virtual ~Ast() = default; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + virtual void accept(ConstVisitor& v) const = 0; + /// Accept a non-const visitor \a v. + virtual void accept(Visitor& v) = 0; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return scanner position information. + const Location& location_get() const; + /// Set scanner position information. + void location_set(const Location&); + /** \} */ + + protected: + /// Scanner position information. + Location location_; + }; +} // namespace ast +#include <ast/ast.hxx> diff --git a/tiger-compiler/src/ast/ast.hxx b/tiger-compiler/src/ast/ast.hxx new file mode 100644 index 0000000..963aaba --- /dev/null +++ b/tiger-compiler/src/ast/ast.hxx @@ -0,0 +1,18 @@ +/** + ** \file ast/ast.hxx + ** \brief Inline methods of ast::Ast. + */ + +#pragma once + +#include <ast/ast.hh> + +namespace ast +{ + inline const Location& Ast::location_get() const { return location_; } + inline void Ast::location_set(const Location& location) + { + location_ = location; + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/break-exp.cc b/tiger-compiler/src/ast/break-exp.cc new file mode 100644 index 0000000..3c76946 --- /dev/null +++ b/tiger-compiler/src/ast/break-exp.cc @@ -0,0 +1,18 @@ +/** + ** \file ast/break-exp.cc + ** \brief Implementation of ast::BreakExp. + */ + +#include <ast/break-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + BreakExp::BreakExp(const Location& location) + : Exp(location) + {} + + void BreakExp::accept(ConstVisitor& v) const { v(*this); } + + void BreakExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/break-exp.hh b/tiger-compiler/src/ast/break-exp.hh new file mode 100644 index 0000000..25d89e8 --- /dev/null +++ b/tiger-compiler/src/ast/break-exp.hh @@ -0,0 +1,49 @@ +/** + ** \file ast/break-exp.hh + ** \brief Declaration of ast::BreakExp. + */ + +#pragma once + +#include <ast/exp.hh> + +namespace ast +{ + /// BreakExp. + class BreakExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a BreakExp node. + explicit BreakExp(const Location& location); + BreakExp(const BreakExp&) = delete; + BreakExp& operator=(const BreakExp&) = delete; + /// Destroy a BreakExp node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + // FIXME DONE: Some code was deleted here. + /// Return definition site. + const Exp* def_get() const; + Exp* def_get(); + // FIXME DONE: Some code was deleted here. + /// Set definition site. + void def_set(Exp*); + /** \} */ + + protected: + /// The loop it breaks. + Exp* def_ = nullptr; + }; +} // namespace ast +#include <ast/break-exp.hxx> diff --git a/tiger-compiler/src/ast/break-exp.hxx b/tiger-compiler/src/ast/break-exp.hxx new file mode 100644 index 0000000..604f754 --- /dev/null +++ b/tiger-compiler/src/ast/break-exp.hxx @@ -0,0 +1,21 @@ +/** + ** \file ast/break-exp.hxx + ** \brief Inline methods of ast::BreakExp. + */ + +#pragma once + +#include <ast/break-exp.hh> + +// Hint: this needs to be done at TC-3. + +namespace ast +{ + + // FIXME DONE: Some code was deleted here. + inline const Exp* BreakExp::def_get() const { return def_; } + inline Exp* BreakExp::def_get() { return def_; } + // FIXME DONE: Some code was deleted here. + inline void BreakExp::def_set(Exp* def) { def_ = def; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/call-exp.cc b/tiger-compiler/src/ast/call-exp.cc new file mode 100644 index 0000000..546ab5f --- /dev/null +++ b/tiger-compiler/src/ast/call-exp.cc @@ -0,0 +1,27 @@ +/** + ** \file ast/call-exp.cc + ** \brief Implementation of ast::CallExp. + */ + +#include <ast/call-exp.hh> +#include <ast/visitor.hh> +#include <misc/algorithm.hh> + +namespace ast +{ + CallExp::CallExp(const Location& location, misc::symbol name, exps_type* args) + : Exp(location) + , name_(name) + , args_(args) + {} + + CallExp::~CallExp() + { + misc::deep_clear(*args_); + delete args_; + } + + void CallExp::accept(ConstVisitor& v) const { v(*this); } + + void CallExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/call-exp.hh b/tiger-compiler/src/ast/call-exp.hh new file mode 100644 index 0000000..a4b6c90 --- /dev/null +++ b/tiger-compiler/src/ast/call-exp.hh @@ -0,0 +1,64 @@ +/** + ** \file ast/call-exp.hh + ** \brief Declaration of ast::CallExp. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/function-dec.hh> +#include <misc/symbol.hh> + +namespace ast +{ + /// CallExp. + class CallExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a CallExp node. + CallExp(const Location& location, misc::symbol name, exps_type* args); + CallExp(const CallExp&) = delete; + CallExp& operator=(const CallExp&) = delete; + /// Destroy a CallExp node. + ~CallExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return identifier of the called function. + misc::symbol name_get() const; + /// Set identifier of the called function. + void name_set(misc::symbol); + /// Return list of arguments passed to the function. + const exps_type& args_get() const; + /// Return list of arguments passed to the function. + exps_type& args_get(); + // FIXME DONE: Some code was deleted here. + /// Return definition site. + const FunctionDec* def_get() const; + FunctionDec* def_get(); + // FIXME DONE: Some code was deleted here. + /// Set definition site. + void def_set(FunctionDec*); + /** \} */ + + protected: + /// Identifier of the called function. + misc::symbol name_; + /// List of arguments passed to the function. + exps_type* args_; + /// Definition site. + FunctionDec* def_ = nullptr; + }; +} // namespace ast +#include <ast/call-exp.hxx> diff --git a/tiger-compiler/src/ast/call-exp.hxx b/tiger-compiler/src/ast/call-exp.hxx new file mode 100644 index 0000000..63b9c51 --- /dev/null +++ b/tiger-compiler/src/ast/call-exp.hxx @@ -0,0 +1,25 @@ +/** + ** \file ast/call-exp.hxx + ** \brief Inline methods of ast::CallExp. + */ + +#pragma once + +#include <ast/call-exp.hh> + +namespace ast +{ + + inline misc::symbol CallExp::name_get() const { return name_; } + inline void CallExp::name_set(misc::symbol name) { name_ = name; } + + inline const exps_type& CallExp::args_get() const { return *args_; } + inline exps_type& CallExp::args_get() { return *args_; } + + // FIXME DONE: Some code was deleted here. + inline const FunctionDec* CallExp::def_get() const { return def_; } + inline FunctionDec* CallExp::def_get() { return def_; } + // FIXME DONE: Some code was deleted here. + inline void CallExp::def_set(FunctionDec* def) { def_ = def; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/cast-exp.cc b/tiger-compiler/src/ast/cast-exp.cc new file mode 100644 index 0000000..e40f8f0 --- /dev/null +++ b/tiger-compiler/src/ast/cast-exp.cc @@ -0,0 +1,26 @@ +/** + ** \file ast/cast-exp.cc + ** \brief Implementation of ast::CastExp. + */ + +#include <ast/cast-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + CastExp::CastExp(const Location& location, Exp* exp, Ty* ty) + : Exp(location) + , exp_(exp) + , ty_(ty) + {} + + CastExp::~CastExp() + { + delete exp_; + delete ty_; + } + + void CastExp::accept(ConstVisitor& v) const { v(*this); } + + void CastExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/cast-exp.hh b/tiger-compiler/src/ast/cast-exp.hh new file mode 100644 index 0000000..a73e7bb --- /dev/null +++ b/tiger-compiler/src/ast/cast-exp.hh @@ -0,0 +1,62 @@ +/** + ** \file ast/cast-exp.hh + ** \brief Declaration of ast::CastExp. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/ty.hh> + +namespace ast +{ + /** \class ast::CastExp + ** \brief Cast the type of an expression to a given type. + ** + ** This node is only used in the bounds checking transformation + ** (see desugar::bounds_checks_add). You don't need to worry + ** about it (nor about the `cast' keyword) if you don't implement + ** this option. + */ + + class CastExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a CastExp node. + CastExp(const Location& location, Exp* exp, Ty* ty); + CastExp(const CastExp&) = delete; + CastExp& operator=(const CastExp&) = delete; + /// Destroy a CastExp node. + ~CastExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return the cast expression. + const Exp& exp_get() const; + /// Return the cast expression. + Exp& exp_get(); + /// Return the target type. + const Ty& ty_get() const; + /// Return the target type. + Ty& ty_get(); + /** \} */ + + protected: + /// The cast expression. + Exp* exp_; + /// The target type. + Ty* ty_; + }; +} // namespace ast +#include <ast/cast-exp.hxx> diff --git a/tiger-compiler/src/ast/cast-exp.hxx b/tiger-compiler/src/ast/cast-exp.hxx new file mode 100644 index 0000000..4f248ad --- /dev/null +++ b/tiger-compiler/src/ast/cast-exp.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/cast-exp.hxx + ** \brief Inline methods of ast::CastExp. + */ + +#pragma once + +#include <ast/cast-exp.hh> + +namespace ast +{ + + inline const Exp& CastExp::exp_get() const { return *exp_; } + inline Exp& CastExp::exp_get() { return *exp_; } + + inline const Ty& CastExp::ty_get() const { return *ty_; } + inline Ty& CastExp::ty_get() { return *ty_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/chunk-interface.hh b/tiger-compiler/src/ast/chunk-interface.hh new file mode 100644 index 0000000..dcaad18 --- /dev/null +++ b/tiger-compiler/src/ast/chunk-interface.hh @@ -0,0 +1,25 @@ +/** + ** \file ast/chunk-interface.hh + ** \brief Declare the interface for ChunkInterface class. + */ + +#pragma once + +#include <ast/ast.hh> + +namespace ast +{ + /// Declare ChunkInterface + class ChunkInterface : public Ast + { + /** \name Ctors and dtors. + ** \{ */ + public: + /// Construct a ChunkInterface + explicit ChunkInterface(const Location& location); + /** \} */ + }; + +} // namespace ast + +#include <ast/chunk-interface.hxx> diff --git a/tiger-compiler/src/ast/chunk-interface.hxx b/tiger-compiler/src/ast/chunk-interface.hxx new file mode 100644 index 0000000..7824297 --- /dev/null +++ b/tiger-compiler/src/ast/chunk-interface.hxx @@ -0,0 +1,16 @@ +/** + ** \file ast/chunk-interface.hxx + ** \brief Inline methods for ast/chunk-interface.hh + */ + +#pragma once + +#include <ast/chunk-interface.hh> + +namespace ast +{ + inline ChunkInterface::ChunkInterface(const Location& location) + : Ast(location) + {} + +} // namespace ast diff --git a/tiger-compiler/src/ast/chunk-list.cc b/tiger-compiler/src/ast/chunk-list.cc new file mode 100644 index 0000000..6a530c4 --- /dev/null +++ b/tiger-compiler/src/ast/chunk-list.cc @@ -0,0 +1,58 @@ +/** + ** \file ast/chunk-list.cc + ** \brief Implementation of ast::ChunkList. + */ + +#include <ast/chunk-interface.hh> +#include <ast/chunk-list.hh> +#include <ast/visitor.hh> +#include <misc/algorithm.hh> + +namespace ast +{ + ChunkList::iterator ChunkList::begin() { return chunks_.begin(); } + + ChunkList::iterator ChunkList::end() { return chunks_.end(); } + + ChunkList::const_iterator ChunkList::begin() const { return chunks_.begin(); } + + ChunkList::const_iterator ChunkList::end() const { return chunks_.end(); } + + void ChunkList::push_front(ChunkInterface* d) + { + chunks_.emplace_front(d); + location_.begin = d->location_get().begin; + } + + void ChunkList::emplace_back(ChunkInterface* d) + { + chunks_.emplace_back(d); + location_.end = d->location_get().end; + } + + void ChunkList::splice_front(ChunkList& ds) + { + chunks_.splice(chunks_.begin(), ds.chunks_get()); + } + + void ChunkList::splice_back(ChunkList& ds) + { + chunks_.splice(chunks_.end(), ds.chunks_get()); + } + + ChunkList::ChunkList(const Location& location) + : Ast(location) + {} + + ChunkList::ChunkList(const Location& location, + const ChunkList::list_type& chunks) + : Ast(location) + , chunks_(chunks) + {} + + ChunkList::~ChunkList() { misc::deep_clear(chunks_); } + + void ChunkList::accept(ConstVisitor& v) const { v(*this); } + + void ChunkList::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/chunk-list.hh b/tiger-compiler/src/ast/chunk-list.hh new file mode 100644 index 0000000..3674e27 --- /dev/null +++ b/tiger-compiler/src/ast/chunk-list.hh @@ -0,0 +1,80 @@ +/** + ** \file ast/chunk-list.hh + ** \brief Declaration of ast::ChunkList. + */ + +#pragma once + +#include <ast/ast.hh> + +namespace ast +{ + /// ChunkList. + class ChunkList : public Ast + { + public: + using list_type = std::list<ChunkInterface*>; + /// Define value type + using value_type = list_type::value_type; + /// Define size type + using size_type = list_type::size_type; + /// Define reference to value type + using reference = list_type::reference; + /// Define const reference to value type + using const_reference = list_type::const_reference; + /// Define shorthand type for D-declations iterator. + using iterator = list_type::iterator; + /// Define shorthand type for D-declations const iterator. + using const_iterator = list_type::const_iterator; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + /// Prepend \a d. + void push_front(ChunkInterface* d); + /// Append \a d. + void emplace_back(ChunkInterface* d); + + /// Splice the content of \a ds in front of this list. + void splice_front(ChunkList& ds); + /// Splice the content of \a ds at the back this list. + void splice_back(ChunkList& ds); + + /// Construct a ChunkList node. + ChunkList(const Location& location); + + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a ChunkList node. + ChunkList(const Location& location, const ChunkList::list_type& chunks); + ChunkList(const ChunkList&) = delete; + ChunkList& operator=(const ChunkList&) = delete; + /// Destroy a ChunkList node. + ~ChunkList() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return declarations. + const ChunkList::list_type& chunks_get() const; + /// Return declarations. + ChunkList::list_type& chunks_get(); + /** \} */ + + protected: + /// Declarations. + ChunkList::list_type chunks_; + }; +} // namespace ast +#include <ast/chunk-list.hxx> diff --git a/tiger-compiler/src/ast/chunk-list.hxx b/tiger-compiler/src/ast/chunk-list.hxx new file mode 100644 index 0000000..6307760 --- /dev/null +++ b/tiger-compiler/src/ast/chunk-list.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/chunk-list.hxx + ** \brief Inline methods of ast::ChunkList. + */ + +#pragma once + +#include <ast/chunk-list.hh> + +namespace ast +{ + + inline const ChunkList::list_type& ChunkList::chunks_get() const + { + return chunks_; + } + inline ChunkList::list_type& ChunkList::chunks_get() { return chunks_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/chunk.hh b/tiger-compiler/src/ast/chunk.hh new file mode 100644 index 0000000..8f59fb0 --- /dev/null +++ b/tiger-compiler/src/ast/chunk.hh @@ -0,0 +1,139 @@ +/** + ** \file ast/chunk.hh + ** \brief Declaration of ast::Chunk. + */ + +#pragma once + +#include <vector> + +#include <ast/chunk-interface.hh> + +namespace ast +{ + template <typename D> + /// Abstract a "list of D-declarations" node. + class Chunk : public ChunkInterface + { + /** \name Member types + ** \{ */ + public: + /// Define shorthand type for list of D-declarations. + using Ds = std::vector<D*>; + /// Define value type + using value_type = typename Ds::value_type; + /// Define size type + using size_type = typename Ds::size_type; + /// Define reference to value type + using reference = typename Ds::reference; + /// Define const reference to value type + using const_reference = typename Ds::const_reference; + /// Define shorthand type for D-declations iterator. + using iterator = typename Ds::iterator; + /// Define shorthand type for D-declations const iterator. + using const_iterator = typename Ds::const_iterator; + + /** \} */ + + /** \name Ctor & dtor. + ** \{ */ + public: + /** \brief Construct an Chunk node with a list of D-declarations. + ** \param location scanner position informations + ** \param decs list of D-declarations */ + Chunk(const Location& location, Ds* decs); + explicit Chunk(const Location& location); + + /** \brief Destroys an Chunk node. + ** + ** Free list and its content. */ + ~Chunk() override; + + /** \} */ + + /** \name Visitors entry point. + ** \{ */ + public: + /// Accept a const visitor \a v. + void accept(Visitor& v) override; + + /// Accept a non-const visitor \a v. + void accept(ConstVisitor& v) const override; + + /** \} */ + + /** \name Accessors. + ** \{ */ + public: /** \brief Access specified element + ** /param pos position of the element to return */ + constexpr reference operator[](size_type pos); + + /** \brief Access specified const element + ** /param pos position of the element to return */ + constexpr const_reference operator[](size_type pos) const; + + /// Access to list of D-declarations (read and write). + Ds& decs_get(); + + /// Access to list of D-declarations (read only). + const Ds& decs_get() const; + + /** \} */ + + /** \name Iterators. + ** \{ */ + public: + /// Return an iterator to the begging. + iterator begin(); + /// Return a const iterator to the begging. + const_iterator begin() const; + + /// Return an iterator to the end. + iterator end(); + /// Return a const iterator to the end. + const_iterator end() const; + + /** \} */ + + /** \name Capacity. + ** \} */ + public: + /// Checks whether the container is empty. +#ifdef SWIG + constexpr bool empty() const noexcept; +#else /* SWIG */ + [[nodiscard]] constexpr bool empty() const noexcept; +#endif /* SWIG */ + /** \name Modifiers. + ** \{ */ + public: + /** \brief Erase the specified element from the container. + ** \param pos position of the element to remove. */ + constexpr iterator erase(const_iterator pos); + + /** \brief Erase the specified elements in range from the container. + ** \param first begin of the range + ** \param last end of the range */ + constexpr iterator erase(const_iterator first, const_iterator last); + + /** \brief Push \a d in front. + ** \param d declaration to push */ + Chunk<D>& push_front(D& d); + + /** \brief Push \a d in back. + ** \param d declaration to push */ + Chunk<D>& emplace_back(D& d); + + /** \} */ + + // SWIG 2 does not understand C++11 constructs, such as data + // member initializers. +#ifndef SWIG + private: + Ds* decs_ = new Ds(); +#endif + }; + +} // namespace ast + +#include <ast/chunk.hxx> diff --git a/tiger-compiler/src/ast/chunk.hxx b/tiger-compiler/src/ast/chunk.hxx new file mode 100644 index 0000000..a3c3ada --- /dev/null +++ b/tiger-compiler/src/ast/chunk.hxx @@ -0,0 +1,118 @@ +/** + ** \file ast/chunk.hxx + ** \brief Implementation of ast::Chunk. + */ + +#pragma once + +#include <ast/chunk.hh> +#include <ast/visitor.hh> +#include <misc/algorithm.hh> + +namespace ast +{ + template <typename D> + Chunk<D>::Chunk(const Location& location, Ds* decs) + : ChunkInterface(location) + , decs_(decs) + {} + + template <typename D> + Chunk<D>::Chunk(const Location& location) + : ChunkInterface(location) + {} + + template <typename D> Chunk<D>::~Chunk() + { + misc::deep_clear(*decs_); + delete decs_; + } + + template <typename D> inline void Chunk<D>::accept(Visitor& v) { v(*this); } + + template <typename D> inline void Chunk<D>::accept(ConstVisitor& v) const + { + v(*this); + } + + template <typename D> + inline constexpr typename Chunk<D>::reference + Chunk<D>::operator[](size_type pos) + { + return decs_->operator[](pos); + } + + template <typename D> + inline constexpr typename Chunk<D>::const_reference + Chunk<D>::operator[](size_type pos) const + { + return decs_->operator[](pos); + } + + template <typename D> inline typename Chunk<D>::Ds& Chunk<D>::decs_get() + { + return *decs_; + } + + template <typename D> + inline const typename Chunk<D>::Ds& Chunk<D>::decs_get() const + { + return *decs_; + } + + template <typename D> inline typename Chunk<D>::iterator Chunk<D>::begin() + { + return decs_->begin(); + } + + template <typename D> + inline typename Chunk<D>::const_iterator Chunk<D>::begin() const + { + return decs_->begin(); + } + + template <typename D> inline typename Chunk<D>::iterator Chunk<D>::end() + { + return decs_->end(); + } + + template <typename D> + inline typename Chunk<D>::const_iterator Chunk<D>::end() const + { + return decs_->end(); + } + + template <typename D> inline constexpr bool Chunk<D>::empty() const noexcept + { + return decs_->empty(); + } + + template <typename D> + inline constexpr typename Chunk<D>::iterator + Chunk<D>::erase(const_iterator pos) + { + return decs_->erase(pos); + } + + template <typename D> + inline constexpr typename Chunk<D>::iterator + Chunk<D>::erase(const_iterator first, const_iterator last) + { + return decs_->erase(first, last); + } + + template <typename D> Chunk<D>& Chunk<D>::push_front(D& d) + { + location_set(location_get() + d.location_get()); + decs_->insert(decs_->begin(), &d); + return *this; + } + + template <typename D> Chunk<D>& Chunk<D>::emplace_back(D& d) + { + location_set(location_get() + d.location_get()); + decs_->emplace_back(&d); + return *this; + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/class-ty.cc b/tiger-compiler/src/ast/class-ty.cc new file mode 100644 index 0000000..ca5e983 --- /dev/null +++ b/tiger-compiler/src/ast/class-ty.cc @@ -0,0 +1,22 @@ +/** + ** \file ast/class-ty.cc + ** \brief Implementation of ast::ClassTy. + */ + +#include <ast/class-ty.hh> +#include <ast/visitor.hh> + +namespace ast +{ + ClassTy::ClassTy(const Location& location, NameTy* super, ChunkList* chunks) + : Ty(location) + , super_(super) + , chunks_(chunks) + {} + + ClassTy::~ClassTy() { delete chunks_; } + + void ClassTy::accept(ConstVisitor& v) const { v(*this); } + + void ClassTy::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/class-ty.hh b/tiger-compiler/src/ast/class-ty.hh new file mode 100644 index 0000000..0045685 --- /dev/null +++ b/tiger-compiler/src/ast/class-ty.hh @@ -0,0 +1,55 @@ +/** + ** \file ast/class-ty.hh + ** \brief Declaration of ast::ClassTy. + */ + +#pragma once + +#include <ast/chunk-list.hh> +#include <ast/name-ty.hh> +#include <ast/ty.hh> + +namespace ast +{ + /// ClassTy. + class ClassTy : public Ty + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a ClassTy node. + ClassTy(const Location& location, NameTy* super, ChunkList* chunks); + ClassTy(const ClassTy&) = delete; + ClassTy& operator=(const ClassTy&) = delete; + /// Destroy a ClassTy node. + ~ClassTy() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return super class. + const NameTy& super_get() const; + /// Return super class. + NameTy& super_get(); + /// Return list of declarations. + const ChunkList& chunks_get() const; + /// Return list of declarations. + ChunkList& chunks_get(); + /** \} */ + + protected: + /// Super class. + NameTy* super_; + /// List of declarations. + ChunkList* chunks_; + }; +} // namespace ast +#include <ast/class-ty.hxx> diff --git a/tiger-compiler/src/ast/class-ty.hxx b/tiger-compiler/src/ast/class-ty.hxx new file mode 100644 index 0000000..70c291b --- /dev/null +++ b/tiger-compiler/src/ast/class-ty.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/class-ty.hxx + ** \brief Inline methods of ast::ClassTy. + */ + +#pragma once + +#include <ast/class-ty.hh> + +namespace ast +{ + + inline const NameTy& ClassTy::super_get() const { return *super_; } + inline NameTy& ClassTy::super_get() { return *super_; } + + inline const ChunkList& ClassTy::chunks_get() const { return *chunks_; } + inline ChunkList& ClassTy::chunks_get() { return *chunks_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/dec.cc b/tiger-compiler/src/ast/dec.cc new file mode 100644 index 0000000..b19ed0b --- /dev/null +++ b/tiger-compiler/src/ast/dec.cc @@ -0,0 +1,17 @@ +/** + ** \file ast/dec.cc + ** \brief Implementation of ast::Dec. + */ + +#include <ast/dec.hh> +#include <ast/visitor.hh> + +namespace ast +{ + Dec::Dec(const Location& location, misc::symbol name) + : Ast(location) + , Typable() + , name_(name) + {} + +} // namespace ast diff --git a/tiger-compiler/src/ast/dec.hh b/tiger-compiler/src/ast/dec.hh new file mode 100644 index 0000000..f61489e --- /dev/null +++ b/tiger-compiler/src/ast/dec.hh @@ -0,0 +1,50 @@ +/** + ** \file ast/dec.hh + ** \brief Declaration of ast::Dec. + */ + +#pragma once + +#include <ast/ast.hh> +#include <ast/typable.hh> +#include <misc/symbol.hh> + +namespace ast +{ + /// Dec. + class Dec + : public Ast + , public Typable + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a Dec node. + Dec(const Location& location, misc::symbol name); + Dec(const Dec&) = delete; + Dec& operator=(const Dec&) = delete; + /// Destroy a Dec node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override = 0; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override = 0; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return name of the defined entity. + misc::symbol name_get() const; + /// Set name of the defined entity. + void name_set(misc::symbol); + /** \} */ + + protected: + /// Name of the defined entity. + misc::symbol name_; + }; +} // namespace ast +#include <ast/dec.hxx> diff --git a/tiger-compiler/src/ast/dec.hxx b/tiger-compiler/src/ast/dec.hxx new file mode 100644 index 0000000..f3c12f5 --- /dev/null +++ b/tiger-compiler/src/ast/dec.hxx @@ -0,0 +1,15 @@ +/** + ** \file ast/dec.hxx + ** \brief Inline methods of ast::Dec. + */ + +#pragma once + +#include <ast/dec.hh> + +namespace ast +{ + inline misc::symbol Dec::name_get() const { return name_; } + inline void Dec::name_set(misc::symbol name) { name_ = name; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/default-visitor.hh b/tiger-compiler/src/ast/default-visitor.hh new file mode 100644 index 0000000..e4e2355 --- /dev/null +++ b/tiger-compiler/src/ast/default-visitor.hh @@ -0,0 +1,151 @@ +/** + ** \file ast/default-visitor.hh + ** \brief Traverse an Abstract Syntax Tree (w/o objects), doing nothing. + */ + +#pragma once + +#include <ast/visitor.hh> + +namespace ast +{ + /** \brief Just visit the whole Ast tree (except object-related nodes). + + GenDefaultVisitor<CONSTNESS-SELECTOR> visits non-object-related + node of the the whole Ast tree, but does nothing else. + + Beware, as there are no implementations visiting object-oriented + constructs (classes, objects, methods), hence this class is + abstract. + + ast::GenDefaultVisitor inherits virtually from ast::GenVisitor + to allow diamond inheritance, e.g. so that a subclass of + ast::GenDefaultVisitor can also inherit missing object-related + implementations from another class (inheriting from + ast::GenVisitor). + + \see ast::NonObjectVisitor for more information. */ + template <template <typename> class Const> + class GenDefaultVisitor : public virtual GenVisitor<Const> + { + public: + /// Super class type. + using super_type = GenVisitor<Const>; + + // Import overloaded \c operator() methods. + using super_type::operator(); + + /// Convenient abbreviation. + template <typename Type> using const_t = typename Const<Type>::type; + + /** \name Ctor & dtor. + ** \{ */ + /// Construct a default visitor. + GenDefaultVisitor(); + /// Destroy a default visitor. + virtual ~GenDefaultVisitor(); + /** \} */ + + /* We cannot simply use `using super_type::operator()' here, + otherwise the linker would complain about missing symbols for + these methods: + + GenVisitor<id_traits>::operator()(ast::MethodDec&) + GenVisitor<id_traits>::operator()(ast::MethodCallExp&) + + This behavior seems to come from the mix between diamond + inheritance and templates. We redefine the following operator + (delegating to GenVisitor's operator()) as a workaround. */ + void operator()(const_t<Ast>& e) override; + + /** \name Visit Variable related nodes. + ** \{ */ + void operator()(const_t<SimpleVar>& e) override; + void operator()(const_t<FieldVar>& e) override; + void operator()(const_t<SubscriptVar>& e) override; + /** \} */ + + /** \name Visit Expression related nodes. + ** \{ */ + void operator()(const_t<NilExp>& e) override; + void operator()(const_t<IntExp>& e) override; + void operator()(const_t<StringExp>& e) override; + void operator()(const_t<CallExp>& e) override; + void operator()(const_t<OpExp>& e) override; + void operator()(const_t<RecordExp>& e) override; + void operator()(const_t<SeqExp>& e) override; + void operator()(const_t<AssignExp>& e) override; + void operator()(const_t<IfExp>& e) override; + void operator()(const_t<WhileExp>& e) override; + void operator()(const_t<ForExp>& e) override; + void operator()(const_t<BreakExp>&) override; + void operator()(const_t<LetExp>& e) override; + void operator()(const_t<ArrayExp>& e) override; + void operator()(const_t<CastExp>& e) override; + void operator()(const_t<FieldInit>& e) override; + /** \} */ + + /** \name Visit Declaration related nodes. + ** + ** Visiting declarations is simple, but there are many clauses. + ** This is because, in Tiger, the declarations are processed by + ** chunks (a chunk of Function declarations, then Var or Type, + ** then ...). + ** So we have to explain + ** \li How to visit a list of chunks; + ** \li how to visit chunks of function, var, or type declarations; + ** \li how to visit a single function, var, or type declaration. + ** \{ */ + + /// Visit a list of function, type and/or variables declarations. + void operator()(const_t<ChunkList>& e) override; + + /// Visit a ChunkInterface chunks. + virtual void operator()(const_t<ChunkInterface>& e); + + template <typename ChunkType> + /** \brief Visit a chunk (i.e., a list of Function, Var, and Type declarations). + ** + ** It is exactly the same in the three cases, so the code is + ** factored via a template method. */ + void chunk_visit(const_t<ChunkType>& e); + + /// Visit Var declarations. + void operator()(const_t<VarChunk>& e) override; + void operator()(const_t<VarDec>& e) override; + + /// Visit Function declarations. + void operator()(const_t<FunctionChunk>& e) override; + void operator()(const_t<FunctionDec>& e) override; + + /// Visit Type declarations. + void operator()(const_t<TypeChunk>& e) override; + void operator()(const_t<TypeDec>& e) override; + + /** \} */ + + /** \name Visit Type related nodes. + ** \{ */ + void operator()(const_t<NameTy>& e) override; + void operator()(const_t<RecordTy>& e) override; + void operator()(const_t<ArrayTy>& e) override; + /** \} */ + + /** \name Visit Field related nodes. */ + void operator()(const_t<Field>& e) override; + }; + + /// Shorthand for a const visitor. + using DefaultConstVisitor = GenDefaultVisitor<misc::constify_traits>; + /// Shorthand for a non const visitor. + using DefaultVisitor = GenDefaultVisitor<misc::id_traits>; + +#ifdef SWIG + /// Shorthand for a const visitor. + %template(DefaultConstVisitor) GenDefaultVisitor<misc::constify_traits>; + /// Shorthand for a non const visitor. + %template(DefaultVisitor) GenDefaultVisitor<misc::id_traits>; +#endif +} // namespace ast + +#include <ast/default-visitor.hxx> diff --git a/tiger-compiler/src/ast/default-visitor.hxx b/tiger-compiler/src/ast/default-visitor.hxx new file mode 100644 index 0000000..3d49e83 --- /dev/null +++ b/tiger-compiler/src/ast/default-visitor.hxx @@ -0,0 +1,247 @@ +/** + ** \file ast/default-visitor.hxx + ** \brief Implementation for ast/default-visitor.hh. + */ + +#pragma once + +#include <ast/all.hh> +#include <ast/default-visitor.hh> +#include <misc/algorithm.hh> + +namespace ast +{ + template <template <typename> class Const> + GenDefaultVisitor<Const>::GenDefaultVisitor() + : GenVisitor<Const>() + {} + + template <template <typename> class Const> + GenDefaultVisitor<Const>::~GenDefaultVisitor() + {} + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<Ast>& e) + { + super_type::operator()(e); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<SimpleVar>&) + {} + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<FieldVar>& e) + { + // FIXME DONE: Some code was deleted here. + e.var_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<SubscriptVar>& e) + { + e.var_get().accept(*this); + e.index_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<NilExp>&) + {} + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<IntExp>&) + {} + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<StringExp>&) + {} + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<CallExp>& e) + { + // FIXME DONE: Some code was deleted here. + for (auto arg : e.args_get()) + arg->accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<OpExp>& e) + { + e.left_get().accept(*this); + e.right_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<RecordExp>& e) + { + // FIXME DONE: Some code was deleted here. + e.type_name_get().accept(*this); + for (auto field : e.fields_get()) + field->accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<SeqExp>& e) + { + // FIXME DONE: Some code was deleted here. + for (auto exp : e.exps_get()) + exp->accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<AssignExp>& e) + { + // FIXME DONE: Some code was deleted here. + e.var_get().accept(*this); + e.exp_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<IfExp>& e) + { + // FIXME DONE: Some code was deleted here. + e.test_get().accept(*this); + e.thenclause_get().accept(*this); + e.elseclause_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<WhileExp>& e) + { + e.test_get().accept(*this); + e.body_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<ForExp>& e) + { + e.vardec_get().accept(*this); + e.hi_get().accept(*this); + e.body_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<BreakExp>&) + {} + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<LetExp>& e) + { + // FIXME DONE: Some code was deleted here. + e.chunks_get().accept(*this); + e.body_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<ArrayExp>& e) + { + // FIXME: Some code was deleted here. + e.type_name_get().accept(*this); + e.size_get().accept(*this); + e.init_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<CastExp>& e) + { + e.exp_get().accept(*this); + e.ty_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<FieldInit>& e) + { + e.init_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<ChunkList>& e) + { + // FIXME DONE: Some code was deleted here. + for (auto chunk : e.chunks_get()) + chunk->accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<ChunkInterface>& e) + { + e.accept(*this); + } + + template <template <typename> class Const> + template <typename ChunkType> + inline void GenDefaultVisitor<Const>::chunk_visit(const_t<ChunkType>& e) + { + for (const auto dec : e) + dec->accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<VarChunk>& e) + { + chunk_visit<VarChunk>(e); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<VarDec>& e) + { + // `type_name' might be omitted. + this->accept(e.type_name_get()); + // `init' can be null in case of formal parameter. + this->accept(e.init_get()); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<FunctionChunk>& e) + { + chunk_visit<FunctionChunk>(e); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<FunctionDec>& e) + { + // FIXME DONE: Some code was deleted here. + e.formals_get().accept(*this); + if (e.result_get() != nullptr) + e.result_get()->accept(*this); + if (e.body_get() != nullptr) + e.body_get()->accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<TypeChunk>& e) + { + chunk_visit<TypeChunk>(e); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<TypeDec>& e) + { + e.ty_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<NameTy>&) + {} + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<RecordTy>& e) + { + // FIXME DONE: Some code was deleted here. + for (auto field : e.fields_get()) + field->accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<ArrayTy>& e) + { + e.base_type_get().accept(*this); + } + + template <template <typename> class Const> + void GenDefaultVisitor<Const>::operator()(const_t<Field>& e) + { + e.type_name_get().accept(*this); + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/dumper-dot.cc b/tiger-compiler/src/ast/dumper-dot.cc new file mode 100644 index 0000000..aef9568 --- /dev/null +++ b/tiger-compiler/src/ast/dumper-dot.cc @@ -0,0 +1,438 @@ +/** + ** \file ast/dumper-dot.cc + ** \brief Implementation of ast::DumperDot. + */ + +#include <ast/all.hh> +#include <ast/dumper-dot.hh> +#include <misc/indent.hh> +#include <misc/symbol.hh> +#include <type/pretty-printer.hh> + +namespace ast +{ + using namespace ast; + + void DumperDot::dump(const std::string& field, const ast::Ast& e) + { + const std::string* old_parent_field = parent_field; + parent_field = &field; + e.accept(*this); + parent_field = old_parent_field; + } + + void DumperDot::dump(const std::string& field, const ast::Ast* e) + { + if (!e) + return; + const std::string* old_parent_field = parent_field; + parent_field = &field; + e->accept(*this); + parent_field = old_parent_field; + } + + DumperDot::DumperDot(std::ostream& ostr) + : ostr_(ostr) + {} + + void DumperDot::dump_type(const ast::Typable& e) + { + // FIXME DONE: Some code was deleted here (Call node_html_field on a e.type_get() if exist). + if (e.type_get()) + node_html_field("typable", *e.type_get()); + } + + void DumperDot::operator()(const ArrayExp& e) + { + unsigned long old_parent_id = node_html_header(e, "ArrayExp"); + dump_type(e); + // FIXME DONE:Some code was deleted here (node_html_ports with properties). + node_html_ports({"type_name", "size", "init"}); + footer_and_link(old_parent_id); + // FIXME DONE: Some code was deleted here (dump). + dump("type_name", e.type_name_get()); + dump("size", e.size_get()); + dump("init", e.init_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const ArrayTy& e) + { + unsigned long old_parent_id = node_html_header(e, "ArrayTy"); + dump_type(e); + node_html_ports({"base_type"}); + footer_and_link(old_parent_id); + dump("base_type", e.base_type_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const AssignExp& e) + { + unsigned long old_parent_id = node_html_header(e, "AssignExp"); + dump_type(e); + // FIXME DONE: Some code was deleted here (node_html_ports with properties). + node_html_ports({"exp", "var"}); + footer_and_link(old_parent_id); + // FIXME DONE: Some code was deleted here (dump). + dump("base_type", e.exp_get()); + dump("var", e.var_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const BreakExp& e) + { + unsigned long old_parent_id = node_html_header(e, "BreakExp"); + dump_type(e); + node_html_ports({"def"}); + footer_and_link(old_parent_id); + dump_def(e); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const CallExp& e) + { + unsigned long old_parent_id = node_html_header(e, "CallExp"); + dump_type(e); + // FIXME DONE: Some code was deleted here (node_html_field). + node_html_field("name", e.name_get()); + node_html_ports(); + // FIXME DONE: Some code was deleted here (node_html_port_list for each list). + node_html_port_list("args",e.args_get(), true); + node_html_one_port("def"); + footer_and_link(old_parent_id); + dump_def(e); + // FIXME DONE: Some code was deleted here (dump_list). + dump_list("args",e.args_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const CastExp& e) + { + unsigned long old_parent_id = node_html_header(e, "CastExp"); + dump_type(e); + node_html_ports({"exp", "ty"}); + footer_and_link(old_parent_id); + dump("exp", e.exp_get()); + dump("ty", e.ty_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const ClassTy& e) + { + unsigned long old_parent_id = node_html_header(e, "ClassTy"); + dump_type(e); + node_html_ports({"super", "chunks"}); + footer_and_link(old_parent_id); + dump("super", e.super_get()); + dump("chunks", e.chunks_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const Field& e) + { + unsigned long old_parent_id = node_html_header(e, "Field"); + node_html_field("name", e.name_get()); + node_html_ports({"type_name"}); + footer_and_link(old_parent_id); + dump("type_name", e.type_name_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const FieldInit& e) + { + unsigned long old_parent_id = node_html_header(e, "FieldInit"); + node_html_field("name", e.name_get()); + node_html_ports({"init"}); + footer_and_link(old_parent_id); + dump("init", e.init_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const FieldVar& e) + { + unsigned long old_parent_id = node_html_header(e, "FieldVar"); + dump_type(e); + // FIXME DONE: Some code was deleted here (node_html_field). + node_html_field("name", e.name_get()); + // FIXME DONE: Some code was deleted here (node_html_ports with properties). + node_html_ports({"var"}); + footer_and_link(old_parent_id); + // FIXME DONE: Some code was deleted here (dump). + dump("var",e.var_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const ForExp& e) + { + unsigned long old_parent_id = node_html_header(e, "ForExp"); + dump_type(e); + node_html_ports({"vardec", "hi", "body"}); + footer_and_link(old_parent_id); + dump("vardec", e.vardec_get()); + dump("hi", e.hi_get()); + dump("body", e.body_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const FunctionDec& e) + { + unsigned long old_parent_id = node_html_header(e, "FunctionDec"); + dump_type(e); + node_html_field("name", e.name_get()); + node_html_ports({"formals", "result", "body"}); + footer_and_link(old_parent_id); + dump("formals", e.formals_get()); + dump("result", e.result_get()); + dump("body", e.body_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const IfExp& e) + { + unsigned long old_parent_id = node_html_header(e, "IfExp"); + dump_type(e); + // FIXME DONE: Some code was deleted here (node_html_ports with properties). + node_html_ports({"test","then_clause","else_clause"}); + footer_and_link(old_parent_id); + // FIXME DONE: Some code was deleted here (dump). + dump("test",e.test_get()); + dump("then_clause",e.thenclause_get()); + dump("else_clause", e.elseclause_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const IntExp& e) + { + unsigned long old_parent_id = node_html_header(e, "IntExp"); + dump_type(e); + node_html_field("value", e.value_get()); + footer_and_link(old_parent_id); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const LetExp& e) + { + unsigned long old_parent_id = node_html_header(e, "LetExp"); + dump_type(e); + // FIXME DONE: Some code was deleted here (node_html_ports with properties). + node_html_ports({"chunk","body"}); + footer_and_link(old_parent_id); + // FIXME DONE: Some code was deleted here (dump). + dump("chunk", e.chunks_get()); + dump("body",e.body_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const MethodCallExp& e) + { + unsigned long old_parent_id = node_html_header(e, "MethodCallExp"); + dump_type(e); + // FIXME DONE: Some code was deleted here (node_html_field). + node_html_field("name", e.name_get()); + // FIXME DONE: Some code was deleted here (node_html_ports with properties). + node_html_ports({"object"}); + // FIXME DONE: Some code was deleted here (node_html_port_list for each list). + node_html_port_list("args",e.args_get(), true); + node_html_one_port("def"); + footer_and_link(old_parent_id); + dump_def(e); + // FIXME DONE: Some code was deleted here (dump and dump_list). + dump("object",e.object_get()); + dump_list("args",e.args_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const MethodDec& e) + { + unsigned long old_parent_id = node_html_header(e, "MethodDec"); + dump_type(e); + node_html_field("name", e.name_get()); + node_html_ports({"formals", "result", "body"}); + footer_and_link(old_parent_id); + dump("formals", e.formals_get()); + dump("result", e.result_get()); + dump("body", e.body_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const NameTy& e) + { + unsigned long old_parent_id = node_html_header(e, "NameTy"); + dump_type(e); + node_html_field("name", e.name_get()); + node_html_ports({"def"}); + footer_and_link(old_parent_id); + dump_def(e); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const NilExp& e) + { + unsigned long old_parent_id = node_html_header(e, "NilExp"); + dump_type(e); + footer_and_link(old_parent_id); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const ObjectExp& e) + { + unsigned long old_parent_id = node_html_header(e, "ObjectExp"); + dump_type(e); + // FIXME DONE: Some code was deleted here (node_html_ports with properties). + node_html_ports({"type_name"}); + footer_and_link(old_parent_id); + // FIXME DONE: Some code was deleted here (dump). + dump("type_name", e.type_name_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const OpExp& e) + { + unsigned long old_parent_id = node_html_header(e, "OpExp"); + dump_type(e); + node_html_field("oper", str(e.oper_get()), "'"); + node_html_ports({"left", "right"}); + footer_and_link(old_parent_id); + dump("left", e.left_get()); + dump("right", e.right_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const RecordExp& e) + { + unsigned long old_parent_id = node_html_header(e, "RecordExp"); + dump_type(e); + // FIXME DONE: Some code was deleted here (node_html_ports with properties). + node_html_ports({"type_name"}); + // FIXME DONE: Some code was deleted here (node_html_port_list for each list). + node_html_port_list("fields",e.fields_get()); + footer_and_link(old_parent_id); + // FIXME DONE: Some code was deleted here (dump and dump_list). + dump("type_name",e.type_name_get()); + dump_list("fields",e.fields_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const RecordTy& e) + { + unsigned long old_parent_id = node_html_header(e, "RecordTy"); + dump_type(e); + node_html_ports(); + // FIXME DONE: Some code was deleted here (node_html_port_list for each list). + node_html_port_list("fields", e.fields_get()); + footer_and_link(old_parent_id); + // FIXME DONE: Some code was deleted here (dump_list). + dump_list("fields",e.fields_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const SeqExp& e) + { + unsigned long old_parent_id = node_html_header(e, "SeqExp"); + dump_type(e); + node_html_ports(); + // FIXME DONE: Some code was deleted here (node_html_port_list for each list). + node_html_port_list("exps", e.exps_get()); + footer_and_link(old_parent_id); + // FIXME DONE: Some code was deleted here (dump_list). + dump_list("fields",e.exps_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const SimpleVar& e) + { + unsigned long old_parent_id = node_html_header(e, "SimpleVar"); + dump_type(e); + node_html_field("name", e.name_get()); + node_html_ports({"def"}); + footer_and_link(old_parent_id); + dump_def(e); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const StringExp& e) + { + unsigned long old_parent_id = node_html_header(e, "StringExp"); + dump_type(e); + // FIXME DONE: Some code was deleted here (node_html_field, use misc::escape). + // WTF ?????? Ce code est completement fait au pif je vous le dis :) + node_html_field("",misc::escape(e.value_get())); + footer_and_link(old_parent_id); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const SubscriptVar& e) + { + unsigned long old_parent_id = node_html_header(e, "SubscriptVar"); + dump_type(e); + node_html_ports({"var", "index"}); + footer_and_link(old_parent_id); + dump("var", e.var_get()); + dump("index", e.index_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const TypeDec& e) + { + unsigned long old_parent_id = node_html_header(e, "TypeDec"); + dump_type(e); + node_html_field("name", e.name_get()); + node_html_ports({"ty"}); + footer_and_link(old_parent_id); + dump("ty", e.ty_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const VarDec& e) + { + unsigned long old_parent_id = node_html_header(e, "VarDec"); + dump_type(e); + node_html_field("name", e.name_get()); + node_html_ports({"type_name", "init"}); + footer_and_link(old_parent_id); + dump("type_name", e.type_name_get()); + dump("init", e.init_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const WhileExp& e) + { + unsigned long old_parent_id = node_html_header(e, "WhileExp"); + dump_type(e); + node_html_ports({"test", "body"}); + footer_and_link(old_parent_id); + dump("test", e.test_get()); + dump("body", e.body_get()); + parent_id = old_parent_id; + } + + void DumperDot::operator()(const ast::AssertExp&) + { + // FIXME: Some code was deleted here. + } + + void DumperDot::operator()(const ast::ChunkList& e) + { + dump_chunk<ast::ChunkList>(e, "ChunkList"); + } + + void DumperDot::operator()(const ast::FunctionChunk& e) + { + dump_chunk<ast::FunctionChunk>(e, "FunctionChunk"); + } + + void DumperDot::operator()(const ast::MethodChunk& e) + { + dump_chunk<ast::MethodChunk>(e, "MethodChunk"); + } + + void DumperDot::operator()(const ast::TypeChunk& e) + { + dump_chunk<ast::TypeChunk>(e, "TypeChunk"); + } + + void DumperDot::operator()(const ast::VarChunk& e) + { + dump_chunk<ast::VarChunk>(e, "VarChunk"); + } +} // namespace ast diff --git a/tiger-compiler/src/ast/dumper-dot.hh b/tiger-compiler/src/ast/dumper-dot.hh new file mode 100644 index 0000000..a297f30 --- /dev/null +++ b/tiger-compiler/src/ast/dumper-dot.hh @@ -0,0 +1,112 @@ + +/** + ** \file ast/dumper-dot.hh + ** \brief Declaration of ast::DumperDot. + */ + +#pragma once + +#include <ast/default-visitor.hh> +#include <misc/concepts.hh> +#include <misc/escape.hh> + +namespace ast +{ + /// \brief Dump an Ast into dot format. + class DumperDot : public ast::DefaultConstVisitor + { + public: + using super_type = ast::DefaultConstVisitor; + + // Import overloaded virtual functions. + using super_type::operator(); + + /// Build a DumperDot. + DumperDot(std::ostream& ostr); + + /// Destroy a DumperDot. + ~DumperDot() override = default; + + // Visit methods. + public: + void operator()(const ast::ArrayExp&) override; + void operator()(const ast::ArrayTy&) override; + void operator()(const ast::AssignExp&) override; + void operator()(const ast::BreakExp&) override; + void operator()(const ast::CallExp&) override; + void operator()(const ast::CastExp&) override; + void operator()(const ast::ChunkList&) override; + void operator()(const ast::ClassTy&) override; + void operator()(const ast::Field&) override; + void operator()(const ast::FieldInit&) override; + void operator()(const ast::FieldVar&) override; + void operator()(const ast::ForExp&) override; + void operator()(const ast::FunctionDec&) override; + void operator()(const ast::IfExp&) override; + void operator()(const ast::IntExp&) override; + void operator()(const ast::LetExp&) override; + void operator()(const ast::MethodCallExp&) override; + void operator()(const ast::MethodDec&) override; + void operator()(const ast::NameTy&) override; + void operator()(const ast::NilExp&) override; + void operator()(const ast::ObjectExp&) override; + void operator()(const ast::OpExp&) override; + void operator()(const ast::RecordExp&) override; + void operator()(const ast::RecordTy&) override; + void operator()(const ast::SeqExp&) override; + void operator()(const ast::SimpleVar&) override; + void operator()(const ast::StringExp&) override; + void operator()(const ast::SubscriptVar&) override; + void operator()(const ast::TypeDec&) override; + void operator()(const ast::VarDec&) override; + void operator()(const ast::WhileExp&) override; + void operator()(const ast::FunctionChunk&) override; + void operator()(const ast::MethodChunk&) override; + void operator()(const ast::TypeChunk&) override; + void operator()(const ast::VarChunk&) override; + void operator()(const ast::AssertExp&) override; + + protected: + void dump(const std::string& field, const ast::Ast& t); + void dump(const std::string& field, const ast::Ast* t); + template <typename Container> + requires misc::ConstIterable<Container> + void dump_list(const std::string& field, const Container& l); + template <typename T> void dump_def(const T& e) const; + void dump_type(const ast::Typable& e); + template <typename E> void dump_chunk(const E& e, const std::string& name); + + void display_link(unsigned long old_parent_id) const; + void footer_and_link(unsigned long old_parent_id) const; + + template <typename T> + unsigned long node_html_header(const T& e, const std::string& type); + template <typename T> + void node_html_field(const std::string& name, + const T& content, + const std::string& sep = ""); + void node_html_one_port(const std::string& p); + void node_html_ports(const std::vector<std::string>& ports = {}); + template <typename T> + void node_html_port_list(const std::string& name, + const T& list, + bool chunk = false); + void node_html_footer() const; + + protected: + /// The stream to print on. + std::ostream& ostr_; + + /// The parent id + unsigned long parent_id = -1; + + /// Number of fields + unsigned long inner_fields = 0; + + /// The parent field + const std::string* parent_field = nullptr; + }; + +} // namespace ast + +#include <ast/dumper-dot.hxx> diff --git a/tiger-compiler/src/ast/dumper-dot.hxx b/tiger-compiler/src/ast/dumper-dot.hxx new file mode 100644 index 0000000..30a7b33 --- /dev/null +++ b/tiger-compiler/src/ast/dumper-dot.hxx @@ -0,0 +1,214 @@ +/** + ** \file ast/dumper-dot.hxx + ** \brief Implementation of ast::DumperDot. + */ + +#pragma once + +#include <cstdint> +#include <ast/dumper-dot.hh> +#include <misc/indent.hh> + +namespace ast +{ + + template <typename Container> + requires misc::ConstIterable<Container> + inline void DumperDot::dump_list(const std::string& field, const Container& l) + { + const std::string* old_parent_field = parent_field; + auto it = l.begin(); + unsigned n = 0; + while (it != l.end()) + { + std::ostringstream o; + o << field; + if (std::next(it) != l.end() || n > 0) + o << n++; + const std::string field_name = o.str(); + parent_field = &field_name; + (*it++)->accept(*this); + } + parent_field = old_parent_field; + } + + template <typename T> inline void DumperDot::dump_def(const T& e) const + { + const ast::Ast* d = nullptr; + // FIXME: Some code was deleted here (set d using definition of e). + (void)e; + if (!d) + return; + ostr_ << parent_id << ":def:s -> " << reinterpret_cast<std::uintptr_t>(d) + << ":nodename [constraint=false, style=dashed, color=\"dimgray\"]" + << misc::iendl; + } + + inline void DumperDot::display_link(unsigned long old_parent_id) const + { + if (parent_field) + ostr_ << old_parent_id << ":" << *parent_field << ":s" + << " -> " << parent_id << ":nodename:n" << misc::iendl; + } + + inline void DumperDot::footer_and_link(unsigned long old_parent_id) const + { + node_html_footer(); + display_link(old_parent_id); + } + + template <typename E> + inline void DumperDot::dump_chunk(const E& e, const std::string& name) + { + unsigned long old_parent_id = parent_id; + parent_id = reinterpret_cast<std::uintptr_t>(&e); + ostr_ << parent_id << " [label=<" << misc::incendl + << "<table cellborder='0' cellspacing='0'>" << misc::incendl << "<tr>" + << misc::incendl; + inner_fields = 0; + node_html_port_list(name, e, true); + ostr_ << misc::decendl << "</tr>" << misc::decendl << "</table>" + << misc::decendl << ">]" << misc::iendl; + display_link(old_parent_id); + dump_list("nodename", e); + parent_id = old_parent_id; + } + + namespace + { + inline void node_html_begin_inner(std::ostream& ostr, bool list = false) + { + ostr << "<td cellpadding='0'>" << misc::incendl + << "<table border='0' cellborder='" << (list ? 0 : 1) << "'" + << " cellspacing='0' cellpadding='" << (list ? 0 : 2) << "'>" + << misc::incendl << "<tr>" << misc::incendl; + } + + inline void node_html_end_inner(std::ostream& ostr) + { + ostr << misc::decendl << "</tr>" << misc::decendl << "</table>" + << misc::decendl << "</td>"; + } + + inline void node_html_separator(std::ostream& ostr) + { + node_html_end_inner(ostr); + ostr << misc::decendl << "</tr>" << misc::iendl << "<tr>" + << misc::incendl; + node_html_begin_inner(ostr); + } + inline void node_html_tr(std::ostream& ostr, + const std::string& port, + const std::string content) + { + ostr << "<td port='" << port << "'>" << content << "</td>"; + } + inline bool ends_with(const std::string& value, const std::string& ending) + { + if (ending.size() > value.size()) + return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); + } + inline std::string node_html_color(const std::string& type) + { + if (ends_with(type, "Dec")) + return "red1"; + else if (ends_with(type, "Var")) + return "orange1"; + else if (ends_with(type, "Ty")) + return "green3"; + else if (ends_with(type, "Exp")) + return "blue2"; + return "black"; + } + + template <typename T> std::string html_escape(const T& input) + { + std::ostringstream i; + i << input; + const std::string& str = i.str(); + std::ostringstream o; + const std::string& specials = "&<>"; + for (const auto& p : str) + if (p == '\\') + o << '\\' << '\\'; + else if (specials.find(p) != std::string::npos) + o << "&#" << static_cast<int>(static_cast<unsigned char>(p)) << ";"; + else + o << p; + return o.str(); + } + } // namespace + + template <typename T> + inline unsigned long DumperDot::node_html_header(const T& e, + const std::string& type) + { + unsigned long old_parent_id = parent_id; + parent_id = reinterpret_cast<std::uintptr_t>(&e); + ostr_ << parent_id << " [label=<" << misc::incendl + << "<table border='0' cellborder='0' cellspacing='0' cellpadding='0'" + << " color='" << node_html_color(type) << "'>" << misc::incendl + << "<tr>" << misc::incendl; + node_html_begin_inner(ostr_); + node_html_tr(ostr_, "nodename", type); + node_html_separator(ostr_); + inner_fields = 0; + return old_parent_id; + } + template <typename T> + inline void DumperDot::node_html_field(const std::string& name, + const T& content, + const std::string& sep) + { + std::ostringstream o; + o << name << ": " << sep << html_escape(content) << sep; + if (inner_fields++) + ostr_ << misc::iendl; + node_html_tr(ostr_, name, o.str()); + } + inline void DumperDot::node_html_one_port(const std::string& p) + { + if (inner_fields++) + ostr_ << misc::iendl; + node_html_tr(ostr_, p, p); + } + inline void DumperDot::node_html_ports(const std::vector<std::string>& ports) + { + if (inner_fields) + node_html_separator(ostr_); + inner_fields = 0; + for (auto p : ports) + node_html_one_port(p); + } + template <typename T> + inline void DumperDot::node_html_port_list(const std::string& name, + const T& list, + bool chunk) + { + if (inner_fields++) + ostr_ << misc::iendl; + const std::string ref = chunk ? "nodename" : name; + node_html_begin_inner(ostr_, true); + long int size = std::distance(list.begin(), list.end()); + ostr_ << "<td port='" << ref << "' colspan='" << (size ? size : 1) << "'>" + << name << "</td>"; + if (size > 1) + { + ostr_ << misc::decendl << "</tr>" << misc::iendl << "<tr>" + << misc::incindent; + for (long int n = 0; n < size; n++) + ostr_ << misc::iendl << "<td port='" << ref << n << "'>" << n + << "</td>"; + } + node_html_end_inner(ostr_); + } + inline void DumperDot::node_html_footer() const + { + if (!inner_fields) + ostr_ << "<td></td>"; + node_html_end_inner(ostr_); + ostr_ << misc::decendl << "</tr>" << misc::decendl << "</table>" + << misc::decendl << ">]" << misc::iendl; + } +} // namespace ast diff --git a/tiger-compiler/src/ast/escapable.cc b/tiger-compiler/src/ast/escapable.cc new file mode 100644 index 0000000..9ca80e4 --- /dev/null +++ b/tiger-compiler/src/ast/escapable.cc @@ -0,0 +1,14 @@ +/**
+ ** \file ast/escapable.cc
+ ** \brief Implementation of ast::Escapable.
+ */
+
+#include <ast/escapable.hh>
+#include <ast/visitor.hh>
+
+namespace ast
+{
+ // FIXME DONE: Some code was deleted here.
+ bool Escapable::escape_get() const { return escaping_; }
+ void Escapable::escape_set(bool escaped) { escaping_ = escaped; }
+} // namespace ast
diff --git a/tiger-compiler/src/ast/escapable.hh b/tiger-compiler/src/ast/escapable.hh new file mode 100644 index 0000000..b062114 --- /dev/null +++ b/tiger-compiler/src/ast/escapable.hh @@ -0,0 +1,30 @@ +/**
+ ** \file ast/escapable.hh
+ ** \brief Declaration of ast::Escapable.
+ */
+
+#pragma once
+
+#include <ast/fwd.hh>
+
+namespace ast
+{
+ /// Escapable.
+ class Escapable
+ {
+ // FIXME DONE: Some code was deleted here.
+ public:
+ // Returns whether the object is escaped
+ bool escape_get() const;
+ // Sets the escaped status of the object
+ void escape_set(bool escaped);
+ // Return definition site.
+ FunctionDec* def_get() const;
+ // Set definition site.
+ void def_set(FunctionDec*);
+ private:
+ bool escaping_ = true;
+ FunctionDec* def_ = nullptr;
+ };
+} // namespace ast
+#include <ast/escapable.hxx>
diff --git a/tiger-compiler/src/ast/escapable.hxx b/tiger-compiler/src/ast/escapable.hxx new file mode 100644 index 0000000..00cb4bb --- /dev/null +++ b/tiger-compiler/src/ast/escapable.hxx @@ -0,0 +1,16 @@ +/**
+ ** \file ast/escapable.hxx
+ ** \brief Inline methods of ast::Escapable.
+ */
+
+#pragma once
+
+#include <ast/escapable.hh>
+
+namespace ast
+{
+ // FIXME DONE: Some code was deleted here.
+ inline FunctionDec* Escapable::def_get() const { return def_; }
+ inline void Escapable::def_set(FunctionDec* dec) { def_ = dec; }
+
+} // namespace ast
diff --git a/tiger-compiler/src/ast/exp.cc b/tiger-compiler/src/ast/exp.cc new file mode 100644 index 0000000..1c3ce32 --- /dev/null +++ b/tiger-compiler/src/ast/exp.cc @@ -0,0 +1,16 @@ +/** + ** \file ast/exp.cc + ** \brief Implementation of ast::Exp. + */ + +#include <ast/exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + Exp::Exp(const Location& location) + : Ast(location) + , Typable() + {} + +} // namespace ast diff --git a/tiger-compiler/src/ast/exp.hh b/tiger-compiler/src/ast/exp.hh new file mode 100644 index 0000000..a4202c1 --- /dev/null +++ b/tiger-compiler/src/ast/exp.hh @@ -0,0 +1,43 @@ +/** + ** \file ast/exp.hh + ** \brief Declaration of ast::Exp. + */ + +#pragma once + +#include <ast/ast.hh> +#include <ast/typable.hh> + +namespace ast +{ + /// Exp. + class Exp + : public Ast + , public Typable + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct an Exp node. + explicit Exp(const Location& location); + Exp(const Exp&) = delete; + Exp& operator=(const Exp&) = delete; + /// Destroy an Exp node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override = 0; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override = 0; + /// \} + + /** \name Accessors. + ** \{ */ + /** \} */ + + protected: + }; +} // namespace ast +#include <ast/exp.hxx> diff --git a/tiger-compiler/src/ast/exp.hxx b/tiger-compiler/src/ast/exp.hxx new file mode 100644 index 0000000..49a8274 --- /dev/null +++ b/tiger-compiler/src/ast/exp.hxx @@ -0,0 +1,11 @@ +/** + ** \file ast/exp.hxx + ** \brief Inline methods of ast::Exp. + */ + +#pragma once + +#include <ast/exp.hh> + +namespace ast +{} // namespace ast diff --git a/tiger-compiler/src/ast/field-init.cc b/tiger-compiler/src/ast/field-init.cc new file mode 100644 index 0000000..54b5266 --- /dev/null +++ b/tiger-compiler/src/ast/field-init.cc @@ -0,0 +1,22 @@ +/** + ** \file ast/field-init.cc + ** \brief Implementation of ast::FieldInit. + */ + +#include <ast/field-init.hh> +#include <ast/visitor.hh> + +namespace ast +{ + FieldInit::FieldInit(const Location& location, misc::symbol name, Exp* init) + : Ast(location) + , name_(name) + , init_(init) + {} + + FieldInit::~FieldInit() { delete init_; } + + void FieldInit::accept(ConstVisitor& v) const { v(*this); } + + void FieldInit::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/field-init.hh b/tiger-compiler/src/ast/field-init.hh new file mode 100644 index 0000000..9ea18b2 --- /dev/null +++ b/tiger-compiler/src/ast/field-init.hh @@ -0,0 +1,55 @@ +/** + ** \file ast/field-init.hh + ** \brief Declaration of ast::FieldInit. + */ + +#pragma once + +#include <ast/ast.hh> +#include <ast/exp.hh> +#include <misc/symbol.hh> + +namespace ast +{ + /// FieldInit. + class FieldInit : public Ast + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a FieldInit node. + FieldInit(const Location& location, misc::symbol name, Exp* init); + FieldInit(const FieldInit&) = delete; + FieldInit& operator=(const FieldInit&) = delete; + /// Destroy a FieldInit node. + ~FieldInit() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return name of the field. + misc::symbol name_get() const; + /// Set name of the field. + void name_set(misc::symbol); + /// Return initial value of the field. + const Exp& init_get() const; + /// Return initial value of the field. + Exp& init_get(); + /** \} */ + + protected: + /// Name of the field. + misc::symbol name_; + /// Initial value of the field. + Exp* init_; + }; +} // namespace ast +#include <ast/field-init.hxx> diff --git a/tiger-compiler/src/ast/field-init.hxx b/tiger-compiler/src/ast/field-init.hxx new file mode 100644 index 0000000..1a895b7 --- /dev/null +++ b/tiger-compiler/src/ast/field-init.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/field-init.hxx + ** \brief Inline methods of ast::FieldInit. + */ + +#pragma once + +#include <ast/field-init.hh> + +namespace ast +{ + + inline misc::symbol FieldInit::name_get() const { return name_; } + inline void FieldInit::name_set(misc::symbol name) { name_ = name; } + + inline const Exp& FieldInit::init_get() const { return *init_; } + inline Exp& FieldInit::init_get() { return *init_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/field-var.cc b/tiger-compiler/src/ast/field-var.cc new file mode 100644 index 0000000..7423fc1 --- /dev/null +++ b/tiger-compiler/src/ast/field-var.cc @@ -0,0 +1,22 @@ +/** + ** \file ast/field-var.cc + ** \brief Implementation of ast::FieldVar. + */ + +#include <ast/field-var.hh> +#include <ast/visitor.hh> + +namespace ast +{ + FieldVar::FieldVar(const Location& location, Var* var, misc::symbol name) + : Var(location) + , var_(var) + , name_(name) + {} + + FieldVar::~FieldVar() { delete var_; } + + void FieldVar::accept(ConstVisitor& v) const { v(*this); } + + void FieldVar::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/field-var.hh b/tiger-compiler/src/ast/field-var.hh new file mode 100644 index 0000000..06c0b9a --- /dev/null +++ b/tiger-compiler/src/ast/field-var.hh @@ -0,0 +1,60 @@ +/** + ** \file ast/field-var.hh + ** \brief Declaration of ast::FieldVar. + */ + +#pragma once + +#include <ast/var.hh> +#include <misc/symbol.hh> + +namespace ast +{ + /// FieldVar. + class FieldVar : public Var + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a FieldVar node. + FieldVar(const Location& location, Var* var, misc::symbol name); + FieldVar(const FieldVar&) = delete; + FieldVar& operator=(const FieldVar&) = delete; + /// Destroy a FieldVar node. + ~FieldVar() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return the record that holds the field. + const Var& var_get() const; + /// Return the record that holds the field. + Var& var_get(); + /// Return the field's name. + misc::symbol name_get() const; + /// Set the field's name. + void name_set(misc::symbol); + /// Return handle the number of the field in the record that holds it. + int index_get() const; + /// Set handle the number of the field in the record that holds it. + void index_set(int); + /** \} */ + + protected: + /// The record that holds the field. + Var* var_; + /// The field's name. + misc::symbol name_; + /// Handle the number of the field in the record that holds it. + int index_ = -1; + }; +} // namespace ast +#include <ast/field-var.hxx> diff --git a/tiger-compiler/src/ast/field-var.hxx b/tiger-compiler/src/ast/field-var.hxx new file mode 100644 index 0000000..cfadc89 --- /dev/null +++ b/tiger-compiler/src/ast/field-var.hxx @@ -0,0 +1,22 @@ +/** + ** \file ast/field-var.hxx + ** \brief Inline methods of ast::FieldVar. + */ + +#pragma once + +#include <ast/field-var.hh> + +namespace ast +{ + + inline const Var& FieldVar::var_get() const { return *var_; } + inline Var& FieldVar::var_get() { return *var_; } + + inline misc::symbol FieldVar::name_get() const { return name_; } + inline void FieldVar::name_set(misc::symbol name) { name_ = name; } + + inline int FieldVar::index_get() const { return index_; } + inline void FieldVar::index_set(int index) { index_ = index; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/field.cc b/tiger-compiler/src/ast/field.cc new file mode 100644 index 0000000..7265f24 --- /dev/null +++ b/tiger-compiler/src/ast/field.cc @@ -0,0 +1,22 @@ +/** + ** \file ast/field.cc + ** \brief Implementation of ast::Field. + */ + +#include <ast/field.hh> +#include <ast/visitor.hh> + +namespace ast +{ + Field::Field(const Location& location, misc::symbol name, NameTy* type_name) + : Ast(location) + , name_(name) + , type_name_(type_name) + {} + + Field::~Field() { delete type_name_; } + + void Field::accept(ConstVisitor& v) const { v(*this); } + + void Field::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/field.hh b/tiger-compiler/src/ast/field.hh new file mode 100644 index 0000000..cbb6352 --- /dev/null +++ b/tiger-compiler/src/ast/field.hh @@ -0,0 +1,55 @@ +/** + ** \file ast/field.hh + ** \brief Declaration of ast::Field. + */ + +#pragma once + +#include <ast/ast.hh> +#include <ast/name-ty.hh> +#include <misc/symbol.hh> + +namespace ast +{ + /// Field. + class Field : public Ast + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a Field node. + Field(const Location& location, misc::symbol name, NameTy* type_name); + Field(const Field&) = delete; + Field& operator=(const Field&) = delete; + /// Destroy a Field node. + ~Field() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return the field name. + misc::symbol name_get() const; + /// Set the field name. + void name_set(misc::symbol); + /// Return the field type name. + const NameTy& type_name_get() const; + /// Return the field type name. + NameTy& type_name_get(); + /** \} */ + + protected: + /// The field name. + misc::symbol name_; + /// The field type name. + NameTy* type_name_; + }; +} // namespace ast +#include <ast/field.hxx> diff --git a/tiger-compiler/src/ast/field.hxx b/tiger-compiler/src/ast/field.hxx new file mode 100644 index 0000000..0c7658c --- /dev/null +++ b/tiger-compiler/src/ast/field.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/field.hxx + ** \brief Inline methods of ast::Field. + */ + +#pragma once + +#include <ast/field.hh> + +namespace ast +{ + + inline misc::symbol Field::name_get() const { return name_; } + inline void Field::name_set(misc::symbol name) { name_ = name; } + + inline const NameTy& Field::type_name_get() const { return *type_name_; } + inline NameTy& Field::type_name_get() { return *type_name_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/for-exp.cc b/tiger-compiler/src/ast/for-exp.cc new file mode 100644 index 0000000..2ed51e1 --- /dev/null +++ b/tiger-compiler/src/ast/for-exp.cc @@ -0,0 +1,28 @@ +/** + ** \file ast/for-exp.cc + ** \brief Implementation of ast::ForExp. + */ + +#include <ast/for-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + ForExp::ForExp(const Location& location, VarDec* vardec, Exp* hi, Exp* body) + : Exp(location) + , vardec_(vardec) + , hi_(hi) + , body_(body) + {} + + ForExp::~ForExp() + { + delete vardec_; + delete hi_; + delete body_; + } + + void ForExp::accept(ConstVisitor& v) const { v(*this); } + + void ForExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/for-exp.hh b/tiger-compiler/src/ast/for-exp.hh new file mode 100644 index 0000000..b06a9be --- /dev/null +++ b/tiger-compiler/src/ast/for-exp.hh @@ -0,0 +1,60 @@ +/** + ** \file ast/for-exp.hh + ** \brief Declaration of ast::ForExp. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/var-dec.hh> + +namespace ast +{ + /// ForExp. + class ForExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a ForExp node. + ForExp(const Location& location, VarDec* vardec, Exp* hi, Exp* body); + ForExp(const ForExp&) = delete; + ForExp& operator=(const ForExp&) = delete; + /// Destroy a ForExp node. + ~ForExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return implicit variable declaration. + const VarDec& vardec_get() const; + /// Return implicit variable declaration. + VarDec& vardec_get(); + /// Return high bound of the loop. + const Exp& hi_get() const; + /// Return high bound of the loop. + Exp& hi_get(); + /// Return instructions executed in the loop. + const Exp& body_get() const; + /// Return instructions executed in the loop. + Exp& body_get(); + /** \} */ + + protected: + /// Implicit variable declaration. + VarDec* vardec_; + /// High bound of the loop. + Exp* hi_; + /// Instructions executed in the loop. + Exp* body_; + }; +} // namespace ast +#include <ast/for-exp.hxx> diff --git a/tiger-compiler/src/ast/for-exp.hxx b/tiger-compiler/src/ast/for-exp.hxx new file mode 100644 index 0000000..c81d30f --- /dev/null +++ b/tiger-compiler/src/ast/for-exp.hxx @@ -0,0 +1,22 @@ +/** + ** \file ast/for-exp.hxx + ** \brief Inline methods of ast::ForExp. + */ + +#pragma once + +#include <ast/for-exp.hh> + +namespace ast +{ + + inline const VarDec& ForExp::vardec_get() const { return *vardec_; } + inline VarDec& ForExp::vardec_get() { return *vardec_; } + + inline const Exp& ForExp::hi_get() const { return *hi_; } + inline Exp& ForExp::hi_get() { return *hi_; } + + inline const Exp& ForExp::body_get() const { return *body_; } + inline Exp& ForExp::body_get() { return *body_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/function-dec.cc b/tiger-compiler/src/ast/function-dec.cc new file mode 100644 index 0000000..c45ca0d --- /dev/null +++ b/tiger-compiler/src/ast/function-dec.cc @@ -0,0 +1,33 @@ +/** + ** \file ast/function-dec.cc + ** \brief Implementation of ast::FunctionDec. + */ + +#include <ast/function-dec.hh> +#include <ast/visitor.hh> + +namespace ast +{ + FunctionDec::FunctionDec(const Location& location, + misc::symbol name, + VarChunk* formals, + NameTy* result, + Exp* body) + : Dec(location, name) + , TypeConstructor() + , formals_(formals) + , result_(result) + , body_(body) + {} + + FunctionDec::~FunctionDec() + { + delete formals_; + delete result_; + delete body_; + } + + void FunctionDec::accept(ConstVisitor& v) const { v(*this); } + + void FunctionDec::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/function-dec.hh b/tiger-compiler/src/ast/function-dec.hh new file mode 100644 index 0000000..0a94e95 --- /dev/null +++ b/tiger-compiler/src/ast/function-dec.hh @@ -0,0 +1,72 @@ +/** + ** \file ast/function-dec.hh + ** \brief Declaration of ast::FunctionDec. + */ + +#pragma once + +#include <ast/chunk.hh> +#include <ast/dec.hh> +#include <ast/exp.hh> +#include <ast/name-ty.hh> +#include <ast/type-constructor.hh> +#include <ast/var-dec.hh> + +namespace ast +{ + /// FunctionDec. + class FunctionDec + : public Dec + , public TypeConstructor + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a FunctionDec node. + FunctionDec(const Location& location, + misc::symbol name, + VarChunk* formals, + NameTy* result, + Exp* body); + FunctionDec(const FunctionDec&) = delete; + FunctionDec& operator=(const FunctionDec&) = delete; + /// Destroy a FunctionDec node. + ~FunctionDec() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return formal arguments. + const VarChunk& formals_get() const; + /// Return formal arguments. + VarChunk& formals_get(); + /// Return result type. + const NameTy* result_get() const; + /// Return result type. + NameTy* result_get(); + /// Return instructions. + const Exp* body_get() const; + /// Return instructions. + Exp* body_get(); + /// Set instructions. + void body_set(Exp*); + /** \} */ + + protected: + /// Formal arguments. + VarChunk* formals_; + /// Result type. + NameTy* result_; + /// Instructions. + Exp* body_; + }; +} // namespace ast +#include <ast/function-dec.hxx> diff --git a/tiger-compiler/src/ast/function-dec.hxx b/tiger-compiler/src/ast/function-dec.hxx new file mode 100644 index 0000000..b9dda47 --- /dev/null +++ b/tiger-compiler/src/ast/function-dec.hxx @@ -0,0 +1,23 @@ +/** + ** \file ast/function-dec.hxx + ** \brief Inline methods of ast::FunctionDec. + */ + +#pragma once + +#include <ast/function-dec.hh> + +namespace ast +{ + + inline const VarChunk& FunctionDec::formals_get() const { return *formals_; } + inline VarChunk& FunctionDec::formals_get() { return *formals_; } + + inline const NameTy* FunctionDec::result_get() const { return result_; } + inline NameTy* FunctionDec::result_get() { return result_; } + + inline const Exp* FunctionDec::body_get() const { return body_; } + inline Exp* FunctionDec::body_get() { return body_; } + inline void FunctionDec::body_set(Exp* body) { body_ = body; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/fwd.hh b/tiger-compiler/src/ast/fwd.hh new file mode 100644 index 0000000..3d2a611 --- /dev/null +++ b/tiger-compiler/src/ast/fwd.hh @@ -0,0 +1,80 @@ +/** + ** \file ast/fwd.hh + ** \brief Forward declarations of all AST classes + ** (needed by the visitors). + */ + +#pragma once + +#include <list> +#include <vector> +#include <misc/fwd.hh> +#include <misc/vector.hh> + +namespace ast +{ + class ArrayExp; + class ArrayTy; + class AssertExp; + class AssignExp; + class Ast; + class BreakExp; + class CallExp; + class CastExp; + class ChunkList; + class ClassTy; + class Dec; + class Escapable; + class Exp; + class Field; + class FieldInit; + class FieldVar; + class ForExp; + class FunctionDec; + class IfExp; + class IntExp; + class LetExp; + class MethodCallExp; + class MethodDec; + class NameTy; + class NilExp; + class ObjectExp; + class OpExp; + class RecordExp; + class RecordTy; + class SeqExp; + class SimpleVar; + class StringExp; + class SubscriptVar; + class Ty; + class Typable; + class TypeConstructor; + class TypeDec; + class Var; + class VarDec; + class WhileExp; + + // From visitor.hh + template <template <typename> class Const> class GenVisitor; + using ConstVisitor = GenVisitor<misc::constify_traits>; + using Visitor = GenVisitor<misc::id_traits>; + + // Collections of nodes. + using exps_type = std::vector<Exp*>; + using fieldinits_type = std::vector<FieldInit*>; + using fields_type = std::vector<Field*>; + + // From chunk-interface.hh. + class ChunkInterface; + + // From chunk-list.hh. + class ChunkList; + + // From chunk.hh. + template <typename T> class Chunk; + using FunctionChunk = Chunk<FunctionDec>; + using MethodChunk = Chunk<MethodDec>; + using TypeChunk = Chunk<TypeDec>; + using VarChunk = Chunk<VarDec>; + +} // namespace ast diff --git a/tiger-compiler/src/ast/if-exp.cc b/tiger-compiler/src/ast/if-exp.cc new file mode 100644 index 0000000..ae1911f --- /dev/null +++ b/tiger-compiler/src/ast/if-exp.cc @@ -0,0 +1,31 @@ +/** + ** \file ast/if-exp.cc + ** \brief Implementation of ast::IfExp. + */ + +#include <ast/if-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + IfExp::IfExp(const Location& location, + Exp* test, + Exp* thenclause, + Exp* elseclause) + : Exp(location) + , test_(test) + , thenclause_(thenclause) + , elseclause_(elseclause) + {} + + IfExp::~IfExp() + { + delete test_; + delete thenclause_; + delete elseclause_; + } + + void IfExp::accept(ConstVisitor& v) const { v(*this); } + + void IfExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/if-exp.hh b/tiger-compiler/src/ast/if-exp.hh new file mode 100644 index 0000000..6b27452 --- /dev/null +++ b/tiger-compiler/src/ast/if-exp.hh @@ -0,0 +1,71 @@ +/** + ** \file ast/if-exp.hh + ** \brief Declaration of ast::IfExp. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/seq-exp.hh> + +namespace ast +{ + /// IfExp. + class IfExp : public Exp + { + public: + IfExp(const Location& location, Exp* test, Exp* thenclause) + : Exp(location) + , test_(test) + , thenclause_(thenclause) + , elseclause_(new SeqExp(location, new exps_type())) + {} + + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct an IfExp node. + IfExp(const Location& location, + Exp* test, + Exp* thenclause, + Exp* elseclause); + IfExp(const IfExp&) = delete; + IfExp& operator=(const IfExp&) = delete; + /// Destroy an IfExp node. + ~IfExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return condition. + const Exp& test_get() const; + /// Return condition. + Exp& test_get(); + /// Return instructions executed if condition is true. + const Exp& thenclause_get() const; + /// Return instructions executed if condition is true. + Exp& thenclause_get(); + /// Return instructions executed if condition is false. + const Exp& elseclause_get() const; + /// Return instructions executed if condition is false. + Exp& elseclause_get(); + /** \} */ + + protected: + /// Condition. + Exp* test_; + /// Instructions executed if condition is true. + Exp* thenclause_; + /// Instructions executed if condition is false. + Exp* elseclause_; + }; +} // namespace ast +#include <ast/if-exp.hxx> diff --git a/tiger-compiler/src/ast/if-exp.hxx b/tiger-compiler/src/ast/if-exp.hxx new file mode 100644 index 0000000..7b6cb07 --- /dev/null +++ b/tiger-compiler/src/ast/if-exp.hxx @@ -0,0 +1,22 @@ +/** + ** \file ast/if-exp.hxx + ** \brief Inline methods of ast::IfExp. + */ + +#pragma once + +#include <ast/if-exp.hh> + +namespace ast +{ + + inline const Exp& IfExp::test_get() const { return *test_; } + inline Exp& IfExp::test_get() { return *test_; } + + inline const Exp& IfExp::thenclause_get() const { return *thenclause_; } + inline Exp& IfExp::thenclause_get() { return *thenclause_; } + + inline const Exp& IfExp::elseclause_get() const { return *elseclause_; } + inline Exp& IfExp::elseclause_get() { return *elseclause_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/int-exp.cc b/tiger-compiler/src/ast/int-exp.cc new file mode 100644 index 0000000..e2fb992 --- /dev/null +++ b/tiger-compiler/src/ast/int-exp.cc @@ -0,0 +1,19 @@ +/** + ** \file ast/int-exp.cc + ** \brief Implementation of ast::IntExp. + */ + +#include <ast/int-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + IntExp::IntExp(const Location& location, int value) + : Exp(location) + , value_(value) + {} + + void IntExp::accept(ConstVisitor& v) const { v(*this); } + + void IntExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/int-exp.hh b/tiger-compiler/src/ast/int-exp.hh new file mode 100644 index 0000000..a15bdf0 --- /dev/null +++ b/tiger-compiler/src/ast/int-exp.hh @@ -0,0 +1,44 @@ +/** + ** \file ast/int-exp.hh + ** \brief Declaration of ast::IntExp. + */ + +#pragma once + +#include <ast/exp.hh> + +namespace ast +{ + /// IntExp. + class IntExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct an IntExp node. + IntExp(const Location& location, int value); + IntExp(const IntExp&) = delete; + IntExp& operator=(const IntExp&) = delete; + /// Destroy an IntExp node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return stored integer value. + int value_get() const; + /** \} */ + + protected: + /// Stored integer value. + int value_; + }; +} // namespace ast +#include <ast/int-exp.hxx> diff --git a/tiger-compiler/src/ast/int-exp.hxx b/tiger-compiler/src/ast/int-exp.hxx new file mode 100644 index 0000000..0308ba7 --- /dev/null +++ b/tiger-compiler/src/ast/int-exp.hxx @@ -0,0 +1,15 @@ +/** + ** \file ast/int-exp.hxx + ** \brief Inline methods of ast::IntExp. + */ + +#pragma once + +#include <ast/int-exp.hh> + +namespace ast +{ + + inline int IntExp::value_get() const { return value_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/let-exp.cc b/tiger-compiler/src/ast/let-exp.cc new file mode 100644 index 0000000..0ded46b --- /dev/null +++ b/tiger-compiler/src/ast/let-exp.cc @@ -0,0 +1,26 @@ +/** + ** \file ast/let-exp.cc + ** \brief Implementation of ast::LetExp. + */ + +#include <ast/let-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + LetExp::LetExp(const Location& location, ChunkList* chunks, Exp* body) + : Exp(location) + , chunks_(chunks) + , body_(body) + {} + + LetExp::~LetExp() + { + delete chunks_; + delete body_; + } + + void LetExp::accept(ConstVisitor& v) const { v(*this); } + + void LetExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/let-exp.hh b/tiger-compiler/src/ast/let-exp.hh new file mode 100644 index 0000000..7955eeb --- /dev/null +++ b/tiger-compiler/src/ast/let-exp.hh @@ -0,0 +1,55 @@ +/** + ** \file ast/let-exp.hh + ** \brief Declaration of ast::LetExp. + */ + +#pragma once + +#include <ast/chunk-list.hh> +#include <ast/exp.hh> +#include <misc/contract.hh> + +namespace ast +{ + /// LetExp. + class LetExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a LetExp node. + LetExp(const Location& location, ChunkList* chunks, Exp* body); + LetExp(const LetExp&) = delete; + LetExp& operator=(const LetExp&) = delete; + /// Destroy a LetExp node. + ~LetExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return list of declarations. + const ChunkList& chunks_get() const; + /// Return list of declarations. + ChunkList& chunks_get(); + /// Return list of instructions. + const Exp& body_get() const; + /// Return list of instructions. + Exp& body_get(); + /** \} */ + + protected: + /// List of declarations. + ChunkList* chunks_; + /// List of instructions. + Exp* body_; + }; +} // namespace ast +#include <ast/let-exp.hxx> diff --git a/tiger-compiler/src/ast/let-exp.hxx b/tiger-compiler/src/ast/let-exp.hxx new file mode 100644 index 0000000..9d6589c --- /dev/null +++ b/tiger-compiler/src/ast/let-exp.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/let-exp.hxx + ** \brief Inline methods of ast::LetExp. + */ + +#pragma once + +#include <ast/let-exp.hh> + +namespace ast +{ + + inline const ChunkList& LetExp::chunks_get() const { return *chunks_; } + inline ChunkList& LetExp::chunks_get() { return *chunks_; } + + inline const Exp& LetExp::body_get() const { return *body_; } + inline Exp& LetExp::body_get() { return *body_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/libast.cc b/tiger-compiler/src/ast/libast.cc new file mode 100644 index 0000000..0bebaa0 --- /dev/null +++ b/tiger-compiler/src/ast/libast.cc @@ -0,0 +1,44 @@ +/** + ** \file ast/libast.cc + ** \brief Public ast interface implementation. + */ + +#include <fstream> + +#include <ast/dumper-dot.hh> +#include <ast/libast.hh> +#include <ast/pretty-printer.hh> + +// Define exported ast functions. +namespace ast +{ + // Making the following variables const is more than merely + // stylistic. If they were not, Swig will create set/get for them, + // and there is no set (operator=), since it has a const member. + + /// xalloc slot to enable escapes display in Ast display. + const misc::xalloc<bool> escapes_display; + /// xalloc slot to enable bindings display in Ast display. + const misc::xalloc<bool> bindings_display; + + // Print the TREE on OSTR. + std::ostream& operator<<(std::ostream& ostr, const Ast& tree) + { + PrettyPrinter print(ostr); + print(tree); + return ostr; + } + + /// Dump \a a on \a ostr. + std::ostream& dump_dot(const Ast& tree, std::ostream& ostr) + { + DumperDot dump_dot(ostr); + ostr << misc::resetindent << "digraph structs {" << misc::incendl; + ostr << "splines=line;" << misc::iendl; + ostr << "node [shape=plaintext]" << misc::iendl; + dump_dot(tree); + ostr << misc::decendl << "}" << misc::iendl; + return ostr; + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/libast.hh b/tiger-compiler/src/ast/libast.hh new file mode 100644 index 0000000..121749d --- /dev/null +++ b/tiger-compiler/src/ast/libast.hh @@ -0,0 +1,26 @@ +/** + ** \file ast/libast.hh + ** \brief Public ast interface declaration. + */ + +#pragma once + +#include <iosfwd> + +#include <misc/xalloc.hh> + +#include <ast/fwd.hh> + +/// Ast management. +namespace ast +{ + extern const misc::xalloc<bool> escapes_display; + extern const misc::xalloc<bool> bindings_display; + + /// Output \a a on \a ostr. + std::ostream& operator<<(std::ostream& ostr, const Ast& tree); + + /// Dump \a a on \a ostr. + std::ostream& dump_dot(const Ast& tree, std::ostream& ostr); + +} // namespace ast diff --git a/tiger-compiler/src/ast/local.am b/tiger-compiler/src/ast/local.am new file mode 100644 index 0000000..1e520c5 --- /dev/null +++ b/tiger-compiler/src/ast/local.am @@ -0,0 +1,30 @@ +ast_basedir = src/ast/ +ast_srcdir = $(srcdir)/%D% +# Don't use ast_srcdir in the include, otherwise Automake can't resolve it. +include $(srcdir)/%D%/ast-nodes.mk + + +src_libtc_la_SOURCES += \ + %D%/location.hh \ + %D%/all.hh \ + %D%/chunk-interface.hh %D%/chunk-interface.hxx \ + %D%/chunk.hh %D%/chunk.hxx \ + %D%/fwd.hh \ + %D%/visitor.hh \ + $(AST_NODES) \ + %D%/default-visitor.hh %D%/default-visitor.hxx \ + %D%/dumper-dot.hh %D%/dumper-dot.hxx %D%/dumper-dot.cc \ + %D%/non-object-visitor.hh %D%/non-object-visitor.hxx \ + %D%/non-assert-visitor.hh %D%/non-assert-visitor.hxx \ + %D%/object-visitor.hh %D%/object-visitor.hxx \ + %D%/assert-visitor.hh %D%/assert-visitor.hxx \ + %D%/pretty-printer.hh %D%/pretty-printer.cc \ + %D%/visitor.hxx \ + %D%/libast.hh %D%/libast.cc + +dist_noinst_DATA += %D%/README.txt + +check_PROGRAMS += %D%/test-ast +%C%_test_ast_LDADD = src/libtc.la + +TASKS += %D%/tasks.hh %D%/tasks.cc diff --git a/tiger-compiler/src/ast/location.hh b/tiger-compiler/src/ast/location.hh new file mode 100644 index 0000000..9e6e398 --- /dev/null +++ b/tiger-compiler/src/ast/location.hh @@ -0,0 +1,14 @@ +/** + ** \file ast/location.hh + ** \brief Definition of ast::Location. + */ + +#pragma once + +#include <misc/symbol.hh> +#include <parse/location.hh> + +namespace ast +{ + using Location = parse::location; +} diff --git a/tiger-compiler/src/ast/method-call-exp.cc b/tiger-compiler/src/ast/method-call-exp.cc new file mode 100644 index 0000000..bdf1f41 --- /dev/null +++ b/tiger-compiler/src/ast/method-call-exp.cc @@ -0,0 +1,24 @@ +/** + ** \file ast/method-call-exp.cc + ** \brief Implementation of ast::MethodCallExp. + */ + +#include <ast/method-call-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + MethodCallExp::MethodCallExp(const Location& location, + misc::symbol name, + exps_type* args, + Var* object) + : CallExp(location, name, args) + , object_(object) + {} + + MethodCallExp::~MethodCallExp() { delete object_; } + + void MethodCallExp::accept(ConstVisitor& v) const { v(*this); } + + void MethodCallExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/method-call-exp.hh b/tiger-compiler/src/ast/method-call-exp.hh new file mode 100644 index 0000000..ef728d9 --- /dev/null +++ b/tiger-compiler/src/ast/method-call-exp.hh @@ -0,0 +1,70 @@ +/** + ** \file ast/method-call-exp.hh + ** \brief Declaration of ast::MethodCallExp. + */ + +#pragma once + +#include <ast/call-exp.hh> +#include <ast/method-dec.hh> +#include <ast/var.hh> + +namespace ast +{ + /** \class ast::MethodCallExp + ** \brief Method call. + ** + ** A method call is \em not a function call in the strict sense + ** of object-oriented programming. Inheritance is used as a + ** factoring tool here. + */ + + class MethodCallExp : public CallExp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a MethodCallExp node. + MethodCallExp(const Location& location, + misc::symbol name, + exps_type* args, + Var* object); + MethodCallExp(const MethodCallExp&) = delete; + MethodCallExp& operator=(const MethodCallExp&) = delete; + /// Destroy a MethodCallExp node. + ~MethodCallExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return the object on which the method is called. + const Var& object_get() const; + /// Return the object on which the method is called. + Var& object_get(); + // FIXME DONE: Some code was deleted here. + /// Return definition site. + const MethodDec* def_get() const; + MethodDec* def_get(); + + // FIXME DONE: Some code was deleted here. + /// Set definition site. + void def_set(MethodDec*); + + /** \} */ + + protected: + /// The object on which the method is called. + Var* object_; + /// Definition site. + MethodDec* def_ = nullptr; + }; +} // namespace ast +#include <ast/method-call-exp.hxx> diff --git a/tiger-compiler/src/ast/method-call-exp.hxx b/tiger-compiler/src/ast/method-call-exp.hxx new file mode 100644 index 0000000..fa49ca9 --- /dev/null +++ b/tiger-compiler/src/ast/method-call-exp.hxx @@ -0,0 +1,21 @@ +/** + ** \file ast/method-call-exp.hxx + ** \brief Inline methods of ast::MethodCallExp. + */ + +#pragma once + +#include <ast/method-call-exp.hh> + +namespace ast +{ + + inline const Var& MethodCallExp::object_get() const { return *object_; } + inline Var& MethodCallExp::object_get() { return *object_; } + + // FIXME DONE: Some code was deleted here. + inline const MethodDec* MethodCallExp::def_get() const { return def_; } + inline MethodDec* MethodCallExp::def_get() { return def_; } + // FIXME DONE: Some code was deleted here. + inline void MethodCallExp::def_set(MethodDec* def) { def_ = def; } +} // namespace ast diff --git a/tiger-compiler/src/ast/method-dec.cc b/tiger-compiler/src/ast/method-dec.cc new file mode 100644 index 0000000..36f07d7 --- /dev/null +++ b/tiger-compiler/src/ast/method-dec.cc @@ -0,0 +1,22 @@ +/** + ** \file ast/method-dec.cc + ** \brief Implementation of ast::MethodDec. + */ + +#include <ast/method-dec.hh> +#include <ast/visitor.hh> + +namespace ast +{ + MethodDec::MethodDec(const Location& location, + misc::symbol name, + VarChunk* formals, + NameTy* result, + Exp* body) + : FunctionDec(location, name, formals, result, body) + {} + + void MethodDec::accept(ConstVisitor& v) const { v(*this); } + + void MethodDec::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/method-dec.hh b/tiger-compiler/src/ast/method-dec.hh new file mode 100644 index 0000000..d91cfd8 --- /dev/null +++ b/tiger-compiler/src/ast/method-dec.hh @@ -0,0 +1,45 @@ +/** + ** \file ast/method-dec.hh + ** \brief Declaration of ast::MethodDec. + */ + +#pragma once + +#include <ast/function-dec.hh> + +namespace ast +{ + /** \class ast::MethodDec + ** \brief Method declaration. + ** + ** A method declaration is \em not a function in the strict + ** sense of object-oriented programming. Inheritance is used + ** as a factoring tool here. + */ + + class MethodDec : public FunctionDec + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a MethodDec node. + MethodDec(const Location& location, + misc::symbol name, + VarChunk* formals, + NameTy* result, + Exp* body); + MethodDec(const MethodDec&) = delete; + MethodDec& operator=(const MethodDec&) = delete; + /// Destroy a MethodDec node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + }; +} // namespace ast +#include <ast/method-dec.hxx> diff --git a/tiger-compiler/src/ast/method-dec.hxx b/tiger-compiler/src/ast/method-dec.hxx new file mode 100644 index 0000000..2c75af3 --- /dev/null +++ b/tiger-compiler/src/ast/method-dec.hxx @@ -0,0 +1,11 @@ +/** + ** \file ast/method-dec.hxx + ** \brief Inline methods of ast::MethodDec. + */ + +#pragma once + +#include <ast/method-dec.hh> + +namespace ast +{} // namespace ast diff --git a/tiger-compiler/src/ast/name-ty.cc b/tiger-compiler/src/ast/name-ty.cc new file mode 100644 index 0000000..96610bb --- /dev/null +++ b/tiger-compiler/src/ast/name-ty.cc @@ -0,0 +1,19 @@ +/** + ** \file ast/name-ty.cc + ** \brief Implementation of ast::NameTy. + */ + +#include <ast/name-ty.hh> +#include <ast/visitor.hh> + +namespace ast +{ + NameTy::NameTy(const Location& location, misc::symbol name) + : Ty(location) + , name_(name) + {} + + void NameTy::accept(ConstVisitor& v) const { v(*this); } + + void NameTy::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/name-ty.hh b/tiger-compiler/src/ast/name-ty.hh new file mode 100644 index 0000000..de08848 --- /dev/null +++ b/tiger-compiler/src/ast/name-ty.hh @@ -0,0 +1,56 @@ +/** + ** \file ast/name-ty.hh + ** \brief Declaration of ast::NameTy. + */ + +#pragma once + +#include <ast/ty.hh> +#include <ast/type-dec.hh> +#include <misc/symbol.hh> + +namespace ast +{ + /// NameTy. + class NameTy : public Ty + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a NameTy node. + NameTy(const Location& location, misc::symbol name); + NameTy(const NameTy&) = delete; + NameTy& operator=(const NameTy&) = delete; + /// Destroy a NameTy node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return the name of the type. + misc::symbol name_get() const; + /// Set the name of the type. + void name_set(misc::symbol); + /// Return definition site. + const TypeDec* def_get() const; + /// Return definition site. + TypeDec* def_get(); + /// Set definition site. + void def_set(TypeDec*); + /** \} */ + + protected: + /// The name of the type. + misc::symbol name_; + /// Definition site. + TypeDec* def_ = nullptr; + }; +} // namespace ast +#include <ast/name-ty.hxx> diff --git a/tiger-compiler/src/ast/name-ty.hxx b/tiger-compiler/src/ast/name-ty.hxx new file mode 100644 index 0000000..d93b383 --- /dev/null +++ b/tiger-compiler/src/ast/name-ty.hxx @@ -0,0 +1,20 @@ +/** + ** \file ast/name-ty.hxx + ** \brief Inline methods of ast::NameTy. + */ + +#pragma once + +#include <ast/name-ty.hh> + +namespace ast +{ + + inline misc::symbol NameTy::name_get() const { return name_; } + inline void NameTy::name_set(misc::symbol name) { name_ = name; } + + inline const TypeDec* NameTy::def_get() const { return def_; } + inline TypeDec* NameTy::def_get() { return def_; } + inline void NameTy::def_set(TypeDec* def) { def_ = def; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/nil-exp.cc b/tiger-compiler/src/ast/nil-exp.cc new file mode 100644 index 0000000..f51c442 --- /dev/null +++ b/tiger-compiler/src/ast/nil-exp.cc @@ -0,0 +1,19 @@ +/** + ** \file ast/nil-exp.cc + ** \brief Implementation of ast::NilExp. + */ + +#include <ast/nil-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + NilExp::NilExp(const Location& location) + : Exp(location) + , TypeConstructor() + {} + + void NilExp::accept(ConstVisitor& v) const { v(*this); } + + void NilExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/nil-exp.hh b/tiger-compiler/src/ast/nil-exp.hh new file mode 100644 index 0000000..c526b4b --- /dev/null +++ b/tiger-compiler/src/ast/nil-exp.hh @@ -0,0 +1,37 @@ +/** + ** \file ast/nil-exp.hh + ** \brief Declaration of ast::NilExp. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/type-constructor.hh> + +namespace ast +{ + /// NilExp. + class NilExp + : public Exp + , public TypeConstructor + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a NilExp node. + explicit NilExp(const Location& location); + NilExp(const NilExp&) = delete; + NilExp& operator=(const NilExp&) = delete; + /// Destroy a NilExp node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + }; +} // namespace ast +#include <ast/nil-exp.hxx> diff --git a/tiger-compiler/src/ast/nil-exp.hxx b/tiger-compiler/src/ast/nil-exp.hxx new file mode 100644 index 0000000..8d13ae6 --- /dev/null +++ b/tiger-compiler/src/ast/nil-exp.hxx @@ -0,0 +1,11 @@ +/** + ** \file ast/nil-exp.hxx + ** \brief Inline methods of ast::NilExp. + */ + +#pragma once + +#include <ast/nil-exp.hh> + +namespace ast +{} // namespace ast diff --git a/tiger-compiler/src/ast/non-assert-visitor.hh b/tiger-compiler/src/ast/non-assert-visitor.hh new file mode 100644 index 0000000..383768a --- /dev/null +++ b/tiger-compiler/src/ast/non-assert-visitor.hh @@ -0,0 +1,51 @@ +/** + ** \file ast/object-visitor.hh + ** \brief Provide default visits for assertion nodes. + */ + +#pragma once + +#include <ast/visitor.hh> + +namespace ast +{ + template <template <typename> class Const> + class GenNonAssertVisitor : virtual public GenVisitor<Const> + { + public: + /// Super class type. + using super_type = GenVisitor<Const>; + + // Import overloaded virtual functions. + using super_type::operator(); + + /// Convenient abbreviation. + template <typename Type> using const_t = typename Const<Type>::type; + + /** \name Ctor & dtor. + ** \{ */ + /// Construct an object visitor. + GenNonAssertVisitor(); + /// Destroy an object visitor. + virtual ~GenNonAssertVisitor(); + /** \} */ + + /// \name Object-related visits. + /// \{ + void operator()(const_t<AssertExp>& e) override; + /// \} + }; + + /// Shorthand for a const visitor. + using NonAssertConstVisitor = GenNonAssertVisitor<misc::constify_traits>; + /// Shorthand for a non const visitor. + using NonAssertVisitor = GenNonAssertVisitor<misc::id_traits>; + +#ifdef SWIG + %template(AssertNonConstVisitor) GenNonAssertVisitor<misc::constify_traits>; + %template(AssertNonVisitor) GenNonAssertVisitor<misc::id_traits>; +#endif + +} // namespace ast + +#include <ast/non-assert-visitor.hxx> diff --git a/tiger-compiler/src/ast/non-assert-visitor.hxx b/tiger-compiler/src/ast/non-assert-visitor.hxx new file mode 100644 index 0000000..dd0990d --- /dev/null +++ b/tiger-compiler/src/ast/non-assert-visitor.hxx @@ -0,0 +1,34 @@ +/** + ** \file ast/assert-visitor.hxx + ** \brief Implementation for ast/assert-visitor.hh. + */ + +#pragma once + +#include <ast/assert-exp.hh> +#include <ast/assert-visitor.hh> +#include <misc/contract.hh> + +namespace ast +{ + template <template <typename> class Const> + GenNonAssertVisitor<Const>::GenNonAssertVisitor() + : GenVisitor<Const>() + {} + + template <template <typename> class Const> + GenNonAssertVisitor<Const>::~GenNonAssertVisitor() + {} + + /*-------------------------------. + | Assert-related visit method. | + `-------------------------------*/ + + template <template <typename> class Const> + void GenNonAssertVisitor<Const>::operator()(const_t<AssertExp>&) + { + // We must not be here (there should be no assert feature in plain Tiger). + unreachable(); + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/non-object-visitor.hh b/tiger-compiler/src/ast/non-object-visitor.hh new file mode 100644 index 0000000..c3fcf1a --- /dev/null +++ b/tiger-compiler/src/ast/non-object-visitor.hh @@ -0,0 +1,92 @@ +/** + ** \file ast/non-object-visitor.hh + ** \brief Provide aborting visits for object-related nodes. + */ + +#pragma once + +#include <ast/visitor.hh> + +namespace ast +{ + /** GenNonObjectVisitor<CONSTNESS-SELECTOR> provides aborting visit + methods for object-related nodes. This class is meant to factor + the code visiting object-related nodes in visitors bound to + process AST \em without objects. + + ast::GenNonObjectVisitor inherits virtually from ast::GenVisitor + to allow diamond inheritance, notably for a ``compatibility'' + purpose with ast::GenDefaultVisitor. + + For instance, type::TypeChecker, a visitor that checks the types + of an AST without objects, inherits from ast::DefaultVisitor to + factor default (``empty'') traversal implementations, and from + ast::NonObjectVisitor to get an aborting behavior for + object-related nodes. + + \verbatim + + /ast::Visitor/ + ^ + (virtual) | (virtual) + ,--------------+--------------. + | | + | | + /ast::DefaultVisitor/ /ast::NonObjectVisitor/ + ^ ^ + | | + `--------------+--------------' + | + | + type::TypeChecker + + \endverbatim + */ + template <template <typename> class Const> + class GenNonObjectVisitor : virtual public GenVisitor<Const> + { + public: + /// Super class type. + using super_type = GenVisitor<Const>; + + // Import overloaded virtual functions. + using super_type::operator(); + + /// Convenient abbreviation. + template <typename Type> using const_t = typename Const<Type>::type; + + /** \name Ctor & dtor. + ** \{ */ + /// Construct a non-object visitor. + GenNonObjectVisitor(); + /// Destroy a non-object visitor. + virtual ~GenNonObjectVisitor(); + /** \} */ + + /// \name Object-related visits. + /// + /// The methods should not be used, since this visitor is for the + /// non-object flavor of the language. + /// \{ + void operator()(const_t<ClassTy>& e) override; + + void operator()(const_t<MethodChunk>& e) override; + void operator()(const_t<MethodDec>& e) override; + + void operator()(const_t<MethodCallExp>& e) override; + void operator()(const_t<ObjectExp>& e) override; + /// \} + }; + + /// Shorthand for a const visitor. + using NonObjectConstVisitor = GenNonObjectVisitor<misc::constify_traits>; + /// Shorthand for a non const visitor. + using NonObjectVisitor = GenNonObjectVisitor<misc::id_traits>; + +#ifdef SWIG + %template(NonObjectConstVisitor) GenNonObjectVisitor<misc::constify_traits>; + %template(NonObjectVisitor) GenNonObjectVisitor<misc::id_traits>; +#endif +} // namespace ast + +#include <ast/non-object-visitor.hxx> diff --git a/tiger-compiler/src/ast/non-object-visitor.hxx b/tiger-compiler/src/ast/non-object-visitor.hxx new file mode 100644 index 0000000..8d49932 --- /dev/null +++ b/tiger-compiler/src/ast/non-object-visitor.hxx @@ -0,0 +1,62 @@ +/** + ** \file ast/non-object-visitor.hxx + ** \brief Implementation for ast/non-object-visitor.hh. + */ + +#pragma once + +#include <ast/all.hh> +#include <ast/non-object-visitor.hh> +#include <misc/contract.hh> + +namespace ast +{ + template <template <typename> class Const> + GenNonObjectVisitor<Const>::GenNonObjectVisitor() + : GenVisitor<Const>() + {} + + template <template <typename> class Const> + GenNonObjectVisitor<Const>::~GenNonObjectVisitor() + {} + + /*-----------------------------------------. + | Object-related visit methods, disabled. | + `-----------------------------------------*/ + + template <template <typename> class Const> + void GenNonObjectVisitor<Const>::operator()(const_t<ClassTy>&) + { + // We must not be here (there should be no object feature in plain Tiger). + unreachable(); + } + + template <template <typename> class Const> + void GenNonObjectVisitor<Const>::operator()(const_t<MethodChunk>&) + { + // We must not be here (there should be no object feature in plain Tiger). + unreachable(); + } + + template <template <typename> class Const> + void GenNonObjectVisitor<Const>::operator()(const_t<MethodDec>&) + { + // We must not be here (there should be no object feature in plain Tiger). + unreachable(); + } + + template <template <typename> class Const> + void GenNonObjectVisitor<Const>::operator()(const_t<MethodCallExp>&) + { + // We must not be here (there should be no object feature in plain Tiger). + unreachable(); + } + + template <template <typename> class Const> + void GenNonObjectVisitor<Const>::operator()(const_t<ObjectExp>&) + { + // We must not be here (there should be no object feature in plain Tiger). + unreachable(); + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/object-exp.cc b/tiger-compiler/src/ast/object-exp.cc new file mode 100644 index 0000000..c2d5808 --- /dev/null +++ b/tiger-compiler/src/ast/object-exp.cc @@ -0,0 +1,19 @@ +/** + ** \file ast/object-exp.cc + ** \brief Implementation of ast::ObjectExp. + */ + +#include <ast/object-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + ObjectExp::ObjectExp(const Location& location, NameTy* type_name) + : Exp(location) + , type_name_(type_name) + {} + + void ObjectExp::accept(ConstVisitor& v) const { v(*this); } + + void ObjectExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/object-exp.hh b/tiger-compiler/src/ast/object-exp.hh new file mode 100644 index 0000000..efab0a5 --- /dev/null +++ b/tiger-compiler/src/ast/object-exp.hh @@ -0,0 +1,47 @@ +/** + ** \file ast/object-exp.hh + ** \brief Declaration of ast::ObjectExp. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/name-ty.hh> + +namespace ast +{ + /// ObjectExp. + class ObjectExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct an ObjectExp node. + ObjectExp(const Location& location, NameTy* type_name); + ObjectExp(const ObjectExp&) = delete; + ObjectExp& operator=(const ObjectExp&) = delete; + /// Destroy an ObjectExp node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return name of the class from which the object is instantiated. + const NameTy& type_name_get() const; + /// Return name of the class from which the object is instantiated. + NameTy& type_name_get(); + /** \} */ + + protected: + /// Name of the class from which the object is instantiated. + NameTy* type_name_; + }; +} // namespace ast +#include <ast/object-exp.hxx> diff --git a/tiger-compiler/src/ast/object-exp.hxx b/tiger-compiler/src/ast/object-exp.hxx new file mode 100644 index 0000000..38fd5f6 --- /dev/null +++ b/tiger-compiler/src/ast/object-exp.hxx @@ -0,0 +1,16 @@ +/** + ** \file ast/object-exp.hxx + ** \brief Inline methods of ast::ObjectExp. + */ + +#pragma once + +#include <ast/object-exp.hh> + +namespace ast +{ + + inline const NameTy& ObjectExp::type_name_get() const { return *type_name_; } + inline NameTy& ObjectExp::type_name_get() { return *type_name_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/object-visitor.hh b/tiger-compiler/src/ast/object-visitor.hh new file mode 100644 index 0000000..b14c829 --- /dev/null +++ b/tiger-compiler/src/ast/object-visitor.hh @@ -0,0 +1,89 @@ +/** + ** \file ast/object-visitor.hh + ** \brief Provide default visits for object-related nodes. + */ + +#pragma once + +#include <ast/visitor.hh> + +namespace ast +{ + /** GenObjectVisitor<CONSTNESS-SELECTOR> provides default visit + methods for object-related nodes. This class is meant to factor + the code visiting object-related nodes. + + ast::GenObjectVisitor inherits virtually from ast::GenVisitor + to allow diamond inheritance, notably for a ``compatibility'' + purpose with ast::GenDefaultVisitor. + + For instance, bind::Binder, a visitor that handles bindings for + an AST without objects, inherits from ast::DefaultVisitor to + factor default (``empty'') traversal implementations for + non-object-related nodes, and from ast::ObjectVisitor for + object-related nodes. + + \verbatim + + /ast::Visitor/ + ^ + (virtual) | (virtual) + ,--------------+--------------. + | | + | | + /ast::DefaultVisitor/ /ast::ObjectVisitor/ + ^ ^ + | | + `--------------+--------------' + | + | + bind::Binder + + \endverbatim + */ + template <template <typename> class Const> + class GenObjectVisitor : virtual public GenVisitor<Const> + { + public: + /// Super class type. + using super_type = GenVisitor<Const>; + + // Import overloaded virtual functions. + using super_type::operator(); + + /// Convenient abbreviation. + template <typename Type> using const_t = typename Const<Type>::type; + + /** \name Ctor & dtor. + ** \{ */ + /// Construct an object visitor. + GenObjectVisitor(); + /// Destroy an object visitor. + virtual ~GenObjectVisitor(); + /** \} */ + + /// \name Object-related visits. + /// \{ + void operator()(const_t<ClassTy>& e) override; + + void operator()(const_t<MethodChunk>& e) override; + void operator()(const_t<MethodDec>& e) override; + + void operator()(const_t<MethodCallExp>& e) override; + void operator()(const_t<ObjectExp>& e) override; + /// \} + }; + + /// Shorthand for a const visitor. + using ObjectConstVisitor = GenObjectVisitor<misc::constify_traits>; + /// Shorthand for a non const visitor. + using ObjectVisitor = GenObjectVisitor<misc::id_traits>; + +#ifdef SWIG + %template(ObjectConstVisitor) GenObjectVisitor<misc::constify_traits>; + %template(ObjectVisitor) GenObjectVisitor<misc::id_traits>; +#endif + +} // namespace ast + +#include <ast/object-visitor.hxx> diff --git a/tiger-compiler/src/ast/object-visitor.hxx b/tiger-compiler/src/ast/object-visitor.hxx new file mode 100644 index 0000000..c4eccbb --- /dev/null +++ b/tiger-compiler/src/ast/object-visitor.hxx @@ -0,0 +1,69 @@ +/** + ** \file ast/object-visitor.hxx + ** \brief Implementation for ast/object-visitor.hh. + */ + +#pragma once + +#include <ast/all.hh> +#include <ast/object-visitor.hh> +#include <misc/contract.hh> + +namespace ast +{ + template <template <typename> class Const> + GenObjectVisitor<Const>::GenObjectVisitor() + : GenVisitor<Const>() + {} + + template <template <typename> class Const> + GenObjectVisitor<Const>::~GenObjectVisitor() + {} + + /*-------------------------------. + | Object-related visit methods. | + `-------------------------------*/ + + template <template <typename> class Const> + void GenObjectVisitor<Const>::operator()(const_t<ClassTy>& e) + { + // FIXME DONE: Some code was deleted here. + e.chunks_get().accept(*this); + } + + template <template <typename> class Const> + void GenObjectVisitor<Const>::operator()(const_t<MethodChunk>& e) + { + // FIXME DONE: Some code was deleted here. + for (const auto dec : e) + dec->accept(*this); + } + + template <template <typename> class Const> + void GenObjectVisitor<Const>::operator()(const_t<MethodDec>& e) + { + // FIXME DONE: Some code was deleted here. + e.formals_get().accept(*this); + if (e.result_get() != nullptr) + e.result_get()->accept(*this); + if (e.body_get() != nullptr) + e.body_get()->accept(*this); + } + + template <template <typename> class Const> + void GenObjectVisitor<Const>::operator()(const_t<MethodCallExp>& e) + { + // FIXME DONE: Some code was deleted here. + e.object_get().accept(*this); + for (auto arg : e.args_get()) + arg->accept(*this); + } + + template <template <typename> class Const> + void GenObjectVisitor<Const>::operator()(const_t<ObjectExp>& e) + { + // FIXME DONE: Some code was deleted here. + e.type_name_get().accept(*this); + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/op-exp.cc b/tiger-compiler/src/ast/op-exp.cc new file mode 100644 index 0000000..6db4940 --- /dev/null +++ b/tiger-compiler/src/ast/op-exp.cc @@ -0,0 +1,42 @@ +/** + ** \file ast/op-exp.cc + ** \brief Implementation of ast::OpExp. + */ + +#include <ast/op-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + OpExp::OpExp(const Location& location, + Exp* left, + OpExp::Oper oper, + Exp* right) + : Exp(location) + , left_(left) + , oper_(oper) + , right_(right) + {} + + OpExp::~OpExp() + { + delete left_; + delete right_; + } + + void OpExp::accept(ConstVisitor& v) const { v(*this); } + + void OpExp::accept(Visitor& v) { v(*this); } +} // namespace ast + +std::string str(ast::OpExp::Oper oper) +{ + static const std::unordered_map<ast::OpExp::Oper, std::string> op_str = { + {ast::OpExp::Oper::add, "+"}, {ast::OpExp::Oper::sub, "-"}, + {ast::OpExp::Oper::mul, "*"}, {ast::OpExp::Oper::div, "/"}, + {ast::OpExp::Oper::eq, "="}, {ast::OpExp::Oper::ne, "<>"}, + {ast::OpExp::Oper::lt, "<"}, {ast::OpExp::Oper::le, "<="}, + {ast::OpExp::Oper::gt, ">"}, {ast::OpExp::Oper::ge, ">="}}; + + return op_str.at(oper); +} diff --git a/tiger-compiler/src/ast/op-exp.hh b/tiger-compiler/src/ast/op-exp.hh new file mode 100644 index 0000000..372650f --- /dev/null +++ b/tiger-compiler/src/ast/op-exp.hh @@ -0,0 +1,80 @@ +/** + ** \file ast/op-exp.hh + ** \brief Declaration of ast::OpExp. + */ + +#pragma once + +#include <unordered_map> +#include <ast/exp.hh> + +namespace ast +{ + /// OpExp. + class OpExp : public Exp + { + public: + /// Operator qualifier. + enum class Oper + { + // Arithmetics. + /** \brief "+" */ add, + /** \brief "-" */ sub, + /** \brief "*" */ mul, + /** \brief "/" */ div, + + // Comparison. + /** \brief "=" */ eq, + /** \brief "<>" */ ne, + /** \brief "<" */ lt, + /** \brief "<=" */ le, + /** \brief ">" */ gt, + /** \brief ">=" */ ge + }; + + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct an OpExp node. + OpExp(const Location& location, Exp* left, OpExp::Oper oper, Exp* right); + OpExp(const OpExp&) = delete; + OpExp& operator=(const OpExp&) = delete; + /// Destroy an OpExp node. + ~OpExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return left operand. + const Exp& left_get() const; + /// Return left operand. + Exp& left_get(); + /// Return operator. + OpExp::Oper oper_get() const; + /// Return right operand. + const Exp& right_get() const; + /// Return right operand. + Exp& right_get(); + /** \} */ + + protected: + /// Left operand. + Exp* left_; + /// Operator. + OpExp::Oper oper_; + /// Right operand. + Exp* right_; + }; +} // namespace ast + +// Return a representation of an operator. +std::string str(ast::OpExp::Oper oper); +#include <ast/op-exp.hxx> diff --git a/tiger-compiler/src/ast/op-exp.hxx b/tiger-compiler/src/ast/op-exp.hxx new file mode 100644 index 0000000..a665c3a --- /dev/null +++ b/tiger-compiler/src/ast/op-exp.hxx @@ -0,0 +1,21 @@ +/** + ** \file ast/op-exp.hxx + ** \brief Inline methods of ast::OpExp. + */ + +#pragma once + +#include <ast/op-exp.hh> + +namespace ast +{ + + inline const Exp& OpExp::left_get() const { return *left_; } + inline Exp& OpExp::left_get() { return *left_; } + + inline OpExp::Oper OpExp::oper_get() const { return oper_; } + + inline const Exp& OpExp::right_get() const { return *right_; } + inline Exp& OpExp::right_get() { return *right_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/pretty-printer.cc b/tiger-compiler/src/ast/pretty-printer.cc new file mode 100644 index 0000000..91dbc87 --- /dev/null +++ b/tiger-compiler/src/ast/pretty-printer.cc @@ -0,0 +1,419 @@ +/** + ** \file ast/pretty-printer.cc + ** \brief Implementation of ast::PrettyPrinter. + */ + +#include <ast/all.hh> +#include <ast/libast.hh> +#include <ast/pretty-printer.hh> +#include <misc/escape.hh> +#include <misc/indent.hh> +#include <misc/separator.hh> + +#include <type/class.hh> + +namespace ast +{ + // Anonymous namespace: these functions are private to this file. + namespace + { + /// Output \a e on \a ostr. + inline std::ostream& operator<<(std::ostream& ostr, const Escapable& e) + { + if (escapes_display(ostr) + // FIXME DONE: Some code was deleted here. + && e.escape_get()) + ostr << "/* escaping */ "; + + return ostr; + } + + /// \brief Output \a e on \a ostr. + /// + /// Used to factor the output of the name declared, + /// and its possible additional attributes. + inline std::ostream& operator<<(std::ostream& ostr, const Dec& e) + { + ostr << e.name_get(); + if (bindings_display(ostr)) + ostr << " /* " << &e << " */"; + return ostr; + } + } // namespace + + PrettyPrinter::PrettyPrinter(std::ostream& ostr) + : ostr_(ostr) + {} + + void PrettyPrinter::operator()(const SimpleVar& e) + { + ostr_ << e.name_get(); + if (bindings_display(ostr_)) + ostr_ << " /* " << e.def_get() << " */"; + } + + void PrettyPrinter::operator()(const FieldVar& e) + { + // FIXME DONE: Some code was deleted here. + ostr_ << e.var_get() << "." << e.name_get(); + } + + /* Foo[10]. */ + void PrettyPrinter::operator()(const SubscriptVar& e) + { + ostr_ << e.var_get() << '[' << misc::incindent << e.index_get() + << misc::decindent << ']'; + } + + void PrettyPrinter::operator()(const CastExp& e) + { + ostr_ << "_cast(" << e.exp_get() << ", " << e.ty_get() << ')'; + } + + // FIXME DONE: Some code was deleted here. + void PrettyPrinter::operator()(const NilExp&) { ostr_ << "nil"; } + void PrettyPrinter::operator()(const IntExp& e) { ostr_ << e.value_get(); } + void PrettyPrinter::operator()(const StringExp& e) + { + ostr_ << "\"" << misc::escape(e.value_get()) << "\""; + } + + void PrettyPrinter::operator()(const ObjectExp& e) + { + ostr_ << "new " << e.type_name_get(); + if (bindings_display(ostr_)) + ostr_ << " /* " << &e.type_name_get() << " */"; + } + + void PrettyPrinter::operator()(const CallExp& e) + { + ostr_ << e.name_get(); + if (bindings_display(ostr_)) + ostr_ << " /* " << e.def_get() << " */"; + ostr_ << "("; + if (!e.args_get().empty()) + { + ostr_ << misc::separate(e.args_get(), ", "); + } + ostr_ << ")"; + } + + void PrettyPrinter::operator()(const MethodCallExp& e) + { + ostr_ << e.object_get() << "." << e.name_get(); + if (bindings_display(ostr_)) + ostr_ << " /* " << e.def_get() << " */"; + ostr_ << "("; + if (!e.args_get().empty()) + { + ostr_ << misc::separate(e.args_get(), ", "); + } + ostr_ << ")"; + } + + void PrettyPrinter::operator()(const OpExp& e) + { + ostr_ << e.left_get() << " " << str(e.oper_get()) << " " << e.right_get(); + } + + void PrettyPrinter::operator()(const RecordExp& e) + { + ostr_ << e.type_name_get(); + + ostr_ << " { "; + if (!e.fields_get().empty()) + { + ostr_ << misc::separate(e.fields_get(), ", "); + } + ostr_ << " }"; + } + + void PrettyPrinter::operator()(const RecordTy& e) + { + ostr_ << "{ "; + if (!e.fields_get().empty()) + { + ostr_ << misc::separate(e.fields_get(), ", "); + } + ostr_ << " }"; + } + + void PrettyPrinter::operator()(const ArrayTy& e) + { + ostr_ << "array of " << e.base_type_get(); + } + + void PrettyPrinter::operator()(const ClassTy& e) + { + ostr_ << "class extends " << e.super_get() << "{" << misc::decendl; + if (!e.chunks_get().chunks_get().empty()) + { + ostr_ << misc::separate(e.chunks_get(), "\n"); + } + ostr_ << " }" << misc::decendl; + } + + void PrettyPrinter::operator()(const Field& e) + { + ostr_ << e.name_get() << " : " << e.type_name_get(); + } + + void PrettyPrinter::operator()(const SeqExp& e) + { + if (e.exps_get().size() == 0) + ostr_ << "()"; + else if (e.exps_get().size() == 1) + ostr_ << *e.exps_get().at(0); + else if (e.exps_get().size() > 1) + { + ostr_ << '(' << misc::incendl << *e.exps_get().at(0); + for (size_t i = 1; i < e.exps_get().size(); ++i) + { + ostr_ << ";" << misc::iendl << *e.exps_get().at(i); + } + ostr_ << misc::decendl << ")"; + } + } + + void PrettyPrinter::operator()(const AssignExp& e) + { + ostr_ << e.var_get() << " := " << e.exp_get(); + } + + void PrettyPrinter::operator()(const IfExp& e) + { + ostr_ << "(if " << e.test_get() << " then" << misc::incendl + << e.thenclause_get() << misc::decendl; + ostr_ << "else" << misc::incendl << e.elseclause_get() << ")" + << misc::decendl; + } + + void PrettyPrinter::operator()(const WhileExp& e) + { + ostr_ << "(while "; + if (bindings_display(ostr_)) + { + ostr_ << "/* " << &e << " /* "; + } + ostr_ << e.test_get() << " do" << misc::incendl << e.body_get() << ")" + << misc::decendl; + } + + void PrettyPrinter::operator()(const ForExp& e) + { + ostr_ << "(for "; + if (bindings_display(ostr_)) + { + ostr_ << "/* " << &e << " */ "; + } + ostr_ << e.vardec_get().name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << &e.vardec_get() << " */"; + } + ostr_ << " := " << *e.vardec_get().init_get() << " to " << e.hi_get() + << " do" << misc::incendl << e.body_get() << ")"; + } + + void PrettyPrinter::operator()(const BreakExp& e) + { + ostr_ << "break"; + if (bindings_display(ostr_)) + { + ostr_ << " /* " << e.def_get() << " */"; + } + } + + void PrettyPrinter::operator()(const LetExp& e) + { + ostr_ << "let" << misc::incendl << e.chunks_get() << misc::decendl << "in" + << misc::incendl << e.body_get() << misc::decendl << "end"; + } + + void PrettyPrinter::operator()(const ArrayExp& e) + { + ostr_ << e.type_name_get() << "[" << e.size_get() << "] of " + << e.init_get(); + } + + void PrettyPrinter::operator()(const FieldInit& e) + { + ostr_ << e.name_get() << " = " << e.init_get(); + } + + void PrettyPrinter::operator()(const VarChunk& e) + { + for (auto dec : e.decs_get()) + { + dec->accept(*this); + ostr_ << misc::iendl; + } + } + + void PrettyPrinter::operator()(const VarDec& e) + { + ostr_ << "var " << static_cast<Escapable>(e) << e.name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << &e << " */"; + } + if (e.type_name_get() != nullptr) + ostr_ << " : " << *e.type_name_get(); + if (e.init_get() != nullptr) + ostr_ << " := " << *e.init_get(); + else + ostr_ << " := 0"; + } + + void PrettyPrinter::operator()(const TypeChunk& e) + { + for (auto dec : e.decs_get()) + { + dec->accept(*this); + ostr_ << misc::iendl; + } + } + + void PrettyPrinter::operator()(const TypeDec& e) + { + if (const auto c = dynamic_cast<const ClassTy*>(&e.ty_get()); c) + { + ostr_ << "class " << e.name_get(); + if (bindings_display(ostr_)) + ostr_ << " /* " << &e << " */"; + ostr_ << " extends " << c->super_get() + << misc::iendl << "{" << misc::incendl; + if (!c->chunks_get().chunks_get().empty()) + { + ostr_ << misc::separate(c->chunks_get(), "\n"); + } + ostr_ << misc::decendl << "}"; + } + else + { + ostr_ << "type " << e.name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << &e << " */"; + } + ostr_ << " = " << e.ty_get(); + } + } + + void PrettyPrinter::operator()(const NameTy& e) + { + ostr_ << e.name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << e.def_get() << " */"; + } + } + + void PrettyPrinter::operator()(const FunctionChunk& e) + { + for (auto dec : e.decs_get()) + { + dec->accept(*this); + ostr_ << misc::iendl; + } + } + + void PrettyPrinter::operator()(const FunctionDec& e) + { + if (e.body_get() == nullptr) + ostr_ << "primitive "; + else + ostr_ << "function "; + ostr_ << e.name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << &e << " */"; + } + ostr_ << "("; + auto decs = e.formals_get().decs_get(); + if (!decs.empty()) + { + ostr_ << static_cast<Escapable>(*decs.at(0)) << decs.at(0)->name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << &decs.at(0) << " */"; + } + ostr_ << " : " << *decs.at(0)->type_name_get(); + for (size_t i = 1; i < decs.size(); ++i) + { + ostr_ << ", " << static_cast<Escapable>(*decs.at(i)) + << decs.at(i)->name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << &decs.at(i) << " */"; + } + ostr_ << " : " << *decs.at(i)->type_name_get(); + } + } + ostr_ << ")"; + if (e.result_get() != nullptr) + { + ostr_ << " : " << *e.result_get(); + } + if (e.body_get() != nullptr) + { + ostr_ << " =" << misc::incendl << *e.body_get() << misc::decindent; + } + ostr_ << misc::iendl; + } + + void PrettyPrinter::operator()(const MethodChunk& e) + { + for (auto dec : e.decs_get()) + { + dec->accept(*this); + ostr_ << misc::iendl; + } + } + + void PrettyPrinter::operator()(const MethodDec& e) + { + ostr_ << "method " << e.name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << &e << " */"; + } + ostr_ << "("; + auto decs = e.formals_get().decs_get(); + if (!decs.empty()) + { + ostr_ << static_cast<Escapable>(*decs.at(0)) << decs.at(0)->name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << &decs.at(0) << " */"; + } + ostr_ << " : " << *decs.at(0)->type_name_get(); + for (size_t i = 1; i < decs.size(); ++i) + { + ostr_ << ", " << static_cast<Escapable>(*decs.at(i)) + << decs.at(i)->name_get(); + if (bindings_display(ostr_)) + { + ostr_ << " /* " << &decs.at(i) << " */"; + } + ostr_ << " : " << *decs.at(i)->type_name_get(); + } + } + ostr_ << ")"; + if (e.result_get() != nullptr) + { + ostr_ << " : " << *e.result_get(); + } + if (e.body_get() != nullptr) + { + ostr_ << " =" << misc::incendl << *e.body_get() << misc::decindent; + } + ostr_ << misc::iendl; + } + + void PrettyPrinter::operator()(const AssertExp& e) + { + ostr_ << "assert " << e.cond_get(); + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/pretty-printer.hh b/tiger-compiler/src/ast/pretty-printer.hh new file mode 100644 index 0000000..7532331 --- /dev/null +++ b/tiger-compiler/src/ast/pretty-printer.hh @@ -0,0 +1,96 @@ +/** + ** \file ast/pretty-printer.hh + ** \brief Declaration of ast::PrettyPrinter. + */ + +#pragma once + +#include <ast/assert-visitor.hh> +#include <ast/default-visitor.hh> +#include <ast/object-visitor.hh> + +namespace ast +{ + /// Visit an Ast and print the content of each node. + class PrettyPrinter + : virtual public DefaultConstVisitor + , virtual public ObjectConstVisitor + , virtual public AssertConstVisitor + { + public: + using super_type = DefaultConstVisitor; + // Import overloaded virtual functions. + using super_type::operator(); + + /// Build to print on \a ostr. + PrettyPrinter(std::ostream& ostr); + + /// Visit methods. + /// \{ + void operator()(const SimpleVar& e) override; + void operator()(const FieldVar& e) override; + void operator()(const SubscriptVar& e) override; + void operator()(const CastExp& e) override; + // FIXME DONE: Some code was deleted here. + void operator()(const NilExp& e) override; + void operator()(const IntExp& e) override; + void operator()(const StringExp& e) override; + void operator()(const ObjectExp& e) override; + void operator()(const CallExp& e) override; + void operator()(const MethodCallExp& e) override; + void operator()(const OpExp& e) override; + void operator()(const RecordExp& e) override; + void operator()(const SeqExp& e) override; + void operator()(const AssignExp& e) override; + void operator()(const IfExp& e) override; + void operator()(const WhileExp& e) override; + void operator()(const ForExp& e) override; + void operator()(const BreakExp&) override; + void operator()(const LetExp& e) override; + void operator()(const ArrayExp& e) override; + void operator()(const FieldInit& e) override; + /// \} + + /// Visit Var declarations. + void operator()(const VarChunk& e) override; + void operator()(const VarDec& e) override; + + /// Visit Function declarations. + void operator()(const FunctionChunk& e) override; + void operator()(const FunctionDec& e) override; + void operator()(const MethodChunk& e) override; + void operator()(const MethodDec& e) override; + + /// Visit Type declarations. + void operator()(const TypeChunk& e) override; + void operator()(const TypeDec& e) override; + + /** \} */ + + /** \name Visit Type related nodes. + ** \{ */ + void operator()(const NameTy& e) override; + void operator()(const RecordTy& e) override; + void operator()(const ArrayTy& e) override; + void operator()(const ClassTy& e) override; + /** \} */ + + /** \name Visit Field related nodes. */ + void operator()(const Field& e) override; + + /** \name Visit Assertion nodes. */ + void operator()(const AssertExp& e) override; + + private: + // Factor pretty-printing of RecordExp and RecordTy. + template <typename RecordClass> void print_record(const RecordClass& e); + + // Whether we are in a ast::ClassTy. + bool within_classty_p_ = false; + + protected: + /// The stream to print on. + std::ostream& ostr_; + }; + +} // namespace ast diff --git a/tiger-compiler/src/ast/record-exp.cc b/tiger-compiler/src/ast/record-exp.cc new file mode 100644 index 0000000..6ca817a --- /dev/null +++ b/tiger-compiler/src/ast/record-exp.cc @@ -0,0 +1,30 @@ +/** + ** \file ast/record-exp.cc + ** \brief Implementation of ast::RecordExp. + */ + +#include <ast/record-exp.hh> +#include <ast/visitor.hh> +#include <misc/algorithm.hh> + +namespace ast +{ + RecordExp::RecordExp(const Location& location, + NameTy* type_name, + fieldinits_type* fields) + : Exp(location) + , type_name_(type_name) + , fields_(fields) + {} + + RecordExp::~RecordExp() + { + delete type_name_; + misc::deep_clear(*fields_); + delete fields_; + } + + void RecordExp::accept(ConstVisitor& v) const { v(*this); } + + void RecordExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/record-exp.hh b/tiger-compiler/src/ast/record-exp.hh new file mode 100644 index 0000000..f0ba79e --- /dev/null +++ b/tiger-compiler/src/ast/record-exp.hh @@ -0,0 +1,57 @@ +/** + ** \file ast/record-exp.hh + ** \brief Declaration of ast::RecordExp. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/field-init.hh> +#include <ast/name-ty.hh> + +namespace ast +{ + /// RecordExp. + class RecordExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a RecordExp node. + RecordExp(const Location& location, + NameTy* type_name, + fieldinits_type* fields); + RecordExp(const RecordExp&) = delete; + RecordExp& operator=(const RecordExp&) = delete; + /// Destroy a RecordExp node. + ~RecordExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return identifier of the record type. + const NameTy& type_name_get() const; + /// Return identifier of the record type. + NameTy& type_name_get(); + /// Return list of field initializations. + const fieldinits_type& fields_get() const; + /// Return list of field initializations. + fieldinits_type& fields_get(); + /** \} */ + + protected: + /// Identifier of the record type. + NameTy* type_name_; + /// List of field initializations. + fieldinits_type* fields_; + }; +} // namespace ast +#include <ast/record-exp.hxx> diff --git a/tiger-compiler/src/ast/record-exp.hxx b/tiger-compiler/src/ast/record-exp.hxx new file mode 100644 index 0000000..ab92edd --- /dev/null +++ b/tiger-compiler/src/ast/record-exp.hxx @@ -0,0 +1,22 @@ +/** + ** \file ast/record-exp.hxx + ** \brief Inline methods of ast::RecordExp. + */ + +#pragma once + +#include <ast/record-exp.hh> + +namespace ast +{ + + inline const NameTy& RecordExp::type_name_get() const { return *type_name_; } + inline NameTy& RecordExp::type_name_get() { return *type_name_; } + + inline const fieldinits_type& RecordExp::fields_get() const + { + return *fields_; + } + inline fieldinits_type& RecordExp::fields_get() { return *fields_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/record-ty.cc b/tiger-compiler/src/ast/record-ty.cc new file mode 100644 index 0000000..5614e96 --- /dev/null +++ b/tiger-compiler/src/ast/record-ty.cc @@ -0,0 +1,26 @@ +/** + ** \file ast/record-ty.cc + ** \brief Implementation of ast::RecordTy. + */ + +#include <ast/record-ty.hh> +#include <ast/visitor.hh> +#include <misc/algorithm.hh> + +namespace ast +{ + RecordTy::RecordTy(const Location& location, fields_type* fields) + : Ty(location) + , fields_(fields) + {} + + RecordTy::~RecordTy() + { + misc::deep_clear(*fields_); + delete fields_; + } + + void RecordTy::accept(ConstVisitor& v) const { v(*this); } + + void RecordTy::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/record-ty.hh b/tiger-compiler/src/ast/record-ty.hh new file mode 100644 index 0000000..d2d1a46 --- /dev/null +++ b/tiger-compiler/src/ast/record-ty.hh @@ -0,0 +1,49 @@ + +/** + ** \file ast/record-ty.hh + ** \brief Declaration of ast::RecordTy. + */ + +#pragma once + +#include <ast/field.hh> +#include <ast/ty.hh> + +namespace ast +{ + /// RecordTy. + class RecordTy : public Ty + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a RecordTy node. + RecordTy(const Location& location, fields_type* fields); + RecordTy(const RecordTy&) = delete; + RecordTy& operator=(const RecordTy&) = delete; + /// Destroy a RecordTy node. + ~RecordTy() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return the field list. + const fields_type& fields_get() const; + /// Return the field list. + fields_type& fields_get(); + /** \} */ + + protected: + /// The field list. + fields_type* fields_; + }; +} // namespace ast +#include <ast/record-ty.hxx> diff --git a/tiger-compiler/src/ast/record-ty.hxx b/tiger-compiler/src/ast/record-ty.hxx new file mode 100644 index 0000000..6d1c91c --- /dev/null +++ b/tiger-compiler/src/ast/record-ty.hxx @@ -0,0 +1,16 @@ +/** + ** \file ast/record-ty.hxx + ** \brief Inline methods of ast::RecordTy. + */ + +#pragma once + +#include <ast/record-ty.hh> + +namespace ast +{ + + inline const fields_type& RecordTy::fields_get() const { return *fields_; } + inline fields_type& RecordTy::fields_get() { return *fields_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/seq-exp.cc b/tiger-compiler/src/ast/seq-exp.cc new file mode 100644 index 0000000..af6bc6c --- /dev/null +++ b/tiger-compiler/src/ast/seq-exp.cc @@ -0,0 +1,26 @@ +/** + ** \file ast/seq-exp.cc + ** \brief Implementation of ast::SeqExp. + */ + +#include <ast/seq-exp.hh> +#include <ast/visitor.hh> +#include <misc/algorithm.hh> + +namespace ast +{ + SeqExp::SeqExp(const Location& location, exps_type* exps) + : Exp(location) + , exps_(exps) + {} + + SeqExp::~SeqExp() + { + misc::deep_clear(*exps_); + delete exps_; + } + + void SeqExp::accept(ConstVisitor& v) const { v(*this); } + + void SeqExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/seq-exp.hh b/tiger-compiler/src/ast/seq-exp.hh new file mode 100644 index 0000000..882c11e --- /dev/null +++ b/tiger-compiler/src/ast/seq-exp.hh @@ -0,0 +1,47 @@ +/** + ** \file ast/seq-exp.hh + ** \brief Declaration of ast::SeqExp. + */ + +#pragma once + +#include <ast/exp.hh> + +namespace ast +{ + /// SeqExp. + class SeqExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a SeqExp node. + SeqExp(const Location& location, exps_type* exps); + SeqExp(const SeqExp&) = delete; + SeqExp& operator=(const SeqExp&) = delete; + /// Destroy a SeqExp node. + ~SeqExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return list of expressions. + const exps_type& exps_get() const; + /// Return list of expressions. + exps_type& exps_get(); + /** \} */ + + protected: + /// List of expressions. + exps_type* exps_; + }; +} // namespace ast +#include <ast/seq-exp.hxx> diff --git a/tiger-compiler/src/ast/seq-exp.hxx b/tiger-compiler/src/ast/seq-exp.hxx new file mode 100644 index 0000000..87e0488 --- /dev/null +++ b/tiger-compiler/src/ast/seq-exp.hxx @@ -0,0 +1,16 @@ +/** + ** \file ast/seq-exp.hxx + ** \brief Inline methods of ast::SeqExp. + */ + +#pragma once + +#include <ast/seq-exp.hh> + +namespace ast +{ + + inline const exps_type& SeqExp::exps_get() const { return *exps_; } + inline exps_type& SeqExp::exps_get() { return *exps_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/simple-var.cc b/tiger-compiler/src/ast/simple-var.cc new file mode 100644 index 0000000..74035e0 --- /dev/null +++ b/tiger-compiler/src/ast/simple-var.cc @@ -0,0 +1,19 @@ +/** + ** \file ast/simple-var.cc + ** \brief Implementation of ast::SimpleVar. + */ + +#include <ast/simple-var.hh> +#include <ast/visitor.hh> + +namespace ast +{ + SimpleVar::SimpleVar(const Location& location, misc::symbol name) + : Var(location) + , name_(name) + {} + + void SimpleVar::accept(ConstVisitor& v) const { v(*this); } + + void SimpleVar::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/simple-var.hh b/tiger-compiler/src/ast/simple-var.hh new file mode 100644 index 0000000..be47767 --- /dev/null +++ b/tiger-compiler/src/ast/simple-var.hh @@ -0,0 +1,56 @@ +/** + ** \file ast/simple-var.hh + ** \brief Declaration of ast::SimpleVar. + */ + +#pragma once + +#include <ast/var-dec.hh> +#include <ast/var.hh> +#include <misc/symbol.hh> + +namespace ast +{ + /// SimpleVar. + class SimpleVar : public Var + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a SimpleVar node. + SimpleVar(const Location& location, misc::symbol name); + SimpleVar(const SimpleVar&) = delete; + SimpleVar& operator=(const SimpleVar&) = delete; + /// Destroy a SimpleVar node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return variable's name. + misc::symbol name_get() const; + /// Set variable's name. + void name_set(misc::symbol); + /// Return definition site. + const VarDec* def_get() const; + /// Return definition site. + VarDec* def_get(); + /// Set definition site. + void def_set(VarDec*); + /** \} */ + + protected: + /// Variable's name. + misc::symbol name_; + /// Definition site. + VarDec* def_ = nullptr; + }; +} // namespace ast +#include <ast/simple-var.hxx> diff --git a/tiger-compiler/src/ast/simple-var.hxx b/tiger-compiler/src/ast/simple-var.hxx new file mode 100644 index 0000000..e89b622 --- /dev/null +++ b/tiger-compiler/src/ast/simple-var.hxx @@ -0,0 +1,20 @@ +/** + ** \file ast/simple-var.hxx + ** \brief Inline methods of ast::SimpleVar. + */ + +#pragma once + +#include <ast/simple-var.hh> + +namespace ast +{ + + inline misc::symbol SimpleVar::name_get() const { return name_; } + inline void SimpleVar::name_set(misc::symbol name) { name_ = name; } + + inline const VarDec* SimpleVar::def_get() const { return def_; } + inline VarDec* SimpleVar::def_get() { return def_; } + inline void SimpleVar::def_set(VarDec* def) { def_ = def; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/string-exp.cc b/tiger-compiler/src/ast/string-exp.cc new file mode 100644 index 0000000..78ff00f --- /dev/null +++ b/tiger-compiler/src/ast/string-exp.cc @@ -0,0 +1,19 @@ +/** + ** \file ast/string-exp.cc + ** \brief Implementation of ast::StringExp. + */ + +#include <ast/string-exp.hh> +#include <ast/visitor.hh> + +namespace ast +{ + StringExp::StringExp(const Location& location, const std::string& value) + : Exp(location) + , value_(value) + {} + + void StringExp::accept(ConstVisitor& v) const { v(*this); } + + void StringExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/string-exp.hh b/tiger-compiler/src/ast/string-exp.hh new file mode 100644 index 0000000..c9fd4f0 --- /dev/null +++ b/tiger-compiler/src/ast/string-exp.hh @@ -0,0 +1,47 @@ +/** + ** \file ast/string-exp.hh + ** \brief Declaration of ast::StringExp. + */ + +#pragma once + +#include <string> +#include <ast/exp.hh> + +namespace ast +{ + /// StringExp. + class StringExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a StringExp node. + StringExp(const Location& location, const std::string& value); + StringExp(const StringExp&) = delete; + StringExp& operator=(const StringExp&) = delete; + /// Destroy a StringExp node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return stored string value. + const std::string& value_get() const; + /// Return stored string value. + std::string& value_get(); + /** \} */ + + protected: + /// Stored string value. + std::string value_; + }; +} // namespace ast +#include <ast/string-exp.hxx> diff --git a/tiger-compiler/src/ast/string-exp.hxx b/tiger-compiler/src/ast/string-exp.hxx new file mode 100644 index 0000000..2c8a429 --- /dev/null +++ b/tiger-compiler/src/ast/string-exp.hxx @@ -0,0 +1,16 @@ +/** + ** \file ast/string-exp.hxx + ** \brief Inline methods of ast::StringExp. + */ + +#pragma once + +#include <ast/string-exp.hh> + +namespace ast +{ + + inline const std::string& StringExp::value_get() const { return value_; } + inline std::string& StringExp::value_get() { return value_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/subscript-var.cc b/tiger-compiler/src/ast/subscript-var.cc new file mode 100644 index 0000000..8c2ab4e --- /dev/null +++ b/tiger-compiler/src/ast/subscript-var.cc @@ -0,0 +1,26 @@ +/** + ** \file ast/subscript-var.cc + ** \brief Implementation of ast::SubscriptVar. + */ + +#include <ast/subscript-var.hh> +#include <ast/visitor.hh> + +namespace ast +{ + SubscriptVar::SubscriptVar(const Location& location, Var* var, Exp* index) + : Var(location) + , var_(var) + , index_(index) + {} + + SubscriptVar::~SubscriptVar() + { + delete var_; + delete index_; + } + + void SubscriptVar::accept(ConstVisitor& v) const { v(*this); } + + void SubscriptVar::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/subscript-var.hh b/tiger-compiler/src/ast/subscript-var.hh new file mode 100644 index 0000000..d771391 --- /dev/null +++ b/tiger-compiler/src/ast/subscript-var.hh @@ -0,0 +1,54 @@ +/** + ** \file ast/subscript-var.hh + ** \brief Declaration of ast::SubscriptVar. + */ + +#pragma once + +#include <ast/exp.hh> +#include <ast/var.hh> + +namespace ast +{ + /// SubscriptVar. + class SubscriptVar : public Var + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a SubscriptVar node. + SubscriptVar(const Location& location, Var* var, Exp* index); + SubscriptVar(const SubscriptVar&) = delete; + SubscriptVar& operator=(const SubscriptVar&) = delete; + /// Destroy a SubscriptVar node. + ~SubscriptVar() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return the mother variable. + const Var& var_get() const; + /// Return the mother variable. + Var& var_get(); + /// Return the offset expression. + const Exp& index_get() const; + /// Return the offset expression. + Exp& index_get(); + /** \} */ + + protected: + /// The mother variable. + Var* var_; + /// The offset expression. + Exp* index_; + }; +} // namespace ast +#include <ast/subscript-var.hxx> diff --git a/tiger-compiler/src/ast/subscript-var.hxx b/tiger-compiler/src/ast/subscript-var.hxx new file mode 100644 index 0000000..5523240 --- /dev/null +++ b/tiger-compiler/src/ast/subscript-var.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/subscript-var.hxx + ** \brief Inline methods of ast::SubscriptVar. + */ + +#pragma once + +#include <ast/subscript-var.hh> + +namespace ast +{ + + inline const Var& SubscriptVar::var_get() const { return *var_; } + inline Var& SubscriptVar::var_get() { return *var_; } + + inline const Exp& SubscriptVar::index_get() const { return *index_; } + inline Exp& SubscriptVar::index_get() { return *index_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/tasks.cc b/tiger-compiler/src/ast/tasks.cc new file mode 100644 index 0000000..7ef95da --- /dev/null +++ b/tiger-compiler/src/ast/tasks.cc @@ -0,0 +1,32 @@ +/** + ** \file ast/tasks.cc + ** \brief Ast Tasks implementation. + */ + +#include <ast/libast.hh> +#include <misc/contract.hh> +#define DEFINE_TASKS 1 +#include <ast/tasks.hh> +#undef DEFINE_TASKS + +namespace ast::tasks +{ + // The abstract syntax tree. + std::unique_ptr<ast::ChunkList> the_program(nullptr); + + void ast_display() + { + // `the_program' should have been set by the parse module by now. + precondition(the_program) << "Could not dump the AST, root is null"; + std::cout << "/* == Abstract Syntax Tree. == */\n" + << *the_program << std::endl; + } + + void ast_dump() + { + // `the_program' should have been set by the parse module by now. + precondition(the_program) << "Could not dump the AST, root is null"; + ast::dump_dot(*the_program, std::cout); + } + +} // namespace ast::tasks diff --git a/tiger-compiler/src/ast/tasks.hh b/tiger-compiler/src/ast/tasks.hh new file mode 100644 index 0000000..490fc90 --- /dev/null +++ b/tiger-compiler/src/ast/tasks.hh @@ -0,0 +1,24 @@ +/** + ** \file ast/tasks.hh + ** \brief Ast module related tasks. + */ + +#pragma once + +#include <ast/chunk-list.hh> +#include <task/libtask.hh> + +namespace ast::tasks +{ + /// Global root node of abstract syntax tree. + extern std::unique_ptr<ast::ChunkList> the_program; + + TASK_GROUP("2. Abstract Syntax Tree"); + + /// Display the abstract syntax tree. + TASK_DECLARE("A|ast-display", "display the AST", ast_display, "parse"); + + /// Display the abstract syntax tree using a dumper. + TASK_DECLARE("ast-dump", "dump the AST", ast_dump, "parse"); + +} // namespace ast::tasks diff --git a/tiger-compiler/src/ast/ty.cc b/tiger-compiler/src/ast/ty.cc new file mode 100644 index 0000000..1b2f5d7 --- /dev/null +++ b/tiger-compiler/src/ast/ty.cc @@ -0,0 +1,17 @@ +/** + ** \file ast/ty.cc + ** \brief Implementation of ast::Ty. + */ + +#include <ast/ty.hh> +#include <ast/visitor.hh> + +namespace ast +{ + Ty::Ty(const Location& location) + : Ast(location) + , Typable() + , TypeConstructor() + {} + +} // namespace ast diff --git a/tiger-compiler/src/ast/ty.hh b/tiger-compiler/src/ast/ty.hh new file mode 100644 index 0000000..847713b --- /dev/null +++ b/tiger-compiler/src/ast/ty.hh @@ -0,0 +1,39 @@ +/** + ** \file ast/ty.hh + ** \brief Declaration of ast::Ty. + */ + +#pragma once + +#include <ast/ast.hh> +#include <ast/typable.hh> +#include <ast/type-constructor.hh> + +namespace ast +{ + /// Ty. + class Ty + : public Ast + , public Typable + , public TypeConstructor + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a Ty node. + explicit Ty(const Location& location); + Ty(const Ty&) = delete; + Ty& operator=(const Ty&) = delete; + /// Destroy a Ty node. + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override = 0; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override = 0; + /// \} + }; +} // namespace ast +#include <ast/ty.hxx> diff --git a/tiger-compiler/src/ast/ty.hxx b/tiger-compiler/src/ast/ty.hxx new file mode 100644 index 0000000..8bce3c5 --- /dev/null +++ b/tiger-compiler/src/ast/ty.hxx @@ -0,0 +1,11 @@ +/** + ** \file ast/ty.hxx + ** \brief Inline methods of ast::Ty. + */ + +#pragma once + +#include <ast/ty.hh> + +namespace ast +{} // namespace ast diff --git a/tiger-compiler/src/ast/typable.cc b/tiger-compiler/src/ast/typable.cc new file mode 100644 index 0000000..889aa4b --- /dev/null +++ b/tiger-compiler/src/ast/typable.cc @@ -0,0 +1,15 @@ +/** + ** \file ast/typable.cc + ** \brief Implementation of ast::Typable. + */ + +#include <ast/typable.hh> +#include <ast/visitor.hh> + +namespace ast +{ + // FIXME DONE: Some code was deleted here. + Typable::Typable() + : type_(nullptr) + {} +} // namespace ast diff --git a/tiger-compiler/src/ast/typable.hh b/tiger-compiler/src/ast/typable.hh new file mode 100644 index 0000000..50c004e --- /dev/null +++ b/tiger-compiler/src/ast/typable.hh @@ -0,0 +1,50 @@ +/** + ** \file ast/typable.hh + ** \brief Declaration of ast::Typable. + */ + +#pragma once + +#include <ast/fwd.hh> +#include <type/fwd.hh> + +namespace ast +{ + /** \class ast::Typable + ** \brief Hold a type information. + ** + ** A Typable node holds a type information (type::Type) about + ** this node. This can be: + ** \li the type of the node itself, if it is a Exp or a Ty, or + ** \li the type of of the declared object, in case of a Dec. + */ + + class Typable + { + // FIXME DONE: Some code was deleted here. + + public: + // Only need for basic constructor and destructor here + Typable(); + virtual ~Typable() = default; + + /* We prohibit copy and assignment as to avoid having + ** multiple Typable referencing the same Type which could + ** potentially mess up the TypeConstructor + */ + Typable(const Typable&) = delete; + Typable& operator=(const Typable&) = delete; + + // Basic getters/setters + void type_set(const type::Type*); + const type::Type* type_get() const; + + // Making sure we can visit thoses "nodes" + virtual void accept(ConstVisitor& v) const = 0; + virtual void accept(Visitor& v) = 0; + + private: + const type::Type* type_; + }; +} // namespace ast +#include <ast/typable.hxx> diff --git a/tiger-compiler/src/ast/typable.hxx b/tiger-compiler/src/ast/typable.hxx new file mode 100644 index 0000000..3af401a --- /dev/null +++ b/tiger-compiler/src/ast/typable.hxx @@ -0,0 +1,24 @@ +/** + ** \file ast/typable.hxx + ** \brief Inline methods of ast::Typable. + */ + +#pragma once + +#include <ast/typable.hh> + +namespace ast +{ + // FIXME DONE: Some code was deleted here. + + inline void Typable::type_set(const type::Type* typ) + { + // Explicitely casting it? + type_ = typ; + } + + inline const type::Type* Typable::type_get() const + { + return type_; + } +} // namespace ast diff --git a/tiger-compiler/src/ast/type-constructor.cc b/tiger-compiler/src/ast/type-constructor.cc new file mode 100644 index 0000000..7786864 --- /dev/null +++ b/tiger-compiler/src/ast/type-constructor.cc @@ -0,0 +1,31 @@ +/** + ** \file ast/type-constructor.cc + ** \brief Implementation of ast::TypeConstructor. + */ + +#include <ast/type-constructor.hh> +#include <ast/visitor.hh> + +namespace ast +{ + // FIXME DONE: Some code was deleted here. + TypeConstructor::TypeConstructor() + : reference_(nullptr) + {} + + TypeConstructor::~TypeConstructor() + { + // IF SOME MEMORY ERRORS HAPPENS, THIS IS THE CULPRIT + delete reference_; + } + + void TypeConstructor::accept(ConstVisitor& v) const + { + v(this); + } + + void TypeConstructor::accept(Visitor& v) + { + v(this); + } +} // namespace ast diff --git a/tiger-compiler/src/ast/type-constructor.hh b/tiger-compiler/src/ast/type-constructor.hh new file mode 100644 index 0000000..87f57d8 --- /dev/null +++ b/tiger-compiler/src/ast/type-constructor.hh @@ -0,0 +1,38 @@ +/** + ** \file ast/type-constructor.hh + ** \brief Declaration of ast::TypeConstructor. + */ + +#pragma once + +#include <ast/fwd.hh> +#include <type/fwd.hh> + +namespace ast +{ + /** \class ast::TypeConstructor + ** \brief Create a new type. + */ + + class TypeConstructor + { + // FIXME DONE: Some code was deleted here. + public: + // Basic default constructor + // BUT we have a custom destructor this time (daring today aren't we?) + TypeConstructor(); + ~TypeConstructor(); + + // Basic accessors + void created_type_set(const type::Type*); + const type::Type* created_type_get() const; + + // Implementing the visitor so this can also be visited + void accept(ConstVisitor& v) const; + void accept(Visitor& v); + + private: + const type::Type* reference_; + }; +} // namespace ast +#include <ast/type-constructor.hxx> diff --git a/tiger-compiler/src/ast/type-constructor.hxx b/tiger-compiler/src/ast/type-constructor.hxx new file mode 100644 index 0000000..86933f3 --- /dev/null +++ b/tiger-compiler/src/ast/type-constructor.hxx @@ -0,0 +1,23 @@ +/** + ** \file ast/type-constructor.hxx + ** \brief Inline methods of ast::TypeConstructor. + */ + +#pragma once + +#include <ast/type-constructor.hh> +#include <type/types.hh> + +namespace ast +{ + // FIXME DONE: Some code was deleted here. + inline void TypeConstructor::created_type_set(const type::Type* typ) + { + reference_ = typ; + } + + inline const type::Type* TypeConstructor::created_type_get() const + { + return reference_; + } +} // namespace ast diff --git a/tiger-compiler/src/ast/type-dec.cc b/tiger-compiler/src/ast/type-dec.cc new file mode 100644 index 0000000..336c42f --- /dev/null +++ b/tiger-compiler/src/ast/type-dec.cc @@ -0,0 +1,22 @@ +/** + ** \file ast/type-dec.cc + ** \brief Implementation of ast::TypeDec. + */ + +#include <ast/type-dec.hh> +#include <ast/visitor.hh> + +namespace ast +{ + TypeDec::TypeDec(const Location& location, misc::symbol name, Ty* ty) + : Dec(location, name) + , TypeConstructor() + , ty_(ty) + {} + + TypeDec::~TypeDec() { delete ty_; } + + void TypeDec::accept(ConstVisitor& v) const { v(*this); } + + void TypeDec::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/type-dec.hh b/tiger-compiler/src/ast/type-dec.hh new file mode 100644 index 0000000..0e19926 --- /dev/null +++ b/tiger-compiler/src/ast/type-dec.hh @@ -0,0 +1,51 @@ +/** + ** \file ast/type-dec.hh + ** \brief Declaration of ast::TypeDec. + */ + +#pragma once + +#include <ast/dec.hh> +#include <ast/ty.hh> +#include <ast/type-constructor.hh> + +namespace ast +{ + /// TypeDec. + class TypeDec + : public Dec + , public TypeConstructor + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a TypeDec node. + TypeDec(const Location& location, misc::symbol name, Ty* ty); + TypeDec(const TypeDec&) = delete; + TypeDec& operator=(const TypeDec&) = delete; + /// Destroy a TypeDec node. + ~TypeDec() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return type definition. + const Ty& ty_get() const; + /// Return type definition. + Ty& ty_get(); + /** \} */ + + protected: + /// Type definition. + Ty* ty_; + }; +} // namespace ast +#include <ast/type-dec.hxx> diff --git a/tiger-compiler/src/ast/type-dec.hxx b/tiger-compiler/src/ast/type-dec.hxx new file mode 100644 index 0000000..69dc086 --- /dev/null +++ b/tiger-compiler/src/ast/type-dec.hxx @@ -0,0 +1,16 @@ +/** + ** \file ast/type-dec.hxx + ** \brief Inline methods of ast::TypeDec. + */ + +#pragma once + +#include <ast/type-dec.hh> + +namespace ast +{ + + inline const Ty& TypeDec::ty_get() const { return *ty_; } + inline Ty& TypeDec::ty_get() { return *ty_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/var-dec.cc b/tiger-compiler/src/ast/var-dec.cc new file mode 100644 index 0000000..85e7eba --- /dev/null +++ b/tiger-compiler/src/ast/var-dec.cc @@ -0,0 +1,31 @@ +/** + ** \file ast/var-dec.cc + ** \brief Implementation of ast::VarDec. + */ + +#include <ast/var-dec.hh> +#include <ast/visitor.hh> + +namespace ast +{ + + VarDec::VarDec(const Location& location, + misc::symbol name, + NameTy* type_name, + Exp* init) + : Dec(location, name) + , Escapable() + , type_name_(type_name) + , init_(init) + {} + + VarDec::~VarDec() + { + delete type_name_; + delete init_; + } + + void VarDec::accept(ConstVisitor& v) const { v(*this); } + + void VarDec::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/var-dec.hh b/tiger-compiler/src/ast/var-dec.hh new file mode 100644 index 0000000..fd15b7e --- /dev/null +++ b/tiger-compiler/src/ast/var-dec.hh @@ -0,0 +1,61 @@ +/** + ** \file ast/var-dec.hh + ** \brief Declaration of ast::VarDec. + */ + +#pragma once + +#include <ast/dec.hh> +#include <ast/escapable.hh> +#include <ast/exp.hh> +#include <ast/name-ty.hh> + +namespace ast +{ + /// VarDec. + class VarDec + : public Dec + , public Escapable + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a VarDec node. + VarDec(const Location& location, + misc::symbol name, + NameTy* type_name, + Exp* init); + VarDec(const VarDec&) = delete; + VarDec& operator=(const VarDec&) = delete; + /// Destroy a VarDec node. + ~VarDec() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return optional type of the declared variable. + const NameTy* type_name_get() const; + /// Return optional type of the declared variable. + NameTy* type_name_get(); + /// Return the initial value (expression) assigned to the variable. + const Exp* init_get() const; + /// Return the initial value (expression) assigned to the variable. + Exp* init_get(); + /** \} */ + + protected: + /// Optional type of the declared variable. + NameTy* type_name_; + /// The initial value (expression) assigned to the variable. + Exp* init_; + }; +} // namespace ast +#include <ast/var-dec.hxx> diff --git a/tiger-compiler/src/ast/var-dec.hxx b/tiger-compiler/src/ast/var-dec.hxx new file mode 100644 index 0000000..c96c3f4 --- /dev/null +++ b/tiger-compiler/src/ast/var-dec.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/var-dec.hxx + ** \brief Inline methods of ast::VarDec. + */ + +#pragma once + +#include <ast/var-dec.hh> + +namespace ast +{ + + inline const NameTy* VarDec::type_name_get() const { return type_name_; } + inline NameTy* VarDec::type_name_get() { return type_name_; } + + inline const Exp* VarDec::init_get() const { return init_; } + inline Exp* VarDec::init_get() { return init_; } + +} // namespace ast diff --git a/tiger-compiler/src/ast/var.cc b/tiger-compiler/src/ast/var.cc new file mode 100644 index 0000000..6bea70c --- /dev/null +++ b/tiger-compiler/src/ast/var.cc @@ -0,0 +1,15 @@ +/** + ** \file ast/var.cc + ** \brief Implementation of ast::Var. + */ + +#include <ast/var.hh> +#include <ast/visitor.hh> + +namespace ast +{ + Var::Var(const Location& location) + : Exp(location) + {} + +} // namespace ast diff --git a/tiger-compiler/src/ast/var.hh b/tiger-compiler/src/ast/var.hh new file mode 100644 index 0000000..286e392 --- /dev/null +++ b/tiger-compiler/src/ast/var.hh @@ -0,0 +1,26 @@ +/** + ** \file ast/var.hh + ** \brief Declaration of ast::Var. + */ + +#pragma once + +#include <ast/exp.hh> + +namespace ast +{ + /// Var. + class Var : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a Var node. + explicit Var(const Location& location); + Var(const Var&) = delete; + Var& operator=(const Var&) = delete; + /// Destroy a Var node. + /** \} */ + }; +} // namespace ast +#include <ast/var.hxx> diff --git a/tiger-compiler/src/ast/var.hxx b/tiger-compiler/src/ast/var.hxx new file mode 100644 index 0000000..1f54528 --- /dev/null +++ b/tiger-compiler/src/ast/var.hxx @@ -0,0 +1,11 @@ +/** + ** \file ast/var.hxx + ** \brief Inline methods of ast::Var. + */ + +#pragma once + +#include <ast/var.hh> + +namespace ast +{} // namespace ast diff --git a/tiger-compiler/src/ast/visitor.hh b/tiger-compiler/src/ast/visitor.hh new file mode 100644 index 0000000..420db00 --- /dev/null +++ b/tiger-compiler/src/ast/visitor.hh @@ -0,0 +1,114 @@ +/** + ** \file ast/visitor.hh + ** \brief Definition of ast::Visitor. + */ + +#pragma once + +#include <functional> +#include <ast/fwd.hh> +#include <misc/select-const.hh> + +namespace ast +{ + /** \brief Root class of all Ast visitors. + ** + ** GenVisitor<CONSTIFY> is the root class of all Ast visitors. */ + template <template <typename> class Const> class GenVisitor + { + /** \name Ctor & dtor. + ** \{ */ + public: + /// Convenient abbreviation. + template <typename Type> using const_t = typename Const<Type>::type; + + /// Destroy a GenVisitor. + virtual ~GenVisitor(); + /** \} */ + + /// The entry point: visit \a e. + virtual void operator()(const_t<Ast>& e); + virtual void operator()(const_t<ArrayExp>&) = 0; + virtual void operator()(const_t<ArrayTy>&) = 0; + virtual void operator()(const_t<AssignExp>&) = 0; + virtual void operator()(const_t<BreakExp>&) = 0; + virtual void operator()(const_t<CallExp>&) = 0; + virtual void operator()(const_t<CastExp>&) = 0; + virtual void operator()(const_t<ChunkList>&) = 0; + virtual void operator()(const_t<ClassTy>&) = 0; + virtual void operator()(const_t<Field>&) = 0; + virtual void operator()(const_t<FieldInit>&) = 0; + virtual void operator()(const_t<FieldVar>&) = 0; + virtual void operator()(const_t<ForExp>&) = 0; + virtual void operator()(const_t<FunctionDec>&) = 0; + virtual void operator()(const_t<IfExp>&) = 0; + virtual void operator()(const_t<IntExp>&) = 0; + virtual void operator()(const_t<LetExp>&) = 0; + virtual void operator()(const_t<MethodCallExp>&) = 0; + virtual void operator()(const_t<MethodDec>&) = 0; + virtual void operator()(const_t<NameTy>&) = 0; + virtual void operator()(const_t<NilExp>&) = 0; + virtual void operator()(const_t<ObjectExp>&) = 0; + virtual void operator()(const_t<OpExp>&) = 0; + virtual void operator()(const_t<RecordExp>&) = 0; + virtual void operator()(const_t<RecordTy>&) = 0; + virtual void operator()(const_t<SeqExp>&) = 0; + virtual void operator()(const_t<SimpleVar>&) = 0; + virtual void operator()(const_t<StringExp>&) = 0; + virtual void operator()(const_t<SubscriptVar>&) = 0; + virtual void operator()(const_t<TypeDec>&) = 0; + virtual void operator()(const_t<VarDec>&) = 0; + virtual void operator()(const_t<WhileExp>&) = 0; + + virtual void operator()(const_t<FunctionChunk>&) = 0; + virtual void operator()(const_t<MethodChunk>&) = 0; + virtual void operator()(const_t<TypeChunk>&) = 0; + virtual void operator()(const_t<VarChunk>&) = 0; + + virtual void operator()(const_t<AssertExp>&) = 0; + + /// Helper to visit nodes manipulated via a pointer. + template <class E> void operator()(E* e); + + protected: + /** A convenient shortcut for recurring code like this: + + \code + if (e) + e->accept(*this); + \endcode + + However, the drawback of this approach is that it doesn't take + care of the constness, and any \a const violation will be + reported \em within the body of this method, not at its + corresponding call site. + + We cannot use the misc/select_const.hh approach here, since + the compiler cannot resolve a function overloaded or + specialized on an associated type of a template. E.g., writing + \a accept like this: + + \code + template <typename E> + void accept(const_t<E>* e); + \endcode + + won't work directly. Of course, one can help the compiler, + providing it with \a E + + \code + accept<ast::NameTy>(e.result_get()); + \endcode + + but this is painful. */ + template <typename E> void accept(E* e); + }; + + /// Shorthand for a const visitor. + using ConstVisitor = GenVisitor<misc::constify_traits>; + /// Shorthand for a non const visitor. + using Visitor = GenVisitor<misc::id_traits>; + +} // namespace ast + +#include <ast/visitor.hxx> diff --git a/tiger-compiler/src/ast/visitor.hxx b/tiger-compiler/src/ast/visitor.hxx new file mode 100644 index 0000000..2765f80 --- /dev/null +++ b/tiger-compiler/src/ast/visitor.hxx @@ -0,0 +1,36 @@ +/** + ** \file ast/visitor.hxx + ** \brief Definition of ast::Visitor. + */ + +#pragma once + +#include <ast/ast.hh> +#include <ast/visitor.hh> + +namespace ast +{ + template <template <typename> class Const> GenVisitor<Const>::~GenVisitor() {} + + template <template <typename> class Const> + void GenVisitor<Const>::operator()(const_t<ast::Ast>& e) + { + e.accept(*this); + } + + template <template <typename> class Const> + template <class E> + void GenVisitor<Const>::operator()(E* e) + { + e->accept(*this); + } + + template <template <typename> class Const> + template <typename E> + void GenVisitor<Const>::accept(E* e) + { + if (e) + e->accept(*this); + } + +} // namespace ast diff --git a/tiger-compiler/src/ast/while-exp.cc b/tiger-compiler/src/ast/while-exp.cc new file mode 100644 index 0000000..3ffa5e1 --- /dev/null +++ b/tiger-compiler/src/ast/while-exp.cc @@ -0,0 +1,26 @@ +/** + ** \file ast/while-exp.cc + ** \brief Implementation of ast::WhileExp. + */ + +#include <ast/visitor.hh> +#include <ast/while-exp.hh> + +namespace ast +{ + WhileExp::WhileExp(const Location& location, Exp* test, Exp* body) + : Exp(location) + , test_(test) + , body_(body) + {} + + WhileExp::~WhileExp() + { + delete test_; + delete body_; + } + + void WhileExp::accept(ConstVisitor& v) const { v(*this); } + + void WhileExp::accept(Visitor& v) { v(*this); } +} // namespace ast diff --git a/tiger-compiler/src/ast/while-exp.hh b/tiger-compiler/src/ast/while-exp.hh new file mode 100644 index 0000000..0f8a787 --- /dev/null +++ b/tiger-compiler/src/ast/while-exp.hh @@ -0,0 +1,53 @@ +/** + ** \file ast/while-exp.hh + ** \brief Declaration of ast::WhileExp. + */ + +#pragma once + +#include <ast/exp.hh> + +namespace ast +{ + /// WhileExp. + class WhileExp : public Exp + { + public: + /** \name Ctor & dtor. + ** \{ */ + /// Construct a WhileExp node. + WhileExp(const Location& location, Exp* test, Exp* body); + WhileExp(const WhileExp&) = delete; + WhileExp& operator=(const WhileExp&) = delete; + /// Destroy a WhileExp node. + ~WhileExp() override; + /** \} */ + + /// \name Visitors entry point. + /// \{ */ + /// Accept a const visitor \a v. + void accept(ConstVisitor& v) const override; + /// Accept a non-const visitor \a v. + void accept(Visitor& v) override; + /// \} + + /** \name Accessors. + ** \{ */ + /// Return exit condition of the loop. + const Exp& test_get() const; + /// Return exit condition of the loop. + Exp& test_get(); + /// Return instructions executed in the loop. + const Exp& body_get() const; + /// Return instructions executed in the loop. + Exp& body_get(); + /** \} */ + + protected: + /// Exit condition of the loop. + Exp* test_; + /// Instructions executed in the loop. + Exp* body_; + }; +} // namespace ast +#include <ast/while-exp.hxx> diff --git a/tiger-compiler/src/ast/while-exp.hxx b/tiger-compiler/src/ast/while-exp.hxx new file mode 100644 index 0000000..d6b9195 --- /dev/null +++ b/tiger-compiler/src/ast/while-exp.hxx @@ -0,0 +1,19 @@ +/** + ** \file ast/while-exp.hxx + ** \brief Inline methods of ast::WhileExp. + */ + +#pragma once + +#include <ast/while-exp.hh> + +namespace ast +{ + + inline const Exp& WhileExp::test_get() const { return *test_; } + inline Exp& WhileExp::test_get() { return *test_; } + + inline const Exp& WhileExp::body_get() const { return *body_; } + inline Exp& WhileExp::body_get() { return *body_; } + +} // namespace ast |
