Exemplo n.º 1
0
        void add_struct_copy_function(Struct st)
        {
            var function = new CCodeFunction(get_ccode_copy_function(st), "void");

            if (st.is_private_symbol())
            {
                function.modifiers = CCodeModifiers.STATIC;
            }
            else if (context.hide_internal && st.is_internal_symbol())
            {
                function.modifiers = CCodeModifiers.INTERNAL;
            }

            function.add_parameter(new CCodeParameter("self", "const " + get_ccode_name(st) + "*"));
            function.add_parameter(new CCodeParameter("dest", get_ccode_name(st) + "*"));

            push_function(function);

            var dest_struct = new GLibValue(get_data_type_for_symbol(st), new CCodeIdentifier("(*dest)"), true);

            foreach (var f in st.get_fields())
            {
                if (f.binding == MemberBinding.INSTANCE)
                {
                    var value = load_field(f, load_this_parameter((TypeSymbol)st));
                    if (requires_copy(f.variable_type))
                    {
                        value = copy_value(value, f);
                        if (value == null)
                        {
                            // error case, continue to avoid critical
                            continue;
                        }
                    }
                    store_field(f, dest_struct, value);
                }
            }

            pop_function();

            cfile.add_function(function);
        }
Exemplo n.º 2
0
        /* Returns lvalue access to the given field */
        public override TargetValue get_field_cvalue(Field field, TargetValue instance)
        {
            var value_type = field.variable_type.copy();

            var result = new GLibValue(value_type);

            if (instance != null)
            {
                result.actual_value_type = field.variable_type.get_actual_type(instance.value_type, null, field);
            }
            result.lvalue = true;
            result.array_null_terminated = get_ccode_array_null_terminated(field);
            if (get_ccode_array_length_expr(field) != null)
            {
                result.array_length_cexpr = new CCodeConstant(get_ccode_array_length_expr(field));
            }
            result.ctype = get_ccode_type(field);

            var array_type    = result.value_type as ArrayType;
            var delegate_type = result.value_type as DelegateType;

            if (field.binding == MemberBinding.INSTANCE)
            {
                CCodeExpression pub_inst = null;

                if (instance != null)
                {
                    pub_inst = get_cvalue_(instance);
                }

                var instance_target_type = get_data_type_for_symbol((TypeSymbol)field.parent_symbol);

                var  cl = instance_target_type.data_type as Class;
                bool is_gtypeinstance = ((instance_target_type.data_type == cl) && (cl == null || !cl.is_compact));

                CCodeExpression inst;
                if (is_gtypeinstance && field.access == SymbolAccessibility.PRIVATE)
                {
                    inst = CCodeMemberAccess.pointer(pub_inst, "priv");
                }
                else
                {
                    if (cl != null)
                    {
                        generate_class_struct_declaration(cl, cfile);
                    }
                    inst = pub_inst;
                }
                if (instance_target_type.data_type.is_reference_type() || (instance != null && instance.value_type is PointerType))
                {
                    result.cvalue = CCodeMemberAccess.pointer(inst, get_ccode_name(field));
                }
                else
                {
                    result.cvalue = new CCodeMemberAccess(inst, get_ccode_name(field));
                }

                if (array_type != null && get_ccode_array_length(field))
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        CCodeExpression length_expr = null;

                        string length_cname;
                        if (get_ccode_array_length_name(field) != null)
                        {
                            length_cname = get_ccode_array_length_name(field);
                        }
                        else
                        {
                            length_cname = get_array_length_cname(get_ccode_name(field), dim);
                        }

                        if (((TypeSymbol)field.parent_symbol).is_reference_type())
                        {
                            length_expr = CCodeMemberAccess.pointer(inst, length_cname);
                        }
                        else
                        {
                            length_expr = new CCodeMemberAccess(inst, length_cname);
                        }

                        result.append_array_length_cvalue(length_expr);
                    }
                    if (array_type.rank == 1 && field.is_internal_symbol())
                    {
                        string size_cname = get_array_size_cname(get_ccode_name(field));

                        if (((TypeSymbol)field.parent_symbol).is_reference_type())
                        {
                            set_array_size_cvalue(result, CCodeMemberAccess.pointer(inst, size_cname));
                        }
                        else
                        {
                            set_array_size_cvalue(result, new CCodeMemberAccess(inst, size_cname));
                        }
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target && get_ccode_delegate_target(field))
                {
                    string target_cname = get_ccode_delegate_target_name(field);
                    string target_destroy_notify_cname = get_delegate_target_destroy_notify_cname(get_ccode_name(field));

                    if (((TypeSymbol)field.parent_symbol).is_reference_type())
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(inst, target_cname);
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(inst, target_destroy_notify_cname);
                        }
                    }
                    else
                    {
                        result.delegate_target_cvalue = new CCodeMemberAccess(inst, target_cname);
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess(inst, target_destroy_notify_cname);
                        }
                    }
                }
            }
            else if (field.binding == MemberBinding.CLASS)
            {
                var cl   = (Class)field.parent_symbol;
                var cast = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_upper_case_name(cl, null) + "_CLASS"));

                CCodeExpression klass;
                if (instance == null)
                {
                    if (get_this_type() == null)
                    {
                        // Accessing the field from a static or class constructor
                        klass = new CCodeIdentifier("klass");
                    }
                    else
                    {
                        // Accessing the field from within an instance method
                        var k = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_GET_CLASS"));
                        k.add_argument(new CCodeIdentifier("self"));
                        klass = k;
                    }
                }
                else
                {
                    // Accessing the field of an instance
                    var k = new CCodeFunctionCall(new CCodeIdentifier("G_OBJECT_GET_CLASS"));
                    k.add_argument(get_cvalue_(instance));
                    klass = k;
                }
                cast.add_argument(klass);

                if (field.access == SymbolAccessibility.PRIVATE)
                {
                    var ccall = new CCodeFunctionCall(new CCodeIdentifier("%s_GET_CLASS_PRIVATE".printf(get_ccode_upper_case_name(cl))));
                    ccall.add_argument(klass);
                    result.cvalue = CCodeMemberAccess.pointer(ccall, get_ccode_name(field));
                }
                else
                {
                    result.cvalue = CCodeMemberAccess.pointer(cast, get_ccode_name(field));
                }
            }
            else
            {
                generate_field_declaration(field, cfile);

                result.cvalue = new CCodeIdentifier(get_ccode_name(field));

                if (array_type != null && get_ccode_array_length(field))
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        string length_cname;
                        if (get_ccode_array_length_name(field) != null)
                        {
                            length_cname = get_ccode_array_length_name(field);
                        }
                        else
                        {
                            length_cname = get_array_length_cname(get_ccode_name(field), dim);
                        }

                        result.append_array_length_cvalue(new CCodeIdentifier(length_cname));
                    }
                    if (array_type.rank == 1 && field.is_internal_symbol())
                    {
                        set_array_size_cvalue(result, new CCodeIdentifier(get_array_size_cname(get_ccode_name(field))));
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target && get_ccode_delegate_target(field))
                {
                    result.delegate_target_cvalue = new CCodeIdentifier(get_ccode_delegate_target_name(field));
                    if (result.value_type.is_disposable())
                    {
                        result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(get_ccode_name(field)));
                    }
                }
            }

            return(result);
        }
