]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Improve handling of generic values, fixes bug 562460
authorJürg Billeter <j@bitron.ch>
Fri, 28 Nov 2008 11:34:22 +0000 (11:34 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Fri, 28 Nov 2008 11:34:22 +0000 (11:34 +0000)
2008-11-28  Jürg Billeter  <j@bitron.ch>

* vala/valadatatype.vala:
* vala/valaexpression.vala:
* vala/valaintegertype.vala:
* vala/valamemberaccess.vala:
* vala/valamethodcall.vala:
* vala/valasemanticanalyzer.vala:
* vala/valavaluetype.vala:
* gobject/valaccodebasemodule.vala:
* gobject/valaccodecontrolflowmodule.vala:

Improve handling of generic values, fixes bug 562460

svn path=/trunk/; revision=2067

ChangeLog
gobject/valaccodebasemodule.vala
gobject/valaccodecontrolflowmodule.vala
vala/valadatatype.vala
vala/valaexpression.vala
vala/valaintegertype.vala
vala/valamemberaccess.vala
vala/valamethodcall.vala
vala/valasemanticanalyzer.vala
vala/valavaluetype.vala

index db6ca5801e2db419d3c5fd8d31e3fe6b849188f5..6f2bff8cc7ac420f2f9d145f8d2c95b28d9fcb5b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-11-28  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valadatatype.vala:
+       * vala/valaexpression.vala:
+       * vala/valaintegertype.vala:
+       * vala/valamemberaccess.vala:
+       * vala/valamethodcall.vala:
+       * vala/valasemanticanalyzer.vala:
+       * vala/valavaluetype.vala:
+       * gobject/valaccodebasemodule.vala:
+       * gobject/valaccodecontrolflowmodule.vala:
+
+       Improve handling of generic values, fixes bug 562460
+
 2008-11-28  Jürg Billeter  <j@bitron.ch>
 
        * vala/valabinaryexpression.vala:
index 039f369dd8819ea9ac394a6a73000660e213f580..99a868114cf95710053be3f61d15646cf80fc0d0 100644 (file)
@@ -2092,8 +2092,22 @@ public class Vala.CCodeBaseModule : CCodeModule {
 
        public override void visit_expression (Expression expr) {
                if (expr.ccodenode != null && !expr.lvalue) {
+                       if (expr.formal_value_type is GenericType && !(expr.value_type is GenericType)) {
+                               if (expr.formal_value_type.type_parameter.parent_symbol != garray_type) {
+                                       // GArray doesn't use pointer-based generics
+                                       expr.ccodenode = convert_from_generic_pointer ((CCodeExpression) expr.ccodenode, expr.value_type);
+                               }
+                       }
+
                        // memory management, implicit casts, and boxing/unboxing
                        expr.ccodenode = transform_expression ((CCodeExpression) expr.ccodenode, expr.value_type, expr.target_type, expr);
+
+                       if (expr.formal_target_type is GenericType && !(expr.target_type is GenericType)) {
+                               if (expr.formal_target_type.type_parameter.parent_symbol != garray_type) {
+                                       // GArray doesn't use pointer-based generics
+                                       expr.ccodenode = convert_to_generic_pointer ((CCodeExpression) expr.ccodenode, expr.target_type);
+                               }
+                       }
                }
        }
 
@@ -3005,12 +3019,6 @@ public class Vala.CCodeBaseModule : CCodeModule {
                        cexpr = get_implicit_cast_expression (cexpr, expression_type, target_type, expr);
                }
 
-               if (expression_type.is_type_argument) {
-                       cexpr = convert_from_generic_pointer (cexpr, target_type);
-               } else if (target_type.is_type_argument) {
-                       cexpr = convert_to_generic_pointer (cexpr, expression_type);
-               }
-
                if (target_type.value_owned && (!expression_type.value_owned || boxing || unboxing)) {
                        // need to copy value
                        if (requires_copy (target_type) && !(expression_type is NullType)) {
index 340b2584e7d33bf07cd79c6e664f3184eb67bb2e..309c508a596decdd37529b62e1082d19768e13a9 100644 (file)
@@ -429,7 +429,7 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
 
                        var element_data_type = collection_type.get_type_arguments ().get (0).copy ();
                        element_data_type.value_owned = false;
-                       element_data_type.is_type_argument = true;
+                       element_expr = convert_from_generic_pointer (element_expr, element_data_type);
                        element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference);
 
                        var cfrag = new CCodeFragment ();
@@ -472,6 +472,7 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
 
                        var element_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, (GenericType) get_method.return_type, stmt);
 
+                       element_expr = convert_from_generic_pointer (element_expr, element_type);
                        element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
 
                        var cfrag = new CCodeFragment ();
index c0d1878256184072ed8a62d655fa23e1c9c43119..1b9b2efdb9e0e537e10e4acc8537e70e8e264135 100644 (file)
@@ -39,11 +39,6 @@ public abstract class Vala.DataType : CodeNode {
         */
        public bool nullable { get; set; }
 
-       /**
-        * Specifies that this type is a generic type argument.
-        */
-       public bool is_type_argument { get; set; }
-
        /**
         * The referred data type.
         */
@@ -481,4 +476,26 @@ public abstract class Vala.DataType : CodeNode {
                }
                return false;
        }
+
+       public DataType get_actual_type (DataType? derived_instance_type, CodeNode node_reference) {
+               if (derived_instance_type == null) {
+                       return this;
+               }
+
+               DataType result = this;
+
+               if (result is GenericType) {
+                       result = SemanticAnalyzer.get_actual_type (derived_instance_type, (GenericType) result, node_reference);
+               }
+
+               if (result.type_argument_list != null) {
+                       // recursely get actual types for type arguments
+                       result = result.copy ();
+                       for (int i = 0; i < result.type_argument_list.size; i++) {
+                               result.type_argument_list[i] = result.type_argument_list[i].get_actual_type (derived_instance_type, node_reference);
+                       }
+               }
+
+               return result;
+       }
 }
index 95db85a5c52fb502b9f368e7360d30340bc3dc82..79ca8b13c61f8b0c828df6b2193c9fb2b027c6e4 100644 (file)
@@ -33,14 +33,18 @@ public abstract class Vala.Expression : CodeNode {
         * The semantic analyzer computes this value.
         */
        public DataType value_type { get; set; }
-       
+
+       public DataType? formal_value_type { get; set; }
+
        /*
         * The static type this expression is expected to have.
         *
         * The semantic analyzer computes this value, lambda expressions use it.
         */
        public DataType target_type { get; set; }
-       
+
+       public DataType? formal_target_type { get; set; }
+
        /**
         * The symbol this expression refers to.
         */
index ac89913277bc8075c55b8a4a4d05cdaa489c28c6..88eee0390972cde781b6f3a5702fc6153d9c5e75 100644 (file)
@@ -37,9 +37,7 @@ public class Vala.IntegerType : ValueType {
        }
 
        public override DataType copy () {
-               var type = new IntegerType (type_symbol, literal_value, literal_type_name);
-               type.is_type_argument = is_type_argument;
-               return type;
+               return new IntegerType (type_symbol, literal_value, literal_type_name);
        }
 
        public override bool compatible (DataType target_type) {
index c5c9cce66c64b15f78a0dfd8b5bbbfc62e36fbd9..031d66f6f383fafc3ddb77a2726b6b73cafd342a 100644 (file)
@@ -487,16 +487,11 @@ public class Vala.MemberAccess : Expression {
                                inner.symbol_reference = this_parameter;
                        }
 
-                       value_type = analyzer.get_value_type_for_symbol (symbol_reference, lvalue);
-
-                       // resolve generic return values
-                       if (value_type is GenericType) {
-                               if (inner != null) {
-                                       value_type = analyzer.get_actual_type (inner.value_type, (GenericType) value_type, this);
-                                       if (value_type == null) {
-                                               return false;
-                                       }
-                               }
+                       formal_value_type = 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, this);
+                       } else {
+                               value_type = formal_value_type;
                        }
 
                        if (symbol_reference is Method) {
index 4e2f92332c40cd763a1138ff7a9e228008af3d4e..984318923e8908ef31ad27f1631d3212236d2f1f 100644 (file)
@@ -134,6 +134,9 @@ public class Vala.MethodCall : Expression {
                        return false;
                }
 
+               // type of target object
+               DataType target_object_type = null;
+
                if (call is MemberAccess) {
                        var ma = (MemberAccess) call;
                        if (ma.prototype_access) {
@@ -141,6 +144,10 @@ public class Vala.MethodCall : Expression {
                                Report.error (source_reference, "Access to instance member `%s' denied".printf (call.symbol_reference.get_full_name ()));
                                return false;
                        }
+
+                       if (ma.inner != null) {
+                               target_object_type = ma.inner.value_type;
+                       }
                }
 
                var mtype = call.value_type;
@@ -220,16 +227,8 @@ public class Vala.MethodCall : Expression {
                                Expression arg = arg_it.get ();
 
                                /* store expected type for callback parameters */
-                               arg.target_type = param.parameter_type;
-
-                               // resolve generic type parameters
-                               var ma = call as MemberAccess;
-                               if (arg.target_type is GenericType) {
-                                       if (ma != null && ma.inner != null) {
-                                               arg.target_type = analyzer.get_actual_type (ma.inner.value_type, (GenericType) arg.target_type, arg);
-                                               assert (arg.target_type != null);
-                                       }
-                               }
+                               arg.formal_target_type = param.parameter_type;
+                               arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, this);
 
                                last_arg = arg;
                        }
@@ -373,9 +372,7 @@ public class Vala.MethodCall : Expression {
                        arg.check (analyzer);
                }
 
-               DataType ret_type;
-
-               ret_type = mtype.get_return_type ();
+               DataType ret_type = mtype.get_return_type ();
                params = mtype.get_parameters ();
 
                if (ret_type is VoidType) {
@@ -391,29 +388,8 @@ public class Vala.MethodCall : Expression {
                        }
                }
 
-               // resolve generic return values
-               var ma = call as MemberAccess;
-               if (ret_type is GenericType) {
-                       if (ma != null && ma.inner != null) {
-                               ret_type = analyzer.get_actual_type (ma.inner.value_type, (GenericType) ret_type, this);
-                               if (ret_type == null) {
-                                       return false;
-                               }
-                       }
-               }
-               Gee.List<DataType> resolved_type_args = new ArrayList<DataType> ();
-               foreach (DataType type_arg in ret_type.get_type_arguments ()) {
-                       if (type_arg is GenericType && ma != null && ma.inner != null) {
-                               resolved_type_args.add (analyzer.get_actual_type (ma.inner.value_type, (GenericType) type_arg, this));
-                       } else {
-                               resolved_type_args.add (type_arg);
-                       }
-               }
-               ret_type = ret_type.copy ();
-               ret_type.remove_all_type_arguments ();
-               foreach (DataType resolved_type_arg in resolved_type_args) {
-                       ret_type.add_type_argument (resolved_type_arg);
-               }
+               formal_value_type = ret_type;
+               value_type = formal_value_type.get_actual_type (target_object_type, this);
 
                if (mtype is MethodType) {
                        var m = ((MethodType) mtype).method_symbol;
@@ -426,8 +402,6 @@ public class Vala.MethodCall : Expression {
                        }
                }
 
-               value_type = ret_type;
-
                analyzer.check_arguments (this, mtype, params, get_argument_list ());
 
                return !error;
index f23448b4592562b578991421435d1221ced3f51a..4b6b7b8e9f56edba43db46193d2d314341c20d04 100644 (file)
@@ -569,10 +569,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        return generic_type;
                }
                actual_type = actual_type.copy ();
-               if (!(derived_instance_type.data_type != null && derived_instance_type.data_type.get_full_name () == "GLib.Array")) {
-                       // GArray doesn't use pointer-based generics
-                       actual_type.is_type_argument = true;
-               }
                actual_type.value_owned = actual_type.value_owned && generic_type.value_owned;
                return actual_type;
        }
index 08df08205090261917155e5e0a844546e20b4ef0..585337913a730fc9eb6e31047e569769548eefa6 100644 (file)
@@ -43,7 +43,6 @@ public class Vala.ValueType : DataType {
                result.nullable = nullable;
                result.is_dynamic = is_dynamic;
                result.floating_reference = floating_reference;
-               result.is_type_argument = is_type_argument;
                
                foreach (DataType arg in get_type_arguments ()) {
                        result.add_type_argument (arg.copy ());