Type check if and while conditions
This commit is contained in:
		| @@ -1,6 +1,5 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <boost/core/noncopyable.hpp> |  | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <elna/source/lexer.hpp> | #include <elna/source/lexer.hpp> | ||||||
| #include "elna/source/types.hpp" | #include "elna/source/types.hpp" | ||||||
| @@ -482,7 +481,7 @@ namespace elna::source | |||||||
|         unary_operator operation() const noexcept; |         unary_operator operation() const noexcept; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class parser : boost::noncopyable |     class parser | ||||||
|     { |     { | ||||||
|         std::unique_ptr<expression> parse_unary_expression(); |         std::unique_ptr<expression> parse_unary_expression(); | ||||||
|         std::unique_ptr<expression> parse_factor(); |         std::unique_ptr<expression> parse_factor(); | ||||||
| @@ -508,6 +507,7 @@ namespace elna::source | |||||||
|  |  | ||||||
|     public: |     public: | ||||||
|         parser(lexer&& tokens); |         parser(lexer&& tokens); | ||||||
|  |         parser(const parser&) = delete; | ||||||
|  |  | ||||||
|         /** |         /** | ||||||
|          * Parses a source text. |          * Parses a source text. | ||||||
|   | |||||||
| @@ -136,7 +136,8 @@ namespace elna::source | |||||||
|             dereference, |             dereference, | ||||||
|             argument, |             argument, | ||||||
|             arithmetic, |             arithmetic, | ||||||
|             comparison |             comparison, | ||||||
|  |             condition | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         /** |         /** | ||||||
|   | |||||||
| @@ -81,9 +81,12 @@ namespace elna::source | |||||||
|         void visit(procedure_definition *procedure) override; |         void visit(procedure_definition *procedure) override; | ||||||
|         void visit(integer_literal *literal) override; |         void visit(integer_literal *literal) override; | ||||||
|         void visit(boolean_literal *literal) override; |         void visit(boolean_literal *literal) override; | ||||||
|  |         void visit(variable_expression *expression) override; | ||||||
|         void visit(unary_expression *expression) override; |         void visit(unary_expression *expression) override; | ||||||
|         void visit(binary_expression *expression) override; |         void visit(binary_expression *expression) override; | ||||||
|         void visit(call_statement *statement) override; |         void visit(call_statement *statement) override; | ||||||
|         void visit(constant_definition *definition) override; |         void visit(constant_definition *definition) override; | ||||||
|  |         void visit(while_statement *statement) override; | ||||||
|  |         void visit(if_statement *statement) override; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -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<const class type> m_type; |         std::shared_ptr<const class type> m_type; | ||||||
|  |  | ||||||
|  |     protected: | ||||||
|  |         typed_info(std::shared_ptr<const class type> type); | ||||||
|  |  | ||||||
|  |     public: | ||||||
|  |         ~typed_info() override; | ||||||
|  |  | ||||||
|  |         std::shared_ptr<const class type> type() const noexcept; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Constant information. | ||||||
|  |      */ | ||||||
|  |     class constant_info final : public typed_info | ||||||
|  |     { | ||||||
|         std::int32_t m_value; |         std::int32_t m_value; | ||||||
|  |  | ||||||
|     public: |     public: | ||||||
|         constant_info(std::shared_ptr<const class type> type, const std::int32_t value); |         constant_info(std::shared_ptr<const class type> type, const std::int32_t value); | ||||||
|         ~constant_info() override; |  | ||||||
|  |  | ||||||
|         std::shared_ptr<const class type> type() const noexcept; |  | ||||||
|         std::int32_t value() const noexcept; |         std::int32_t value() const noexcept; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Variable information. |      * Variable information. | ||||||
|      */ |      */ | ||||||
|     class variable_info final : public info |     class variable_info final : public typed_info | ||||||
|     { |     { | ||||||
|         std::shared_ptr<const class type> m_type; |  | ||||||
|  |  | ||||||
|     public: |     public: | ||||||
|         std::ptrdiff_t offset{ 0 }; |         std::ptrdiff_t offset{ 0 }; | ||||||
|  |  | ||||||
|         explicit variable_info(std::shared_ptr<const class type> type); |         explicit variable_info(std::shared_ptr<const class type> type); | ||||||
|         ~variable_info() override; |  | ||||||
|         std::shared_ptr<const class type> type() noexcept; |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Procedure parameter information. |      * Procedure parameter information. | ||||||
|      */ |      */ | ||||||
|     class parameter_info final : public info |     class parameter_info final : public typed_info | ||||||
|     { |     { | ||||||
|         std::shared_ptr<const class type> m_type; |  | ||||||
|  |  | ||||||
|     public: |     public: | ||||||
|         std::ptrdiff_t offset{ 0 }; |         std::ptrdiff_t offset{ 0 }; | ||||||
|  |  | ||||||
|         explicit parameter_info(std::shared_ptr<const class type> type); |         explicit parameter_info(std::shared_ptr<const class type> type); | ||||||
|         ~parameter_info() override; |  | ||||||
|         std::shared_ptr<const class type> type() const noexcept; |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -169,6 +169,11 @@ namespace elna::source | |||||||
|         literal->data_type = std::dynamic_pointer_cast<type_info>(table->lookup("Boolean"))->type(); |         literal->data_type = std::dynamic_pointer_cast<type_info>(table->lookup("Boolean"))->type(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     void type_analysis_visitor::visit(variable_expression *expression) | ||||||
|  |     { | ||||||
|  |         expression->data_type = std::dynamic_pointer_cast<typed_info>(table->lookup(expression->name()))->type(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     void type_analysis_visitor::visit(unary_expression *expression) |     void type_analysis_visitor::visit(unary_expression *expression) | ||||||
|     { |     { | ||||||
|         empty_visitor::visit(expression); |         empty_visitor::visit(expression); | ||||||
| @@ -272,6 +277,34 @@ namespace elna::source | |||||||
|         definition->body().accept(this); |         definition->body().accept(this); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     void type_analysis_visitor::visit(while_statement *statement) | ||||||
|  |     { | ||||||
|  |         statement->prerequisite().accept(this); | ||||||
|  |         auto condition_type = std::dynamic_pointer_cast<const primitive_type>(statement->prerequisite().data_type); | ||||||
|  |  | ||||||
|  |         if (condition_type != nullptr && *condition_type != boolean_type) | ||||||
|  |         { | ||||||
|  |             auto new_error = std::make_unique<type_mismatch>(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<const primitive_type>(statement->prerequisite().data_type); | ||||||
|  |  | ||||||
|  |         if (condition_type != nullptr && *condition_type != boolean_type) | ||||||
|  |         { | ||||||
|  |             auto new_error = std::make_unique<type_mismatch>(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<std::unique_ptr<error>>& type_analysis_visitor::errors() const noexcept |     const std::list<std::unique_ptr<error>>& type_analysis_visitor::errors() const noexcept | ||||||
|     { |     { | ||||||
|         return m_errors; |         return m_errors; | ||||||
|   | |||||||
| @@ -55,53 +55,40 @@ namespace elna::source | |||||||
|         return m_type; |         return m_type; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     constant_info::constant_info(const std::shared_ptr<const class type> type, const std::int32_t value) |     typed_info::typed_info(std::shared_ptr<const class type> type) | ||||||
|         : m_type(type), m_value(value) |         : m_type(type) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     constant_info::~constant_info() |     typed_info::~typed_info() | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     std::shared_ptr<const class type> constant_info::type() const noexcept |     std::shared_ptr<const class type> typed_info::type() const noexcept | ||||||
|     { |     { | ||||||
|         return m_type; |         return m_type; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     constant_info::constant_info(const std::shared_ptr<const class type> type, const std::int32_t value) | ||||||
|  |         : typed_info(type), m_value(value) | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|     std::int32_t constant_info::value() const noexcept |     std::int32_t constant_info::value() const noexcept | ||||||
|     { |     { | ||||||
|         return m_value; |         return m_value; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     variable_info::variable_info(std::shared_ptr<const class type> type) |     variable_info::variable_info(std::shared_ptr<const class type> type) | ||||||
|         : m_type(type) |         : typed_info(type) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     variable_info::~variable_info() |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::shared_ptr<const class type> variable_info::type() noexcept |  | ||||||
|     { |  | ||||||
|         return m_type; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     parameter_info::parameter_info(std::shared_ptr<const class type> type) |     parameter_info::parameter_info(std::shared_ptr<const class type> type) | ||||||
|         : m_type(type) |         : typed_info(type) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     parameter_info::~parameter_info() |  | ||||||
|     { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::shared_ptr<const class type> parameter_info::type() const noexcept |  | ||||||
|     { |  | ||||||
|         return m_type; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     intrinsic_info::intrinsic_info(const class procedure_type& type) |     intrinsic_info::intrinsic_info(const class procedure_type& type) | ||||||
|         : m_type(std::make_shared<procedure_type>(type)) |         : m_type(std::make_shared<procedure_type>(type)) | ||||||
|     { |     { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user