summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/ast/pretty-printer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tiger-compiler/src/ast/pretty-printer.cc')
-rw-r--r--tiger-compiler/src/ast/pretty-printer.cc419
1 files changed, 419 insertions, 0 deletions
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