summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/object/desugar-visitor.hh
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/object/desugar-visitor.hh
add: added projectsHEADmain
Diffstat (limited to 'tiger-compiler/src/object/desugar-visitor.hh')
-rw-r--r--tiger-compiler/src/object/desugar-visitor.hh301
1 files changed, 301 insertions, 0 deletions
diff --git a/tiger-compiler/src/object/desugar-visitor.hh b/tiger-compiler/src/object/desugar-visitor.hh
new file mode 100644
index 0000000..3c2b455
--- /dev/null
+++ b/tiger-compiler/src/object/desugar-visitor.hh
@@ -0,0 +1,301 @@
+/**
+ ** \file object/desugar-visitor.hh
+ ** \brief Declaration of object::DesugarVisitor.
+ */
+
+#pragma once
+
+#include <astclone/cloner.hh>
+#include <object/fwd.hh>
+#include <parse/tweast.hh>
+
+namespace object
+{
+ /// \brief Desugar some object structures while duplicating an Ast.
+ class DesugarVisitor : public astclone::Cloner
+ {
+ public:
+ /// Superclass.
+ using super_type = astclone::Cloner;
+
+ // Import overloaded virtual functions.
+ using super_type::operator();
+
+ /// Build a DesugarVisitor.
+ DesugarVisitor(const class_names_type& class_names);
+
+ /// Special version of the visit of a ChunkList allowing the
+ /// transformation of an ast::ChunkInterface to either a single ast::ChunkInterface or
+ /// to an ast::ChunkList.
+ void operator()(const ast::ChunkList& e) override;
+
+ /// \name Desugar class declarations.
+ /// \{
+
+ /// Desugar class declarations.
+ void operator()(const ast::TypeChunk& e) override;
+ /// Handle the builtin Object.
+ void operator()(const ast::FunctionDec& e) override;
+ /// Desugar class names.
+ void operator()(const ast::NameTy& e) override;
+
+ /// \}
+
+ /// \name Desugar class instantiations and object usage.
+ /// \{
+
+ /// Desugar polymorphic initializations.
+ void operator()(const ast::VarDec& e) override;
+ /// Desugar manifest objects.
+ void operator()(const ast::ObjectExp& e) override;
+ /// Desugar polymorphic branching.
+ void operator()(const ast::IfExp& e) override;
+ /// Desugar polymorphic assignments.
+ void operator()(const ast::AssignExp& e) override;
+ /// Desugar polymorphic insertion.
+ void operator()(const ast::ArrayExp& e) override;
+ void operator()(const ast::RecordExp& e) override;
+ /// Add object casts around arguments when needed.
+ void operator()(const ast::CallExp& e) override;
+
+ /// \}
+
+ /// \name Desugar accesses to class members.
+ /// \{
+
+ /// Desugar accesses to attributes.
+ void operator()(const ast::FieldVar& e) override;
+
+ /// Handle dynamic dispatch within scope.
+ void operator()(const ast::LetExp& e) override;
+
+ /// Desugar calls to methods.
+ void operator()(const ast::MethodCallExp& e) override;
+
+ /// \}
+
+ /// \brief Desugar actuals arguments in routine calls.
+ ///
+ /// \param actuals the actual arguments of the initial AST
+ /// \param formals the formal arguments of the routine
+ /// \return the desugared actual arguments
+ ast::exps_type* recurse_args(const ast::exps_type& actuals,
+ const type::Record& formals);
+
+ /// A list of classes (e.g., useful to represent a set of subclasses).
+ using classes_type = std::vector<const type::Class*>;
+
+ private:
+ /// \name Code generation.
+ /// \{
+
+ using pair_class_method =
+ std::pair<const type::Class*, const type::Method*>;
+ using dispatch_list_type = std::set<pair_class_method>;
+
+ /// \brief Desugar the constructor of the current class
+ ///
+ /// \param functions the tweast containing the constructor being desugared
+ /// \param cls the class whose constructor is being desugared
+ /// \param class_name the desugared version of the class name
+ void desugar_constructor(parse::Tweast& functions,
+ const type::Class* cls,
+ misc::symbol class_name);
+
+ /// \brief Desugar the current method.
+ ///
+ /// \param functions the tweast containing the method being desugared
+ /// \param method the methods being desugared
+ /// \param class_name the desugared version of the class name
+ void desugar_method(parse::Tweast& functions,
+ const type::Method* method,
+ misc::symbol class_name);
+
+ /// \brief Dispatch the method between the different classes.
+ ///
+ /// \param functions the tweast containing the dispatch
+ /// \param e the block of type being processed
+ /// \param cls the cls being desugared
+ /// \param method the method being dispatched
+ /// \param class_name the desugared version of the class name
+ /// \param sub_dispatches the processed classes/methods for dispatch
+ void dispatch_function(parse::Tweast& functions,
+ const ast::TypeChunk& e,
+ const type::Class* cls,
+ const type::Method* method,
+ misc::symbol class_name,
+ dispatch_list_type& sub_dispatches);
+
+ /// \brief Handle a class declaration.
+ ///
+ /// This is a declaration of a class: remove it and replace it with
+ ///
+ /// (1) a class type label (integer constant),
+ /// (2) new data structures:
+ /// - an actual structure holding the data of the class,
+ /// - a variant able to store any concrete type for this
+ /// class;
+ /// (3) new functions:
+ /// - a constructor,
+ /// - conversion routines used in polymorphic assignments (upcasts),
+ /// - conversion routines used in dynamic dispatch (downcasts),
+ /// - (desugared) methods,
+ /// - dispatch functions.
+ ///
+ /// We must take care of the order in which these declarations
+ /// are injected, since (1), (2) and (3) are declaration of
+ /// different kinds (variable, type and function respectively).
+ /// Mixing them would break the block of type declarations
+ /// (TypeChunk, or ``chunk'' of TypeDec's) being currently
+ /// visited. Thus we collect all class definitions from E,
+ /// replace them by new data structures ((2)) and inject the
+ /// rest of the new material *after* the TypeChunk ((1) and
+ /// (3)).
+ void handle_class(const ast::TypeChunk& e,
+ const type::Class* cls,
+ parse::Tweast& functions,
+ dispatch_list_type& sub_dispatches);
+
+ /// \brief Return the name of a type.
+ ///
+ /// \param type either a builtin type or a type::Named
+ /// \result the name of the type
+ std::string type_symbol(const type::Type* type);
+
+ /// Return the name of the upcast function between types \a from
+ /// and \a to.
+ std::string upcast_fun_name(const type::Class* from, const type::Class* to);
+ /// Return the name of the downcast function between types \a from
+ /// and \a to.
+ std::string downcast_fun_name(const type::Class* from,
+ const type::Class* to);
+
+ /// Return the name of the dispatch function for \a method,
+ /// defined in class \a owner.
+ std::string dispatch_fun_name(const type::Class* owner,
+ const type::Method* method);
+
+ /// Check if the type \a source_type of \a source_exp matches
+ /// \a target_type, and generate a type conversion wrapper if
+ /// needed.
+ void adapt_type(ast::Exp*& source_exp,
+ const type::Class* source_type,
+ const type::Class* target_type);
+
+ /// The type of a list of initializations for the field of a variant.
+ using field_inits_type = misc::map<const type::Class*, std::string>;
+
+ /// \brief Generate a variant expression.
+ ///
+ /// \param static_type the type of the class whose variant is built
+ /// \param exact_type the exact type of the data stored in the variant
+ /// \param inits the initalization value of the variant (must be
+ /// of type \a dynamic_type).
+ /// \return the generated variant expression
+ ast::Exp* variant_exp(const type::Class* static_type,
+ const std::string& exact_type,
+ const field_inits_type& inits);
+
+ /// Syntactic sugar for the previous routine.
+ ast::Exp* variant_exp(const type::Class* static_type,
+ const type::Class* dynamic_type,
+ const field_inits_type& inits);
+
+ /// \brief Populate a variant fields.
+ ///
+ /// \param class_type the type of the class used to populate the variant
+ /// \param input the tweast containing the variant being built
+ void fill_variant_fields(const type::Class* class_type,
+ parse::Tweast* input);
+
+ /// \brief Generate code for a variant type on a TWEAST.
+ ///
+ /// Contrary to object::DesugarVisitor::variant_exp, we
+ /// cannot directly generate an expression, since the client
+ /// TWEAST won't accept an ast::Ty* as a metavariable.
+ ///
+ /// \param class_type the type of the class whose variant is built
+ /// \return the TWEAST on which the code is generated
+ parse::Tweast* variant_ty(const type::Class* class_type);
+
+ /// \brief Populate an initialization list.
+ ///
+ /// \param class_type the type of the class used to populate the list
+ /// \param inits the initialization list
+ void fill_init_list(const type::Class* class_type, field_inits_type& inits);
+
+ /// \brief Generate a conversion routine.
+ ///
+ /// \param name the type of the generated function
+ /// \param source the type of the converted value
+ /// \param target the target type of the conversion
+ /// \param exact_type the exact type of the returned variant
+ /// \return the TWEAST on which the code is generated
+ parse::Tweast* cast_function(const std::string& name,
+ const type::Class* source,
+ const type::Class* target,
+ const type::Class* exact_type);
+
+ /// Syntactic sugar for object::DesugarVisitor::cast_function,
+ /// used to generate an upcast function.
+ parse::Tweast* upcast_function(const type::Class* source,
+ const type::Class* target);
+
+ /// Syntactic sugar for object::DesugarVisitor::cast_function,
+ /// used to generate a downcast function.
+ parse::Tweast* downcast_function(const type::Class* source,
+ const type::Class* target);
+
+ /// \brief Generate an expression looking like a switch
+ /// expression, to dispatch a method call. Do not generate code
+ /// for classes outside typechunk. If this function is used to create a sub
+ /// dispatch function, recursive call should be true, in order to call
+ /// the previous dispatch function if nothing matches.
+ ///
+ /// \param class_type the static type of the class owning the method
+ /// \param method the called method
+ /// \param typechunk the current chunk
+ /// \param dispatch_method the recursively called dispatch method
+ /// \return the generated expression
+ ast::Exp* dispatch_switch(const type::Class* class_type,
+ const type::Method* method,
+ const ast::TypeChunk* typechunk,
+ const type::Method* dispatch_method = nullptr);
+
+ /// \brief Generate a (static) call to a desugared method.
+ ///
+ /// \note The dynamic dispatch must have been performed before
+ /// using this generator.
+ ///
+ /// \param class_name the class where the method resides
+ /// \param method_name the name of the method
+ /// \param target the name of the target (object)
+ /// \param formals the actual arguments (other than the target)
+ /// \return the TWEAST on which the code is generated
+ parse::Tweast* method_call(misc::symbol class_name,
+ misc::symbol method_name,
+ const std::string& target,
+ const ast::VarChunk& formals);
+
+ /// \}
+
+ private:
+ /// The names of the classes defined in the program.
+ class_names_type class_names_;
+
+ /// TWEAST of desugared types.
+ parse::Tweast types_;
+ /// TWEAST of class ids.
+ parse::Tweast class_ids_;
+
+ /// TWEAST of upcast functions.
+ parse::Tweast funs_tweast;
+
+ /// Vector keeping track of added dispatch functions within a scope.
+ misc::vector<const type::Method*> dispatch_added_;
+
+ /// Map / counter giving the correct current dispatch extensions for a method
+ misc::map<const type::Method*, unsigned int> dispatch_map_;
+ };
+
+} // namespace object