diff --git a/boot/ast.cc b/boot/ast.cc index 2ff5a00..89a1ad0 100644 --- a/boot/ast.cc +++ b/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() { return this; @@ -534,37 +529,11 @@ namespace elna::boot 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) : node(position), name(name) { } - void variable_expression::accept(parser_visitor *visitor) - { - visitor->visit(this); - } - variable_expression *variable_expression::is_variable() { 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() { 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() { return *m_base; @@ -639,11 +598,6 @@ namespace elna::boot { } - void dereference_expression::accept(parser_visitor *visitor) - { - visitor->visit(this); - } - expression& dereference_expression::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() { 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 this; @@ -857,11 +801,6 @@ namespace elna::boot { } - void assign_statement::accept(parser_visitor *visitor) - { - visitor->visit(this); - } - assign_statement *assign_statement::is_assign() { 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() { 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() { return this; diff --git a/gcc/elna-diagnostic.cc b/gcc/elna-diagnostic.cc index 3668048..ea92ece 100644 --- a/gcc/elna-diagnostic.cc +++ b/gcc/elna-diagnostic.cc @@ -44,39 +44,41 @@ namespace elna::gcc { 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"; } - else if (type == elna_word_type_node) + else if (unqualified_type == elna_word_type_node) { return "Word"; } - else if (type == elna_bool_type_node) + else if (unqualified_type == elna_bool_type_node) { return "Bool"; } - else if (type == elna_byte_type_node) + else if (unqualified_type == elna_byte_type_node) { return "Byte"; } - else if (type == elna_float_type_node) + else if (unqualified_type == elna_float_type_node) { return "Float"; } - else if (type == elna_char_type_node) + else if (unqualified_type == elna_char_type_node) { return "Char"; } - else if (type == elna_string_type_node) + else if (unqualified_type == elna_string_type_node) { 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 "()"; } - else if (is_pointer_type(type)) + else if (is_pointer_type(unqualified_type)) { tree pointer_target_type = TREE_TYPE(type); @@ -107,23 +109,25 @@ namespace elna::gcc } } 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; } - else if (is_array_type(type)) + else if (is_array_type(unqualified_type)) { return "array"; } 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) { - return print_aggregate_name(type, "union"); + return print_aggregate_name(unqualified_type, "union"); } else { diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 9d247c0..284ac5d 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -1046,13 +1046,14 @@ namespace elna::gcc 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))); } else if (is_array_type(aggregate_type) && expression->field() == "ptr") { 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 { @@ -1099,25 +1100,27 @@ namespace elna::gcc 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()); - 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)) { tree assignment = build2_loc(statement_location, MODIFY_EXPR, void_type_node, lvalue, rvalue); append_statement(assignment); - this->current_expression = NULL_TREE; } else { - error_at(statement_location, - "cannot assign value of type '%s' to variable of type '%s'", + error_at(statement_location, "Cannot assign value of type '%s' to variable of type '%s'", print_type(TREE_TYPE(rvalue)).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) diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 9e4c4e7..59de3fc 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -481,11 +481,16 @@ namespace elna::boot public: return_statement(const struct position position, expression *return_expression); - void accept(parser_visitor *visitor); - virtual return_statement *is_return() override; + + template + void accept(V *visitor) + { + visitor->visit(this); + } expression *return_expression(); + virtual return_statement *is_return() override; virtual ~return_statement() override; }; @@ -497,8 +502,29 @@ namespace elna::boot virtual field_access_expression *is_field_access(); virtual dereference_expression *is_dereference(); + template + 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: @@ -511,7 +537,12 @@ namespace elna::boot const std::string name; variable_expression(const struct position position, const std::string& name); - void accept(parser_visitor *visitor); + + template + void accept(V *visitor) + { + visitor->visit(this); + } variable_expression *is_variable() override; }; @@ -523,7 +554,12 @@ namespace elna::boot public: array_access_expression(const struct position position, expression *base, expression *index); - void accept(parser_visitor *visitor); + + template + void accept(V *visitor) + { + visitor->visit(this); + } expression& base(); expression& index(); @@ -541,7 +577,12 @@ namespace elna::boot public: field_access_expression(const struct position position, expression *base, const std::string& field); - void accept(parser_visitor *visitor); + + template + void accept(V *visitor) + { + visitor->visit(this); + } expression& base(); std::string& field(); @@ -557,12 +598,16 @@ namespace elna::boot public: dereference_expression(const struct position position, expression *base); - void accept(parser_visitor *visitor); + + template + void accept(parser_visitor *visitor) + { + visitor->visit(this); + } expression& base(); dereference_expression *is_dereference() override; - ~dereference_expression() override; }; @@ -577,12 +622,17 @@ namespace elna::boot std::vector arguments; procedure_call(const struct position position, designator_expression *callable); - void accept(parser_visitor *visitor); - virtual procedure_call *is_call_statement() override; - virtual procedure_call *is_call_expression() override; + + template + void accept(V *visitor) + { + visitor->visit(this); + } designator_expression& callable(); + virtual procedure_call *is_call_statement() override; + virtual procedure_call *is_call_expression() override; virtual ~procedure_call() override; }; @@ -599,13 +649,18 @@ namespace elna::boot */ assign_statement(const struct position position, designator_expression *lvalue, expression *rvalue); - void accept(parser_visitor *visitor); + + template + void accept(V *visitor) + { + visitor->visit(this); + } designator_expression& lvalue(); expression& rvalue(); - virtual ~assign_statement() 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, std::vector *alternative = nullptr); - void accept(parser_visitor *visitor); - virtual if_statement *is_if() override; + + template + void accept(V *visitor) + { + visitor->visit(this); + } conditional_statements& body(); std::vector *alternative(); + virtual if_statement *is_if() override; virtual ~if_statement() override; }; @@ -640,11 +700,16 @@ namespace elna::boot public: std::vector branches; while_statement(const struct position position, conditional_statements *body); - void accept(parser_visitor *visitor); - while_statement *is_while() override; + + template + void accept(V *visitor) + { + visitor->visit(this); + } conditional_statements& body(); + while_statement *is_while() override; virtual ~while_statement() override; }; @@ -781,9 +846,14 @@ namespace elna::boot std::vector statements; defer_statement(const struct position position); - void accept(parser_visitor *visitor); - defer_statement *is_defer() override; + template + void accept(V *visitor) + { + visitor->visit(this); + } + + defer_statement *is_defer() override; virtual ~defer_statement() override; };