Type check the return statement
This commit is contained in:
@ -138,6 +138,7 @@ namespace elna::boot
|
||||
explicit node(const position position);
|
||||
|
||||
public:
|
||||
virtual void accept(parser_visitor *visitor) = 0;
|
||||
virtual ~node() = 0;
|
||||
|
||||
/**
|
||||
@ -155,41 +156,6 @@ namespace elna::boot
|
||||
virtual return_statement *is_return();
|
||||
virtual defer_statement *is_defer();
|
||||
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
|
||||
@ -202,12 +168,6 @@ namespace elna::boot
|
||||
virtual designator_expression *is_designator();
|
||||
virtual procedure_call *is_call_expression();
|
||||
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<procedure_type_expression> is_procedure();
|
||||
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
protected:
|
||||
type_expression(const struct position position);
|
||||
};
|
||||
@ -251,7 +209,7 @@ namespace elna::boot
|
||||
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;
|
||||
};
|
||||
|
||||
@ -264,7 +222,7 @@ namespace elna::boot
|
||||
|
||||
array_type_expression(const struct position position,
|
||||
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;
|
||||
|
||||
type_expression& base();
|
||||
@ -276,7 +234,7 @@ namespace elna::boot
|
||||
|
||||
public:
|
||||
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;
|
||||
|
||||
type_expression& base();
|
||||
@ -291,7 +249,7 @@ namespace elna::boot
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
@ -302,7 +260,7 @@ namespace elna::boot
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
@ -311,12 +269,12 @@ namespace elna::boot
|
||||
*/
|
||||
class variable_declaration : public definition
|
||||
{
|
||||
std::shared_ptr<type_expression> m_type;
|
||||
std::shared_ptr<type_expression> m_variable_type;
|
||||
|
||||
public:
|
||||
variable_declaration(const struct position position, const std::string& identifier,
|
||||
std::shared_ptr<type_expression> type, const bool exported = false);
|
||||
void accept(parser_visitor *visitor);
|
||||
std::shared_ptr<type_expression> variable_type, const bool exported = false);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
|
||||
type_expression& variable_type();
|
||||
};
|
||||
@ -336,7 +294,6 @@ namespace elna::boot
|
||||
virtual literal<std::string> *is_string() = 0;
|
||||
|
||||
literal_expression *is_literal() override;
|
||||
void accept(parser_visitor *visitor);
|
||||
|
||||
protected:
|
||||
literal_expression();
|
||||
@ -350,14 +307,9 @@ namespace elna::boot
|
||||
literal_expression *m_body;
|
||||
|
||||
public:
|
||||
/**
|
||||
* \param position Source code position.
|
||||
* \param identifier Constant name.
|
||||
* \param body Constant value.
|
||||
*/
|
||||
constant_definition(const struct position position, const std::string& identifier,
|
||||
const bool exported, literal_expression *body);
|
||||
void accept(parser_visitor *visitor);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
|
||||
literal_expression& body();
|
||||
|
||||
@ -389,7 +341,7 @@ namespace elna::boot
|
||||
procedure_type_expression(const struct position position,
|
||||
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;
|
||||
};
|
||||
|
||||
@ -406,7 +358,7 @@ namespace elna::boot
|
||||
|
||||
procedure_definition(const struct position position, const std::string& identifier,
|
||||
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();
|
||||
|
||||
@ -423,7 +375,7 @@ namespace elna::boot
|
||||
public:
|
||||
type_definition(const struct position position, const std::string& identifier,
|
||||
const bool exported, std::shared_ptr<type_expression> expression);
|
||||
void accept(parser_visitor *visitor);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
|
||||
type_expression& body();
|
||||
};
|
||||
@ -438,7 +390,7 @@ namespace elna::boot
|
||||
|
||||
public:
|
||||
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;
|
||||
|
||||
type_expression& target();
|
||||
@ -454,7 +406,7 @@ namespace elna::boot
|
||||
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;
|
||||
};
|
||||
|
||||
@ -480,17 +432,12 @@ namespace elna::boot
|
||||
expression *m_return_expression{ nullptr };
|
||||
|
||||
public:
|
||||
return_statement(const struct position position, expression *return_expression);
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
return_statement(const struct position position, expression *return_expression = nullptr);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
virtual return_statement *is_return() override;
|
||||
|
||||
expression *return_expression();
|
||||
|
||||
virtual return_statement *is_return() override;
|
||||
virtual ~return_statement() override;
|
||||
};
|
||||
|
||||
@ -502,29 +449,8 @@ namespace elna::boot
|
||||
virtual field_access_expression *is_field_access();
|
||||
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;
|
||||
void accept(parser_visitor *visitor);
|
||||
~designator_expression() = 0;
|
||||
|
||||
protected:
|
||||
@ -537,12 +463,7 @@ namespace elna::boot
|
||||
const std::string name;
|
||||
|
||||
variable_expression(const struct position position, const std::string& name);
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
void accept(parser_visitor *visitor) override;
|
||||
|
||||
variable_expression *is_variable() override;
|
||||
};
|
||||
@ -554,12 +475,7 @@ namespace elna::boot
|
||||
|
||||
public:
|
||||
array_access_expression(const struct position position, expression *base, expression *index);
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
void accept(parser_visitor *visitor) override;
|
||||
|
||||
expression& base();
|
||||
expression& index();
|
||||
@ -577,12 +493,7 @@ namespace elna::boot
|
||||
public:
|
||||
field_access_expression(const struct position position, expression *base,
|
||||
const std::string& field);
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
void accept(parser_visitor *visitor) override;
|
||||
|
||||
expression& base();
|
||||
std::string& field();
|
||||
@ -598,16 +509,12 @@ namespace elna::boot
|
||||
|
||||
public:
|
||||
dereference_expression(const struct position position, expression *base);
|
||||
|
||||
template<typename V>
|
||||
void accept(parser_visitor *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
void accept(parser_visitor *visitor) override;
|
||||
|
||||
expression& base();
|
||||
|
||||
dereference_expression *is_dereference() override;
|
||||
|
||||
~dereference_expression() override;
|
||||
};
|
||||
|
||||
@ -622,17 +529,12 @@ namespace elna::boot
|
||||
std::vector<expression *> arguments;
|
||||
|
||||
procedure_call(const struct position position, designator_expression *callable);
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
void accept(parser_visitor *visitor) override;
|
||||
virtual procedure_call *is_call_statement() override;
|
||||
virtual procedure_call *is_call_expression() override;
|
||||
|
||||
designator_expression& callable();
|
||||
|
||||
virtual procedure_call *is_call_statement() override;
|
||||
virtual procedure_call *is_call_expression() override;
|
||||
virtual ~procedure_call() override;
|
||||
};
|
||||
|
||||
@ -649,18 +551,13 @@ namespace elna::boot
|
||||
*/
|
||||
assign_statement(const struct position position, designator_expression *lvalue,
|
||||
expression *rvalue);
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
void accept(parser_visitor *visitor) override;
|
||||
|
||||
designator_expression& lvalue();
|
||||
expression& rvalue();
|
||||
|
||||
assign_statement *is_assign() 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,
|
||||
std::vector<statement *> *alternative = nullptr);
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
void accept(parser_visitor *visitor) override;
|
||||
virtual if_statement *is_if() override;
|
||||
|
||||
conditional_statements& body();
|
||||
std::vector<statement *> *alternative();
|
||||
|
||||
virtual if_statement *is_if() override;
|
||||
virtual ~if_statement() override;
|
||||
};
|
||||
|
||||
@ -700,16 +592,11 @@ namespace elna::boot
|
||||
public:
|
||||
std::vector<conditional_statements *> branches;
|
||||
while_statement(const struct position position, conditional_statements *body);
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
void accept(parser_visitor *visitor) override;
|
||||
while_statement *is_while() override;
|
||||
|
||||
conditional_statements& body();
|
||||
|
||||
while_statement *is_while() override;
|
||||
virtual ~while_statement() override;
|
||||
};
|
||||
|
||||
@ -721,7 +608,7 @@ namespace elna::boot
|
||||
std::vector<statement *> body;
|
||||
|
||||
block(const struct position position);
|
||||
void accept(parser_visitor *visitor);
|
||||
virtual void accept(parser_visitor *visitor) override;
|
||||
|
||||
virtual ~block() override;
|
||||
};
|
||||
@ -733,7 +620,7 @@ namespace elna::boot
|
||||
std::vector<procedure_definition *> procedures;
|
||||
|
||||
program(const struct position position);
|
||||
void accept(parser_visitor *visitor);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
|
||||
virtual ~program() override;
|
||||
};
|
||||
@ -833,8 +720,7 @@ namespace elna::boot
|
||||
}
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
void accept(parser_visitor *visitor) override
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
@ -846,14 +732,9 @@ namespace elna::boot
|
||||
std::vector<statement *> statements;
|
||||
|
||||
defer_statement(const struct position position);
|
||||
|
||||
template<typename V>
|
||||
void accept(V *visitor)
|
||||
{
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
void accept(parser_visitor *visitor) override;
|
||||
defer_statement *is_defer() override;
|
||||
|
||||
virtual ~defer_statement() override;
|
||||
};
|
||||
|
||||
@ -867,7 +748,7 @@ namespace elna::boot
|
||||
binary_expression(const struct position position, expression *lhs,
|
||||
expression *rhs, const binary_operator operation);
|
||||
|
||||
void accept(parser_visitor *visitor);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
binary_expression *is_binary() override;
|
||||
|
||||
expression& lhs();
|
||||
@ -886,7 +767,7 @@ namespace elna::boot
|
||||
unary_expression(const struct position position, expression *operand,
|
||||
const unary_operator operation);
|
||||
|
||||
void accept(parser_visitor *visitor);
|
||||
void accept(parser_visitor *visitor) override;
|
||||
unary_expression *is_unary() override;
|
||||
|
||||
expression& operand();
|
||||
|
@ -61,28 +61,28 @@ namespace elna::boot
|
||||
void visit(pointer_type_expression *type_expression) override;
|
||||
void visit(program *program) override;
|
||||
void visit(type_definition *definition) override;
|
||||
void visit(record_type_expression *) override;
|
||||
void visit(union_type_expression *) override;
|
||||
void visit(record_type_expression *type_expression) override;
|
||||
void visit(union_type_expression *type_expression) override;
|
||||
void visit(procedure_type_expression *) override;
|
||||
|
||||
void visit(variable_declaration *) override;
|
||||
void visit(variable_declaration *declaration) override;
|
||||
void visit(constant_definition *) override;
|
||||
void visit(procedure_definition *) override;
|
||||
void visit(assign_statement *) override;
|
||||
void visit(if_statement *) override;
|
||||
void visit(while_statement *) override;
|
||||
void visit(return_statement *) override;
|
||||
void visit(defer_statement *) override;
|
||||
void visit(procedure_call *) override;
|
||||
void visit(block *) override;
|
||||
void visit(cast_expression *) override;
|
||||
void visit(traits_expression *) override;
|
||||
void visit(binary_expression *) override;
|
||||
void visit(unary_expression *) override;
|
||||
void visit(procedure_definition *definition) override;
|
||||
void visit(assign_statement *statement) override;
|
||||
void visit(if_statement *statement) override;
|
||||
void visit(while_statement *statement) override;
|
||||
void visit(return_statement *statement) override;
|
||||
void visit(defer_statement *statement) override;
|
||||
void visit(procedure_call *call) override;
|
||||
void visit(block *block) override;
|
||||
void visit(cast_expression *expression) override;
|
||||
void visit(traits_expression *trait) override;
|
||||
void visit(binary_expression *expression) override;
|
||||
void visit(unary_expression *expression) override;
|
||||
void visit(variable_expression *) override;
|
||||
void visit(array_access_expression *) override;
|
||||
void visit(field_access_expression *) override;
|
||||
void visit(dereference_expression *) override;
|
||||
void visit(array_access_expression *expression) override;
|
||||
void visit(field_access_expression *expression) override;
|
||||
void visit(dereference_expression *expression) override;
|
||||
void visit(literal<std::int32_t> *) override;
|
||||
void visit(literal<std::uint32_t> *) override;
|
||||
void visit(literal<double> *) override;
|
||||
|
@ -111,12 +111,16 @@ namespace elna::boot
|
||||
explicit primitive_type(const std::string& identifier);
|
||||
};
|
||||
|
||||
using type_field = std::pair<std::string, type>;
|
||||
|
||||
struct record_type
|
||||
{
|
||||
std::vector<type_field> fields;
|
||||
};
|
||||
|
||||
struct union_type
|
||||
{
|
||||
std::vector<type_field> fields;
|
||||
};
|
||||
|
||||
class type_info;
|
||||
|
@ -34,13 +34,15 @@ namespace elna::gcc
|
||||
{
|
||||
std::deque<std::unique_ptr<boot::error>> do_semantic_analysis(const char *path,
|
||||
std::unique_ptr<boot::program>& ast, std::shared_ptr<boot::symbol_table> info_table,
|
||||
std::shared_ptr<symbol_table> symbols);
|
||||
tree handle_symbol(const std::string& symbol_name, const boot::type& type, std::shared_ptr<symbol_table> symbols);
|
||||
std::shared_ptr<symbol_table> symbols, std::unordered_map<std::string, tree>& unresolved);
|
||||
tree handle_symbol(const std::string& symbol_name, const boot::type& type,
|
||||
std::shared_ptr<symbol_table> symbols, std::unordered_map<std::string, tree>& unresolved);
|
||||
|
||||
class generic_visitor final : public boot::parser_visitor
|
||||
{
|
||||
tree current_expression{ NULL_TREE };
|
||||
std::shared_ptr<symbol_table> symbols;
|
||||
std::unordered_map<std::string, tree> unresolved;
|
||||
|
||||
tree build_label_decl(const char *name, location_t loc);
|
||||
tree build_procedure_type(boot::procedure_type_expression& type);
|
||||
@ -68,7 +70,8 @@ namespace elna::gcc
|
||||
void visit_statements(const std::vector<boot::statement *>& statements);
|
||||
|
||||
public:
|
||||
generic_visitor(std::shared_ptr<symbol_table> symbol_table);
|
||||
generic_visitor(std::shared_ptr<symbol_table> symbol_table,
|
||||
std::unordered_map<std::string, tree>&& unresolved);
|
||||
|
||||
void visit(boot::program *program) override;
|
||||
void visit(boot::procedure_definition *definition) override;
|
||||
|
@ -81,4 +81,5 @@ namespace elna::gcc
|
||||
tree_code operator_code, tree left, tree right);
|
||||
tree build_field(location_t location, tree record_type, const std::string name, tree type);
|
||||
tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name);
|
||||
tree build_global_pointer_type(tree type);
|
||||
}
|
||||
|
Reference in New Issue
Block a user