Type check if and while conditions
This commit is contained in:
		| @@ -1,6 +1,5 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <boost/core/noncopyable.hpp> | ||||
| #include <memory> | ||||
| #include <elna/source/lexer.hpp> | ||||
| #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<expression> parse_unary_expression(); | ||||
|         std::unique_ptr<expression> parse_factor(); | ||||
| @@ -508,6 +507,7 @@ namespace elna::source | ||||
|  | ||||
|     public: | ||||
|         parser(lexer&& tokens); | ||||
|         parser(const parser&) = delete; | ||||
|  | ||||
|         /** | ||||
|          * Parses a source text. | ||||
|   | ||||
| @@ -136,7 +136,8 @@ namespace elna::source | ||||
|             dereference, | ||||
|             argument, | ||||
|             arithmetic, | ||||
|             comparison | ||||
|             comparison, | ||||
|             condition | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|   | ||||
| @@ -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; | ||||
|     }; | ||||
| } | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|     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; | ||||
|  | ||||
|     public: | ||||
|         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; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Variable information. | ||||
|      */ | ||||
|     class variable_info final : public info | ||||
|     class variable_info final : public typed_info | ||||
|     { | ||||
|         std::shared_ptr<const class type> m_type; | ||||
|  | ||||
|     public: | ||||
|         std::ptrdiff_t offset{ 0 }; | ||||
|  | ||||
|         explicit variable_info(std::shared_ptr<const class type> type); | ||||
|         ~variable_info() override; | ||||
|         std::shared_ptr<const class type> type() noexcept; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * 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: | ||||
|         std::ptrdiff_t offset{ 0 }; | ||||
|  | ||||
|         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(); | ||||
|     } | ||||
|  | ||||
|     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) | ||||
|     { | ||||
|         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<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 | ||||
|     { | ||||
|         return m_errors; | ||||
|   | ||||
| @@ -55,53 +55,40 @@ namespace elna::source | ||||
|         return m_type; | ||||
|     } | ||||
|  | ||||
|     constant_info::constant_info(const std::shared_ptr<const class type> type, const std::int32_t value) | ||||
|         : m_type(type), m_value(value) | ||||
|     typed_info::typed_info(std::shared_ptr<const class type> type) | ||||
|         : 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; | ||||
|     } | ||||
|  | ||||
|     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 | ||||
|     { | ||||
|         return m_value; | ||||
|     } | ||||
|  | ||||
|     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) | ||||
|         : 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) | ||||
|         : m_type(std::make_shared<procedure_type>(type)) | ||||
|     { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user