Exemplo n.º 3
0
        /* Returns lvalue access to the given local variable */
        public override TargetValue get_local_cvalue(LocalVariable local)
        {
            var result = new GLibValue(local.variable_type.copy());

            result.lvalue = true;

            var array_type    = local.variable_type as ArrayType;
            var delegate_type = local.variable_type as DelegateType;

            if (local.is_result)
            {
                // used in postconditions
                // structs are returned as out parameter
                if (local.variable_type != null && local.variable_type.is_real_non_null_struct_type())
                {
                    result.cvalue = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("result"));
                }
                else
                {
                    result.cvalue = new CCodeIdentifier("result");
                }
                if (array_type != null && !array_type.fixed_length && ((current_method != null && get_ccode_array_length(current_method)) || current_property_accessor != null))
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        result.append_array_length_cvalue(new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression(get_array_length_cname("result", dim))));
                    }
                }
            }
            else if (local.captured)
            {
                // captured variables are stored on the heap
                var block = (Block)local.parent_symbol;
                result.cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_local_cname(local));
                if (array_type != null && !array_type.fixed_length)
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        result.append_array_length_cvalue(CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_array_length_cname(get_local_cname(local), dim)));
                    }
                    if (array_type.rank == 1)
                    {
                        result.array_size_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_array_size_cname(get_local_cname(local)));
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                {
                    result.delegate_target_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_delegate_target_cname(get_local_cname(local)));
                    if (delegate_type.is_disposable())
                    {
                        result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_delegate_target_destroy_notify_cname(get_local_cname(local)));
                    }
                }
            }
            else
            {
                result.cvalue = get_local_cexpression(local);
                if (array_type != null && !array_type.fixed_length)
                {
                    for (int dim = 1; dim <= array_type.rank; dim++)
                    {
                        result.append_array_length_cvalue(get_variable_cexpression(get_array_length_cname(get_local_cname(local), dim)));
                    }
                    if (array_type.rank == 1)
                    {
                        result.array_size_cvalue = get_variable_cexpression(get_array_size_cname(get_local_cname(local)));
                    }
                }
                else if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                {
                    if (is_in_coroutine())
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_delegate_target_cname(get_local_cname(local)));
                        if (local.variable_type.value_owned)
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_delegate_target_destroy_notify_cname(get_local_cname(local)));
                        }
                    }
                    else
                    {
                        result.delegate_target_cvalue = new CCodeIdentifier(get_delegate_target_cname(get_local_cname(local)));
                        if (local.variable_type.value_owned)
                        {
                            result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(get_local_cname(local)));
                        }
                    }
                }
            }

            return(result);
        }
