[vala/staging] vala: Add GenericType.dup/destroy fields
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging] vala: Add GenericType.dup/destroy fields
- Date: Mon, 4 Nov 2019 10:30:01 +0000 (UTC)
commit d14248fdfa5ba2a39dfb8ce8a6a6a4a083c4f081
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Fri Nov 1 21:31:47 2019 +0100
vala: Add GenericType.dup/destroy fields
This provides direct access to the according values of generic-types
and type-parameters.
Fixes https://gitlab.gnome.org/GNOME/vala/issues/190
codegen/valaccodememberaccessmodule.vala | 4 ++
tests/Makefile.am | 1 +
tests/generics/member-dup-destroy.vala | 88 ++++++++++++++++++++++++++++++++
vala/Makefile.am | 2 +
vala/valagenericdestroyfield.vala | 36 +++++++++++++
vala/valagenericdupfield.vala | 36 +++++++++++++
vala/valagenerictype.vala | 24 +++++++++
vala/valamemberaccess.vala | 5 ++
vala/valasemanticanalyzer.vala | 3 ++
9 files changed, 199 insertions(+)
---
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index 7674402ca..e520ede93 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -125,6 +125,10 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
CCodeExpression delegate_target_destroy_notify;
get_delegate_target_cexpression (expr.inner, out delegate_target_destroy_notify);
set_cvalue (expr, delegate_target_destroy_notify);
+ } else if (expr.symbol_reference is GenericDupField) {
+ set_cvalue (expr, get_dup_func_expression (expr.inner.value_type,
expr.source_reference));
+ } else if (expr.symbol_reference is GenericDestroyField) {
+ set_cvalue (expr, get_destroy_func_expression (expr.inner.value_type));
} else if (expr.symbol_reference is Field) {
var field = (Field) expr.symbol_reference;
if (expr.lvalue) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0265bc99c..daf29e9dc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -502,6 +502,7 @@ TESTS = \
generics/constructor-chain-up.vala \
generics/inference-static-function.vala \
generics/parameter-sizeof-initializer.vala \
+ generics/member-dup-destroy.vala \
generics/type-parameter-properties.vala \
generics/bug640330.test \
generics/bug640330.vala \
diff --git a/tests/generics/member-dup-destroy.vala b/tests/generics/member-dup-destroy.vala
new file mode 100644
index 000000000..defe162dc
--- /dev/null
+++ b/tests/generics/member-dup-destroy.vala
@@ -0,0 +1,88 @@
+delegate void FooFunc ();
+
+class Foo<G> : Object {
+ public Foo () {
+ assert (typeof (G) == typeof (string));
+ assert (G.dup == (BoxedCopyFunc) string.dup);
+ assert (G.destroy == (DestroyNotify) free);
+
+ G g = null;
+ assert (g.dup == (BoxedCopyFunc) string.dup);
+ assert (g.destroy == (DestroyNotify) free);
+ }
+
+ public void foo () {
+ assert (typeof (G) == typeof (string));
+ assert (G.dup == (BoxedCopyFunc) string.dup);
+ assert (G.destroy == (DestroyNotify) free);
+
+ G g = null;
+ assert (g.dup == (BoxedCopyFunc) string.dup);
+ assert (g.destroy == (DestroyNotify) free);
+ }
+
+ public async void foo_async () {
+ assert (typeof (G) == typeof (string));
+ assert (G.dup == (BoxedCopyFunc) string.dup);
+ assert (G.destroy == (DestroyNotify) free);
+
+ G g = null;
+ assert (g.dup == (BoxedCopyFunc) string.dup);
+ assert (g.destroy == (DestroyNotify) free);
+ }
+
+ public void foo_captured () {
+ FooFunc f = () => {
+ assert (typeof (G) == typeof (string));
+ assert (G.dup == (BoxedCopyFunc) string.dup);
+ assert (G.destroy == (DestroyNotify) free);
+
+ G g = null;
+ assert (g.dup == (BoxedCopyFunc) string.dup);
+ assert (g.destroy == (DestroyNotify) free);
+ };
+ f ();
+ }
+}
+
+void bar<T> (T t) {
+ assert (typeof (T) == typeof (Foo));
+ assert (T.dup == (BoxedCopyFunc) Object.@ref);
+ assert (T.destroy == (DestroyNotify) Object.unref);
+
+ assert (t.dup == (BoxedCopyFunc) Object.@ref);
+ assert (t.destroy == (DestroyNotify) Object.unref);
+}
+
+async void bar_async<T> (T t) {
+ assert (typeof (T) == typeof (Foo));
+ assert (T.dup == (BoxedCopyFunc) Object.@ref);
+ assert (T.destroy == (DestroyNotify) Object.unref);
+
+ assert (t.dup == (BoxedCopyFunc) Object.@ref);
+ assert (t.destroy == (DestroyNotify) Object.unref);
+}
+
+void bar_captured<T> (T t) {
+ FooFunc f = () => {
+ assert (typeof (T) == typeof (Foo));
+ assert (T.dup == (BoxedCopyFunc) Object.@ref);
+ assert (T.destroy == (DestroyNotify) Object.unref);
+
+ assert (t.dup == (BoxedCopyFunc) Object.@ref);
+ assert (t.destroy == (DestroyNotify) Object.unref);
+ };
+ f ();
+}
+
+void main () {
+ var foo = new Foo<string> ();
+
+ foo.foo ();
+ foo.foo_async.begin ();
+ foo.foo_captured ();
+
+ bar<Foo> (foo);
+ bar_async<Foo>.begin (foo);
+ bar_captured<Foo> (foo);
+}
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 57c758fdc..c6aed1c54 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -90,6 +90,8 @@ libvala_la_VALASOURCES = \
valaforeachstatement.vala \
valaforstatement.vala \
valagirparser.vala \
+ valagenericdestroyfield.vala \
+ valagenericdupfield.vala \
valagenerictype.vala \
valagenieparser.vala \
valageniescanner.vala \
diff --git a/vala/valagenericdestroyfield.vala b/vala/valagenericdestroyfield.vala
new file mode 100644
index 000000000..6627bcca2
--- /dev/null
+++ b/vala/valagenericdestroyfield.vala
@@ -0,0 +1,36 @@
+/* valagenericdestroyfield.vala
+ *
+ * Copyright (C) 2019 Rico Tzschichholz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Rico Tzschichholz <ricotz ubuntu com>
+ */
+
+/**
+ * Represents the Generic.destroy field.
+ */
+public class Vala.GenericDestroyField : Field {
+ /**
+ * Creates a new generic destroy field.
+ *
+ * @return newly created field
+ */
+ public GenericDestroyField (SourceReference source_reference) {
+ base ("destroy", CodeContext.get ().analyzer.delegate_target_destroy_type, null,
source_reference);
+ external = true;
+ }
+}
diff --git a/vala/valagenericdupfield.vala b/vala/valagenericdupfield.vala
new file mode 100644
index 000000000..12ab9ecea
--- /dev/null
+++ b/vala/valagenericdupfield.vala
@@ -0,0 +1,36 @@
+/* valagenericdupfield.vala
+ *
+ * Copyright (C) 2019 Rico Tzschichholz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Rico Tzschichholz <ricotz ubuntu com>
+ */
+
+/**
+ * Represents the Generic.dup field.
+ */
+public class Vala.GenericDupField : Field {
+ /**
+ * Creates a new generic dup field.
+ *
+ * @return newly created field
+ */
+ public GenericDupField (SourceReference source_reference) {
+ base ("dup", CodeContext.get ().analyzer.generics_dup_func_type, null, source_reference);
+ external = true;
+ }
+}
diff --git a/vala/valagenerictype.vala b/vala/valagenerictype.vala
index e5e1a50a8..1f7a2d1ee 100644
--- a/vala/valagenerictype.vala
+++ b/vala/valagenerictype.vala
@@ -31,6 +31,9 @@ public class Vala.GenericType : DataType {
*/
public weak TypeParameter type_parameter { get; set; }
+ GenericDupField? dup_field;
+ GenericDestroyField? destroy_field;
+
public GenericType (TypeParameter type_parameter) {
this.type_parameter = type_parameter;
// type parameters are always considered nullable
@@ -74,6 +77,27 @@ public class Vala.GenericType : DataType {
}
public override Symbol? get_member (string member_name) {
+ if (member_name == "dup") {
+ return get_dup_field ();
+ } else if (member_name == "destroy") {
+ return get_destroy_field ();
+ }
return null;
}
+
+ unowned GenericDupField get_dup_field () {
+ if (dup_field == null) {
+ dup_field = new GenericDupField (source_reference);
+ dup_field.access = SymbolAccessibility.PUBLIC;
+ }
+ return dup_field;
+ }
+
+ unowned GenericDestroyField get_destroy_field () {
+ if (destroy_field == null) {
+ destroy_field = new GenericDestroyField (source_reference);
+ destroy_field.access = SymbolAccessibility.PUBLIC;
+ }
+ return destroy_field;
+ }
}
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 9316e5644..421ee8a9f 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -362,6 +362,11 @@ public class Vala.MemberAccess : Expression {
}
}
+ if (inner is MemberAccess && inner.symbol_reference is TypeParameter) {
+ inner.value_type = new GenericType ((TypeParameter) inner.symbol_reference);
+ inner.value_type.source_reference = source_reference;
+ }
+
if (symbol_reference == null && inner.value_type != null) {
if (pointer_member_access) {
symbol_reference = inner.value_type.get_pointer_member (member_name);
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 25c812dc4..c83d58b53 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -169,6 +169,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public Class gsource_type;
public DataType delegate_target_type;
public DelegateType delegate_target_destroy_type;
+ public DelegateType generics_dup_func_type;
Delegate destroy_notify;
@@ -236,6 +237,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
delegate_target_type = new StructValueType ((Struct) glib_ns.scope.lookup
("pointer"));
destroy_notify = (Delegate) glib_ns.scope.lookup ("DestroyNotify");
delegate_target_destroy_type = new DelegateType (destroy_notify);
+
+ generics_dup_func_type = new DelegateType ((Delegate) glib_ns.scope.lookup
("BoxedCopyFunc"));
} else {
delegate_target_type = new PointerType (new VoidType ());
destroy_notify = new Delegate ("ValaDestroyNotify", new VoidType ());
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]