From 4dbc5aca0da4a83d0f5d109e28fc91041a784e3d Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 5 Jun 2024 19:53:04 +0200 Subject: [PATCH] Type check if and while conditions --- include/elna/source/parser.hpp | 4 ++-- include/elna/source/result.hpp | 3 ++- include/elna/source/semantic.hpp | 3 +++ include/elna/source/symbol_table.hpp | 33 +++++++++++++++----------- source/semantic.cpp | 33 ++++++++++++++++++++++++++ source/symbol_table.cpp | 35 +++++++++------------------- 6 files changed, 70 insertions(+), 41 deletions(-) diff --git a/include/elna/source/parser.hpp b/include/elna/source/parser.hpp index 5ad14a1..ff3ec2d 100644 --- a/include/elna/source/parser.hpp +++ b/include/elna/source/parser.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "elna/source/types.hpp" @@ -482,7 +481,7 @@ namespace elna::source unary_operator operation() const noexcept; }; - class parser : boost::noncopyable + class parser { std::unique_ptr parse_unary_expression(); std::unique_ptr parse_factor(); @@ -508,6 +507,7 @@ namespace elna::source public: parser(lexer&& tokens); + parser(const parser&) = delete; /** * Parses a source text. diff --git a/include/elna/source/result.hpp b/include/elna/source/result.hpp index c219e50..a67fcab 100644 --- a/include/elna/source/result.hpp +++ b/include/elna/source/result.hpp @@ -136,7 +136,8 @@ namespace elna::source dereference, argument, arithmetic, - comparison + comparison, + condition }; /** diff --git a/include/elna/source/semantic.hpp b/include/elna/source/semantic.hpp index afde1da..2bda336 100644 --- a/include/elna/source/semantic.hpp +++ b/include/elna/source/semantic.hpp @@ -81,9 +81,12 @@ namespace elna::source void visit(procedure_definition *procedure) override; void visit(integer_literal *literal) override; void visit(boolean_literal *literal) override; + void visit(variable_expression *expression) override; void visit(unary_expression *expression) override; void visit(binary_expression *expression) override; void visit(call_statement *statement) override; void visit(constant_definition *definition) override; + void visit(while_statement *statement) override; + void visit(if_statement *statement) override; }; } diff --git a/include/elna/source/symbol_table.hpp b/include/elna/source/symbol_table.hpp index 820c77c..f0eb9fa 100644 --- a/include/elna/source/symbol_table.hpp +++ b/include/elna/source/symbol_table.hpp @@ -35,49 +35,54 @@ namespace elna::source }; /** - * Constant information. + * Information for a typed symbol. */ - class constant_info final : public info + class typed_info : public info { std::shared_ptr m_type; + + protected: + typed_info(std::shared_ptr type); + + public: + ~typed_info() override; + + std::shared_ptr type() const noexcept; + }; + + /** + * Constant information. + */ + class constant_info final : public typed_info + { std::int32_t m_value; public: constant_info(std::shared_ptr type, const std::int32_t value); - ~constant_info() override; - std::shared_ptr type() const noexcept; std::int32_t value() const noexcept; }; /** * Variable information. */ - class variable_info final : public info + class variable_info final : public typed_info { - std::shared_ptr m_type; - public: std::ptrdiff_t offset{ 0 }; explicit variable_info(std::shared_ptr type); - ~variable_info() override; - std::shared_ptr type() noexcept; }; /** * Procedure parameter information. */ - class parameter_info final : public info + class parameter_info final : public typed_info { - std::shared_ptr m_type; - public: std::ptrdiff_t offset{ 0 }; explicit parameter_info(std::shared_ptr type); - ~parameter_info() override; - std::shared_ptr type() const noexcept; }; /** diff --git a/source/semantic.cpp b/source/semantic.cpp index 45c04be..0a50ec7 100644 --- a/source/semantic.cpp +++ b/source/semantic.cpp @@ -169,6 +169,11 @@ namespace elna::source literal->data_type = std::dynamic_pointer_cast(table->lookup("Boolean"))->type(); } + void type_analysis_visitor::visit(variable_expression *expression) + { + expression->data_type = std::dynamic_pointer_cast(table->lookup(expression->name()))->type(); + } + void type_analysis_visitor::visit(unary_expression *expression) { empty_visitor::visit(expression); @@ -272,6 +277,34 @@ namespace elna::source definition->body().accept(this); } + void type_analysis_visitor::visit(while_statement *statement) + { + statement->prerequisite().accept(this); + auto condition_type = std::dynamic_pointer_cast(statement->prerequisite().data_type); + + if (condition_type != nullptr && *condition_type != boolean_type) + { + auto new_error = std::make_unique(condition_type, + type_mismatch::operation::condition, this->filename, statement->prerequisite().position()); + m_errors.push_back(std::move(new_error)); + } + statement->body().accept(this); + } + + void type_analysis_visitor::visit(if_statement *statement) + { + statement->prerequisite().accept(this); + auto condition_type = std::dynamic_pointer_cast(statement->prerequisite().data_type); + + if (condition_type != nullptr && *condition_type != boolean_type) + { + auto new_error = std::make_unique(condition_type, + type_mismatch::operation::condition, this->filename, statement->prerequisite().position()); + m_errors.push_back(std::move(new_error)); + } + statement->body().accept(this); + } + const std::list>& type_analysis_visitor::errors() const noexcept { return m_errors; diff --git a/source/symbol_table.cpp b/source/symbol_table.cpp index 86ac1f2..8801fa7 100644 --- a/source/symbol_table.cpp +++ b/source/symbol_table.cpp @@ -55,53 +55,40 @@ namespace elna::source return m_type; } - constant_info::constant_info(const std::shared_ptr type, const std::int32_t value) - : m_type(type), m_value(value) + typed_info::typed_info(std::shared_ptr type) + : m_type(type) { } - constant_info::~constant_info() + typed_info::~typed_info() { } - std::shared_ptr constant_info::type() const noexcept + std::shared_ptr typed_info::type() const noexcept { return m_type; } + constant_info::constant_info(const std::shared_ptr type, const std::int32_t value) + : typed_info(type), m_value(value) + { + } + std::int32_t constant_info::value() const noexcept { return m_value; } variable_info::variable_info(std::shared_ptr type) - : m_type(type) + : typed_info(type) { } - variable_info::~variable_info() - { - } - - std::shared_ptr variable_info::type() noexcept - { - return m_type; - } - parameter_info::parameter_info(std::shared_ptr type) - : m_type(type) + : typed_info(type) { } - parameter_info::~parameter_info() - { - } - - std::shared_ptr parameter_info::type() const noexcept - { - return m_type; - } - intrinsic_info::intrinsic_info(const class procedure_type& type) : m_type(std::make_shared(type)) {