Exemplo n.º 1
0
        public override string get_dynamic_signal_connect_after_wrapper_name(DynamicSignal sig)
        {
            if (sig.dynamic_type.data_type == null ||
                !sig.dynamic_type.data_type.is_subtype_of(gobject_type))
            {
                return(base.get_dynamic_signal_connect_wrapper_name(sig));
            }

            string connect_wrapper_name = "_%sconnect_after".printf(get_dynamic_signal_cname(sig));
            var    func = new CCodeFunction(connect_wrapper_name, "gulong");

            func.add_parameter(new CCodeParameter("obj", "gpointer"));
            func.add_parameter(new CCodeParameter("signal_name", "const char *"));
            func.add_parameter(new CCodeParameter("handler", "GCallback"));
            func.add_parameter(new CCodeParameter("data", "gpointer"));
            push_function(func);
            generate_gobject_connect_wrapper(sig, true);
            pop_function();

            // append to C source file
            cfile.add_function_declaration(func);
            cfile.add_function(func);

            return(connect_wrapper_name);
        }
Exemplo n.º 2
0
        void generate_gobject_connect_wrapper(DynamicSignal sig, bool after)
        {
            var m = (Method)sig.handler.symbol_reference;

            sig.accept(this);

            string connect_func = "g_signal_connect_object";

            if (m.binding != MemberBinding.INSTANCE)
            {
                if (!after)
                {
                    connect_func = "g_signal_connect";
                }
                else
                {
                    connect_func = "g_signal_connect_after";
                }
            }

            var call = new CCodeFunctionCall(new CCodeIdentifier(connect_func));

            call.add_argument(new CCodeIdentifier("obj"));
            call.add_argument(new CCodeIdentifier("signal_name"));
            call.add_argument(new CCodeIdentifier("handler"));
            call.add_argument(new CCodeIdentifier("data"));

            if (m.binding == MemberBinding.INSTANCE)
            {
                if (!after)
                {
                    call.add_argument(new CCodeConstant("0"));
                }
                else
                {
                    call.add_argument(new CCodeConstant("G_CONNECT_AFTER"));
                }
            }

            ccode.add_return(call);
        }
Exemplo n.º 3
0
 public override string get_dynamic_signal_cname(DynamicSignal node)
 {
     return("dynamic_%s%d_".printf(node.name, signal_wrapper_id++));
 }
