Exemplo n.º 1
0
        public override void visit_property(Property prop)
        {
            base.visit_property(prop);

            if (is_gobject_property(prop) && prop.parent_symbol is Class)
            {
                prop_enum.add_value(new CCodeEnumValue(get_ccode_upper_case_name(prop)));

                if (prop.initializer != null && prop.set_accessor != null && !prop.set_accessor.automatic_body)
                {
                    // generate a custom initializer if it couldn't be done at class_init time
                    bool has_spec_initializer = prop.property_type.data_type is ValaEnum;
                    if (!has_spec_initializer && prop.property_type.data_type is Struct)
                    {
                        var param_spec_func = get_ccode_param_spec_function(prop.property_type.data_type);
                        has_spec_initializer = param_spec_func != "g_param_spec_boxed";
                    }
                    if (!has_spec_initializer)
                    {
                        push_context(instance_init_context);

                        prop.initializer.emit(this);

                        var inst_ma = MemberAccess.simple("this");
                        inst_ma.target_value = new GLibValue(get_data_type_for_symbol((Class)prop.parent_symbol), new CCodeIdentifier("self"), true);
                        store_property(prop, inst_ma, prop.initializer.target_value);

                        temp_ref_values.Clear();
                        pop_context();
                    }
                }
            }
        }
