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