summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/astclone
diff options
context:
space:
mode:
Diffstat (limited to 'tiger-compiler/src/astclone')
-rw-r--r--tiger-compiler/src/astclone/cloner.cc311
-rw-r--r--tiger-compiler/src/astclone/cloner.hh102
-rw-r--r--tiger-compiler/src/astclone/cloner.hxx72
-rw-r--r--tiger-compiler/src/astclone/libastclone.hh42
-rw-r--r--tiger-compiler/src/astclone/libastclone.hxx40
-rw-r--r--tiger-compiler/src/astclone/local.am12
-rw-r--r--tiger-compiler/src/astclone/tasks.cc26
-rw-r--r--tiger-compiler/src/astclone/tasks.hh20
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