Make array ptr and length properties constant
This commit is contained in:
		
							
								
								
									
										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()
 | 
			
		||||
    {
 | 
			
		||||
        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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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<typename V>
 | 
			
		||||
        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<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:
 | 
			
		||||
@@ -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<typename V>
 | 
			
		||||
        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<typename V>
 | 
			
		||||
        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<typename V>
 | 
			
		||||
        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<typename V>
 | 
			
		||||
        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<expression *> 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<typename V>
 | 
			
		||||
        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<typename V>
 | 
			
		||||
        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<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();
 | 
			
		||||
        std::vector<statement *> *alternative();
 | 
			
		||||
 | 
			
		||||
        virtual if_statement *is_if() override;
 | 
			
		||||
        virtual ~if_statement() override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -640,11 +700,16 @@ namespace elna::boot
 | 
			
		||||
    public:
 | 
			
		||||
        std::vector<conditional_statements *> branches;
 | 
			
		||||
        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();
 | 
			
		||||
 | 
			
		||||
        while_statement *is_while() override;
 | 
			
		||||
        virtual ~while_statement() override;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -781,9 +846,14 @@ namespace elna::boot
 | 
			
		||||
        std::vector<statement *> statements;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user