From: Rico Tzschichholz Date: Thu, 27 Apr 2023 21:37:13 +0000 (+0200) Subject: WIP Handle extended syntax X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e7aa4a01e50ee515c28d22a7240abfaa5f7cc9f;p=thirdparty%2Fvala.git WIP Handle extended syntax --- diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala index 7a497b7b4..34c81f14f 100644 --- a/vala/valacodewriter.vala +++ b/vala/valacodewriter.vala @@ -1793,16 +1793,14 @@ public class Vala.CodeWriter : CodeVisitor { void write_type_parameter_constraints (List 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 { diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index f947f7cdf..97a7202a1 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -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 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; - } } diff --git a/vala/valagenerictype.vala b/vala/valagenerictype.vala index 3a81449c1..c4e770fbd 100644 --- a/vala/valagenerictype.vala +++ b/vala/valagenerictype.vala @@ -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); diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala index 6f3a83692..e56b614c4 100644 --- a/vala/valamethodcall.vala +++ b/vala/valamethodcall.vala @@ -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) { diff --git a/vala/valaparser.vala b/vala/valaparser.vala index f69a98387..cc5d9b2c1 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -4046,12 +4046,12 @@ public class Vala.Parser : CodeVisitor { do { /* where T : - where T : + where T : [, ] 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)); } } diff --git a/vala/valatypeparameter.vala b/vala/valatypeparameter.vala index 64bd048d8..dd96dcd50 100644 --- a/vala/valatypeparameter.vala +++ b/vala/valatypeparameter.vala @@ -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 type_constraint_list; + static List _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 (); + } + type_constraint_list.add (arg); + arg.parent_node = this; + } + + /** + * Returns the list of generic type constraints. + * + * @return type constraint list + */ + public unowned List 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 (); + } + 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 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; + } + } } }