Make array ptr and length properties constant
This commit is contained in:
parent
6ccb195c09
commit
c022805c53
71
boot/ast.cc
71
boot/ast.cc
@ -503,11 +503,6 @@ namespace elna::boot
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
@ -534,37 +529,11 @@ 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;
|
||||||
@ -576,11 +545,6 @@ 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;
|
||||||
@ -608,11 +572,6 @@ 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;
|
||||||
@ -639,11 +598,6 @@ 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;
|
||||||
@ -732,11 +686,6 @@ 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;
|
||||||
@ -831,11 +780,6 @@ 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;
|
||||||
@ -857,11 +801,6 @@ 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;
|
||||||
@ -908,11 +847,6 @@ 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;
|
||||||
@ -943,11 +877,6 @@ 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;
|
||||||
|
@ -44,39 +44,41 @@ namespace elna::gcc
|
|||||||
{
|
{
|
||||||
gcc_assert(TYPE_P(type));
|
gcc_assert(TYPE_P(type));
|
||||||
|
|
||||||
if (type == elna_int_type_node)
|
tree unqualified_type = get_qualified_type(type, TYPE_UNQUALIFIED);
|
||||||
|
|
||||||
|
if (unqualified_type == elna_int_type_node)
|
||||||
{
|
{
|
||||||
return "Int";
|
return "Int";
|
||||||
}
|
}
|
||||||
else if (type == elna_word_type_node)
|
else if (unqualified_type == elna_word_type_node)
|
||||||
{
|
{
|
||||||
return "Word";
|
return "Word";
|
||||||
}
|
}
|
||||||
else if (type == elna_bool_type_node)
|
else if (unqualified_type == elna_bool_type_node)
|
||||||
{
|
{
|
||||||
return "Bool";
|
return "Bool";
|
||||||
}
|
}
|
||||||
else if (type == elna_byte_type_node)
|
else if (unqualified_type == elna_byte_type_node)
|
||||||
{
|
{
|
||||||
return "Byte";
|
return "Byte";
|
||||||
}
|
}
|
||||||
else if (type == elna_float_type_node)
|
else if (unqualified_type == elna_float_type_node)
|
||||||
{
|
{
|
||||||
return "Float";
|
return "Float";
|
||||||
}
|
}
|
||||||
else if (type == elna_char_type_node)
|
else if (unqualified_type == elna_char_type_node)
|
||||||
{
|
{
|
||||||
return "Char";
|
return "Char";
|
||||||
}
|
}
|
||||||
else if (type == elna_string_type_node)
|
else if (unqualified_type == elna_string_type_node)
|
||||||
{
|
{
|
||||||
return "String";
|
return "String";
|
||||||
}
|
}
|
||||||
else if (is_void_type(type)) // For procedures without a return type.
|
else if (is_void_type(unqualified_type)) // For procedures without a return type.
|
||||||
{
|
{
|
||||||
return "()";
|
return "()";
|
||||||
}
|
}
|
||||||
else if (is_pointer_type(type))
|
else if (is_pointer_type(unqualified_type))
|
||||||
{
|
{
|
||||||
tree pointer_target_type = TREE_TYPE(type);
|
tree pointer_target_type = TREE_TYPE(type);
|
||||||
|
|
||||||
@ -107,23 +109,25 @@ namespace elna::gcc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
output += ')';
|
output += ')';
|
||||||
if (!is_void_type(TREE_TYPE(type)))
|
tree return_type = TREE_TYPE(type);
|
||||||
|
|
||||||
|
if (!is_void_type(return_type))
|
||||||
{
|
{
|
||||||
output += " -> " + print_type(TREE_TYPE(type));
|
output += " -> " + print_type(return_type);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
else if (is_array_type(type))
|
else if (is_array_type(unqualified_type))
|
||||||
{
|
{
|
||||||
return "array";
|
return "array";
|
||||||
}
|
}
|
||||||
else if (TREE_CODE(type) == RECORD_TYPE)
|
else if (TREE_CODE(type) == RECORD_TYPE)
|
||||||
{
|
{
|
||||||
return print_aggregate_name(type, "record");
|
return print_aggregate_name(unqualified_type, "record");
|
||||||
}
|
}
|
||||||
else if (TREE_CODE(type) == UNION_TYPE)
|
else if (TREE_CODE(type) == UNION_TYPE)
|
||||||
{
|
{
|
||||||
return print_aggregate_name(type, "union");
|
return print_aggregate_name(unqualified_type, "union");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1046,13 +1046,14 @@ namespace elna::gcc
|
|||||||
|
|
||||||
if (is_array_type(aggregate_type) && expression->field() == "length")
|
if (is_array_type(aggregate_type) && expression->field() == "length")
|
||||||
{
|
{
|
||||||
this->current_expression = fold_convert(elna_word_type_node,
|
this->current_expression = fold_convert(build_qualified_type(elna_word_type_node, TYPE_QUAL_CONST),
|
||||||
TYPE_MAX_VALUE(TYPE_DOMAIN(aggregate_type)));
|
TYPE_MAX_VALUE(TYPE_DOMAIN(aggregate_type)));
|
||||||
}
|
}
|
||||||
else if (is_array_type(aggregate_type) && expression->field() == "ptr")
|
else if (is_array_type(aggregate_type) && expression->field() == "ptr")
|
||||||
{
|
{
|
||||||
tree ptr_type = build_pointer_type_for_mode(TREE_TYPE(aggregate_type), VOIDmode, true);
|
tree ptr_type = build_pointer_type_for_mode(TREE_TYPE(aggregate_type), VOIDmode, true);
|
||||||
this->current_expression = build1(ADDR_EXPR, ptr_type, this->current_expression);
|
this->current_expression = build1(ADDR_EXPR,
|
||||||
|
build_qualified_type(ptr_type, TYPE_QUAL_CONST), this->current_expression);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1099,25 +1100,27 @@ namespace elna::gcc
|
|||||||
|
|
||||||
if (TREE_CODE(lvalue) == CONST_DECL)
|
if (TREE_CODE(lvalue) == CONST_DECL)
|
||||||
{
|
{
|
||||||
error_at(statement_location, "cannot modify constant '%s'",
|
error_at(statement_location, "Cannot modify constant '%s'",
|
||||||
statement->lvalue().is_variable()->name.c_str());
|
statement->lvalue().is_variable()->name.c_str());
|
||||||
this->current_expression = error_mark_node;
|
}
|
||||||
|
else if (TYPE_READONLY(TREE_TYPE(lvalue)))
|
||||||
|
{
|
||||||
|
error_at(statement_location, "Cannot modify a constant expression of type '%s'",
|
||||||
|
print_type(TREE_TYPE(lvalue)).c_str());
|
||||||
}
|
}
|
||||||
else if (is_assignable_from(TREE_TYPE(lvalue), rvalue))
|
else if (is_assignable_from(TREE_TYPE(lvalue), rvalue))
|
||||||
{
|
{
|
||||||
tree assignment = build2_loc(statement_location, MODIFY_EXPR, void_type_node, lvalue, rvalue);
|
tree assignment = build2_loc(statement_location, MODIFY_EXPR, void_type_node, lvalue, rvalue);
|
||||||
|
|
||||||
append_statement(assignment);
|
append_statement(assignment);
|
||||||
this->current_expression = NULL_TREE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error_at(statement_location,
|
error_at(statement_location, "Cannot assign value of type '%s' to variable of type '%s'",
|
||||||
"cannot assign value of type '%s' to variable of type '%s'",
|
|
||||||
print_type(TREE_TYPE(rvalue)).c_str(),
|
print_type(TREE_TYPE(rvalue)).c_str(),
|
||||||
print_type(TREE_TYPE(lvalue)).c_str());
|
print_type(TREE_TYPE(lvalue)).c_str());
|
||||||
this->current_expression = error_mark_node;
|
|
||||||
}
|
}
|
||||||
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::if_statement *statement)
|
void generic_visitor::visit(boot::if_statement *statement)
|
||||||
|
@ -481,11 +481,16 @@ namespace elna::boot
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
return_statement(const struct position position, expression *return_expression);
|
return_statement(const struct position position, expression *return_expression);
|
||||||
void accept(parser_visitor *visitor);
|
|
||||||
virtual return_statement *is_return() override;
|
template<typename V>
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -497,8 +502,29 @@ 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:
|
||||||
@ -511,7 +537,12 @@ 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);
|
|
||||||
|
template<typename V>
|
||||||
|
void accept(V *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
variable_expression *is_variable() override;
|
variable_expression *is_variable() override;
|
||||||
};
|
};
|
||||||
@ -523,7 +554,12 @@ 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);
|
|
||||||
|
template<typename V>
|
||||||
|
void accept(V *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
expression& base();
|
expression& base();
|
||||||
expression& index();
|
expression& index();
|
||||||
@ -541,7 +577,12 @@ 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);
|
|
||||||
|
template<typename V>
|
||||||
|
void accept(V *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
expression& base();
|
expression& base();
|
||||||
std::string& field();
|
std::string& field();
|
||||||
@ -557,12 +598,16 @@ 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);
|
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -577,12 +622,17 @@ 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);
|
|
||||||
virtual procedure_call *is_call_statement() override;
|
template<typename V>
|
||||||
virtual procedure_call *is_call_expression() override;
|
void accept(V *visitor)
|
||||||
|
{
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -599,13 +649,18 @@ 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);
|
|
||||||
|
template<typename V>
|
||||||
|
void accept(V *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
designator_expression& lvalue();
|
designator_expression& lvalue();
|
||||||
expression& rvalue();
|
expression& rvalue();
|
||||||
|
|
||||||
virtual ~assign_statement() override;
|
|
||||||
assign_statement *is_assign() override;
|
assign_statement *is_assign() override;
|
||||||
|
virtual ~assign_statement() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -621,12 +676,17 @@ 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);
|
|
||||||
virtual if_statement *is_if() override;
|
template<typename V>
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -640,11 +700,16 @@ 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);
|
|
||||||
while_statement *is_while() override;
|
template<typename V>
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -781,9 +846,14 @@ 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);
|
|
||||||
defer_statement *is_defer() override;
|
|
||||||
|
|
||||||
|
template<typename V>
|
||||||
|
void accept(V *visitor)
|
||||||
|
{
|
||||||
|
visitor->visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
defer_statement *is_defer() override;
|
||||||
virtual ~defer_statement() override;
|
virtual ~defer_statement() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user