Exemplo n.º 4
0
        /* Returns access values to the given parameter */
        public override TargetValue get_parameter_cvalue(Parameter param)
        {
            var result = new GLibValue(param.variable_type.copy());

            result.lvalue = true;
            result.array_null_terminated = get_ccode_array_null_terminated(param);
            if (get_ccode_array_length_expr(param) != null)
            {
                result.array_length_cexpr = new CCodeConstant(get_ccode_array_length_expr(param));
            }
            result.ctype = get_ccode_type(param);

            var array_type    = result.value_type as ArrayType;
            var delegate_type = result.value_type as DelegateType;

            bool is_unowned_delegate = delegate_type != null && !param.variable_type.value_owned;

            if ((param.captured || is_in_coroutine()) && !is_unowned_delegate)
            {
                result.value_type.value_owned = true;
            }

            if (param.name == "this")
            {
                if (is_in_coroutine())
                {
                    // use closure
                    result.cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), "self");
                }
                else
                {
                    var st = result.value_type.data_type as Struct;
                    if (st != null && !st.is_simple_type())
                    {
                        result.cvalue = new CCodeIdentifier("(*self)");
                    }
                    else
                    {
                        result.cvalue = new CCodeIdentifier("self");
                    }
                }
            }
            else
            {
                string name = param.name;

                if (param.captured)
                {
                    // captured variables are stored on the heap
                    var block = param.parent_symbol as Block;
                    if (block == null)
                    {
                        block = ((Method)param.parent_symbol).body;
                    }
                    result.cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_variable_cname(param.name));
                    if (array_type != null && get_ccode_array_length(param))
                    {
                        for (int dim = 1; dim <= array_type.rank; dim++)
                        {
                            result.append_array_length_cvalue(CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_parameter_array_length_cname(param, dim)));
                        }
                    }
                    else if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_ccode_delegate_target_name(param));
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(get_variable_cexpression("_data%d_".printf(get_block_id(block))), get_delegate_target_destroy_notify_cname(get_variable_cname(param.name)));
                        }
                    }
                }
                else if (is_in_coroutine())
                {
                    // use closure
                    result.cvalue = get_variable_cexpression(param.name);
                    if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                    {
                        result.delegate_target_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_ccode_delegate_target_name(param));
                        if (delegate_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = CCodeMemberAccess.pointer(new CCodeIdentifier("_data_"), get_delegate_target_destroy_notify_cname(get_variable_cname(param.name)));
                        }
                    }
                }
                else
                {
                    var type_as_struct = result.value_type.data_type as Struct;

                    if (param.direction == ParameterDirection.OUT)
                    {
                        name = "_vala_%s".printf(name);
                    }

                    if (param.direction == ParameterDirection.REF ||
                        (param.direction == ParameterDirection.IN && type_as_struct != null && !type_as_struct.is_simple_type() && !result.value_type.nullable))
                    {
                        result.cvalue = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier(get_variable_cname(name)));
                    }
                    else
                    {
                        // Property setters of non simple structs shall replace all occurrences
                        // of the "value" formal parameter with a dereferencing version of that
                        // parameter.
                        if (current_property_accessor != null &&
                            current_property_accessor.writable &&
                            current_property_accessor.value_parameter == param &&
                            current_property_accessor.prop.property_type.is_real_struct_type() &&
                            !current_property_accessor.prop.property_type.nullable)
                        {
                            result.cvalue = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier("value"));
                        }
                        else
                        {
                            result.cvalue = get_variable_cexpression(name);
                        }
                    }
                    if (delegate_type != null && delegate_type.delegate_symbol.has_target)
                    {
                        var target_cname = get_ccode_delegate_target_name(param);
                        if (param.direction == ParameterDirection.OUT)
                        {
                            target_cname = "_vala_%s".printf(target_cname);
                        }
                        CCodeExpression target_expr = new CCodeIdentifier(target_cname);
                        CCodeExpression delegate_target_destroy_notify = new CCodeIdentifier(get_delegate_target_destroy_notify_cname(get_variable_cname(name)));
                        if (param.direction == ParameterDirection.REF)
                        {
                            // accessing argument of ref param
                            target_expr = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, target_expr);
                            delegate_target_destroy_notify = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, delegate_target_destroy_notify);
                        }
                        result.delegate_target_cvalue = target_expr;
                        if (result.value_type.is_disposable())
                        {
                            result.delegate_target_destroy_notify_cvalue = delegate_target_destroy_notify;
                        }
                    }
                }
                if (!param.captured && array_type != null)
                {
                    if (get_ccode_array_length(param) && !get_ccode_array_null_terminated(param))
                    {
                        for (int dim = 1; dim <= array_type.rank; dim++)
                        {
                            CCodeExpression length_expr = get_variable_cexpression(get_parameter_array_length_cname(param, dim));
                            if (param.direction == ParameterDirection.OUT)
                            {
                                length_expr = get_variable_cexpression(get_array_length_cname(get_variable_cname(name), dim));
                            }
                            else if (param.direction == ParameterDirection.REF)
                            {
                                // accessing argument of ref param
                                length_expr = new CCodeUnaryExpression(CCodeUnaryOperator.POINTER_INDIRECTION, length_expr);
                            }
                            result.append_array_length_cvalue(length_expr);
                        }
                    }
                }
            }

            return(result);
        }
