Type check the return statement
This commit is contained in:
parent
c022805c53
commit
d57934973d
191
boot/ast.cc
191
boot/ast.cc
@ -33,14 +33,6 @@ namespace elna::boot
|
|||||||
return this->source_position;
|
return this->source_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
statement::statement()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
statement::~statement()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
assign_statement *statement::is_assign()
|
assign_statement *statement::is_assign()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -71,14 +63,6 @@ namespace elna::boot
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
expression::expression()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
expression::~expression()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
cast_expression *expression::is_cast()
|
cast_expression *expression::is_cast()
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -114,39 +98,6 @@ namespace elna::boot
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void expression::accept(parser_visitor *visitor)
|
|
||||||
{
|
|
||||||
if (cast_expression *node = is_cast())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (traits_expression *node = is_traits())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (binary_expression *node = is_binary())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (unary_expression *node = is_unary())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (designator_expression *node = is_designator())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (procedure_call *node = is_call_expression())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (literal_expression *node = is_literal())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
type_expression::type_expression(const struct position position)
|
type_expression::type_expression(const struct position position)
|
||||||
: node(position)
|
: node(position)
|
||||||
{
|
{
|
||||||
@ -182,35 +133,6 @@ namespace elna::boot
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void type_expression::accept(parser_visitor *visitor)
|
|
||||||
{
|
|
||||||
if (std::shared_ptr<primitive_type_expression> node = is_primitive())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (std::shared_ptr<array_type_expression> node = is_array())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (std::shared_ptr<pointer_type_expression> node = is_pointer())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (std::shared_ptr<record_type_expression> node = is_record())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (std::shared_ptr<union_type_expression> node = is_union())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (std::shared_ptr<procedure_type_expression> node = is_procedure())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
|
primitive_type_expression::primitive_type_expression(const struct position position, const std::string& name)
|
||||||
: type_expression(position), name(name)
|
: type_expression(position), name(name)
|
||||||
{
|
{
|
||||||
@ -301,8 +223,8 @@ namespace elna::boot
|
|||||||
}
|
}
|
||||||
|
|
||||||
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
|
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
|
||||||
std::shared_ptr<type_expression> type, const bool exported)
|
std::shared_ptr<type_expression> variable_type, const bool exported)
|
||||||
: definition(position, identifier, exported), m_type(type)
|
: definition(position, identifier, exported), m_variable_type(variable_type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +235,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
type_expression& variable_declaration::variable_type()
|
type_expression& variable_declaration::variable_type()
|
||||||
{
|
{
|
||||||
return *m_type;
|
return *m_variable_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
definition::definition(const struct position position, const std::string& identifier, const bool exported)
|
definition::definition(const struct position position, const std::string& identifier, const bool exported)
|
||||||
@ -462,47 +384,16 @@ namespace elna::boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void literal_expression::accept(parser_visitor *visitor)
|
|
||||||
{
|
|
||||||
if (literal<std::int32_t> *node = is_int())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (literal<std::uint32_t> *node = is_word())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (literal<double> *node = is_float())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (literal<bool> *node = is_bool())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (literal<unsigned char> *node = is_char())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (literal<std::nullptr_t> *node = is_nil())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else if (literal<std::string> *node = is_string())
|
|
||||||
{
|
|
||||||
return node->accept(visitor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defer_statement::defer_statement(const struct position position)
|
defer_statement::defer_statement(const struct position position)
|
||||||
: node(position)
|
: node(position)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void defer_statement::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
defer_statement *defer_statement::is_defer()
|
defer_statement *defer_statement::is_defer()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -529,11 +420,37 @@ namespace elna::boot
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void designator_expression::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
if (variable_expression *node = is_variable())
|
||||||
|
{
|
||||||
|
return visitor->visit(node);
|
||||||
|
}
|
||||||
|
else if (array_access_expression *node = is_array_access())
|
||||||
|
{
|
||||||
|
return visitor->visit(node);
|
||||||
|
}
|
||||||
|
else if (field_access_expression *node = is_field_access())
|
||||||
|
{
|
||||||
|
return visitor->visit(node);
|
||||||
|
}
|
||||||
|
else if (dereference_expression *node = is_dereference())
|
||||||
|
{
|
||||||
|
return visitor->visit(node);
|
||||||
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
variable_expression::variable_expression(const struct position position, const std::string& name)
|
variable_expression::variable_expression(const struct position position, const std::string& name)
|
||||||
: node(position), name(name)
|
: node(position), name(name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void variable_expression::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
variable_expression *variable_expression::is_variable()
|
variable_expression *variable_expression::is_variable()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -545,6 +462,11 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void array_access_expression::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
expression& array_access_expression::index()
|
expression& array_access_expression::index()
|
||||||
{
|
{
|
||||||
return *m_index;
|
return *m_index;
|
||||||
@ -572,6 +494,11 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void field_access_expression::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
expression& field_access_expression::base()
|
expression& field_access_expression::base()
|
||||||
{
|
{
|
||||||
return *m_base;
|
return *m_base;
|
||||||
@ -598,6 +525,11 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dereference_expression::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
expression& dereference_expression::base()
|
expression& dereference_expression::base()
|
||||||
{
|
{
|
||||||
return *m_base;
|
return *m_base;
|
||||||
@ -686,6 +618,11 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void procedure_call::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
procedure_call *procedure_call::is_call_statement()
|
procedure_call *procedure_call::is_call_statement()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -780,6 +717,11 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void return_statement::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
return_statement *return_statement::is_return()
|
return_statement *return_statement::is_return()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -801,6 +743,11 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assign_statement::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
assign_statement *assign_statement::is_assign()
|
assign_statement *assign_statement::is_assign()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -847,6 +794,11 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void if_statement::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
if_statement *if_statement::is_if()
|
if_statement *if_statement::is_if()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
@ -877,6 +829,11 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void while_statement::accept(parser_visitor *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
while_statement *while_statement::is_while()
|
while_statement *while_statement::is_while()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
|
@ -286,10 +286,15 @@ if_statement:
|
|||||||
$$ = new boot::if_statement(boot::make_position(@1), then, _else);
|
$$ = new boot::if_statement(boot::make_position(@1), then, _else);
|
||||||
std::swap($5, $$->branches);
|
std::swap($5, $$->branches);
|
||||||
}
|
}
|
||||||
return_statement: "return" expression
|
return_statement:
|
||||||
|
"return" expression
|
||||||
{
|
{
|
||||||
$$ = new boot::return_statement(boot::make_position(@1), $2);
|
$$ = new boot::return_statement(boot::make_position(@1), $2);
|
||||||
}
|
}
|
||||||
|
| "return"
|
||||||
|
{
|
||||||
|
$$ = new boot::return_statement(boot::make_position(@1));
|
||||||
|
}
|
||||||
defer_statement: DEFER statements "end"
|
defer_statement: DEFER statements "end"
|
||||||
{
|
{
|
||||||
$$ = new boot::defer_statement(boot::make_position(@1));
|
$$ = new boot::defer_statement(boot::make_position(@1));
|
||||||
|
@ -1225,18 +1225,42 @@ namespace elna::gcc
|
|||||||
void generic_visitor::visit(boot::return_statement *statement)
|
void generic_visitor::visit(boot::return_statement *statement)
|
||||||
{
|
{
|
||||||
boot::expression *return_expression = statement->return_expression();
|
boot::expression *return_expression = statement->return_expression();
|
||||||
|
location_t statement_position = get_location(&statement->position());
|
||||||
|
tree set_result{ NULL_TREE };
|
||||||
|
tree return_type = TREE_TYPE(TREE_TYPE(current_function_decl));
|
||||||
|
|
||||||
if (return_expression == nullptr)
|
if (TREE_THIS_VOLATILE(current_function_decl) == 1)
|
||||||
{
|
{
|
||||||
|
error_at(statement_position, "This procedure is not allowed to return");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return_expression->accept(this);
|
if (return_expression != nullptr)
|
||||||
|
{
|
||||||
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(current_function_decl),
|
return_expression->accept(this);
|
||||||
this->current_expression);
|
|
||||||
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
|
|
||||||
append_statement(return_stmt);
|
|
||||||
|
|
||||||
|
set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(current_function_decl),
|
||||||
|
this->current_expression);
|
||||||
|
}
|
||||||
|
if (return_type == void_type_node && set_result != NULL_TREE)
|
||||||
|
{
|
||||||
|
error_at(statement_position, "Proper procedure is not allowed to return a value");
|
||||||
|
}
|
||||||
|
else if (return_type != void_type_node && set_result == NULL_TREE)
|
||||||
|
{
|
||||||
|
error_at(statement_position, "Procedure is expected to return a value of type '%s'",
|
||||||
|
print_type(return_type).c_str());
|
||||||
|
}
|
||||||
|
else if (return_type != void_type_node && !is_assignable_from(return_type, this->current_expression))
|
||||||
|
{
|
||||||
|
error_at(statement_position, "Cannot return '%s' from a procedure returning '%s'",
|
||||||
|
print_type(return_type).c_str(),
|
||||||
|
print_type(TREE_TYPE(this->current_expression)).c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tree return_stmt = build1_loc(statement_position, RETURN_EXPR, void_type_node, set_result);
|
||||||
|
append_statement(return_stmt);
|
||||||
|
}
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +138,7 @@ namespace elna::boot
|
|||||||
explicit node(const position position);
|
explicit node(const position position);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual void accept(parser_visitor *visitor) = 0;
|
||||||
virtual ~node() = 0;
|
virtual ~node() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,41 +156,6 @@ namespace elna::boot
|
|||||||
virtual return_statement *is_return();
|
virtual return_statement *is_return();
|
||||||
virtual defer_statement *is_defer();
|
virtual defer_statement *is_defer();
|
||||||
virtual procedure_call *is_call_statement();
|
virtual procedure_call *is_call_statement();
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
if (assign_statement *node = is_assign())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
else if (if_statement *node = is_if())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
else if (while_statement *node = is_while())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
else if (return_statement *node = is_return())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
else if (defer_statement *node = is_defer())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
else if (procedure_call *node = is_call_statement())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
~statement() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
statement();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class expression : public virtual node
|
class expression : public virtual node
|
||||||
@ -202,12 +168,6 @@ namespace elna::boot
|
|||||||
virtual designator_expression *is_designator();
|
virtual designator_expression *is_designator();
|
||||||
virtual procedure_call *is_call_expression();
|
virtual procedure_call *is_call_expression();
|
||||||
virtual literal_expression *is_literal();
|
virtual literal_expression *is_literal();
|
||||||
|
|
||||||
void accept(parser_visitor *visitor);
|
|
||||||
~expression() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
expression();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -236,8 +196,6 @@ namespace elna::boot
|
|||||||
virtual std::shared_ptr<union_type_expression> is_union();
|
virtual std::shared_ptr<union_type_expression> is_union();
|
||||||
virtual std::shared_ptr<procedure_type_expression> is_procedure();
|
virtual std::shared_ptr<procedure_type_expression> is_procedure();
|
||||||
|
|
||||||
void accept(parser_visitor *visitor);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
type_expression(const struct position position);
|
type_expression(const struct position position);
|
||||||
};
|
};
|
||||||
@ -251,7 +209,7 @@ namespace elna::boot
|
|||||||
const std::string name;
|
const std::string name;
|
||||||
|
|
||||||
primitive_type_expression(const struct position position, const std::string& name);
|
primitive_type_expression(const struct position position, const std::string& name);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
std::shared_ptr<primitive_type_expression> is_primitive() override;
|
std::shared_ptr<primitive_type_expression> is_primitive() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -264,7 +222,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
array_type_expression(const struct position position,
|
array_type_expression(const struct position position,
|
||||||
std::shared_ptr<type_expression> base, const std::uint32_t size);
|
std::shared_ptr<type_expression> base, const std::uint32_t size);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
std::shared_ptr<array_type_expression> is_array() override;
|
std::shared_ptr<array_type_expression> is_array() override;
|
||||||
|
|
||||||
type_expression& base();
|
type_expression& base();
|
||||||
@ -276,7 +234,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
pointer_type_expression(const struct position position, std::shared_ptr<type_expression> base);
|
pointer_type_expression(const struct position position, std::shared_ptr<type_expression> base);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
std::shared_ptr<pointer_type_expression> is_pointer() override;
|
std::shared_ptr<pointer_type_expression> is_pointer() override;
|
||||||
|
|
||||||
type_expression& base();
|
type_expression& base();
|
||||||
@ -291,7 +249,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
record_type_expression(const struct position position, std::vector<field_declaration>&& fields);
|
record_type_expression(const struct position position, std::vector<field_declaration>&& fields);
|
||||||
|
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
std::shared_ptr<record_type_expression> is_record() override;
|
std::shared_ptr<record_type_expression> is_record() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -302,7 +260,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
union_type_expression(const struct position position, std::vector<field_declaration>&& fields);
|
union_type_expression(const struct position position, std::vector<field_declaration>&& fields);
|
||||||
|
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
std::shared_ptr<union_type_expression> is_union() override;
|
std::shared_ptr<union_type_expression> is_union() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -311,12 +269,12 @@ namespace elna::boot
|
|||||||
*/
|
*/
|
||||||
class variable_declaration : public definition
|
class variable_declaration : public definition
|
||||||
{
|
{
|
||||||
std::shared_ptr<type_expression> m_type;
|
std::shared_ptr<type_expression> m_variable_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
variable_declaration(const struct position position, const std::string& identifier,
|
variable_declaration(const struct position position, const std::string& identifier,
|
||||||
std::shared_ptr<type_expression> type, const bool exported = false);
|
std::shared_ptr<type_expression> variable_type, const bool exported = false);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
type_expression& variable_type();
|
type_expression& variable_type();
|
||||||
};
|
};
|
||||||
@ -336,7 +294,6 @@ namespace elna::boot
|
|||||||
virtual literal<std::string> *is_string() = 0;
|
virtual literal<std::string> *is_string() = 0;
|
||||||
|
|
||||||
literal_expression *is_literal() override;
|
literal_expression *is_literal() override;
|
||||||
void accept(parser_visitor *visitor);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
literal_expression();
|
literal_expression();
|
||||||
@ -350,14 +307,9 @@ namespace elna::boot
|
|||||||
literal_expression *m_body;
|
literal_expression *m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* \param position Source code position.
|
|
||||||
* \param identifier Constant name.
|
|
||||||
* \param body Constant value.
|
|
||||||
*/
|
|
||||||
constant_definition(const struct position position, const std::string& identifier,
|
constant_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, literal_expression *body);
|
const bool exported, literal_expression *body);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
literal_expression& body();
|
literal_expression& body();
|
||||||
|
|
||||||
@ -389,7 +341,7 @@ namespace elna::boot
|
|||||||
procedure_type_expression(const struct position position,
|
procedure_type_expression(const struct position position,
|
||||||
return_declaration return_type = return_declaration());
|
return_declaration return_type = return_declaration());
|
||||||
|
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
std::shared_ptr<procedure_type_expression> is_procedure() override;
|
std::shared_ptr<procedure_type_expression> is_procedure() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -406,7 +358,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
procedure_definition(const struct position position, const std::string& identifier,
|
procedure_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body = nullptr);
|
const bool exported, std::shared_ptr<procedure_type_expression> heading, block *body = nullptr);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
procedure_type_expression& heading();
|
procedure_type_expression& heading();
|
||||||
|
|
||||||
@ -423,7 +375,7 @@ namespace elna::boot
|
|||||||
public:
|
public:
|
||||||
type_definition(const struct position position, const std::string& identifier,
|
type_definition(const struct position position, const std::string& identifier,
|
||||||
const bool exported, std::shared_ptr<type_expression> expression);
|
const bool exported, std::shared_ptr<type_expression> expression);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
type_expression& body();
|
type_expression& body();
|
||||||
};
|
};
|
||||||
@ -438,7 +390,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
cast_expression(const struct position position, std::shared_ptr<type_expression> target, expression *value);
|
cast_expression(const struct position position, std::shared_ptr<type_expression> target, expression *value);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
cast_expression *is_cast() override;
|
cast_expression *is_cast() override;
|
||||||
|
|
||||||
type_expression& target();
|
type_expression& target();
|
||||||
@ -454,7 +406,7 @@ namespace elna::boot
|
|||||||
const std::string name;
|
const std::string name;
|
||||||
|
|
||||||
traits_expression(const struct position position, const std::string& name);
|
traits_expression(const struct position position, const std::string& name);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
traits_expression *is_traits() override;
|
traits_expression *is_traits() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -480,17 +432,12 @@ namespace elna::boot
|
|||||||
expression *m_return_expression{ nullptr };
|
expression *m_return_expression{ nullptr };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
return_statement(const struct position position, expression *return_expression);
|
return_statement(const struct position position, expression *return_expression = nullptr);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
virtual return_statement *is_return() override;
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
expression *return_expression();
|
expression *return_expression();
|
||||||
|
|
||||||
virtual return_statement *is_return() override;
|
|
||||||
virtual ~return_statement() override;
|
virtual ~return_statement() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -502,29 +449,8 @@ namespace elna::boot
|
|||||||
virtual field_access_expression *is_field_access();
|
virtual field_access_expression *is_field_access();
|
||||||
virtual dereference_expression *is_dereference();
|
virtual dereference_expression *is_dereference();
|
||||||
|
|
||||||
template<typename V>
|
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
if (variable_expression *node = is_variable())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
else if (array_access_expression *node = is_array_access())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
else if (field_access_expression *node = is_field_access())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
else if (dereference_expression *node = is_dereference())
|
|
||||||
{
|
|
||||||
return visitor->visit(node);
|
|
||||||
}
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
designator_expression *is_designator() override;
|
designator_expression *is_designator() override;
|
||||||
|
void accept(parser_visitor *visitor);
|
||||||
~designator_expression() = 0;
|
~designator_expression() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -537,12 +463,7 @@ namespace elna::boot
|
|||||||
const std::string name;
|
const std::string name;
|
||||||
|
|
||||||
variable_expression(const struct position position, const std::string& name);
|
variable_expression(const struct position position, const std::string& name);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
variable_expression *is_variable() override;
|
variable_expression *is_variable() override;
|
||||||
};
|
};
|
||||||
@ -554,12 +475,7 @@ namespace elna::boot
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
array_access_expression(const struct position position, expression *base, expression *index);
|
array_access_expression(const struct position position, expression *base, expression *index);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
expression& base();
|
expression& base();
|
||||||
expression& index();
|
expression& index();
|
||||||
@ -577,12 +493,7 @@ namespace elna::boot
|
|||||||
public:
|
public:
|
||||||
field_access_expression(const struct position position, expression *base,
|
field_access_expression(const struct position position, expression *base,
|
||||||
const std::string& field);
|
const std::string& field);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
expression& base();
|
expression& base();
|
||||||
std::string& field();
|
std::string& field();
|
||||||
@ -598,16 +509,12 @@ namespace elna::boot
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
dereference_expression(const struct position position, expression *base);
|
dereference_expression(const struct position position, expression *base);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
|
||||||
void accept(parser_visitor *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
expression& base();
|
expression& base();
|
||||||
|
|
||||||
dereference_expression *is_dereference() override;
|
dereference_expression *is_dereference() override;
|
||||||
|
|
||||||
~dereference_expression() override;
|
~dereference_expression() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -622,17 +529,12 @@ namespace elna::boot
|
|||||||
std::vector<expression *> arguments;
|
std::vector<expression *> arguments;
|
||||||
|
|
||||||
procedure_call(const struct position position, designator_expression *callable);
|
procedure_call(const struct position position, designator_expression *callable);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
virtual procedure_call *is_call_statement() override;
|
||||||
void accept(V *visitor)
|
virtual procedure_call *is_call_expression() override;
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
designator_expression& callable();
|
designator_expression& callable();
|
||||||
|
|
||||||
virtual procedure_call *is_call_statement() override;
|
|
||||||
virtual procedure_call *is_call_expression() override;
|
|
||||||
virtual ~procedure_call() override;
|
virtual ~procedure_call() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -649,18 +551,13 @@ namespace elna::boot
|
|||||||
*/
|
*/
|
||||||
assign_statement(const struct position position, designator_expression *lvalue,
|
assign_statement(const struct position position, designator_expression *lvalue,
|
||||||
expression *rvalue);
|
expression *rvalue);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
designator_expression& lvalue();
|
designator_expression& lvalue();
|
||||||
expression& rvalue();
|
expression& rvalue();
|
||||||
|
|
||||||
assign_statement *is_assign() override;
|
|
||||||
virtual ~assign_statement() override;
|
virtual ~assign_statement() override;
|
||||||
|
assign_statement *is_assign() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -676,17 +573,12 @@ namespace elna::boot
|
|||||||
|
|
||||||
if_statement(const struct position position, conditional_statements *body,
|
if_statement(const struct position position, conditional_statements *body,
|
||||||
std::vector<statement *> *alternative = nullptr);
|
std::vector<statement *> *alternative = nullptr);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
virtual if_statement *is_if() override;
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
conditional_statements& body();
|
conditional_statements& body();
|
||||||
std::vector<statement *> *alternative();
|
std::vector<statement *> *alternative();
|
||||||
|
|
||||||
virtual if_statement *is_if() override;
|
|
||||||
virtual ~if_statement() override;
|
virtual ~if_statement() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -700,16 +592,11 @@ namespace elna::boot
|
|||||||
public:
|
public:
|
||||||
std::vector<conditional_statements *> branches;
|
std::vector<conditional_statements *> branches;
|
||||||
while_statement(const struct position position, conditional_statements *body);
|
while_statement(const struct position position, conditional_statements *body);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
while_statement *is_while() override;
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
conditional_statements& body();
|
conditional_statements& body();
|
||||||
|
|
||||||
while_statement *is_while() override;
|
|
||||||
virtual ~while_statement() override;
|
virtual ~while_statement() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -721,7 +608,7 @@ namespace elna::boot
|
|||||||
std::vector<statement *> body;
|
std::vector<statement *> body;
|
||||||
|
|
||||||
block(const struct position position);
|
block(const struct position position);
|
||||||
void accept(parser_visitor *visitor);
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
virtual ~block() override;
|
virtual ~block() override;
|
||||||
};
|
};
|
||||||
@ -733,7 +620,7 @@ namespace elna::boot
|
|||||||
std::vector<procedure_definition *> procedures;
|
std::vector<procedure_definition *> procedures;
|
||||||
|
|
||||||
program(const struct position position);
|
program(const struct position position);
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
virtual ~program() override;
|
virtual ~program() override;
|
||||||
};
|
};
|
||||||
@ -833,8 +720,7 @@ namespace elna::boot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename V>
|
void accept(parser_visitor *visitor) override
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
{
|
||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
@ -846,14 +732,9 @@ namespace elna::boot
|
|||||||
std::vector<statement *> statements;
|
std::vector<statement *> statements;
|
||||||
|
|
||||||
defer_statement(const struct position position);
|
defer_statement(const struct position position);
|
||||||
|
void accept(parser_visitor *visitor) override;
|
||||||
template<typename V>
|
|
||||||
void accept(V *visitor)
|
|
||||||
{
|
|
||||||
visitor->visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
defer_statement *is_defer() override;
|
defer_statement *is_defer() override;
|
||||||
|
|
||||||
virtual ~defer_statement() override;
|
virtual ~defer_statement() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -867,7 +748,7 @@ namespace elna::boot
|
|||||||
binary_expression(const struct position position, expression *lhs,
|
binary_expression(const struct position position, expression *lhs,
|
||||||
expression *rhs, const binary_operator operation);
|
expression *rhs, const binary_operator operation);
|
||||||
|
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
binary_expression *is_binary() override;
|
binary_expression *is_binary() override;
|
||||||
|
|
||||||
expression& lhs();
|
expression& lhs();
|
||||||
@ -886,7 +767,7 @@ namespace elna::boot
|
|||||||
unary_expression(const struct position position, expression *operand,
|
unary_expression(const struct position position, expression *operand,
|
||||||
const unary_operator operation);
|
const unary_operator operation);
|
||||||
|
|
||||||
void accept(parser_visitor *visitor);
|
void accept(parser_visitor *visitor) override;
|
||||||
unary_expression *is_unary() override;
|
unary_expression *is_unary() override;
|
||||||
|
|
||||||
expression& operand();
|
expression& operand();
|
||||||
|
@ -68,7 +68,7 @@ namespace elna::gcc
|
|||||||
void visit_statements(const std::vector<boot::statement *>& statements);
|
void visit_statements(const std::vector<boot::statement *>& statements);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
generic_visitor(std::shared_ptr<symbol_table> symbol_table);
|
explicit generic_visitor(std::shared_ptr<symbol_table> symbol_table);
|
||||||
|
|
||||||
void visit(boot::program *program) override;
|
void visit(boot::program *program) override;
|
||||||
void visit(boot::procedure_definition *definition) override;
|
void visit(boot::procedure_definition *definition) override;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user