diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
| commit | 967be9e750221ab2ab783f95df79bb26d290a45e (patch) | |
| tree | 6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/src/assert | |
Diffstat (limited to 'tiger-compiler/src/assert')
| -rw-r--r-- | tiger-compiler/src/assert/binder.cc | 12 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/binder.hh | 22 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/desugar-visitor.cc | 33 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/desugar-visitor.hh | 42 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/desugar-visitor.hxx | 39 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/libassert.cc | 36 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/libassert.hh | 79 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/libassert.hxx | 45 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/local.am | 17 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/renamer.cc | 18 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/renamer.hh | 30 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/tasks.cc | 53 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/tasks.hh | 59 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/type-checker.cc | 21 | ||||
| -rw-r--r-- | tiger-compiler/src/assert/type-checker.hh | 30 |
15 files changed, 536 insertions, 0 deletions
diff --git a/tiger-compiler/src/assert/binder.cc b/tiger-compiler/src/assert/binder.cc new file mode 100644 index 0000000..04008bc --- /dev/null +++ b/tiger-compiler/src/assert/binder.cc @@ -0,0 +1,12 @@ +/** + ** \file assert/binder.cc + ** \brief Implementation of assert::Binder. + */ + +#include <assert/binder.hh> + +namespace assert { + + Binder::Binder() = default; + +} // namespace assert diff --git a/tiger-compiler/src/assert/binder.hh b/tiger-compiler/src/assert/binder.hh new file mode 100644 index 0000000..7ede6d7 --- /dev/null +++ b/tiger-compiler/src/assert/binder.hh @@ -0,0 +1,22 @@ +/** + ** \file assert/binder.hh + ** \brief Declaration of assert::Binder. + */ + +#pragma once + +#include <bind/binder.hh> + +namespace assert { + + class Binder + : public bind::Binder + { + public: + using super_class = bind::Binder; + + // Build a Binder + Binder(); + }; + +} // namespace assert diff --git a/tiger-compiler/src/assert/desugar-visitor.cc b/tiger-compiler/src/assert/desugar-visitor.cc new file mode 100644 index 0000000..5f18a07 --- /dev/null +++ b/tiger-compiler/src/assert/desugar-visitor.cc @@ -0,0 +1,33 @@ +/** + ** \file assert/desugar-visitor.cc + ** \brief Implementation of assert::DesugarVisitor. + */ + +#include <assert/desugar-visitor.hh> + +namespace assert +{ + + DesugarVisitor::DesugarVisitor(const bool desugar_for_p, + const bool desugar_string_cmp_p) + : super_type(desugar_for_p, desugar_string_cmp_p) + {} + + void DesugarVisitor::operator()(const ast::AssertExp& e) + { + // FIXME DONE: Some code was deleted here. (replace the AssertExp to a CallExp) + const ast::Location location = e.location_get(); + + const auto args = new ast::exps_type; + + const std::string condition_text = get_formatted_assert_cond(e); + const std::string filename = get_formatted_location(e.location_get()); + + args->push_back(recurse(e.cond_get())); + args->push_back(new ast::StringExp(location, condition_text)); + args->push_back(new ast::StringExp(location, filename)); + + result_ = new ast::CallExp(location, "assertion", args); + } + +} // namespace assert diff --git a/tiger-compiler/src/assert/desugar-visitor.hh b/tiger-compiler/src/assert/desugar-visitor.hh new file mode 100644 index 0000000..88d689e --- /dev/null +++ b/tiger-compiler/src/assert/desugar-visitor.hh @@ -0,0 +1,42 @@ +/** + ** \file assert/desugar-visitor.hh + ** \brief Declaration of assert::DesugarVisitor. + */ + +#pragma once + +#include <ast/assert-visitor.hh> +#include <desugar/desugar-visitor.hh> + +namespace assert { + + class DesugarVisitor + : public desugar::DesugarVisitor + , public ast::AssertConstVisitor + { + public: + using super_type = desugar::DesugarVisitor; + using super_type::operator(); + + // Build a DesugarVisitor + DesugarVisitor(bool desugar_for_p, bool desugar_string_cmp_p); + + // Desugar assertions + // \param e Node to visit + void operator()(const ast::AssertExp& e) override; + + private: + + // Retrieve the pretty-printed version of an assertion's condition as a + // string + // \param e Node to pretty-print. + inline std::string get_formatted_assert_cond(const ast::AssertExp& e); + + // Retrieve the pretty-printed version of a Location as a string + // \param loc Location record to pretty-print + inline std::string get_formatted_location(const ast::Location& loc); + }; + +} // namespace assert + +#include <assert/desugar-visitor.hxx> diff --git a/tiger-compiler/src/assert/desugar-visitor.hxx b/tiger-compiler/src/assert/desugar-visitor.hxx new file mode 100644 index 0000000..9e839c1 --- /dev/null +++ b/tiger-compiler/src/assert/desugar-visitor.hxx @@ -0,0 +1,39 @@ +/** + ** \file assert/desugar-visitor.hxx + ** \brief Implementation of assert::DesugarVisitor (inlined methods). + */ + +#pragma once + +#include <assert/desugar-visitor.hh> + +#include <sstream> +#include <string> + +#include <ast/pretty-printer.hh> + +namespace assert +{ + + inline std::string + DesugarVisitor::get_formatted_assert_cond(const ast::AssertExp& e) + { + std::stringstream stream{}; + ast::PrettyPrinter pretty_printer(stream); + + pretty_printer(e.cond_get()); + + return stream.str(); + } + + inline std::string + DesugarVisitor::get_formatted_location(const ast::Location& loc) + { + std::stringstream stream{}; + + stream << loc; + + return stream.str(); + } + +} diff --git a/tiger-compiler/src/assert/libassert.cc b/tiger-compiler/src/assert/libassert.cc new file mode 100644 index 0000000..8114b74 --- /dev/null +++ b/tiger-compiler/src/assert/libassert.cc @@ -0,0 +1,36 @@ +/** + ** \file assert/libassert.cc + ** \brief Implementation of functions exported by the assert module. + */ + +#include <assert/binder.hh> +#include <assert/libassert.hh> +#include <assert/renamer.hh> +#include <assert/type-checker.hh> +#include <misc/error.hh> + +namespace assert +{ + + misc::error bind(ast::Ast& last) + { + Binder binder; + binder(last); + return binder.error_get(); + } + + misc::error types_check(ast::Ast& tree) + { + TypeChecker typer; + typer(tree); + return typer.error_get(); + } + + misc::error rename(ast::Ast& ast) + { + Renamer renamer; + renamer(ast); + return misc::error{}; + } + +} diff --git a/tiger-compiler/src/assert/libassert.hh b/tiger-compiler/src/assert/libassert.hh new file mode 100644 index 0000000..aba01b1 --- /dev/null +++ b/tiger-compiler/src/assert/libassert.hh @@ -0,0 +1,79 @@ +/** + ** \file assert/libassert.hh + ** \brief Declare functions and variables exported by assert module. + */ + +#pragma once + +#include <ast/fwd.hh> +#include <misc/error.hh> + +namespace assert +{ + /*-------. + | Bind. | + `-------*/ + + /// \brief Bind the whole AST in place, return the error code + /// + /// \param last the ast you want to bind + /// + /// \return a misc::error that serve to indicate possible failure + misc::error bind(ast::Ast& last); + + /*----------------. + | Compute types. | + `----------------*/ + + /** \brief Check types allowing assertions. + + \param tree abstract syntax tree's root. + + \return success of the type-checking. */ + misc::error types_check(ast::Ast& tree); + + /*---------. + | Rename. | + `---------*/ + + /// \brief Rename the whole ast in place + /// + /// \param ast the ast you want to rename + /// + /// \return a misc::error that serve to indicate possible failure + misc::error rename(ast::Ast& ast); + + /*---------------------. + | Desugar assertions. | + `---------------------*/ + + /** \brief Remove assertions constructs from an AST. + + \param tree abstract syntax tree's root, whose bindings + and types have been computed, and whose + identifiers are all unique. + \param class_names the names of the class types of the AST + + \return the desugared, bound and type-checked AST. */ + template <typename A> + A* desugar(const A& tree, bool desugar_for_p, bool desugar_string_cmp_p); + + /** \brief Remove assertions constructs from an AST without recomputing + its bindings nor its types. + + This function acts like assertions::assertions_desugar, but stops just + after the desugaring step (in fact, assertions::desugar is built + upon this function). It is meant to be used as a test of + DesugarVisitor (i.e., even if the desugared tree is badly bound + or typed, it can still be pretty-printed). + + \param tree AST to desugar. + \param class_names the names of the class types of the AST + + \return the desugared AST. */ + template <typename A> + A* raw_desugar(const A& tree, bool desugar_for_p, bool desugar_string_cmp_p); + +} + +#include <assert/libassert.hxx> diff --git a/tiger-compiler/src/assert/libassert.hxx b/tiger-compiler/src/assert/libassert.hxx new file mode 100644 index 0000000..fcd2eb4 --- /dev/null +++ b/tiger-compiler/src/assert/libassert.hxx @@ -0,0 +1,45 @@ +/** + ** \file assert/libassert.hxx + ** \brief Implementation of functions exported by the assert module. + */ + +#pragma once + +#include <memory> + +#include <assert/desugar-visitor.hh> +#include <assert/libassert.hh> +#include <misc/contract.hh> +#include <misc/error.hh> + +namespace assert +{ + + template <typename A> void bind_and_types_check(A& tree) + { + misc::error e; + e << ::assert::bind(tree); + e.ice_on_error_here(); + e << ::assert::types_check(tree); + e.ice_on_error_here(); + } + + template <typename A> + A* raw_desugar(const A& tree, bool desugar_for_p, bool desugar_string_cmp_p) + { + DesugarVisitor desugar(desugar_for_p, desugar_string_cmp_p); + desugar(tree); + return dynamic_cast<A*>(desugar.result_get()); + } + + template <typename A> + A* desugar(const A& tree, bool desugar_for_p, bool desugar_string_cmp_p) + { + A* desugared = raw_desugar(tree, desugar_for_p, desugar_string_cmp_p); + assertion(desugared); + std::unique_ptr<A> desugared_ptr(desugared); + bind_and_types_check(*desugared_ptr); + return desugared_ptr.release(); + } + +} diff --git a/tiger-compiler/src/assert/local.am b/tiger-compiler/src/assert/local.am new file mode 100644 index 0000000..18a8421 --- /dev/null +++ b/tiger-compiler/src/assert/local.am @@ -0,0 +1,17 @@ +## assert module + +src_libtc_la_SOURCES += \ + %D%/libassert.hh \ + %D%/libassert.cc \ + %D%/libassert.hxx + +src_libtc_la_SOURCES += \ + %D%/binder.hh %D%/binder.cc \ + %D%/desugar-visitor.hh %D%/desugar-visitor.cc %D%/desugar-visitor.hxx \ + %D%/type-checker.hh %D%/type-checker.cc \ + %D%/renamer.hh %D%/renamer.cc + + +## tasks + +TASKS += %D%/tasks.hh %D%/tasks.cc diff --git a/tiger-compiler/src/assert/renamer.cc b/tiger-compiler/src/assert/renamer.cc new file mode 100644 index 0000000..7c63cfa --- /dev/null +++ b/tiger-compiler/src/assert/renamer.cc @@ -0,0 +1,18 @@ +/** + ** \file assert/renamer.cc + ** \brief Implementation of assert::Renamer. + */ + +#include <assert/renamer.hh> + +namespace assert +{ + + Renamer::Renamer() = default; + + void Renamer::operator()(ast::AssertExp& e) + { + ast::AssertVisitor::operator()(e); + } + +} // namespace assert diff --git a/tiger-compiler/src/assert/renamer.hh b/tiger-compiler/src/assert/renamer.hh new file mode 100644 index 0000000..6a5bd14 --- /dev/null +++ b/tiger-compiler/src/assert/renamer.hh @@ -0,0 +1,30 @@ +/** + ** \file assert/renamer.hh + ** \brief Declaration of assert::Renamer. + */ + +#pragma once + +#include <ast/assert-visitor.hh> +#include <bind/renamer.hh> + +namespace assert { + + class Renamer + : public bind::Renamer + , public ast::AssertVisitor + { + public: + using super_type = ::bind::Renamer; + using super_type::operator(); + + // Build a renamer + Renamer(); + + // Visiting method for AssertExp nodes (redirects to + // `ast::AssertVisitor::operator()(ast::AssertExp&)`) + // \param e Node to visit + void operator()(ast::AssertExp& e) override; + }; + +} // namespace assert diff --git a/tiger-compiler/src/assert/tasks.cc b/tiger-compiler/src/assert/tasks.cc new file mode 100644 index 0000000..3e43ecd --- /dev/null +++ b/tiger-compiler/src/assert/tasks.cc @@ -0,0 +1,53 @@ +/** + ** \file assert/tasks.cc + ** \brief Assert module related tasks' implementation. + */ + +#include <ast/tasks.hh> +#include <astclone/libastclone.hh> +#include <assert/libassert.hh> +#include <common.hh> +#include <desugar/tasks.hh> +#include <escapes/tasks.hh> +#include <llvmtranslate/tasks.hh> +#define DEFINE_TASKS 1 +#include <assert/tasks.hh> +#undef DEFINE_TASKS + +namespace assert::tasks +{ + void parse() {} + + void bind() + { + task_error() << ::assert::bind(*ast::tasks::the_program.get()) + << &misc::error::exit_on_error; + } + + void types_compute() + { + task_error() << ::assert::types_check(*ast::tasks::the_program.get()) + << &misc::error::exit_on_error; + } + + void rename() + { + task_error() << ::assert::rename(*ast::tasks::the_program.get()) + << &misc::error::exit_on_error; + } + + void desugar() + { + astclone::apply(::assert::desugar, ast::tasks::the_program, + desugar::tasks::desugar_for_p, + desugar::tasks::desugar_string_cmp_p); + } + + void raw_desugar() + { + astclone::apply(::assert::raw_desugar, ast::tasks::the_program, + desugar::tasks::desugar_for_p, + desugar::tasks::desugar_string_cmp_p); + } + +} // namespace assert::tasks diff --git a/tiger-compiler/src/assert/tasks.hh b/tiger-compiler/src/assert/tasks.hh new file mode 100644 index 0000000..7f062de --- /dev/null +++ b/tiger-compiler/src/assert/tasks.hh @@ -0,0 +1,59 @@ +/** + ** \file assert/tasks.hh + ** \brief Assert module related tasks. + */ + +#pragma once + +#include <task/libtask.hh> + +// The tasks of the assert module +namespace assert::tasks +{ + TASK_GROUP("Assert"); + + // Enable assert extensions. + BOOLEAN_TASK_DECLARE("assert", + "enable assert extensions", + enable_assert_extensions_p, + ""); + + // Parse the input file, allowing assertions. + TASK_DECLARE("assert-parse", + "parse a file, allowing assertions", + parse, + "assert parse"); + + // Bind the parsed file, allowing assertions. + TASK_DECLARE("assert-bindings-compute", + "bind the name uses to their definitions, allowing assertions", + bind, + "assert-parse"); + + // Check for type violation, allowing assertions. + TASK_DECLARE("assert-types-compute", + "check for type violations, allowing assertions", + types_compute, + "assert-bindings-compute"); + + // Perform a renaming, before desugaring assertions. + TASK_DECLARE("assert-rename", + "rename identifiers to unique names, allowing assertions", + rename, + "assert-bindings-compute"); + + // Remove syntactic sugar from the Ast. + TASK_DECLARE("assert-desugar", + "remove assertions constructs from the program", + desugar, + "assert-rename assert-types-compute"); + + // Remove syntactic sugar from the Ast without recomputing + // bindings nor types. + TASK_DECLARE("raw-assert-desugar", + "remove assertions constructs from the program " + "without recomputing bindings nor types", + raw_desugar, + "assert-rename assert-types-compute"); + +} // namespace assert::tasks diff --git a/tiger-compiler/src/assert/type-checker.cc b/tiger-compiler/src/assert/type-checker.cc new file mode 100644 index 0000000..894ff6f --- /dev/null +++ b/tiger-compiler/src/assert/type-checker.cc @@ -0,0 +1,21 @@ +/** + ** \file assert/type-checker.cc + ** \brief Implementation of assert::TypeChecker. + */ + +#include <assert/type-checker.hh> + +namespace assert +{ + + TypeChecker::TypeChecker() = default; + + void TypeChecker::operator()(ast::AssertExp& e) + { + // FIXME DONE: Some code was deleted here. (implement method documentation) + check_type(e.cond_get(), "assertion", type::Int::instance()); + + type_default(e, &type::Void::instance()); + } + +} // namespace assert diff --git a/tiger-compiler/src/assert/type-checker.hh b/tiger-compiler/src/assert/type-checker.hh new file mode 100644 index 0000000..e15e393 --- /dev/null +++ b/tiger-compiler/src/assert/type-checker.hh @@ -0,0 +1,30 @@ +/** + ** \file assert/type-checker.hh + ** \brief Declaration of assert::TypeChecker. + */ + +#pragma once + +#include <ast/assert-visitor.hh> +#include <type/type-checker.hh> + +namespace assert { + + class TypeChecker + : public type::TypeChecker + , public ast::AssertVisitor + { + public: + using super_type = type::TypeChecker; + using super_type::operator(); + + // Build a TypeChecker + TypeChecker(); + + // Type an AssertExp node. All AssertExp must follow the typing table : + // cond_ : int | assert cond_ : void + // \param e Node to visit + void operator()(ast::AssertExp& e) override; + }; + +} // assert |