Exemplo n.º 2
0
        public override bool check(CodeContext context)
        {
            // convert to simple loop

            var block = new Block(source_reference);

            // initializer
            foreach (var init_expr in initializer)
            {
                block.add_statement(new ExpressionStatement(init_expr, init_expr.source_reference));
            }

            // do not generate if block if condition is always true
            if (condition == null || always_true(condition))
            {
            }
            else if (always_false(condition))
            {
                // do not generate if block if condition is always false
                body.insert_statement(0, new BreakStatement(condition.source_reference));
            }
            else
            {
                // condition
                var if_condition = new UnaryExpression(UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference);
                var true_block   = new Block(condition.source_reference);
                true_block.add_statement(new BreakStatement(condition.source_reference));
                var if_stmt = new IfStatement(if_condition, true_block, null, condition.source_reference);
                body.insert_statement(0, if_stmt);
            }

            // iterator
            var first_local = new LocalVariable(context.analyzer.bool_type.copy(), get_temp_name(), new BooleanLiteral(true, source_reference), source_reference);

            block.add_statement(new DeclarationStatement(first_local, source_reference));

            var iterator_block = new Block(source_reference);

            foreach (var it_expr in iterator)
            {
                iterator_block.add_statement(new ExpressionStatement(it_expr, it_expr.source_reference));
            }

            var first_if = new IfStatement(new UnaryExpression(UnaryOperator.LOGICAL_NEGATION, MemberAccess.simple(first_local.name, source_reference), source_reference), iterator_block, null, source_reference);

            body.insert_statement(0, first_if);
            body.insert_statement(1, new ExpressionStatement(new Assignment(MemberAccess.simple(first_local.name, source_reference), new BooleanLiteral(false, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference));

            block.add_statement(new Loop(body, source_reference));

            var parent_block = (Block)parent_node;

            parent_block.replace_statement(this, block);

            return(block.check(context));
        }
Exemplo n.º 3
0
        void visit_subroutine(Subroutine m)
        {
            if (m.body == null)
            {
                return;
            }

            m.entry_block  = BasicBlock.entry();
            m.return_block = new BasicBlock();
            m.exit_block   = BasicBlock.exit();

            m.return_block.connect(m.exit_block);

            if (m is Method)
            {
                // ensure out parameters are defined at end of method
                foreach (var param in ((Method)m).get_parameters())
                {
                    if (param.direction == ParameterDirection.OUT)
                    {
                        var param_ma = MemberAccess.simple(param.name, param.source_reference);
                        param_ma.symbol_reference = param;
                        m.return_block.add_node(param_ma);
                    }
                }
            }

            current_block = new BasicBlock();
            m.entry_block.connect(current_block);
            current_block.add_node(m);

            jump_stack.Add(JumpTarget.return_target(m.return_block));
            jump_stack.Add(JumpTarget.exit_target(m.exit_block));

            m.accept_children(this);

            jump_stack.RemoveAt(jump_stack.Count - 1);

            if (current_block != null)
            {
                // end of method body reachable

                if (m.has_result)
                {
                    Report.error(m.source_reference, "missing return statement at end of subroutine body");
                    m.error = true;
                }

                current_block.connect(m.return_block);
            }

            analyze_body(m.entry_block);
        }
Exemplo n.º 4
0
        public override bool check(CodeContext context)
        {
            // convert to simple loop

            // do not generate variable and if block if condition is always true
            if (always_true(condition))
            {
                var loop = new Loop(body, source_reference);

                var _parent_block = parent_node as Block;
                _parent_block.replace_statement(this, loop);

                return(loop.check(context));
            }

            var block = new Block(source_reference);

            var first_local = new LocalVariable(context.analyzer.bool_type.copy(), get_temp_name(), new BooleanLiteral(true, source_reference), source_reference);

            block.add_statement(new DeclarationStatement(first_local, source_reference));

            var if_condition = new UnaryExpression(UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference);
            var true_block   = new Block(condition.source_reference);

            true_block.add_statement(new BreakStatement(condition.source_reference));
            var if_stmt = new IfStatement(if_condition, true_block, null, condition.source_reference);

            var condition_block = new Block(condition.source_reference);

            condition_block.add_statement(if_stmt);

            var first_if = new IfStatement(new UnaryExpression(UnaryOperator.LOGICAL_NEGATION, MemberAccess.simple(first_local.name, source_reference), source_reference), condition_block, null, source_reference);

            body.insert_statement(0, first_if);
            body.insert_statement(1, new ExpressionStatement(new Assignment(MemberAccess.simple(first_local.name, source_reference), new BooleanLiteral(false, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference));

            block.add_statement(new Loop(body, source_reference));

            var parent_block = (Block)parent_node;

            parent_block.replace_statement(this, block);

            return(block.check(context));
        }
Exemplo n.º 5
0
        // Create an access to a temporary variable, with proper reference transfer if needed
        public static Expression create_temp_access(LocalVariable local, DataType target_type)
        {
            Expression temp_access = MemberAccess.simple(local.name, local.source_reference);

            var target_owned = target_type != null && target_type.value_owned;

            if (target_owned && local.variable_type.is_disposable())
            {
                temp_access             = new ReferenceTransferExpression(temp_access, local.source_reference);
                temp_access.target_type = target_type != null?target_type.copy() : local.variable_type.copy();

                temp_access.target_type.value_owned = true;
            }
            else
            {
                temp_access.target_type = target_type != null?target_type.copy() : null;
            }

            return(temp_access);
        }
Exemplo n.º 6
0
        bool check_with_index(CodeContext context, DataType collection_type)
        {
            var get_method = collection_type.get_member("get") as Method;

            if (get_method == null)
            {
                return(false);
            }
            if (get_method.get_parameters().Count != 1)
            {
                return(false);
            }
            var size_property = collection_type.get_member("size") as Property;

            if (size_property == null)
            {
                return(false);
            }

            add_statement(new DeclarationStatement(new LocalVariable(null, "_%s_list".printf(variable_name), collection, source_reference), source_reference));
            add_statement(new DeclarationStatement(new LocalVariable(null, "_%s_size".printf(variable_name), new MemberAccess(MemberAccess.simple("_%s_list".printf(variable_name), source_reference), "size", source_reference), source_reference), source_reference));
            add_statement(new DeclarationStatement(new LocalVariable(null, "_%s_index".printf(variable_name), new UnaryExpression(UnaryOperator.MINUS, new IntegerLiteral("1", source_reference), source_reference), source_reference), source_reference));
            var next        = new UnaryExpression(UnaryOperator.INCREMENT, MemberAccess.simple("_%s_index".printf(variable_name), source_reference), source_reference);
            var conditional = new BinaryExpression(BinaryOperator.LESS_THAN, next, MemberAccess.simple("_%s_size".printf(variable_name), source_reference), source_reference);
            var loop        = new WhileStatement(conditional, body, source_reference);

            add_statement(loop);

            var get_call = new MethodCall(new MemberAccess(MemberAccess.simple("_%s_list".printf(variable_name), source_reference), "get", source_reference), source_reference);

            get_call.add_argument(MemberAccess.simple("_%s_index".printf(variable_name), source_reference));
            body.insert_statement(0, new DeclarationStatement(new LocalVariable(type_reference, variable_name, get_call, source_reference), source_reference));

            is_checked = false;
            return(base.check(context));
        }
Exemplo n.º 7
0
        public override bool check(CodeContext context)
        {
            if (is_checked)
            {
                return(!error);
            }

            is_checked = true;

            return_type.check(context);

            foreach (Parameter param in parameters)
            {
                if (param.ellipsis)
                {
                    Report.error(param.source_reference, "Signals with variable argument lists are not supported");
                    return(false);
                }

                param.check(context);
            }

            if (!is_virtual && body != null)
            {
                Report.error(source_reference, "Only virtual signals can have a default signal handler body");
            }


            if (is_virtual)
            {
                default_handler = new Method(name, return_type, source_reference);

                default_handler.owner            = owner;
                default_handler.access           = access;
                default_handler.external         = external;
                default_handler.hides            = hides;
                default_handler.is_virtual       = true;
                default_handler.signal_reference = this;
                default_handler.body             = body;


                foreach (Parameter param in parameters)
                {
                    default_handler.add_parameter(param);
                }

                var cl = parent_symbol as ObjectTypeSymbol;

                cl.add_hidden_method(default_handler);
                default_handler.check(context);
            }

            if (!external_package && get_attribute("HasEmitter") != null)
            {
                emitter = new Method(name, return_type, source_reference);

                emitter.owner  = owner;
                emitter.access = access;

                var body = new Block(source_reference);
                var call = new MethodCall(MemberAccess.simple(name, source_reference), source_reference);

                foreach (Parameter param in parameters)
                {
                    emitter.add_parameter(param);
                    call.add_argument(MemberAccess.simple(param.name, source_reference));
                }

                if (return_type is VoidType)
                {
                    body.add_statement(new ExpressionStatement(call, source_reference));
                }
                else
                {
                    body.add_statement(new ReturnStatement(call, source_reference));
                }
                emitter.body = body;

                var cl = parent_symbol as ObjectTypeSymbol;

                cl.add_hidden_method(emitter);
                emitter.check(context);
            }


            if (!external_package && !hides && get_hidden_member() != null)
            {
                Report.warning(source_reference, "%s hides inherited signal `%s'. Use the `new' keyword if hiding was intentional".printf(get_full_name(), get_hidden_member().get_full_name()));
            }

            return(!error);
        }
Exemplo n.º 8
0
        bool check_with_iterator(CodeContext context, DataType collection_type)
        {
            use_iterator = true;

            if (check_with_index(context, collection_type))
            {
                return(true);
            }

            var iterator_method = collection_type.get_member("iterator") as Method;

            if (iterator_method == null)
            {
                Report.error(collection.source_reference, "`%s' does not have an `iterator' method".printf(collection_type.ToString()));
                error = true;
                return(false);
            }
            if (iterator_method.get_parameters().Count != 0)
            {
                Report.error(collection.source_reference, "`%s' must not have any parameters".printf(iterator_method.get_full_name()));
                error = true;
                return(false);
            }
            var iterator_type = iterator_method.return_type.get_actual_type(collection_type, null, this);

            if (iterator_type is VoidType)
            {
                Report.error(collection.source_reference, "`%s' must return an iterator".printf(iterator_method.get_full_name()));
                error = true;
                return(false);
            }

            var iterator_call = new MethodCall(new MemberAccess(collection, "iterator", source_reference), source_reference);

            add_statement(new DeclarationStatement(new LocalVariable(iterator_type, "_%s_it".printf(variable_name), iterator_call, source_reference), source_reference));

            var next_value_method = iterator_type.get_member("next_value") as Method;
            var next_method       = iterator_type.get_member("next") as Method;

            if (next_value_method != null)
            {
                if (next_value_method.get_parameters().Count != 0)
                {
                    Report.error(collection.source_reference, "`%s' must not have any parameters".printf(next_value_method.get_full_name()));
                    error = true;
                    return(false);
                }
                var element_type = next_value_method.return_type.get_actual_type(iterator_type, null, this);
                if (!element_type.nullable)
                {
                    Report.error(collection.source_reference, "return type of `%s' must be nullable".printf(next_value_method.get_full_name()));
                    error = true;
                    return(false);
                }

                if (!analyze_element_type(element_type))
                {
                    return(false);
                }

                add_statement(new DeclarationStatement(new LocalVariable(type_reference, variable_name, null, source_reference), source_reference));

                var next_value_call = new MethodCall(new MemberAccess(MemberAccess.simple("_%s_it".printf(variable_name), source_reference), "next_value", source_reference), source_reference);
                var assignment      = new Assignment(new MemberAccess(null, variable_name, source_reference), next_value_call, AssignmentOperator.SIMPLE, source_reference);
                var conditional     = new BinaryExpression(BinaryOperator.INEQUALITY, assignment, new NullLiteral(source_reference), source_reference);
                var loop            = new WhileStatement(conditional, body, source_reference);
                add_statement(loop);
            }
            else if (next_method != null)
            {
                if (next_method.get_parameters().Count != 0)
                {
                    Report.error(collection.source_reference, "`%s' must not have any parameters".printf(next_method.get_full_name()));
                    error = true;
                    return(false);
                }
                if (!next_method.return_type.compatible(context.analyzer.bool_type))
                {
                    Report.error(collection.source_reference, "`%s' must return a boolean value".printf(next_method.get_full_name()));
                    error = true;
                    return(false);
                }
                var get_method = iterator_type.get_member("get") as Method;
                if (get_method == null)
                {
                    Report.error(collection.source_reference, "`%s' does not have a `get' method".printf(iterator_type.ToString()));
                    error = true;
                    return(false);
                }
                if (get_method.get_parameters().Count != 0)
                {
                    Report.error(collection.source_reference, "`%s' must not have any parameters".printf(get_method.get_full_name()));
                    error = true;
                    return(false);
                }
                var element_type = get_method.return_type.get_actual_type(iterator_type, null, this);
                if (element_type is VoidType)
                {
                    Report.error(collection.source_reference, "`%s' must return an element".printf(get_method.get_full_name()));
                    error = true;
                    return(false);
                }

                if (!analyze_element_type(element_type))
                {
                    return(false);
                }

                var next_call = new MethodCall(new MemberAccess(MemberAccess.simple("_%s_it".printf(variable_name), source_reference), "next", source_reference), source_reference);
                var loop      = new WhileStatement(next_call, body, source_reference);
                add_statement(loop);

                var get_call = new MethodCall(new MemberAccess(MemberAccess.simple("_%s_it".printf(variable_name), source_reference), "get", source_reference), source_reference);
                body.insert_statement(0, new DeclarationStatement(new LocalVariable(type_reference, variable_name, get_call, source_reference), source_reference));
            }
            else
            {
                Report.error(collection.source_reference, "`%s' does not have a `next_value' or `next' method".printf(iterator_type.ToString()));
                error = true;
                return(false);
            }

            is_checked = false;
            return(base.check(context));
        }
Exemplo n.º 9
0
        public override bool check(CodeContext context)
        {
            if (is_checked)
            {
                return(!error);
            }

            is_checked = true;

            if (class_name != null && class_name != parent_symbol.name)
            {
                // class_name is null for constructors generated by GIdlParser
                Report.error(source_reference, "missing return type in method `%s.%s´".printf(context.analyzer.current_symbol.get_full_name(), class_name));
                error = true;
                return(false);
            }

            var old_source_file = context.analyzer.current_source_file;
            var old_symbol      = context.analyzer.current_symbol;

            if (source_reference != null)
            {
                context.analyzer.current_source_file = source_reference.file;
            }
            context.analyzer.current_symbol = this;

            foreach (Parameter param in get_parameters())
            {
                param.check(context);
            }

            foreach (DataType error_type in get_error_types())
            {
                error_type.check(context);
            }

            foreach (Expression precondition in get_preconditions())
            {
                precondition.check(context);
            }

            foreach (Expression postcondition in get_postconditions())
            {
                postcondition.check(context);
            }

            if (body != null)
            {
                body.check(context);

                var cl = parent_symbol as Class;

                // ensure we chain up to base constructor
                if (!chain_up && cl != null && cl.base_class != null)
                {
                    if (cl.base_class.default_construction_method != null &&
                        !cl.base_class.default_construction_method.has_construct_function)
                    {
                        // directly chain up to Object
                        var old_insert_block = context.analyzer.insert_block;
                        context.analyzer.current_symbol = body;
                        context.analyzer.insert_block   = body;

                        var stmt = new ExpressionStatement(new MethodCall(new MemberAccess(MemberAccess.simple("GLib", source_reference), "Object", source_reference), source_reference), source_reference);
                        body.insert_statement(0, stmt);
                        stmt.check(context);

                        context.analyzer.current_symbol = this;
                        context.analyzer.insert_block   = old_insert_block;
                    }
                    else if (cl.base_class.default_construction_method == null ||
                             cl.base_class.default_construction_method.access == SymbolAccessibility.PRIVATE)
                    {
                        Report.error(source_reference, "unable to chain up to private base constructor");
                    }
                    else if (cl.base_class.default_construction_method.get_required_arguments() > 0)
                    {
                        Report.error(source_reference, "unable to chain up to base constructor requiring arguments");
                    }
                    else
                    {
                        var old_insert_block = context.analyzer.insert_block;
                        context.analyzer.current_symbol = body;
                        context.analyzer.insert_block   = body;

                        var stmt = new ExpressionStatement(new MethodCall(new BaseAccess(source_reference), source_reference), source_reference);
                        body.insert_statement(0, stmt);
                        stmt.check(context);

                        context.analyzer.current_symbol = this;
                        context.analyzer.insert_block   = old_insert_block;
                    }
                }
            }

            context.analyzer.current_source_file = old_source_file;
            context.analyzer.current_symbol      = old_symbol;

            if (is_abstract || is_virtual || overrides)
            {
                Report.error(source_reference, "The creation method `%s' cannot be marked as override, virtual, or abstract".printf(get_full_name()));
                return(false);
            }

            // check that all errors that can be thrown in the method body are declared
            if (body != null)
            {
                foreach (DataType body_error_type in body.get_error_types())
                {
                    bool can_propagate_error = false;
                    foreach (DataType method_error_type in get_error_types())
                    {
                        if (body_error_type.compatible(method_error_type))
                        {
                            can_propagate_error = true;
                        }
                    }
                    if (!can_propagate_error && !((ErrorType)body_error_type).dynamic_error)
                    {
                        Report.warning(body_error_type.source_reference, "unhandled error `%s'".printf(body_error_type.ToString()));
                    }
                }
            }

            return(!error);
        }
Exemplo n.º 10
0
        public override bool check(CodeContext context)
        {
            if (is_checked)
            {
                return(!error);
            }

            is_checked = true;

            if (!value_type.check(context))
            {
                error = true;
                return(false);
            }

            var old_symbol = context.analyzer.current_symbol;

            context.analyzer.current_symbol = this;

            if (writable || construction)
            {
                value_parameter = new Parameter("value", value_type, source_reference);
            }

            if (prop.source_type == SourceFileType.SOURCE)
            {
                if (body == null && !prop.interface_only && !prop.is_abstract)
                {
                    /* no accessor body specified, insert default body */

                    automatic_body = true;
                    body           = new Block(source_reference);
                    var ma = MemberAccess.simple("_%s".printf(prop.name), source_reference);
                    if (readable)
                    {
                        body.add_statement(new ReturnStatement(ma, source_reference));
                    }
                    else
                    {
                        Expression value = MemberAccess.simple("value", source_reference);
                        if (value_type.value_owned)
                        {
                            value = new ReferenceTransferExpression(value, source_reference);
                        }
                        var assignment = new Assignment(ma, value, AssignmentOperator.SIMPLE, source_reference);
                        body.add_statement(new ExpressionStatement(assignment));
                    }
                }
            }

            if ((prop.is_abstract || prop.is_virtual || prop.overrides) && access == SymbolAccessibility.PRIVATE)
            {
                error = true;
                Report.error(source_reference, "Property `%s' with private accessor cannot be marked as abstract, virtual or override".printf(prop.get_full_name()));
                return(false);
            }

            if (body != null)
            {
                if (writable || construction)
                {
                    body.scope.add(value_parameter.name, value_parameter);
                }

                body.check(context);

                foreach (DataType body_error_type in body.get_error_types())
                {
                    if (!((ErrorType)body_error_type).dynamic_error)
                    {
                        Report.warning(body_error_type.source_reference, "unhandled error `%s'".printf(body_error_type.ToString()));
                    }
                }
            }

            context.analyzer.current_symbol = old_symbol;

            return(!error);
        }