Type check if and while conditions

This commit is contained in:
Eugen Wissner 2024-06-05 19:53:04 +02:00
parent 7845c700d8
commit 4dbc5aca0d
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
6 changed files with 70 additions and 41 deletions

View File

@ -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.

View File

@ -136,7 +136,8 @@ namespace elna::source
dereference, dereference,
argument, argument,
arithmetic, arithmetic,
comparison comparison,
condition
}; };
/** /**

View File

@ -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;
}; };
} }

View File

@ -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;
}; };
/** /**

View File

@ -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;

View File

@ -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))
{ {