Exemplo n.º 5
0
        CCodeFunction generate_free_function(Method m)
        {
            var dataname = Symbol.lower_case_to_camel_case(get_ccode_name(m)) + "Data";

            var freefunc = new CCodeFunction(get_ccode_real_name(m) + "_data_free", "void");

            freefunc.modifiers = CCodeModifiers.STATIC;
            freefunc.add_parameter(new CCodeParameter("_data", "gpointer"));

            push_context(new EmitContext(m));
            push_function(freefunc);

            ccode.add_declaration(dataname + "*", new CCodeVariableDeclarator("_data_", new CCodeIdentifier("_data")));

            foreach (Parameter param in m.get_parameters())
            {
                if (!param.captured && param.direction != ParameterDirection.OUT)
                {
                    var param_type = param.variable_type.copy();
                    if (!param_type.value_owned)
                    {
                        param_type.value_owned = !no_implicit_copy(param_type);
                    }

                    if (requires_destroy(param_type))
                    {
                        ccode.add_expression(destroy_parameter(param));
                    }
                }
            }

            if (requires_destroy(m.return_type))
            {
                if (get_ccode_array_length(m) || !(m.return_type is ArrayType))
                {
                    /* this is very evil. */
                    var v = new LocalVariable(m.return_type, ".result");
                    ccode.add_expression(destroy_local(v));
                }
                else
                {
                    var v = new GLibValue(m.return_type, new CCodeIdentifier("_data_->result"), true);
                    v.array_null_terminated = get_ccode_array_null_terminated(m);
                    ccode.add_expression(destroy_value(v));
                }
            }

            if (m.binding == MemberBinding.INSTANCE)
            {
                var this_type = m.this_parameter.variable_type.copy();
                this_type.value_owned = true;

                if (requires_destroy(this_type))
                {
                    ccode.add_expression(destroy_parameter(m.this_parameter));
                }
            }

            var freecall = new CCodeFunctionCall(new CCodeIdentifier("g_slice_free"));

            freecall.add_argument(new CCodeIdentifier(dataname));
            freecall.add_argument(new CCodeIdentifier("_data_"));
            ccode.add_expression(freecall);

            pop_context();

            cfile.add_function_declaration(freefunc);
            cfile.add_function(freefunc);

            return(freefunc);
        }