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

View File

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

View File

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

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

View File

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

View File

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