summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/ast
diff options
context:
space:
mode:
authorMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
committerMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
commit967be9e750221ab2ab783f95df79bb26d290a45e (patch)
tree6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/src/ast
add: added projectsHEADmain
Diffstat (limited to 'tiger-compiler/src/ast')
-rw-r--r--tiger-compiler/src/ast/README.txt66
-rw-r--r--tiger-compiler/src/ast/all.hh51
-rw-r--r--tiger-compiler/src/ast/array-exp.cc31
-rw-r--r--tiger-compiler/src/ast/array-exp.hh60
-rw-r--r--tiger-compiler/src/ast/array-exp.hxx22
-rw-r--r--tiger-compiler/src/ast/array-ty.cc21
-rw-r--r--tiger-compiler/src/ast/array-ty.hh48
-rw-r--r--tiger-compiler/src/ast/array-ty.hxx16
-rw-r--r--tiger-compiler/src/ast/assert-exp.cc24
-rw-r--r--tiger-compiler/src/ast/assert-exp.hh42
-rw-r--r--tiger-compiler/src/ast/assert-exp.hxx14
-rw-r--r--tiger-compiler/src/ast/assert-visitor.hh51
-rw-r--r--tiger-compiler/src/ast/assert-visitor.hxx32
-rw-r--r--tiger-compiler/src/ast/assign-exp.cc26
-rw-r--r--tiger-compiler/src/ast/assign-exp.hh54
-rw-r--r--tiger-compiler/src/ast/assign-exp.hxx19
-rw-r--r--tiger-compiler/src/ast/ast-nodes.mk41
-rw-r--r--tiger-compiler/src/ast/ast.cc15
-rw-r--r--tiger-compiler/src/ast/ast.hh48
-rw-r--r--tiger-compiler/src/ast/ast.hxx18
-rw-r--r--tiger-compiler/src/ast/break-exp.cc18
-rw-r--r--tiger-compiler/src/ast/break-exp.hh49
-rw-r--r--tiger-compiler/src/ast/break-exp.hxx21
-rw-r--r--tiger-compiler/src/ast/call-exp.cc27
-rw-r--r--tiger-compiler/src/ast/call-exp.hh64
-rw-r--r--tiger-compiler/src/ast/call-exp.hxx25
-rw-r--r--tiger-compiler/src/ast/cast-exp.cc26
-rw-r--r--tiger-compiler/src/ast/cast-exp.hh62
-rw-r--r--tiger-compiler/src/ast/cast-exp.hxx19
-rw-r--r--tiger-compiler/src/ast/chunk-interface.hh25
-rw-r--r--tiger-compiler/src/ast/chunk-interface.hxx16
-rw-r--r--tiger-compiler/src/ast/chunk-list.cc58
-rw-r--r--tiger-compiler/src/ast/chunk-list.hh80
-rw-r--r--tiger-compiler/src/ast/chunk-list.hxx19
-rw-r--r--tiger-compiler/src/ast/chunk.hh139
-rw-r--r--tiger-compiler/src/ast/chunk.hxx118
-rw-r--r--tiger-compiler/src/ast/class-ty.cc22
-rw-r--r--tiger-compiler/src/ast/class-ty.hh55
-rw-r--r--tiger-compiler/src/ast/class-ty.hxx19
-rw-r--r--tiger-compiler/src/ast/dec.cc17
-rw-r--r--tiger-compiler/src/ast/dec.hh50
-rw-r--r--tiger-compiler/src/ast/dec.hxx15
-rw-r--r--tiger-compiler/src/ast/default-visitor.hh151
-rw-r--r--tiger-compiler/src/ast/default-visitor.hxx247
-rw-r--r--tiger-compiler/src/ast/dumper-dot.cc438
-rw-r--r--tiger-compiler/src/ast/dumper-dot.hh112
-rw-r--r--tiger-compiler/src/ast/dumper-dot.hxx214
-rw-r--r--tiger-compiler/src/ast/escapable.cc14
-rw-r--r--tiger-compiler/src/ast/escapable.hh30
-rw-r--r--tiger-compiler/src/ast/escapable.hxx16
-rw-r--r--tiger-compiler/src/ast/exp.cc16
-rw-r--r--tiger-compiler/src/ast/exp.hh43
-rw-r--r--tiger-compiler/src/ast/exp.hxx11
-rw-r--r--tiger-compiler/src/ast/field-init.cc22
-rw-r--r--tiger-compiler/src/ast/field-init.hh55
-rw-r--r--tiger-compiler/src/ast/field-init.hxx19
-rw-r--r--tiger-compiler/src/ast/field-var.cc22
-rw-r--r--tiger-compiler/src/ast/field-var.hh60
-rw-r--r--tiger-compiler/src/ast/field-var.hxx22
-rw-r--r--tiger-compiler/src/ast/field.cc22
-rw-r--r--tiger-compiler/src/ast/field.hh55
-rw-r--r--tiger-compiler/src/ast/field.hxx19
-rw-r--r--tiger-compiler/src/ast/for-exp.cc28
-rw-r--r--tiger-compiler/src/ast/for-exp.hh60
-rw-r--r--tiger-compiler/src/ast/for-exp.hxx22
-rw-r--r--tiger-compiler/src/ast/function-dec.cc33
-rw-r--r--tiger-compiler/src/ast/function-dec.hh72
-rw-r--r--tiger-compiler/src/ast/function-dec.hxx23
-rw-r--r--tiger-compiler/src/ast/fwd.hh80
-rw-r--r--tiger-compiler/src/ast/if-exp.cc31
-rw-r--r--tiger-compiler/src/ast/if-exp.hh71
-rw-r--r--tiger-compiler/src/ast/if-exp.hxx22
-rw-r--r--tiger-compiler/src/ast/int-exp.cc19
-rw-r--r--tiger-compiler/src/ast/int-exp.hh44
-rw-r--r--tiger-compiler/src/ast/int-exp.hxx15
-rw-r--r--tiger-compiler/src/ast/let-exp.cc26
-rw-r--r--tiger-compiler/src/ast/let-exp.hh55
-rw-r--r--tiger-compiler/src/ast/let-exp.hxx19
-rw-r--r--tiger-compiler/src/ast/libast.cc44
-rw-r--r--tiger-compiler/src/ast/libast.hh26
-rw-r--r--tiger-compiler/src/ast/local.am30
-rw-r--r--tiger-compiler/src/ast/location.hh14
-rw-r--r--tiger-compiler/src/ast/method-call-exp.cc24
-rw-r--r--tiger-compiler/src/ast/method-call-exp.hh70
-rw-r--r--tiger-compiler/src/ast/method-call-exp.hxx21
-rw-r--r--tiger-compiler/src/ast/method-dec.cc22
-rw-r--r--tiger-compiler/src/ast/method-dec.hh45
-rw-r--r--tiger-compiler/src/ast/method-dec.hxx11
-rw-r--r--tiger-compiler/src/ast/name-ty.cc19
-rw-r--r--tiger-compiler/src/ast/name-ty.hh56
-rw-r--r--tiger-compiler/src/ast/name-ty.hxx20
-rw-r--r--tiger-compiler/src/ast/nil-exp.cc19
-rw-r--r--tiger-compiler/src/ast/nil-exp.hh37
-rw-r--r--tiger-compiler/src/ast/nil-exp.hxx11
-rw-r--r--tiger-compiler/src/ast/non-assert-visitor.hh51
-rw-r--r--tiger-compiler/src/ast/non-assert-visitor.hxx34
-rw-r--r--tiger-compiler/src/ast/non-object-visitor.hh92
-rw-r--r--tiger-compiler/src/ast/non-object-visitor.hxx62
-rw-r--r--tiger-compiler/src/ast/object-exp.cc19
-rw-r--r--tiger-compiler/src/ast/object-exp.hh47
-rw-r--r--tiger-compiler/src/ast/object-exp.hxx16
-rw-r--r--tiger-compiler/src/ast/object-visitor.hh89
-rw-r--r--tiger-compiler/src/ast/object-visitor.hxx69
-rw-r--r--tiger-compiler/src/ast/op-exp.cc42
-rw-r--r--tiger-compiler/src/ast/op-exp.hh80
-rw-r--r--tiger-compiler/src/ast/op-exp.hxx21
-rw-r--r--tiger-compiler/src/ast/pretty-printer.cc419
-rw-r--r--tiger-compiler/src/ast/pretty-printer.hh96
-rw-r--r--tiger-compiler/src/ast/record-exp.cc30
-rw-r--r--tiger-compiler/src/ast/record-exp.hh57
-rw-r--r--tiger-compiler/src/ast/record-exp.hxx22
-rw-r--r--tiger-compiler/src/ast/record-ty.cc26
-rw-r--r--tiger-compiler/src/ast/record-ty.hh49
-rw-r--r--tiger-compiler/src/ast/record-ty.hxx16
-rw-r--r--tiger-compiler/src/ast/seq-exp.cc26
-rw-r--r--tiger-compiler/src/ast/seq-exp.hh47
-rw-r--r--tiger-compiler/src/ast/seq-exp.hxx16
-rw-r--r--tiger-compiler/src/ast/simple-var.cc19
-rw-r--r--tiger-compiler/src/ast/simple-var.hh56
-rw-r--r--tiger-compiler/src/ast/simple-var.hxx20
-rw-r--r--tiger-compiler/src/ast/string-exp.cc19
-rw-r--r--tiger-compiler/src/ast/string-exp.hh47
-rw-r--r--tiger-compiler/src/ast/string-exp.hxx16
-rw-r--r--tiger-compiler/src/ast/subscript-var.cc26
-rw-r--r--tiger-compiler/src/ast/subscript-var.hh54
-rw-r--r--tiger-compiler/src/ast/subscript-var.hxx19
-rw-r--r--tiger-compiler/src/ast/tasks.cc32
-rw-r--r--tiger-compiler/src/ast/tasks.hh24
-rw-r--r--tiger-compiler/src/ast/ty.cc17
-rw-r--r--tiger-compiler/src/ast/ty.hh39
-rw-r--r--tiger-compiler/src/ast/ty.hxx11
-rw-r--r--tiger-compiler/src/ast/typable.cc15
-rw-r--r--tiger-compiler/src/ast/typable.hh50
-rw-r--r--tiger-compiler/src/ast/typable.hxx24
-rw-r--r--tiger-compiler/src/ast/type-constructor.cc31
-rw-r--r--tiger-compiler/src/ast/type-constructor.hh38
-rw-r--r--tiger-compiler/src/ast/type-constructor.hxx23
-rw-r--r--tiger-compiler/src/ast/type-dec.cc22
-rw-r--r--tiger-compiler/src/ast/type-dec.hh51
-rw-r--r--tiger-compiler/src/ast/type-dec.hxx16
-rw-r--r--tiger-compiler/src/ast/var-dec.cc31
-rw-r--r--tiger-compiler/src/ast/var-dec.hh61
-rw-r--r--tiger-compiler/src/ast/var-dec.hxx19
-rw-r--r--tiger-compiler/src/ast/var.cc15
-rw-r--r--tiger-compiler/src/ast/var.hh26
-rw-r--r--tiger-compiler/src/ast/var.hxx11
-rw-r--r--tiger-compiler/src/ast/visitor.hh114
-rw-r--r--tiger-compiler/src/ast/visitor.hxx36
-rw-r--r--tiger-compiler/src/ast/while-exp.cc26
-rw-r--r--tiger-compiler/src/ast/while-exp.hh53
-rw-r--r--tiger-compiler/src/ast/while-exp.hxx19
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 << ":&nbsp;" << 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