Report.error (expr.source_reference, "unsupported use of length field of multi-dimensional array");
}
set_cvalue (expr, get_array_length_cexpression (expr.inner, 1));
+ } else if (expr.symbol_reference is DelegateTargetField) {
+ if (!((DelegateType) expr.inner.value_type).delegate_symbol.has_target) {
+ Report.error (expr.source_reference, "unsupported use of target field of delegate without target");
+ }
+ CCodeExpression delegate_target_destroy_notify;
+ set_cvalue (expr, get_delegate_target_cexpression (expr.inner, out delegate_target_destroy_notify));
+ } else if (expr.symbol_reference is DelegateDestroyField) {
+ if (!((DelegateType) expr.inner.value_type).delegate_symbol.has_target) {
+ Report.error (expr.source_reference, "unsupported use of destroy field of delegate without target");
+ }
+ 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 Field) {
var field = (Field) expr.symbol_reference;
if (expr.lvalue) {
delegates/instance-method-to-no-target.test \
delegates/lambda-mixed-instance-static.vala \
delegates/lambda-shared-closure.vala \
+ delegates/member-target-destroy.vala \
delegates/reference_transfer.vala \
delegates/return-array-null-terminated.vala \
delegates/wrapper.vala \
--- /dev/null
+delegate string Foo ();
+
+string bar (string s) {
+ return s;
+}
+
+void foo_free (void* data) {
+ GLib.free (data);
+}
+
+void main () {
+ Foo foo = (Foo) bar;
+ assert (foo.target == null);
+ assert (foo.destroy == null);
+
+ string* foo_data = "foo".dup ();
+ foo.target = foo_data;
+ foo.destroy = (GLib.DestroyNotify) foo_free;
+
+ assert (foo () == "foo");
+ assert (foo.target == foo_data);
+ assert (foo.destroy == (GLib.DestroyNotify) foo_free);
+}
valadatatype.vala \
valadeclarationstatement.vala \
valadelegate.vala \
+ valadelegatedestroyfield.vala \
+ valadelegatetargetfield.vala \
valadelegatetype.vala \
valadeletestatement.vala \
valadestructor.vala \
(local != null || param != null || field != null) &&
!is_array_add () &&
!(field is ArrayLengthField) &&
+ !(field is DelegateTargetField) &&
+ !(field is DelegateDestroyField) &&
!(left.value_type.is_real_non_null_struct_type () && right is ObjectCreationExpression)) {
// visit_assignment not necessary
if (instance && ma.inner != null) {
--- /dev/null
+/* valadelegatedestroyfield.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 Delegate.destroy field.
+ */
+public class Vala.DelegateDestroyField : Field {
+ /**
+ * Creates a new delegate destroy field.
+ *
+ * @return newly created field
+ */
+ public DelegateDestroyField (SourceReference source_reference) {
+ base ("destroy", CodeContext.get ().analyzer.delegate_target_destroy_type, null, source_reference);
+ external = true;
+ }
+}
--- /dev/null
+/* valadelegatetargetfield.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 Delegate.target field.
+ */
+public class Vala.DelegateTargetField : Field {
+ /**
+ * Creates a new delegate target field.
+ *
+ * @return newly created field
+ */
+ public DelegateTargetField (SourceReference source_reference) {
+ base ("target", new PointerType (new VoidType ()), null, source_reference);
+ external = true;
+ }
+}
public bool is_called_once { get; set; }
+ DelegateTargetField? target_field;
+ DelegateDestroyField? destroy_field;
+
public DelegateType (Delegate delegate_symbol) {
base (delegate_symbol);
this.is_called_once = (delegate_symbol.get_attribute_string ("CCode", "scope") == "async");
}
+ public override Symbol? get_member (string member_name) {
+ if (member_name == "target") {
+ return get_target_field ();
+ } else if (member_name == "destroy") {
+ return get_destroy_field ();
+ }
+ return null;
+ }
+
+ unowned DelegateTargetField get_target_field () {
+ if (target_field == null) {
+ target_field = new DelegateTargetField (source_reference);
+ target_field.access = SymbolAccessibility.PUBLIC;
+ }
+ return target_field;
+ }
+
+ unowned DelegateDestroyField get_destroy_field () {
+ if (destroy_field == null) {
+ destroy_field = new DelegateDestroyField (source_reference);
+ destroy_field.access = SymbolAccessibility.PUBLIC;
+ }
+ return destroy_field;
+ }
+
public override DataType copy () {
var result = new DelegateType (delegate_symbol);
result.source_reference = source_reference;