Exemplo n.º 4
0
        public override bool check(CodeContext context)
        {
            if (is_checked)
            {
                return(!error);
            }

            is_checked = true;

            if (inner != null)
            {
                inner.check(context);
            }

            foreach (DataType type_arg in type_argument_list)
            {
                type_arg.check(context);
            }

            Symbol    base_symbol    = null;
            Parameter this_parameter = null;
            bool      may_access_instance_members = false;
            bool      may_access_klass_members    = false;

            symbol_reference = null;

            if (qualified)
            {
                base_symbol      = context.analyzer.root_symbol;
                symbol_reference = context.analyzer.root_symbol.scope.lookup(member_name);
            }
            else if (inner == null)
            {
                if (member_name == "this")
                {
                    if (!context.analyzer.is_in_instance_method())
                    {
                        error = true;
                        Report.error(source_reference, "This access invalid outside of instance methods");
                        return(false);
                    }
                }

                base_symbol = context.analyzer.current_symbol;

                // track whether method has been found to make sure that access
                // to instance member is denied from within static lambda expressions
                bool method_found = false;

                var sym = context.analyzer.current_symbol;
                while (sym != null && symbol_reference == null)
                {
                    if (!method_found)
                    {
                        if (sym is CreationMethod)
                        {
                            var cm = (CreationMethod)sym;
                            this_parameter = cm.this_parameter;
                            may_access_instance_members = true;
                            may_access_klass_members    = true;
                            method_found = true;
                        }
                        else if (sym is Property)
                        {
                            var prop = (Property)sym;
                            this_parameter = prop.this_parameter;
                            may_access_instance_members = (prop.binding == MemberBinding.INSTANCE);
                            may_access_klass_members    = (prop.binding != MemberBinding.STATIC);
                            method_found = true;
                        }
                        else if (sym is Constructor)
                        {
                            var c = (Constructor)sym;
                            this_parameter = c.this_parameter;
                            may_access_instance_members = (c.binding == MemberBinding.INSTANCE);
                            may_access_klass_members    = true;
                            method_found = true;
                        }
                        else if (sym is Destructor)
                        {
                            var d = (Destructor)sym;
                            this_parameter = d.this_parameter;
                            may_access_instance_members = (d.binding == MemberBinding.INSTANCE);
                            may_access_klass_members    = true;
                            method_found = true;
                        }
                        else if (sym is Method)
                        {
                            var m = (Method)sym;
                            this_parameter = m.this_parameter;
                            may_access_instance_members = (m.binding == MemberBinding.INSTANCE);
                            may_access_klass_members    = (m.binding != MemberBinding.STATIC);
                            method_found = true;
                        }
                    }

                    symbol_reference = SemanticAnalyzer.symbol_lookup_inherited(sym, member_name);

                    if (symbol_reference == null && sym is TypeSymbol && may_access_instance_members)
                    {
                        // used for generated to_string methods in enums
                        symbol_reference = this_parameter.variable_type.get_member(member_name);

                        if (symbol_reference != null && is_instance_symbol(symbol_reference))
                        {
                            // implicit this
                            inner                        = new MemberAccess(null, "this", source_reference);
                            inner.value_type             = this_parameter.variable_type.copy();
                            inner.value_type.value_owned = false;
                            inner.symbol_reference       = this_parameter;

                            symbol_reference = inner.value_type.get_member(member_name);
                        }
                    }

                    if (symbol_reference == null)
                    {
                        if (sym is TypeSymbol)
                        {
                            // do not allow instance access to outer classes
                            this_parameter = null;
                            may_access_instance_members = false;
                            may_access_klass_members    = false;
                        }
                    }

                    sym = sym.parent_symbol;
                }

                if (symbol_reference == null && source_reference != null)
                {
                    foreach (UsingDirective ns in source_reference.using_directives)
                    {
                        var local_sym = ns.namespace_symbol.scope.lookup(member_name);
                        if (local_sym != null)
                        {
                            if (symbol_reference != null && symbol_reference != local_sym)
                            {
                                error = true;
                                Report.error(source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf(member_name, symbol_reference.get_full_name(), local_sym.get_full_name()));
                                return(false);
                            }
                            symbol_reference = local_sym;
                        }
                    }
                }
            }
            else
            {
                if (inner.error)
                {
                    /* if there was an error in the inner expression, skip this check */
                    error = true;
                    return(false);
                }

                if (inner.value_type is PointerType)
                {
                    var pointer_type = inner.value_type as PointerType;
                    if (pointer_type != null && pointer_type.base_type is ValaValueType)
                    {
                        // transform foo->bar to (*foo).bar
                        inner = new PointerIndirection(inner, source_reference);
                        inner.check(context);
                        pointer_member_access = false;
                    }
                }

                if (inner is MemberAccess)
                {
                    var ma = (MemberAccess)inner;
                    if (ma.prototype_access)
                    {
                        error = true;
                        Report.error(source_reference, "Access to instance member `%s' denied".printf(inner.symbol_reference.get_full_name()));
                        return(false);
                    }
                }

                if (inner is MemberAccess || inner is BaseAccess)
                {
                    base_symbol = inner.symbol_reference;

                    if (symbol_reference == null && (base_symbol is Namespace || base_symbol is TypeSymbol))
                    {
                        symbol_reference = base_symbol.scope.lookup(member_name);
                        if (inner is BaseAccess)
                        {
                            // inner expression is base access
                            // access to instance members of the base type possible
                            may_access_instance_members = true;
                            may_access_klass_members    = true;
                        }
                    }
                }

                if (symbol_reference == null && inner.value_type != null)
                {
                    if (pointer_member_access)
                    {
                        symbol_reference = inner.value_type.get_pointer_member(member_name);
                    }
                    else
                    {
                        if (inner.value_type.data_type != null)
                        {
                            base_symbol = inner.value_type.data_type;
                        }
                        symbol_reference = inner.value_type.get_member(member_name);
                    }
                    if (symbol_reference != null)
                    {
                        // inner expression is variable, field, or parameter
                        // access to instance members of the corresponding type possible
                        may_access_instance_members = true;
                        may_access_klass_members    = true;
                    }
                }

                if (symbol_reference == null && inner.value_type != null && inner.value_type.is_dynamic)
                {
                    // allow late bound members for dynamic types
                    var dynamic_object_type = (ObjectType)inner.value_type;
                    if (parent_node is MethodCall)
                    {
                        var invoc = (MethodCall)parent_node;
                        if (invoc.call == this)
                        {
                            // dynamic method
                            DataType ret_type;
                            if (invoc.target_type != null)
                            {
                                ret_type             = invoc.target_type.copy();
                                ret_type.value_owned = true;
                            }
                            else if (invoc.parent_node is ExpressionStatement)
                            {
                                ret_type = new VoidType();
                            }
                            else
                            {
                                // expect dynamic object of the same type
                                ret_type = inner.value_type.copy();
                            }
                            var m = new DynamicMethod(inner.value_type, member_name, ret_type, source_reference);
                            m.invocation = invoc;
                            var err = new ErrorType(null, null);
                            err.dynamic_error = true;
                            m.add_error_type(err);
                            m.access = SymbolAccessibility.PUBLIC;
                            m.add_parameter(Parameter.with_ellipsis());
                            dynamic_object_type.type_symbol.scope.add(null, m);
                            symbol_reference = m;
                        }
                    }
                    else if (parent_node is Assignment)
                    {
                        var a = (Assignment)parent_node;
                        if (a.left == this &&
                            (a.Operator == AssignmentOperator.ADD ||
                             a.Operator == AssignmentOperator.SUB))
                        {
                            // dynamic signal
                            var s = new DynamicSignal(inner.value_type, member_name, new VoidType(), source_reference);
                            s.handler = a.right;
                            s.access  = SymbolAccessibility.PUBLIC;
                            dynamic_object_type.type_symbol.scope.add(null, s);
                            symbol_reference = s;
                        }
                        else if (a.left == this)
                        {
                            // dynamic property assignment
                            var prop = new DynamicProperty(inner.value_type, member_name, source_reference);
                            prop.access       = SymbolAccessibility.PUBLIC;
                            prop.set_accessor = new PropertyAccessor(false, true, false, null, null, prop.source_reference);
                            prop.owner        = inner.value_type.data_type.scope;
                            dynamic_object_type.type_symbol.scope.add(null, prop);
                            symbol_reference = prop;
                        }
                    }
                    else if (parent_node is MemberAccess && inner is MemberAccess && parent_node.parent_node is MethodCall)
                    {
                        var ma = (MemberAccess)parent_node;
                        if (ma.member_name == "connect" || ma.member_name == "connect_after")
                        {
                            // dynamic signal
                            var s     = new DynamicSignal(inner.value_type, member_name, new VoidType(), source_reference);
                            var mcall = (MethodCall)parent_node.parent_node;
                            // the first argument is the handler
                            if (mcall.get_argument_list().Count > 0)
                            {
                                s.handler = mcall.get_argument_list()[0];
                            }
                            s.access = SymbolAccessibility.PUBLIC;
                            dynamic_object_type.type_symbol.scope.add(null, s);
                            symbol_reference = s;
                        }
                    }
                    if (symbol_reference == null)
                    {
                        // dynamic property read access
                        var prop = new DynamicProperty(inner.value_type, member_name, source_reference);
                        if (target_type != null)
                        {
                            prop.property_type = target_type;
                        }
                        else
                        {
                            // expect dynamic object of the same type
                            prop.property_type = inner.value_type.copy();
                        }
                        prop.access       = SymbolAccessibility.PUBLIC;
                        prop.get_accessor = new PropertyAccessor(true, false, false, prop.property_type.copy(), null, prop.source_reference);
                        prop.owner        = inner.value_type.data_type.scope;
                        dynamic_object_type.type_symbol.scope.add(null, prop);
                        symbol_reference = prop;
                    }
                    if (symbol_reference != null)
                    {
                        may_access_instance_members = true;
                        may_access_klass_members    = true;
                    }
                }
            }

            if (symbol_reference == null)
            {
                error = true;

                string base_type_name = "(null)";
                if (inner != null && inner.value_type != null)
                {
                    base_type_name = inner.value_type.ToString();
                }
                else if (base_symbol != null)
                {
                    base_type_name = base_symbol.get_full_name();
                }

                Report.error(source_reference, "The name `%s' does not exist in the context of `%s'".printf(member_name, base_type_name));
                return(false);
            }

            var  member   = symbol_reference;
            var  access   = SymbolAccessibility.PUBLIC;
            bool instance = false;
            bool klass    = false;
            bool generics = false;

            if (!member.check(context))
            {
                return(false);
            }

            if (member is LocalVariable)
            {
                var local = (LocalVariable)member;
                var block = local.parent_symbol as Block;
                if (block != null && context.analyzer.find_parent_method_or_property_accessor(block) != context.analyzer.current_method_or_property_accessor)
                {
                    // mark all methods between current method and the captured
                    // block as closures (to support nested closures)
                    Symbol sym = context.analyzer.current_method_or_property_accessor;
                    while (sym != block)
                    {
                        var method = sym as Method;
                        if (method != null)
                        {
                            method.closure = true;
                            // consider captured variables as used
                            // as we require captured variables to be initialized
                            method.add_captured_variable(local);
                        }
                        sym = sym.parent_symbol;
                    }

                    local.captured = true;
                    block.captured = true;
                }
            }
            else if (member is Parameter)
            {
                var param = (Parameter)member;
                var m     = param.parent_symbol as Method;
                if (m != null && m != context.analyzer.current_method_or_property_accessor && param != m.this_parameter)
                {
                    // mark all methods between current method and the captured
                    // parameter as closures (to support nested closures)
                    Symbol sym = context.analyzer.current_method_or_property_accessor;
                    while (sym != m)
                    {
                        var method = sym as Method;
                        if (method != null)
                        {
                            method.closure = true;
                        }
                        sym = sym.parent_symbol;
                    }

                    param.captured  = true;
                    m.body.captured = true;

                    if (param.direction != ParameterDirection.IN)
                    {
                        error = true;
                        Report.error(source_reference, "Cannot capture reference or output parameter `%s'".printf(param.get_full_name()));
                    }
                }
                else
                {
                    var acc = param.parent_symbol.parent_symbol as PropertyAccessor;
                    if (acc != null && acc != context.analyzer.current_method_or_property_accessor && param != acc.prop.this_parameter)
                    {
                        // mark all methods between current method and the captured
                        // parameter as closures (to support nested closures)
                        Symbol sym = context.analyzer.current_method_or_property_accessor;
                        while (sym != m)
                        {
                            var method = sym as Method;
                            if (method != null)
                            {
                                method.closure = true;
                            }
                            sym = sym.parent_symbol;
                        }

                        param.captured    = true;
                        acc.body.captured = true;
                    }
                }
            }
            else if (member is Field)
            {
                var f = (Field)member;
                access   = f.access;
                instance = (f.binding == MemberBinding.INSTANCE);
                klass    = (f.binding == MemberBinding.CLASS);

                // do not allow access to fields of generic types
                // if instance type does not specify type arguments
                if (f.variable_type is GenericType)
                {
                    generics = true;
                }
            }
            else if (member is Constant)
            {
                var c = (Constant)member;
                access = c.access;

                var block = c.parent_symbol as Block;
                if (block != null && context.analyzer.find_parent_method_or_property_accessor(block) != context.analyzer.current_method_or_property_accessor)
                {
                    error = true;
                    Report.error(source_reference, "internal error: accessing local constants of outer methods is not supported yet");
                    return(false);
                }
            }
            else if (member is Method)
            {
                var m = (Method)member;
                if (m.is_async_callback)
                {
                    // ensure to use right callback method for virtual/abstract async methods
                    // and also for lambda expressions within async methods
                    var async_method = context.analyzer.current_async_method;

                    bool is_valid_access = false;
                    if (async_method != null)
                    {
                        if (m == async_method.get_callback_method())
                        {
                            is_valid_access = true;
                        }
                        else if (async_method.base_method != null && m == async_method.base_method.get_callback_method())
                        {
                            is_valid_access = true;
                        }
                        else if (async_method.base_interface_method != null && m == async_method.base_interface_method.get_callback_method())
                        {
                            is_valid_access = true;
                        }
                    }
                    if (!is_valid_access)
                    {
                        error = true;
                        Report.error(source_reference, "Access to async callback `%s' not allowed in this context".printf(m.get_full_name()));
                        return(false);
                    }

                    if (async_method != context.analyzer.current_method)
                    {
                        Symbol sym = context.analyzer.current_method;
                        while (sym != async_method)
                        {
                            var method = sym as Method;
                            if (method != null)
                            {
                                method.closure = true;
                            }
                            sym = sym.parent_symbol;
                        }
                        async_method.body.captured = true;
                    }

                    m = async_method.get_callback_method();
                    symbol_reference = m;
                    member           = symbol_reference;
                }
                else if (m.base_method != null)
                {
                    // refer to base method to inherit default arguments
                    m = m.base_method;

                    if (m.signal_reference != null)
                    {
                        // method is class/default handler for a signal
                        // let signal deal with member access
                        symbol_reference = m.signal_reference;
                    }
                    else
                    {
                        symbol_reference = m;
                    }

                    member = symbol_reference;
                }
                else if (m.base_interface_method != null)
                {
                    // refer to base method to inherit default arguments
                    m = m.base_interface_method;

                    if (m.signal_reference != null)
                    {
                        // method is class/default handler for a signal
                        // let signal deal with member access
                        symbol_reference = m.signal_reference;
                    }
                    else
                    {
                        symbol_reference = m;
                    }

                    member = symbol_reference;
                }
                access = m.access;
                if (!(m is CreationMethod))
                {
                    instance = (m.binding == MemberBinding.INSTANCE);
                }
                klass = (m.binding == MemberBinding.CLASS);

                // do not allow access to methods using generic type parameters
                // if instance type does not specify type arguments
                foreach (var param in m.get_parameters())
                {
                    var _generic_type = param.variable_type as GenericType;
                    if (_generic_type != null && _generic_type.type_parameter.parent_symbol is TypeSymbol)
                    {
                        generics = true;
                        break;
                    }
                }
                var generic_type = m.return_type as GenericType;
                if (generic_type != null && generic_type.type_parameter.parent_symbol is TypeSymbol)
                {
                    generics = true;
                }
            }
            else if (member is Property)
            {
                var prop = (Property)member;
                if (!prop.check(context))
                {
                    error = true;
                    return(false);
                }
                if (prop.base_property != null)
                {
                    // refer to base property
                    prop             = prop.base_property;
                    symbol_reference = prop;
                    member           = symbol_reference;
                }
                else if (prop.base_interface_property != null)
                {
                    // refer to base property
                    prop             = prop.base_interface_property;
                    symbol_reference = prop;
                    member           = symbol_reference;
                }
                access = prop.access;
                if (lvalue)
                {
                    if (prop.set_accessor == null)
                    {
                        error = true;
                        Report.error(source_reference, "Property `%s' is read-only".printf(prop.get_full_name()));
                        return(false);
                    }
                    if (prop.access == SymbolAccessibility.PUBLIC)
                    {
                        access = prop.set_accessor.access;
                    }
                    else if (prop.access == SymbolAccessibility.PROTECTED &&
                             prop.set_accessor.access != SymbolAccessibility.PUBLIC)
                    {
                        access = prop.set_accessor.access;
                    }
                }
                else
                {
                    if (prop.get_accessor == null)
                    {
                        error = true;
                        Report.error(source_reference, "Property `%s' is write-only".printf(prop.get_full_name()));
                        return(false);
                    }
                    if (prop.access == SymbolAccessibility.PUBLIC)
                    {
                        access = prop.get_accessor.access;
                    }
                    else if (prop.access == SymbolAccessibility.PROTECTED &&
                             prop.get_accessor.access != SymbolAccessibility.PUBLIC)
                    {
                        access = prop.get_accessor.access;
                    }
                }
                instance = (prop.binding == MemberBinding.INSTANCE);

                // do not allow access to properties of generic types
                // if instance type does not specify type arguments
                if (prop.property_type is GenericType)
                {
                    generics = true;
                }
            }
            else if (member is Signal)
            {
                instance = true;
                access   = member.access;
            }

            member.used = true;
            member.version.check(source_reference);

            if (access == SymbolAccessibility.PROTECTED)
            {
                var target_type = (TypeSymbol)member.parent_symbol;

                bool in_subtype = false;
                for (Symbol this_symbol = context.analyzer.current_symbol; this_symbol != null; this_symbol = this_symbol.parent_symbol)
                {
                    if (this_symbol == target_type)
                    {
                        // required for interfaces with non-abstract methods
                        // accessing protected interface members
                        in_subtype = true;
                        break;
                    }

                    var cl = this_symbol as Class;
                    if (cl != null && cl.is_subtype_of(target_type))
                    {
                        in_subtype = true;
                        break;
                    }
                }

                if (!in_subtype)
                {
                    error = true;
                    Report.error(source_reference, "Access to protected member `%s' denied".printf(member.get_full_name()));
                    return(false);
                }
            }
            else if (access == SymbolAccessibility.PRIVATE)
            {
                var target_type = member.parent_symbol;

                bool in_target_type = false;
                for (Symbol this_symbol = context.analyzer.current_symbol; this_symbol != null; this_symbol = this_symbol.parent_symbol)
                {
                    if (target_type == this_symbol)
                    {
                        in_target_type = true;
                        break;
                    }
                }

                if (!in_target_type)
                {
                    error = true;
                    Report.error(source_reference, "Access to private member `%s' denied".printf(member.get_full_name()));
                    return(false);
                }
            }

            if (generics && inner != null)
            {
                var instance_type = inner.value_type;
                var pointer_type  = inner.value_type as PointerType;
                if (pointer_type != null)
                {
                    instance_type = pointer_type.base_type;
                }

                // instance type might be a subtype of the parent symbol of the member
                // that subtype might not be generic, so do not report an error in that case
                var object_type = instance_type as ObjectType;
                if (object_type != null && object_type.type_symbol.get_type_parameters().Count > 0 &&
                    instance_type.get_type_arguments().Count == 0)
                {
                    error = true;
                    Report.error(inner.source_reference, "missing generic type arguments");
                    return(false);
                }
            }

            if ((instance && !may_access_instance_members) ||
                (klass && !may_access_klass_members))
            {
                prototype_access = true;

                if (symbol_reference is Method)
                {
                    // also set static type for prototype access
                    // required when using instance methods as delegates in constants
                    // TODO replace by MethodPrototype
                    value_type = context.analyzer.get_value_type_for_symbol(symbol_reference, lvalue);
                }
                else if (symbol_reference is Field)
                {
                    value_type = new FieldPrototype((Field)symbol_reference);
                }
                else
                {
                    value_type = new InvalidType();
                }

                if (target_type != null)
                {
                    value_type.value_owned = target_type.value_owned;
                }
            }
            else
            {
                // implicit this access
                if (instance && inner == null)
                {
                    inner                        = new MemberAccess(null, "this", source_reference);
                    inner.value_type             = this_parameter.variable_type.copy();
                    inner.value_type.value_owned = false;
                    inner.symbol_reference       = this_parameter;
                }
                else
                {
                    check_lvalue_access();
                }

                if (!instance && !klass && !(symbol_reference is CreationMethod) && may_access_instance_members && inner != null)
                {
                    if (inner.symbol_reference is Method)
                    {
                        // do not warn when calling .begin or .end on static async method
                    }
                    else
                    {
                        Report.warning(source_reference, "Access to static member `%s' with an instance reference".printf(symbol_reference.get_full_name()));
                    }
                }

                if (context.experimental_non_null && instance && inner.value_type.nullable &&
                    !(inner.value_type is PointerType) && !(inner.value_type is GenericType) &&
                    !(inner.value_type is ArrayType))
                {
                    Report.error(source_reference, "Access to instance member `%s' from nullable reference denied".printf(symbol_reference.get_full_name()));
                }

                var m        = symbol_reference as Method;
                var inner_ma = inner as MemberAccess;
                if (m != null && m.binding == MemberBinding.STATIC && m.parent_symbol is ObjectTypeSymbol &&
                    inner != null && inner.value_type == null && inner_ma.type_argument_list.Count > 0)
                {
                    // support static methods in generic classes
                    inner.value_type = new ObjectType((ObjectTypeSymbol)m.parent_symbol);

                    foreach (var type_argument in inner_ma.type_argument_list)
                    {
                        inner.value_type.add_type_argument(type_argument);
                    }
                }

                formal_value_type = context.analyzer.get_value_type_for_symbol(symbol_reference, lvalue);
                if (inner != null && formal_value_type != null)
                {
                    value_type = formal_value_type.get_actual_type(inner.value_type, null, this);
                }
                else
                {
                    value_type = formal_value_type;
                }

                if (symbol_reference is Method)
                {
                    var method = (Method)symbol_reference;
                    if (target_type != null)
                    {
                        value_type.value_owned = target_type.value_owned;
                    }
                    if (instance && method.parent_symbol is TypeSymbol)
                    {
                        inner.target_type             = SemanticAnalyzer.get_data_type_for_symbol((TypeSymbol)method.parent_symbol);
                        inner.target_type.value_owned = method.this_parameter.variable_type.value_owned;
                    }
                }
                else if (symbol_reference is Property)
                {
                    var prop = (Property)symbol_reference;
                    if (instance && prop.parent_symbol != null)
                    {
                        inner.target_type = SemanticAnalyzer.get_data_type_for_symbol((TypeSymbol)prop.parent_symbol);
                    }
                }
                else if ((symbol_reference is Field ||
                          symbol_reference is Signal) &&
                         instance && symbol_reference.parent_symbol != null)
                {
                    var parent_type = SemanticAnalyzer.get_data_type_for_symbol((TypeSymbol)symbol_reference.parent_symbol);
                    inner.target_type = parent_type.get_actual_type(inner.value_type, null, this);
                }
            }

            return(!error);
        }