diff options
Diffstat (limited to 'tiger-compiler/src/astclone')
| -rw-r--r-- | tiger-compiler/src/astclone/cloner.cc | 311 | ||||
| -rw-r--r-- | tiger-compiler/src/astclone/cloner.hh | 102 | ||||
| -rw-r--r-- | tiger-compiler/src/astclone/cloner.hxx | 72 | ||||
| -rw-r--r-- | tiger-compiler/src/astclone/libastclone.hh | 42 | ||||
| -rw-r--r-- | tiger-compiler/src/astclone/libastclone.hxx | 40 | ||||
| -rw-r--r-- | tiger-compiler/src/astclone/local.am | 12 | ||||
| -rw-r--r-- | tiger-compiler/src/astclone/tasks.cc | 26 | ||||
| -rw-r--r-- | tiger-compiler/src/astclone/tasks.hh | 20 |
8 files changed, 625 insertions, 0 deletions
diff --git a/tiger-compiler/src/astclone/cloner.cc b/tiger-compiler/src/astclone/cloner.cc new file mode 100644 index 0000000..8e26fa7 --- /dev/null +++ b/tiger-compiler/src/astclone/cloner.cc @@ -0,0 +1,311 @@ +/** + ** \file astclone/cloner.cc + ** \brief Implementation of astclone::Cloner. + */ + +#include <ast/all.hh> +#include <astclone/cloner.hh> +#include <misc/symbol.hh> + +namespace astclone +{ + using namespace ast; + + Cloner::Cloner() + : result_(nullptr) + {} + + Ast* Cloner::result_get() { return result_; } + + void Cloner::operator()(const ast::ArrayExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& loc = e.location_get(); + NameTy* type_name = recurse(e.type_name_get()); + Exp* size = recurse(e.size_get()); + Exp* init = recurse(e.init_get()); + result_ = new ArrayExp(loc, type_name, size, init); + } + + void Cloner::operator()(const ast::ArrayTy& e) + { + const Location& location = e.location_get(); + NameTy* base_type = recurse(e.base_type_get()); + result_ = new ArrayTy(location, base_type); + } + + void Cloner::operator()(const ast::AssertExp& e) + { + const Location& location = e.location_get(); + Exp* cond = recurse(e.cond_get()); + result_ = new AssertExp(location, cond); + } + + void Cloner::operator()(const ast::AssignExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + Var* variable = recurse(e.var_get()); + Exp* value = recurse(e.exp_get()); + result_ = new AssignExp(location, variable, value); + } + + void Cloner::operator()(const ast::BreakExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + result_ = new BreakExp(location); + } + + void Cloner::operator()(const ast::CallExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + // Apparently, we DO have a default copy constructor for symbols... + misc::symbol id = e.name_get(); + exps_type* args = recurse_collection(e.args_get()); + result_ = new CallExp(location, id, args); + } + + void Cloner::operator()(const ast::CastExp& e) + { + const Location& location = e.location_get(); + Exp* exp = recurse(e.exp_get()); + Ty* ty = recurse(e.ty_get()); + result_ = new CastExp(location, exp, ty); + } + + void Cloner::operator()(const ast::ChunkList& e) + { + const Location& location = e.location_get(); + ChunkList::list_type chunks = *recurse_collection(e.chunks_get()); + result_ = new ChunkList(location, chunks); + } + + void Cloner::operator()(const ast::ClassTy& e) + { + const Location& location = e.location_get(); + NameTy* super = recurse(e.super_get()); + ChunkList* chunks = recurse(e.chunks_get()); + result_ = new ClassTy(location, super, chunks); + } + + void Cloner::operator()(const ast::Field& e) + { + const Location& location = e.location_get(); + misc::symbol name = e.name_get(); + NameTy* type_name = recurse(e.type_name_get()); + result_ = new Field(location, name, type_name); + } + + void Cloner::operator()(const ast::FieldInit& e) + { + const Location& location = e.location_get(); + misc::symbol name = e.name_get(); + Exp* init = recurse(e.init_get()); + result_ = new FieldInit(location, name, init); + } + + void Cloner::operator()(const ast::FieldVar& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + Var* variable = recurse(e.var_get()); + misc::symbol id = e.name_get(); + result_ = new FieldVar(location, variable, id); + } + + void Cloner::operator()(const ast::ForExp& e) + { + const Location& location = e.location_get(); + VarDec* vardec = recurse(e.vardec_get()); + Exp* hi = recurse(e.hi_get()); + Exp* body = recurse(e.body_get()); + result_ = new ForExp(location, vardec, hi, body); + } + + void Cloner::operator()(const ast::FunctionDec& e) + { + const Location& location = e.location_get(); + misc::symbol name = e.name_get(); + VarChunk* formals = recurse(e.formals_get()); + NameTy* result = recurse(e.result_get()); + Exp* body = recurse(e.body_get()); + auto fundec = new FunctionDec(location, name, formals, result, body); + result_ = fundec; + } + + void Cloner::operator()(const ast::IfExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + Exp* cond = recurse(e.test_get()); + Exp* thenclause = recurse(e.thenclause_get()); + Exp* elseclause = recurse(e.elseclause_get()); + result_ = new IfExp(location, cond, thenclause, elseclause); + } + + void Cloner::operator()(const ast::IntExp& e) + { + const Location& location = e.location_get(); + int value = e.value_get(); + result_ = new IntExp(location, value); + } + + void Cloner::operator()(const ast::LetExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + Exp* body = recurse(e.body_get()); + ChunkList* chunky = recurse(e.chunks_get()); + result_ = new LetExp(location, chunky, body); + } + + void Cloner::operator()(const ast::MethodCallExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + misc::symbol id = e.name_get(); + exps_type* args = recurse_collection(e.args_get()); + Var* variable = recurse(e.object_get()); + result_ = new MethodCallExp(location, id, args, variable); + } + + void Cloner::operator()(const ast::MethodDec& e) + { + const Location& location = e.location_get(); + misc::symbol name = e.name_get(); + VarChunk* formals = recurse(e.formals_get()); + NameTy* result = recurse(e.result_get()); + Exp* body = recurse(e.body_get()); + result_ = new MethodDec(location, name, formals, result, body); + } + + void Cloner::operator()(const ast::NameTy& e) + { + const Location& location = e.location_get(); + misc::symbol name = e.name_get(); + result_ = new NameTy(location, name); + } + + void Cloner::operator()(const ast::NilExp& e) + { + const Location& location = e.location_get(); + result_ = new NilExp(location); + } + + void Cloner::operator()(const ast::ObjectExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + NameTy* name = recurse(e.type_name_get()); + result_ = new ObjectExp(location, name); + } + + void Cloner::operator()(const ast::OpExp& e) + { + const Location& location = e.location_get(); + Exp* left = recurse(e.left_get()); + OpExp::Oper oper = e.oper_get(); + Exp* right = recurse(e.right_get()); + result_ = new OpExp(location, left, oper, right); + } + + void Cloner::operator()(const ast::RecordExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + NameTy* name = recurse(e.type_name_get()); + fieldinits_type* fields = recurse_collection(e.fields_get()); + result_ = new RecordExp(location, name, fields); + } + + void Cloner::operator()(const ast::RecordTy& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + fields_type* fields = recurse_collection(e.fields_get()); + result_ = new RecordTy(location, fields); + } + + void Cloner::operator()(const ast::SeqExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + exps_type* types = recurse_collection(e.exps_get()); + result_ = new SeqExp(location, types); + } + + void Cloner::operator()(const ast::SimpleVar& e) + { + const Location& location = e.location_get(); + misc::symbol name = e.name_get(); + result_ = new SimpleVar(location, name); + } + + void Cloner::operator()(const ast::StringExp& e) + { + // FIXME DONE: Some code was deleted here. + const Location& location = e.location_get(); + const std::string& txt = e.value_get(); + result_ = new StringExp(location, txt); + } + + void Cloner::operator()(const ast::SubscriptVar& e) + { + const Location& location = e.location_get(); + Var* var = recurse(e.var_get()); + Exp* index = recurse(e.index_get()); + result_ = new SubscriptVar(location, var, index); + } + + void Cloner::operator()(const ast::TypeDec& e) + { + const Location& location = e.location_get(); + misc::symbol name = e.name_get(); + Ty* ty = recurse(e.ty_get()); + result_ = new TypeDec(location, name, ty); + } + + void Cloner::operator()(const ast::VarDec& e) + { + const Location& location = e.location_get(); + misc::symbol name = e.name_get(); + NameTy* type_name = recurse(e.type_name_get()); + Exp* init = recurse(e.init_get()); + // FIXME DONE: Some code was deleted here (Cloned node instantiation). + result_ = new VarDec(location, name, type_name, init); + } + + void Cloner::operator()(const ast::WhileExp& e) + { + const Location& location = e.location_get(); + Exp* test = recurse(e.test_get()); + Exp* body = recurse(e.body_get()); + result_ = new WhileExp(location, test, body); + } + + void Cloner::operator()(const ast::FunctionChunk& e) + { + chunk_visit<ast::FunctionChunk>(e); + } + + void Cloner::operator()(const ast::MethodChunk& e) + { + // FIXME DONE: Some code was deleted here. + chunk_visit<ast::MethodChunk>(e); + } + + void Cloner::operator()(const ast::TypeChunk& e) + { + // FIXME DONE: Some code was deleted here. + chunk_visit<ast::TypeChunk>(e); + } + + void Cloner::operator()(const ast::VarChunk& e) + { + // FIXME DONE: Some code was deleted here. + chunk_visit<ast::VarChunk>(e); + } + +} // namespace astclone diff --git a/tiger-compiler/src/astclone/cloner.hh b/tiger-compiler/src/astclone/cloner.hh new file mode 100644 index 0000000..f1405d1 --- /dev/null +++ b/tiger-compiler/src/astclone/cloner.hh @@ -0,0 +1,102 @@ +/** + ** \file astclone/cloner.hh + ** \brief Declaration of astclone::Cloner. + */ + +#pragma once + +#include <ast/default-visitor.hh> + +namespace astclone +{ + /// \brief Duplicate an Ast. + class Cloner : public ast::DefaultConstVisitor + { + public: + using super_type = ast::DefaultConstVisitor; + + // Import overloaded virtual functions. + using super_type::operator(); + + /// Build a Cloner. + Cloner(); + + /// Destroy a Cloner. + ~Cloner() override = default; + + // Return the cloned Ast. + ast::Ast* result_get(); + + template <typename T> T* recurse(const T& t); + + template <typename T> T* recurse(const T* t); + + /** \brief Clone a collection object. + + Using overloading for this method is tempting, but it would + lead to the same prototype than the first \a recurse method. + + A partial specialization for \a std::list<T> would work, but is + not allowed by C++ standard. As a consequence, we are stuck to + using different names. + */ + template <typename CollectionType> + CollectionType* recurse_collection(const CollectionType& c); + + // Visit methods. + public: + void operator()(const ast::ArrayExp&) override; + void operator()(const ast::ArrayTy&) override; + void operator()(const ast::AssertExp&) 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; + + 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 ChunkType& e); + + // As we can't mix template and virtual methods, we have to + // duplicate these methods. That's too bad. :( + void operator()(const ast::FunctionChunk&) override; + void operator()(const ast::MethodChunk&) override; + void operator()(const ast::TypeChunk&) override; + void operator()(const ast::VarChunk&) override; + + protected: + /// The cloned Ast. + ast::Ast* result_; + }; + +} // namespace astclone + +#include <astclone/cloner.hxx> diff --git a/tiger-compiler/src/astclone/cloner.hxx b/tiger-compiler/src/astclone/cloner.hxx new file mode 100644 index 0000000..9e7d161 --- /dev/null +++ b/tiger-compiler/src/astclone/cloner.hxx @@ -0,0 +1,72 @@ +/** + ** \file astclone/cloner.hxx + ** \brief Template methods of astclone::Cloner. + */ + +#pragma once + +#include <ast/libast.hh> +#include <astclone/cloner.hh> + +namespace astclone +{ + using namespace ast; + + template <typename T> T* Cloner::recurse(const T& t) + { + t.accept(*this); + T* res = dynamic_cast<T*>(result_); + assertion(res); + return res; + } + + template <typename T> T* Cloner::recurse(const T* const t) + { + T* res = nullptr; + if (t) + { + t->accept(*this); + res = dynamic_cast<T*>(result_); + assertion(res); + } + return res; + } + + template <typename CollectionType> + CollectionType* Cloner::recurse_collection(const CollectionType& c) + { + auto res = new CollectionType; + + using elt_type = typename CollectionType::value_type; + for (const elt_type& e : c) + { + e->accept(*this); + auto elt = dynamic_cast<elt_type>(result_); + assertion(elt); + res->emplace_back(elt); + } + + return res; + } + + template <typename ChunkType> void Cloner::chunk_visit(const ChunkType& e) + { + const Location& location = e.location_get(); + + // The type of the list contained by this node. + using elt_type = typename ChunkType::Ds; + // The cloned list of declarations. + auto decs = new elt_type; + + for (const typename elt_type::value_type& i : e) + { + i->accept(*this); + auto dec = dynamic_cast<typename elt_type::value_type>(result_); + assertion(dec); + decs->emplace_back(dec); + } + // The cloned ChunkInterface. + result_ = new ChunkType(location, decs); + } + +} // namespace astclone diff --git a/tiger-compiler/src/astclone/libastclone.hh b/tiger-compiler/src/astclone/libastclone.hh new file mode 100644 index 0000000..d62fea9 --- /dev/null +++ b/tiger-compiler/src/astclone/libastclone.hh @@ -0,0 +1,42 @@ +/** + ** \file astclone/libastclone.hh + ** \brief Declare functions and variables exported by the Astclone module. + */ + +#pragma once + +#include <memory> + +#include <ast/fwd.hh> + +/// Cloning an ast::Ast. +namespace astclone +{ + /** \brief Make a deep copy of an AST. + ** \param tree abstract syntax tree's root. + ** \return the cloned AST. */ + template <typename T> T* clone(const T& tree); + + template <typename A> using applicable = auto(const A&) -> A*; + + template <typename A> + using applicable_with_bools = auto(const A&, bool, bool) -> A*; + + template <typename A, typename B> + using applicable_object = auto(const A&, const B&) -> A*; + + /// Have the pure function \a f side effect on \a t. + template <typename A> void apply(applicable<A> f, std::unique_ptr<A>& t1); + + template <typename A> + void apply(applicable_with_bools<A> f, + std::unique_ptr<A>& t1, + bool cond_1, + bool cond_2); + + template <typename A, typename B> + void apply(applicable_object<A, B> f, std::unique_ptr<A>& t1, const B& t3); + +} // namespace astclone + +#include <astclone/libastclone.hxx> diff --git a/tiger-compiler/src/astclone/libastclone.hxx b/tiger-compiler/src/astclone/libastclone.hxx new file mode 100644 index 0000000..b6fe380 --- /dev/null +++ b/tiger-compiler/src/astclone/libastclone.hxx @@ -0,0 +1,40 @@ +#pragma once + +#include <ast/exp.hh> +#include <astclone/cloner.hh> +#include <astclone/libastclone.hh> + +// Define exported clone functions. +namespace astclone +{ + template <typename T> T* clone(const T& tree) + { + Cloner clone; + clone(tree); + return dynamic_cast<T*>(clone.result_get()); + } + + template <typename A> void apply(applicable<A> f, std::unique_ptr<A>& t1) + { + A* t2 = f(*t1); + t1.reset(t2); + } + + template <typename A> + void apply(applicable_with_bools<A> f, + std::unique_ptr<A>& t1, + bool cond_1, + bool cond_2) + { + A* t2 = f(*t1, cond_1, cond_2); + t1.reset(t2); + } + + template <typename A, typename B> + void apply(applicable_object<A, B> f, std::unique_ptr<A>& t1, B& t3) + { + A* t2 = f(*t1, t3); + t1.reset(t2); + } + +} // namespace astclone diff --git a/tiger-compiler/src/astclone/local.am b/tiger-compiler/src/astclone/local.am new file mode 100644 index 0000000..302667b --- /dev/null +++ b/tiger-compiler/src/astclone/local.am @@ -0,0 +1,12 @@ +## astclone module. + +src_libtc_la_SOURCES += \ + %D%/cloner.hh %D%/cloner.hxx %D%/cloner.cc \ + %D%/libastclone.hh %D%/libastclone.hxx + +check_PROGRAMS += %D%/test-cloner +%C%_test_cloner_LDADD = src/libtc.la +%C%_test_cloner_CPPFLAGS = $(AM_CPPFLAGS) -DPKGDATADIR=\"$(pkgdatadir)\" + + +TASKS += %D%/tasks.hh %D%/tasks.cc diff --git a/tiger-compiler/src/astclone/tasks.cc b/tiger-compiler/src/astclone/tasks.cc new file mode 100644 index 0000000..ae6d973 --- /dev/null +++ b/tiger-compiler/src/astclone/tasks.cc @@ -0,0 +1,26 @@ +/** + ** \file astclone/tasks.cc + ** \brief Astclone module related tasks' implementation. + **/ + +#include <ast/tasks.hh> + +#include <astclone/libastclone.hh> +#define DEFINE_TASKS 1 +#include <astclone/tasks.hh> +#undef DEFINE_TASKS + +#include <common.hh> + +namespace astclone::tasks +{ + void clone() + { + ast::ChunkList* ds = ::astclone::clone(*ast::tasks::the_program); + if (!ds) + task_error() << misc::error::error_type::failure << "Cloning Failed\n" + << &misc::error::exit; + ast::tasks::the_program.reset(ds); + } + +} // namespace astclone::tasks diff --git a/tiger-compiler/src/astclone/tasks.hh b/tiger-compiler/src/astclone/tasks.hh new file mode 100644 index 0000000..25b346b --- /dev/null +++ b/tiger-compiler/src/astclone/tasks.hh @@ -0,0 +1,20 @@ +/** + ** \file astclone/tasks.hh + ** \brief Astclone module tasks. + */ + +#pragma once + +#include <misc/fwd.hh> + +#include <task/libtask.hh> + +/// Tasks of the astclone module. +namespace astclone::tasks +{ + TASK_GROUP("2.5 Cloning"); + + /// Clone ast::tasks::the_program, and replace it with its copy. + TASK_DECLARE("clone", "clone the Ast", clone, "parse"); + +} // namespace astclone::tasks |
