]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
WIP Handle extended syntax
authorRico Tzschichholz <ricotz@ubuntu.com>
Thu, 27 Apr 2023 21:37:13 +0000 (23:37 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 30 Jan 2024 14:19:43 +0000 (15:19 +0100)
vala/valacodewriter.vala
vala/valadatatype.vala
vala/valagenerictype.vala
vala/valamethodcall.vala
vala/valaparser.vala
vala/valatypeparameter.vala

index 7a497b7b483b12ebba2b8e79066a62a29d69c9d2..34c81f14f4abf54aadccf9142c530cd98d7f7a32 100644 (file)
@@ -1793,16 +1793,14 @@ public class Vala.CodeWriter : CodeVisitor {
        void write_type_parameter_constraints (List<TypeParameter> type_params) {
                if (type_params.size > 0) {
                        foreach (TypeParameter type_param in type_params) {
-                               unowned DataType? type_constraint = type_param.type_constraint;
-                               if (type_constraint == null) {
+                               if (!type_param.has_type_constraints ()) {
                                        continue;
                                }
                                write_string (" where ");
                                write_identifier (type_param.name);
                                write_string (" : ");
                                bool first = true;
-                               //FIXME
-                               foreach (DataType type in new DataType[] { type_constraint }) {
+                               foreach (DataType type in type_param.get_type_constraints ()) {
                                        if (first) {
                                                first = false;
                                        } else {
index f947f7cdf483fddc07d3062a883db08aa9287801..97a7202a1e9a8ac159800b8cec40c9f7a0c0a897 100644 (file)
@@ -319,9 +319,10 @@ public abstract class Vala.DataType : CodeNode {
 
                /* temporarily ignore type parameters */
                if (target_type is GenericType) {
-                       unowned DataType? constraint_type = ((GenericType) target_type).type_parameter.type_constraint;
-                       if (constraint_type != null) {
-                               return compatible (constraint_type);
+                       foreach (DataType type_constraint in ((GenericType) target_type).type_parameter.get_type_constraints ()) {
+                               if (!compatible (type_constraint)) {
+                                       return false;
+                               }
                        }
                        return true;
                }
@@ -574,7 +575,7 @@ public abstract class Vala.DataType : CodeNode {
                        }
                }
 
-               return get_constrained_type (type_param);
+               return type_param.get_constrained_type ();
        }
 
        /**
@@ -706,7 +707,7 @@ public abstract class Vala.DataType : CodeNode {
                        var type_params = ((GenericSymbol) type_symbol).get_type_parameters ();
                        bool mitigated = true;
                        foreach (var t in type_params) {
-                               var ct = get_constrained_type (t);
+                               var ct = t.get_constrained_type ();
                                if (ct != null) {
                                        Report.notice (source_reference, "`%s' requires type arguments, constraining `%s' to `%s'", type_symbol.to_string (), t.name, ct.to_qualified_string ());
                                        add_type_argument (ct);
@@ -732,23 +733,16 @@ public abstract class Vala.DataType : CodeNode {
                        }
 
                        it.next ();
-                       unowned DataType? constraint_type = it.get ().type_constraint;
-                       if (constraint_type != null && !type.compatible (constraint_type)) {
-                               error = true;
-                               Report.error (type.source_reference, "Cannot convert from `%s' to `%s'", type.to_string (), constraint_type.to_string ());
-                               return false;
+                       unowned List<DataType> type_constraints = it.get ().get_type_constraints ();
+                       foreach (DataType type_constraint in type_constraints) {
+                               if (!type.compatible (type_constraint)) {
+                                       error = true;
+                                       Report.error (type.source_reference, "Cannot convert from `%s' to `%s'", type.to_string (), type_constraint.to_string ());
+                                       return false;
+                               }
                        }
                }
 
                return true;
        }
-
-       DataType? get_constrained_type (TypeParameter type_param) {
-               unowned DataType? type = type_param.type_constraint;
-               if (type != null) {
-                       return type.copy ();
-               }
-
-               return null;
-       }
 }
index 3a81449c1ff6b82aec27382c2427bfee6584f3d8..c4e770fbd273d800ea64b4362dbf0a74113b75ad 100644 (file)
@@ -53,9 +53,13 @@ public class Vala.GenericType : DataType {
        }
 
        public override bool compatible (DataType target_type) {
-               unowned DataType? constraint_type = type_parameter.type_constraint;
-               if (constraint_type != null) {
-                       return constraint_type.compatible (target_type);
+               if (type_parameter.has_type_constraints ()) {
+                       foreach (DataType type_constraint in type_parameter.get_type_constraints ()) {
+                               if (!type_constraint.compatible (target_type)) {
+                                       return false;
+                               }
+                       }
+                       return true;
                }
 
                return base.compatible (target_type);
index 6f3a83692be31a0d669c6ad3903275f44dec699b..e56b614c478956f7671aea9d988682ff93ef917d 100644 (file)
@@ -613,10 +613,10 @@ public class Vala.MethodCall : Expression, CallableExpression {
                                                        type_arg = m.return_type.infer_type_argument (type_param, target_type);
                                                }
 
-                                               unowned DataType? ct = type_param.type_constraint;
+                                               DataType? ct = type_param.get_constrained_type ();
                                                if (ct != null) {
                                                        Report.notice (source_reference, "`%s' requires type arguments, constraining `%s' to `%s'", m.to_string (), type_param.name, ct.to_qualified_string ());
-                                                       type_arg = ct.copy ();
+                                                       type_arg = ct;
                                                }
 
                                                if (type_arg == null) {
index f69a98387d8ace57718d50524d87f4f9869c85a8..cc5d9b2c1fbdfb893615e715603a85be63d0653e 100644 (file)
@@ -4046,12 +4046,12 @@ public class Vala.Parser : CodeVisitor {
                        do {
                                /*
                                where T : <base class name>
-                               where T : <interface name>
+                               where T : <interface name>[, <interface name>]
                                where T : U
                                */
                                begin = get_location ();
                                var type = parse_type (true, false);
-                               type_param.type_constraint = type;
+                               type_param.add_type_constraint (type);
                        } while (accept (TokenType.COMMA));
                }
        }
index 64bd048d8bf14275fab01e37042ae0d6c49a4686..dd96dcd50b199ddea4617b9d3f3cac6d2c28fdd6 100644 (file)
@@ -26,22 +26,8 @@ using GLib;
  * Represents a generic type parameter in the source code.
  */
 public class Vala.TypeParameter : TypeSymbol {
-       public DataType? type_constraint {
-               get {
-                       if (_type_constraint is GenericType) {
-                               return ((GenericType) _type_constraint).type_parameter.type_constraint;
-                       }
-                       return _type_constraint;
-               }
-               set {
-                       _type_constraint = value;
-                       if (_type_constraint != null) {
-                               _type_constraint.parent_node = this;
-                       }
-               }
-       }
-
-       DataType? _type_constraint;
+       List<DataType> type_constraint_list;
+       static List<DataType> _empty_type_list;
 
        /**
         * Creates a new generic type parameter.
@@ -55,19 +41,86 @@ public class Vala.TypeParameter : TypeSymbol {
                access = SymbolAccessibility.PUBLIC;
        }
 
+       /**
+        * Appends the specified type as generic type constraint.
+        *
+        * @param arg a type reference
+        */
+       public void add_type_constraint (DataType arg) {
+               if (type_constraint_list == null) {
+                       type_constraint_list = new ArrayList<DataType> ();
+               }
+               type_constraint_list.add (arg);
+               arg.parent_node = this;
+       }
+
+       /**
+        * Returns the list of generic type constraints.
+        *
+        * @return type constraint list
+        */
+       public unowned List<DataType> get_type_constraints () {
+               if (type_constraint_list != null) {
+                       if (type_constraint_list.size > 0 && type_constraint_list[0] is GenericType) {
+                               return ((GenericType) type_constraint_list[0]).type_parameter.get_type_constraints ();
+                       }
+                       return type_constraint_list;
+               }
+               if (_empty_type_list == null) {
+                       _empty_type_list = new ArrayList<DataType> ();
+               }
+               return _empty_type_list;
+       }
+
+       public bool has_type_constraints () {
+               if (type_constraint_list == null) {
+                       return false;
+               }
+
+               return type_constraint_list.size > 0;
+       }
+
+       public DataType? get_constrained_type () {
+               if (!has_type_constraints ()) {
+                       return null;
+               }
+
+               unowned List<DataType> type_constraints = get_type_constraints ();
+               if (type_constraints.size == 1) {
+                       return type_constraints[0].copy ();
+               }
+               foreach (DataType type_constraint in type_constraints) {
+                       if (type_constraint is ClassType) {
+                               return type_constraint.copy ();
+                       } else if (type_constraint is InterfaceType) {
+                               //FIXME Represent all given interfaces
+                               return type_constraint.copy ();
+                       }
+               }
+
+               return null;
+       }
+
        public override void accept (CodeVisitor visitor) {
                visitor.visit_type_parameter (this);
        }
 
        public override void accept_children (CodeVisitor visitor) {
-               if (_type_constraint != null) {
-                       _type_constraint.accept (visitor);
+               if (type_constraint_list != null && type_constraint_list.size > 0) {
+                       foreach (DataType type_constraint in type_constraint_list) {
+                               type_constraint.accept (visitor);
+                       }
                }
        }
 
        public override void replace_type (DataType old_type, DataType new_type) {
-               if (_type_constraint == old_type) {
-                       type_constraint = new_type;
+               if (type_constraint_list != null) {
+                       for (int i = 0; i < type_constraint_list.size; i++) {
+                               if (type_constraint_list[i] == old_type) {
+                                       type_constraint_list[i] = new_type;
+                                       return;
+                               }
+                       }
                }
        }