Type check if and while conditions
This commit is contained in:
parent
7845c700d8
commit
4dbc5aca0d
@ -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))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user