summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Schrader <nick.schrader@mailbox.org>2020-07-19 22:13:37 +0200
committerRico Tzschichholz <ricotz@ubuntu.com>2023-03-19 12:55:01 +0100
commitb16397964c37e0337410d3cab90c2136ff8264fa (patch)
treeb5638c7aa9e60a99eeae1e907adf4dc60fe091c3
parented68b9f412bd6932e384cc8c6ac89257ae40142f (diff)
downloadvala-wip/issue/658.tar.gz
vala: Add support for anonymous delegateswip/issue/658
void foo (delegate(string, int) => int d) { ... } Fixes https://gitlab.gnome.org/GNOME/vala/issues/658
-rw-r--r--tests/Makefile.am20
-rw-r--r--tests/delegates/anonymous-array.c-expected117
-rw-r--r--tests/delegates/anonymous-array.vala15
-rw-r--r--tests/delegates/anonymous-dynamic.test15
-rw-r--r--tests/delegates/anonymous-generics.test19
-rw-r--r--tests/delegates/anonymous-inner-dynamic-param.test15
-rw-r--r--tests/delegates/anonymous-inner-dynamic-return.test15
-rw-r--r--tests/delegates/anonymous-inner-owned-unowned.c-expected500
-rw-r--r--tests/delegates/anonymous-inner-owned-unowned.vala41
-rw-r--r--tests/delegates/anonymous-inner-params.test19
-rw-r--r--tests/delegates/anonymous-inner-ref-out.c-expected100
-rw-r--r--tests/delegates/anonymous-inner-ref-out.vala24
-rw-r--r--tests/delegates/anonymous-optional-param.test19
-rw-r--r--tests/delegates/anonymous-out.test15
-rw-r--r--tests/delegates/anonymous-param-attrs.c-expected62
-rw-r--r--tests/delegates/anonymous-param-attrs.vala11
-rw-r--r--tests/delegates/anonymous-params.test15
-rw-r--r--tests/delegates/anonymous-ref.test15
-rw-r--r--tests/delegates/anonymous-return-anonymous.test18
-rw-r--r--tests/delegates/anonymous-throws.test21
-rw-r--r--tests/delegates/anonymous-type-param.c-expected423
-rw-r--r--tests/delegates/anonymous-type-param.vala20
-rw-r--r--tests/delegates/anonymous-variadic.test19
-rw-r--r--tests/delegates/anonymous.c-expected70
-rw-r--r--tests/delegates/anonymous.vala9
-rw-r--r--tests/methods/parameter-anonymous-delegate-optional.c-expected89
-rw-r--r--tests/methods/parameter-anonymous-delegate-optional.vala8
-rw-r--r--tests/methods/parameter-anonymous-delegate.c-expected130
-rw-r--r--tests/methods/parameter-anonymous-delegate.vala21
-rw-r--r--vala/valacallabletype.vala6
-rw-r--r--vala/valacodewriter.vala47
-rw-r--r--vala/valaparser.vala139
32 files changed, 2049 insertions, 8 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7b4317a18..4824493c7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -203,6 +203,8 @@ TESTS = \
methods/extern.vala \
methods/iterator.vala \
methods/local-functions.vala \
+ methods/parameter-anonymous-delegate.vala \
+ methods/parameter-anonymous-delegate-optional.vala \
methods/parameter-fixed-array-initializer.vala \
methods/parameter-out-free-on-error.vala \
methods/parameter-ref-array-resize.vala \
@@ -446,6 +448,24 @@ TESTS = \
structs/bug775761.vala \
structs/bug777194.vala \
structs/bug777194-2.vala \
+ delegates/anonymous.vala \
+ delegates/anonymous-array.vala \
+ delegates/anonymous-dynamic.test \
+ delegates/anonymous-generics.test \
+ delegates/anonymous-inner-dynamic-param.test \
+ delegates/anonymous-inner-dynamic-return.test \
+ delegates/anonymous-inner-params.test \
+ delegates/anonymous-inner-ref-out.vala \
+ delegates/anonymous-inner-owned-unowned.vala \
+ delegates/anonymous-optional-param.test \
+ delegates/anonymous-out.test \
+ delegates/anonymous-params.test \
+ delegates/anonymous-param-attrs.vala \
+ delegates/anonymous-ref.test \
+ delegates/anonymous-return-anonymous.test \
+ delegates/anonymous-throws.test \
+ delegates/anonymous-type-param.vala \
+ delegates/anonymous-variadic.test \
delegates/casting.vala \
delegates/class-field-initializer.vala \
delegates/compatible.vala \
diff --git a/tests/delegates/anonymous-array.c-expected b/tests/delegates/anonymous-array.c-expected
new file mode 100644
index 000000000..d38f7a44c
--- /dev/null
+++ b/tests/delegates/anonymous-array.c-expected
@@ -0,0 +1,117 @@
+/* delegates_anonymous_array.c generated by valac, the Vala compiler
+ * generated from delegates_anonymous_array.vala, do not modify */
+
+#include <glib.h>
+#include <string.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef gint (*__delegate0_) (gint* p0, gint p0_length1, gint* p1, gint p1_length1, gpointer user_data);
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+static void _vala_main (void);
+VALA_EXTERN void f (__delegate0_ abc,
+ gpointer abc_target);
+static gint __lambda4_ (gint* a,
+ gint a_length1,
+ gint* b,
+ gint b_length1);
+static gint ___lambda4____delegate0_ (gint* p0,
+ gint p0_length1,
+ gint* p1,
+ gint p1_length1,
+ gpointer self);
+
+static gint
+__lambda4_ (gint* a,
+ gint a_length1,
+ gint* b,
+ gint b_length1)
+{
+ gint r = 0;
+ gint result;
+ r = 0;
+ {
+ gint i = 0;
+ i = 0;
+ {
+ gboolean _tmp0_ = FALSE;
+ _tmp0_ = TRUE;
+ while (TRUE) {
+ gint _tmp2_;
+ gint _tmp3_;
+ if (!_tmp0_) {
+ gint _tmp1_;
+ _tmp1_ = i;
+ i = _tmp1_ + 1;
+ }
+ _tmp0_ = FALSE;
+ if (!(i < a_length1)) {
+ break;
+ }
+ _tmp2_ = a[i];
+ _tmp3_ = b[i];
+ r += _tmp2_ * _tmp3_;
+ }
+ }
+ }
+ result = r;
+ return result;
+}
+
+static gint
+___lambda4____delegate0_ (gint* p0,
+ gint p0_length1,
+ gint* p1,
+ gint p1_length1,
+ gpointer self)
+{
+ gint result;
+ result = __lambda4_ (p0, p0_length1, p1, p1_length1);
+ return result;
+}
+
+static void
+_vala_main (void)
+{
+ f (___lambda4____delegate0_, NULL);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
+void
+f (__delegate0_ abc,
+ gpointer abc_target)
+{
+ gint i[3] = {0};
+ gint _tmp0_[3] = {0};
+ gint j[3] = {0};
+ gint _tmp1_[3] = {0};
+ _tmp0_[0] = 1;
+ _tmp0_[1] = 2;
+ _tmp0_[2] = 3;
+ memcpy (i, _tmp0_, 3 * sizeof (gint));
+ _tmp1_[0] = 7;
+ _tmp1_[1] = 8;
+ _tmp1_[2] = 9;
+ memcpy (j, _tmp1_, 3 * sizeof (gint));
+ _vala_assert (abc (i, (gint) 3, j, (gint) 3, abc_target) == 50, "abc (i, j) == 50");
+}
+
diff --git a/tests/delegates/anonymous-array.vala b/tests/delegates/anonymous-array.vala
new file mode 100644
index 000000000..b032b2915
--- /dev/null
+++ b/tests/delegates/anonymous-array.vala
@@ -0,0 +1,15 @@
+void main () {
+ f ((a, b) => {
+ int r = 0;
+ for (int i = 0; i < a.length; i++) {
+ r += a[i] * b[i];
+ }
+ return r;
+ });
+}
+
+void f (delegate(int[], int[]) => int abc) {
+ int i[] = {1, 2, 3};
+ int j[] = {7, 8, 9};
+ assert (abc (i, j) == 50);
+}
diff --git a/tests/delegates/anonymous-dynamic.test b/tests/delegates/anonymous-dynamic.test
new file mode 100644
index 000000000..fdbf22824
--- /dev/null
+++ b/tests/delegates/anonymous-dynamic.test
@@ -0,0 +1,15 @@
+Invalid Code
+
+/*
+ * 9.9-9.33: error: Anonymous delegates cannot be dynamic types
+ * void p (dynamic delegate() => int d) {
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ */
+
+void p (dynamic delegate() => int d) {
+ d ();
+}
+
+void main () {
+ p (() => 7);
+}
diff --git a/tests/delegates/anonymous-generics.test b/tests/delegates/anonymous-generics.test
new file mode 100644
index 000000000..112e06463
--- /dev/null
+++ b/tests/delegates/anonymous-generics.test
@@ -0,0 +1,19 @@
+Invalid Code
+
+/*
+ * 13.17-13.17: error: syntax error, expected `('
+ * void f (delegate<T>(int) => void y) {
+ * ^
+ */
+
+void main () {
+ f (t);
+}
+
+void f (delegate<T>(int) => void y) {
+ y (1);
+}
+
+void t (int a) {
+ assert (a == 1);
+}
diff --git a/tests/delegates/anonymous-inner-dynamic-param.test b/tests/delegates/anonymous-inner-dynamic-param.test
new file mode 100644
index 000000000..3d8199625
--- /dev/null
+++ b/tests/delegates/anonymous-inner-dynamic-param.test
@@ -0,0 +1,15 @@
+Invalid Code
+
+/*
+ * 7.18-7.28: error: Dynamic types not allowed in anonymous delegates
+ * void p (delegate(dynamic int) => void d) {
+ * ^^^^^^^^^^^
+ */
+
+void p (delegate(dynamic int) => void d) {
+ d (7);
+}
+
+void main () {
+ return;
+}
diff --git a/tests/delegates/anonymous-inner-dynamic-return.test b/tests/delegates/anonymous-inner-dynamic-return.test
new file mode 100644
index 000000000..0a2b6adf7
--- /dev/null
+++ b/tests/delegates/anonymous-inner-dynamic-return.test
@@ -0,0 +1,15 @@
+Invalid Code
+
+/*
+ * 9.23-9.33: error: Dynamic types not allowed in anonymous delegates
+ * void p (delegate() => dynamic int d) {
+ * ^^^^^^^^^^^
+ */
+
+void p (delegate() => dynamic int d) {
+ var x = d ();
+}
+
+void main () {
+ return;
+}
diff --git a/tests/delegates/anonymous-inner-owned-unowned.c-expected b/tests/delegates/anonymous-inner-owned-unowned.c-expected
new file mode 100644
index 000000000..53ac2b25e
--- /dev/null
+++ b/tests/delegates/anonymous-inner-owned-unowned.c-expected
@@ -0,0 +1,500 @@
+/* delegates_anonymous_inner_owned_unowned.c generated by valac, the Vala compiler
+ * generated from delegates_anonymous_inner_owned_unowned.vala, do not modify */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef struct _Aaa Aaa;
+
+#define TYPE_BBB (bbb_get_type ())
+#define BBB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BBB, Bbb))
+#define BBB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BBB, BbbClass))
+#define IS_BBB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BBB))
+#define IS_BBB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BBB))
+#define BBB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BBB, BbbClass))
+
+typedef struct _Bbb Bbb;
+typedef struct _BbbClass BbbClass;
+typedef struct _BbbPrivate BbbPrivate;
+#define _aaa_free0(var) ((var == NULL) ? NULL : (var = (aaa_free (var), NULL)))
+typedef struct _ParamSpecBbb ParamSpecBbb;
+typedef void (*__delegate0_) (Aaa* p0, gpointer user_data);
+typedef void (*__delegate1_) (Aaa* p0, gpointer user_data);
+typedef Aaa* (*__delegate2_) (gpointer user_data);
+typedef Aaa* (*__delegate3_) (gpointer user_data);
+#define _bbb_unref0(var) ((var == NULL) ? NULL : (var = (bbb_unref (var), NULL)))
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+struct _Aaa {
+ gint i;
+};
+
+struct _Bbb {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ BbbPrivate * priv;
+};
+
+struct _BbbClass {
+ GTypeClass parent_class;
+ void (*finalize) (Bbb *self);
+};
+
+struct _BbbPrivate {
+ Aaa* a;
+};
+
+struct _ParamSpecBbb {
+ GParamSpec parent_instance;
+};
+
+static gint Bbb_private_offset;
+static gpointer bbb_parent_class = NULL;
+
+VALA_EXTERN void aaa_free (Aaa * self);
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (Aaa, aaa_free)
+static void aaa_instance_init (Aaa * self);
+VALA_EXTERN Aaa* aaa_new (void);
+VALA_EXTERN gpointer bbb_ref (gpointer instance);
+VALA_EXTERN void bbb_unref (gpointer instance);
+VALA_EXTERN GParamSpec* param_spec_bbb (const gchar* name,
+ const gchar* nick,
+ const gchar* blurb,
+ GType object_type,
+ GParamFlags flags);
+VALA_EXTERN void value_set_bbb (GValue* value,
+ gpointer v_object);
+VALA_EXTERN void value_take_bbb (GValue* value,
+ gpointer v_object);
+VALA_EXTERN gpointer value_get_bbb (const GValue* value);
+VALA_EXTERN GType bbb_get_type (void) G_GNUC_CONST ;
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (Bbb, bbb_unref)
+VALA_EXTERN Aaa* bbb_get_a (Bbb* self);
+VALA_EXTERN Bbb* bbb_new (void);
+VALA_EXTERN Bbb* bbb_construct (GType object_type);
+static void bbb_finalize (Bbb * obj);
+static GType bbb_get_type_once (void);
+VALA_EXTERN void p (__delegate0_ d,
+ gpointer d_target);
+VALA_EXTERN void q (__delegate1_ d,
+ gpointer d_target);
+VALA_EXTERN void r (__delegate2_ d,
+ gpointer d_target);
+VALA_EXTERN void s (__delegate3_ d,
+ gpointer d_target);
+static void _vala_main (void);
+static void __lambda4_ (Aaa* a);
+static void ___lambda4____delegate0_ (Aaa* p0,
+ gpointer self);
+static void __lambda5_ (Aaa* a);
+static void ___lambda5____delegate1_ (Aaa* p0,
+ gpointer self);
+static Aaa* __lambda6_ (void);
+static Aaa* ___lambda6____delegate2_ (gpointer self);
+static Aaa* _bbb_get_a___delegate3_ (gpointer self);
+
+Aaa*
+aaa_new (void)
+{
+ Aaa* self;
+ self = g_slice_new0 (Aaa);
+ aaa_instance_init (self);
+ return self;
+}
+
+static void
+aaa_instance_init (Aaa * self)
+{
+ self->i = 42;
+}
+
+void
+aaa_free (Aaa * self)
+{
+ g_slice_free (Aaa, self);
+}
+
+static inline gpointer
+bbb_get_instance_private (Bbb* self)
+{
+ return G_STRUCT_MEMBER_P (self, Bbb_private_offset);
+}
+
+Aaa*
+bbb_get_a (Bbb* self)
+{
+ Aaa* x = NULL;
+ Aaa* _tmp0_;
+ Aaa* result;
+ g_return_val_if_fail (IS_BBB (self), NULL);
+ _tmp0_ = self->priv->a;
+ x = _tmp0_;
+ _aaa_free0 (self->priv->a);
+ self->priv->a = NULL;
+ result = x;
+ return result;
+}
+
+Bbb*
+bbb_construct (GType object_type)
+{
+ Bbb* self = NULL;
+ self = (Bbb*) g_type_create_instance (object_type);
+ return self;
+}
+
+Bbb*
+bbb_new (void)
+{
+ return bbb_construct (TYPE_BBB);
+}
+
+static void
+value_bbb_init (GValue* value)
+{
+ value->data[0].v_pointer = NULL;
+}
+
+static void
+value_bbb_free_value (GValue* value)
+{
+ if (value->data[0].v_pointer) {
+ bbb_unref (value->data[0].v_pointer);
+ }
+}
+
+static void
+value_bbb_copy_value (const GValue* src_value,
+ GValue* dest_value)
+{
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = bbb_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+static gpointer
+value_bbb_peek_pointer (const GValue* value)
+{
+ return value->data[0].v_pointer;
+}
+
+static gchar*
+value_bbb_collect_value (GValue* value,
+ guint n_collect_values,
+ GTypeCValue* collect_values,
+ guint collect_flags)
+{
+ if (collect_values[0].v_pointer) {
+ Bbb * object;
+ object = collect_values[0].v_pointer;
+ if (object->parent_instance.g_class == NULL) {
+ return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
+ } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
+ return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
+ }
+ value->data[0].v_pointer = bbb_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+static gchar*
+value_bbb_lcopy_value (const GValue* value,
+ guint n_collect_values,
+ GTypeCValue* collect_values,
+ guint collect_flags)
+{
+ Bbb ** object_p;
+ object_p = collect_values[0].v_pointer;
+ if (!object_p) {
+ return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+ }
+ if (!value->data[0].v_pointer) {
+ *object_p = NULL;
+ } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
+ *object_p = value->data[0].v_pointer;
+ } else {
+ *object_p = bbb_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+GParamSpec*
+param_spec_bbb (const gchar* name,
+ const gchar* nick,
+ const gchar* blurb,
+ GType object_type,
+ GParamFlags flags)
+{
+ ParamSpecBbb* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_BBB), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+gpointer
+value_get_bbb (const GValue* value)
+{
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BBB), NULL);
+ return value->data[0].v_pointer;
+}
+
+void
+value_set_bbb (GValue* value,
+ gpointer v_object)
+{
+ Bbb * old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BBB));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_BBB));
+ g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
+ value->data[0].v_pointer = v_object;
+ bbb_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ bbb_unref (old);
+ }
+}
+
+void
+value_take_bbb (GValue* value,
+ gpointer v_object)
+{
+ Bbb * old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_BBB));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_BBB));
+ g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
+ value->data[0].v_pointer = v_object;
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ bbb_unref (old);
+ }
+}
+
+static void
+bbb_class_init (BbbClass * klass,
+ gpointer klass_data)
+{
+ bbb_parent_class = g_type_class_peek_parent (klass);
+ ((BbbClass *) klass)->finalize = bbb_finalize;
+ g_type_class_adjust_private_offset (klass, &Bbb_private_offset);
+}
+
+static void
+bbb_instance_init (Bbb * self,
+ gpointer klass)
+{
+ Aaa* _tmp0_;
+ self->priv = bbb_get_instance_private (self);
+ _tmp0_ = aaa_new ();
+ self->priv->a = _tmp0_;
+ self->ref_count = 1;
+}
+
+static void
+bbb_finalize (Bbb * obj)
+{
+ Bbb * self;
+ self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_BBB, Bbb);
+ g_signal_handlers_destroy (self);
+ _aaa_free0 (self->priv->a);
+}
+
+static GType
+bbb_get_type_once (void)
+{
+ static const GTypeValueTable g_define_type_value_table = { value_bbb_init, value_bbb_free_value, value_bbb_copy_value, value_bbb_peek_pointer, "p", value_bbb_collect_value, "p", value_bbb_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (BbbClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) bbb_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Bbb), 0, (GInstanceInitFunc) bbb_instance_init, &g_define_type_value_table };
+ static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
+ GType bbb_type_id;
+ bbb_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Bbb", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ Bbb_private_offset = g_type_add_instance_private (bbb_type_id, sizeof (BbbPrivate));
+ return bbb_type_id;
+}
+
+GType
+bbb_get_type (void)
+{
+ static volatile gsize bbb_type_id__once = 0;
+ if (g_once_init_enter (&bbb_type_id__once)) {
+ GType bbb_type_id;
+ bbb_type_id = bbb_get_type_once ();
+ g_once_init_leave (&bbb_type_id__once, bbb_type_id);
+ }
+ return bbb_type_id__once;
+}
+
+gpointer
+bbb_ref (gpointer instance)
+{
+ Bbb * self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+void
+bbb_unref (gpointer instance)
+{
+ Bbb * self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ BBB_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
+void
+p (__delegate0_ d,
+ gpointer d_target)
+{
+ Aaa* a = NULL;
+ Aaa* _tmp0_;
+ Aaa* _tmp1_;
+ Aaa* _tmp2_;
+ _tmp0_ = aaa_new ();
+ a = _tmp0_;
+ _tmp1_ = a;
+ a = NULL;
+ d (_tmp1_, d_target);
+ _tmp2_ = a;
+ _vala_assert (_tmp2_ == NULL, "a == null");
+ _aaa_free0 (a);
+}
+
+void
+q (__delegate1_ d,
+ gpointer d_target)
+{
+ Aaa* a = NULL;
+ Aaa* _tmp0_;
+ _tmp0_ = aaa_new ();
+ a = _tmp0_;
+ d (a, d_target);
+ _vala_assert (a->i == 42, "a.i == 42");
+ _aaa_free0 (a);
+}
+
+void
+r (__delegate2_ d,
+ gpointer d_target)
+{
+ Aaa* _tmp0_;
+ Aaa* _tmp1_;
+ _tmp0_ = d (d_target);
+ _tmp1_ = _tmp0_;
+ _vala_assert (_tmp1_->i == 42, "d ().i == 42");
+ _aaa_free0 (_tmp1_);
+}
+
+void
+s (__delegate3_ d,
+ gpointer d_target)
+{
+ Aaa* _tmp0_;
+ _tmp0_ = d (d_target);
+ _vala_assert (_tmp0_->i != 42, "d ().i != 42");
+}
+
+static void
+__lambda4_ (Aaa* a)
+{
+ g_return_if_fail (a != NULL);
+ _vala_assert (a->i == 42, "a.i == 42");
+ _aaa_free0 (a);
+}
+
+static void
+___lambda4____delegate0_ (Aaa* p0,
+ gpointer self)
+{
+ __lambda4_ (p0);
+}
+
+static void
+__lambda5_ (Aaa* a)
+{
+ g_return_if_fail (a != NULL);
+ _vala_assert (a->i == 42, "a.i == 42");
+}
+
+static void
+___lambda5____delegate1_ (Aaa* p0,
+ gpointer self)
+{
+ __lambda5_ (p0);
+}
+
+static Aaa*
+__lambda6_ (void)
+{
+ Aaa* _tmp0_;
+ Aaa* result;
+ _tmp0_ = aaa_new ();
+ result = _tmp0_;
+ return result;
+}
+
+static Aaa*
+___lambda6____delegate2_ (gpointer self)
+{
+ Aaa* result;
+ result = __lambda6_ ();
+ return result;
+}
+
+static Aaa*
+_bbb_get_a___delegate3_ (gpointer self)
+{
+ Aaa* result;
+ result = bbb_get_a ((Bbb*) self);
+ return result;
+}
+
+static void
+_vala_main (void)
+{
+ Bbb* _tmp0_;
+ Bbb* _tmp1_;
+ p (___lambda4____delegate0_, NULL);
+ q (___lambda5____delegate1_, NULL);
+ r (___lambda6____delegate2_, NULL);
+ _tmp0_ = bbb_new ();
+ _tmp1_ = _tmp0_;
+ s (_bbb_get_a___delegate3_, _tmp1_);
+ _bbb_unref0 (_tmp1_);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/delegates/anonymous-inner-owned-unowned.vala b/tests/delegates/anonymous-inner-owned-unowned.vala
new file mode 100644
index 000000000..7c3381e45
--- /dev/null
+++ b/tests/delegates/anonymous-inner-owned-unowned.vala
@@ -0,0 +1,41 @@
+[Compact]
+class Aaa {
+ public int i = 42;
+}
+
+class Bbb {
+ Aaa a = new Aaa ();
+
+ public unowned Aaa get_a () {
+ unowned Aaa x = a;
+ a = null;
+ return x;
+ }
+}
+
+void p (delegate(owned Aaa) => void d) {
+ var a = new Aaa ();
+ d ((owned) a);
+ assert (a == null);
+}
+
+void q (delegate(Aaa) => void d) {
+ var a = new Aaa ();
+ d (a);
+ assert (a.i == 42);
+}
+
+void r (delegate() => Aaa d) {
+ assert (d ().i == 42);
+}
+
+void s (delegate() => unowned Aaa d) {
+ assert (d ().i != 42);
+}
+
+void main () {
+ p ((a) => assert (a.i == 42));
+ q ((a) => assert (a.i == 42));
+ r (() => new Aaa());
+ s (new Bbb().get_a);
+}
diff --git a/tests/delegates/anonymous-inner-params.test b/tests/delegates/anonymous-inner-params.test
new file mode 100644
index 000000000..4dcb3e698
--- /dev/null
+++ b/tests/delegates/anonymous-inner-params.test
@@ -0,0 +1,19 @@
+Invalid Code
+
+/*
+ * 13.18-13.23: error: Params-arrays not allowed in anonymous delegates
+ * void f (delegate(params string[]) => void y) {
+ * ^^^^^^
+ */
+
+void main () {
+ f (t);
+}
+
+void f (delegate(params string[]) => void y) {
+ y ("1", "2", "3");
+}
+
+void t (params string[] p) {
+ assert (p.length == 3);
+}
diff --git a/tests/delegates/anonymous-inner-ref-out.c-expected b/tests/delegates/anonymous-inner-ref-out.c-expected
new file mode 100644
index 000000000..4ab8a1206
--- /dev/null
+++ b/tests/delegates/anonymous-inner-ref-out.c-expected
@@ -0,0 +1,100 @@
+/* delegates_anonymous_inner_ref_out.c generated by valac, the Vala compiler
+ * generated from delegates_anonymous_inner_ref_out.vala, do not modify */
+
+#include <glib.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef void (*__delegate0_) (gint* p0, gpointer user_data);
+typedef void (*__delegate1_) (gint* p0, gpointer user_data);
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+static void _vala_main (void);
+VALA_EXTERN void f (__delegate0_ x,
+ gpointer x_target);
+VALA_EXTERN void t (gint* a);
+static void _t___delegate0_ (gint* p0,
+ gpointer self);
+VALA_EXTERN void g (__delegate1_ y,
+ gpointer y_target);
+VALA_EXTERN void d (gint* a);
+static void _d___delegate1_ (gint* p0,
+ gpointer self);
+
+static void
+_t___delegate0_ (gint* p0,
+ gpointer self)
+{
+ t (p0);
+}
+
+static void
+_d___delegate1_ (gint* p0,
+ gpointer self)
+{
+ d (p0);
+}
+
+static void
+_vala_main (void)
+{
+ f (_t___delegate0_, NULL);
+ g (_d___delegate1_, NULL);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
+void
+f (__delegate0_ x,
+ gpointer x_target)
+{
+ gint i = 0;
+ i = 42;
+ x (&i, x_target);
+ _vala_assert (i == 7, "i == 7");
+}
+
+void
+g (__delegate1_ y,
+ gpointer y_target)
+{
+ gint i = 0;
+ gint _tmp0_ = 0;
+ y (&_tmp0_, y_target);
+ i = _tmp0_;
+ _vala_assert (i == 42, "i == 42");
+}
+
+void
+t (gint* a)
+{
+ *a = 7;
+}
+
+void
+d (gint* a)
+{
+ gint _vala_a = 0;
+ _vala_a = 42;
+ if (a) {
+ *a = _vala_a;
+ }
+}
+
diff --git a/tests/delegates/anonymous-inner-ref-out.vala b/tests/delegates/anonymous-inner-ref-out.vala
new file mode 100644
index 000000000..b094d1ca0
--- /dev/null
+++ b/tests/delegates/anonymous-inner-ref-out.vala
@@ -0,0 +1,24 @@
+void main () {
+ f (t);
+ g (d);
+}
+
+void f (delegate(ref int) => void x) {
+ int i = 42;
+ x (ref i);
+ assert (i == 7);
+}
+
+void g (delegate(out int) => void y) {
+ int i;
+ y (out i);
+ assert (i == 42);
+}
+
+void t (ref int a) {
+ a = 7;
+}
+
+void d (out int a) {
+ a = 42;
+}
diff --git a/tests/delegates/anonymous-optional-param.test b/tests/delegates/anonymous-optional-param.test
new file mode 100644
index 000000000..4ac24c470
--- /dev/null
+++ b/tests/delegates/anonymous-optional-param.test
@@ -0,0 +1,19 @@
+Invalid Code
+
+/*
+ * 11.21-11.21: error: Optional parameters not allowed in anonymous delegates
+ * void f (delegate(int=123) => int y) {
+ * ^
+ */
+
+void main () {
+ f (t);
+}
+
+void f (delegate(int=123) => int y) {
+ y (1);
+}
+
+int t (int a) {
+ return a;
+}
diff --git a/tests/delegates/anonymous-out.test b/tests/delegates/anonymous-out.test
new file mode 100644
index 000000000..731320623
--- /dev/null
+++ b/tests/delegates/anonymous-out.test
@@ -0,0 +1,15 @@
+Invalid Code
+
+/*
+ * 13.9-13.33: error: Anonymous delegates cannot be `out` parameters
+ * void f (out delegate(int) => void x) {
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ */
+
+void main () {
+ assert (true);
+}
+
+void f (out delegate(int) => void x) {
+ x(42);
+}
diff --git a/tests/delegates/anonymous-param-attrs.c-expected b/tests/delegates/anonymous-param-attrs.c-expected
new file mode 100644
index 000000000..19961e26f
--- /dev/null
+++ b/tests/delegates/anonymous-param-attrs.c-expected
@@ -0,0 +1,62 @@
+/* delegates_anonymous_param_attrs.c generated by valac, the Vala compiler
+ * generated from delegates_anonymous_param_attrs.vala, do not modify */
+
+#include <glib.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef void (*__delegate0_) (gint8 p0, gpointer user_data);
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+VALA_EXTERN void f (__delegate0_ d,
+ gpointer d_target);
+VALA_EXTERN void t (gint a);
+static void _vala_main (void);
+static void _t___delegate0_ (gint8 p0,
+ gpointer self);
+
+void
+f (__delegate0_ d,
+ gpointer d_target)
+{
+ d ((gint8) 300, d_target);
+}
+
+void
+t (gint a)
+{
+ _vala_assert (a == 44, "a == 44");
+}
+
+static void
+_t___delegate0_ (gint8 p0,
+ gpointer self)
+{
+ t (p0);
+}
+
+static void
+_vala_main (void)
+{
+ f (_t___delegate0_, NULL);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/delegates/anonymous-param-attrs.vala b/tests/delegates/anonymous-param-attrs.vala
new file mode 100644
index 000000000..4b0726b1f
--- /dev/null
+++ b/tests/delegates/anonymous-param-attrs.vala
@@ -0,0 +1,11 @@
+void f (delegate([CCode (type = "gint8")] int) => void d) {
+ d (300);
+}
+
+void t (int a) {
+ assert (a == 44);
+}
+
+void main () {
+ f (t);
+}
diff --git a/tests/delegates/anonymous-params.test b/tests/delegates/anonymous-params.test
new file mode 100644
index 000000000..4772114bd
--- /dev/null
+++ b/tests/delegates/anonymous-params.test
@@ -0,0 +1,15 @@
+Invalid Code
+
+/*
+ * 9.9-9.32: error: Anonymous delegates cannot be param-arrays
+ * void p (params delegate() => int d) {
+ * ^^^^^^^^^^^^^^^^^^^^^^^^
+ */
+
+void p (params delegate() => int d) {
+ d ();
+}
+
+void main () {
+ return;
+}
diff --git a/tests/delegates/anonymous-ref.test b/tests/delegates/anonymous-ref.test
new file mode 100644
index 000000000..e79835a38
--- /dev/null
+++ b/tests/delegates/anonymous-ref.test
@@ -0,0 +1,15 @@
+Invalid Code
+
+/*
+ * 13.9-13.33: error: Anonymous delegates cannot be `ref` parameters
+ * void f (ref delegate(int) => void x) {
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^
+ */
+
+void main() {
+ assert (true);
+}
+
+void f (ref delegate(int) => void x) {
+ x (42);
+}
diff --git a/tests/delegates/anonymous-return-anonymous.test b/tests/delegates/anonymous-return-anonymous.test
new file mode 100644
index 000000000..47be7785f
--- /dev/null
+++ b/tests/delegates/anonymous-return-anonymous.test
@@ -0,0 +1,18 @@
+Invalid Code
+
+ /*
+ * 9.26-9.33: error: syntax error, anonymous delegate not allowed here
+ * void f (delegate(int) => delegate() => int d) {
+ * ^^^^^^^^
+ */
+
+void f (delegate(int) => delegate() => int d) {
+ var r = d (14);
+ stdout.printf("%d\n", r ());
+}
+
+void main () {
+ f ((a) => {
+ return () => a;
+ });
+}
diff --git a/tests/delegates/anonymous-throws.test b/tests/delegates/anonymous-throws.test
new file mode 100644
index 000000000..ff11a805d
--- /dev/null
+++ b/tests/delegates/anonymous-throws.test
@@ -0,0 +1,21 @@
+Invalid Code
+
+/*
+ * 11.30-11.30: error: syntax error, following expression/statement delimiter `)' missing
+ * void f (delegate(int) => int y throws Error) {
+ * ^
+ */
+
+void main () {
+ f (t);
+}
+
+void f (delegate(int) => int y throws Error) {
+ try {
+ y (1);
+ } catch {}
+}
+
+int t (int a) throws Error {
+ return a;
+}
diff --git a/tests/delegates/anonymous-type-param.c-expected b/tests/delegates/anonymous-type-param.c-expected
new file mode 100644
index 000000000..d4240d4c5
--- /dev/null
+++ b/tests/delegates/anonymous-type-param.c-expected
@@ -0,0 +1,423 @@
+/* delegates_anonymous_type_param.c generated by valac, the Vala compiler
+ * generated from delegates_anonymous_type_param.vala, do not modify */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+#define TYPE_COMP (comp_get_type ())
+#define COMP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_COMP, Comp))
+#define COMP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_COMP, CompClass))
+#define IS_COMP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_COMP))
+#define IS_COMP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_COMP))
+#define COMP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_COMP, CompClass))
+
+typedef struct _Comp Comp;
+typedef struct _CompClass CompClass;
+typedef gchar* (*__delegate0_) (Comp* p0, Comp* p1, gpointer user_data);
+#define _g_free0(var) (var = (g_free (var), NULL))
+#define _comp_unref0(var) ((var == NULL) ? NULL : (var = (comp_unref (var), NULL)))
+typedef struct _CompPrivate CompPrivate;
+typedef struct _ParamSpecComp ParamSpecComp;
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+struct _Comp {
+ GTypeInstance parent_instance;
+ volatile int ref_count;
+ CompPrivate * priv;
+};
+
+struct _CompClass {
+ GTypeClass parent_class;
+ void (*finalize) (Comp *self);
+};
+
+struct _CompPrivate {
+ GType a_type;
+ GBoxedCopyFunc a_dup_func;
+ GDestroyNotify a_destroy_func;
+ gpointer _a;
+};
+
+struct _ParamSpecComp {
+ GParamSpec parent_instance;
+};
+
+static gint Comp_private_offset;
+static gpointer comp_parent_class = NULL;
+
+static void _vala_main (void);
+VALA_EXTERN gpointer comp_ref (gpointer instance);
+VALA_EXTERN void comp_unref (gpointer instance);
+VALA_EXTERN GParamSpec* param_spec_comp (const gchar* name,
+ const gchar* nick,
+ const gchar* blurb,
+ GType object_type,
+ GParamFlags flags);
+VALA_EXTERN void value_set_comp (GValue* value,
+ gpointer v_object);
+VALA_EXTERN void value_take_comp (GValue* value,
+ gpointer v_object);
+VALA_EXTERN gpointer value_get_comp (const GValue* value);
+VALA_EXTERN GType comp_get_type (void) G_GNUC_CONST ;
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (Comp, comp_unref)
+VALA_EXTERN void f (__delegate0_ abc,
+ gpointer abc_target);
+VALA_EXTERN gchar* t (Comp* a,
+ Comp* b);
+static gchar* _t___delegate0_ (Comp* p0,
+ Comp* p1,
+ gpointer self);
+VALA_EXTERN gconstpointer comp_get_a (Comp* self);
+VALA_EXTERN Comp* comp_new (GType a_type,
+ GBoxedCopyFunc a_dup_func,
+ GDestroyNotify a_destroy_func,
+ gconstpointer a);
+VALA_EXTERN Comp* comp_construct (GType object_type,
+ GType a_type,
+ GBoxedCopyFunc a_dup_func,
+ GDestroyNotify a_destroy_func,
+ gconstpointer a);
+static void comp_set_a (Comp* self,
+ gconstpointer value);
+static void comp_finalize (Comp * obj);
+static GType comp_get_type_once (void);
+
+static gchar*
+_t___delegate0_ (Comp* p0,
+ Comp* p1,
+ gpointer self)
+{
+ gchar* result;
+ result = t (p0, p1);
+ return result;
+}
+
+static void
+_vala_main (void)
+{
+ f (_t___delegate0_, NULL);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
+gchar*
+t (Comp* a,
+ Comp* b)
+{
+ gconstpointer _tmp0_;
+ gconstpointer _tmp1_;
+ gconstpointer _tmp2_;
+ gconstpointer _tmp3_;
+ gchar* _tmp4_;
+ gchar* result;
+ g_return_val_if_fail (IS_COMP (a), NULL);
+ g_return_val_if_fail (IS_COMP (b), NULL);
+ _tmp0_ = comp_get_a (a);
+ _tmp1_ = _tmp0_;
+ _tmp2_ = comp_get_a (b);
+ _tmp3_ = _tmp2_;
+ _tmp4_ = g_strconcat ((const gchar*) _tmp1_, (const gchar*) _tmp3_, NULL);
+ result = _tmp4_;
+ return result;
+}
+
+void
+f (__delegate0_ abc,
+ gpointer abc_target)
+{
+ Comp* _tmp0_;
+ Comp* _tmp1_;
+ Comp* _tmp2_;
+ Comp* _tmp3_;
+ gchar* _tmp4_;
+ gchar* _tmp5_;
+ _tmp0_ = comp_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free, "x");
+ _tmp1_ = _tmp0_;
+ _tmp2_ = comp_new (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free, "y");
+ _tmp3_ = _tmp2_;
+ _tmp4_ = abc (_tmp1_, _tmp3_, abc_target);
+ _tmp5_ = _tmp4_;
+ _vala_assert (g_strcmp0 (_tmp5_, "xy") == 0, "abc(new Comp<string> (\"x\"), new Comp<string> (\"y\")) == \"xy\"");
+ _g_free0 (_tmp5_);
+ _comp_unref0 (_tmp3_);
+ _comp_unref0 (_tmp1_);
+}
+
+static inline gpointer
+comp_get_instance_private (Comp* self)
+{
+ return G_STRUCT_MEMBER_P (self, Comp_private_offset);
+}
+
+Comp*
+comp_construct (GType object_type,
+ GType a_type,
+ GBoxedCopyFunc a_dup_func,
+ GDestroyNotify a_destroy_func,
+ gconstpointer a)
+{
+ Comp* self = NULL;
+ self = (Comp*) g_type_create_instance (object_type);
+ self->priv->a_type = a_type;
+ self->priv->a_dup_func = a_dup_func;
+ self->priv->a_destroy_func = a_destroy_func;
+ comp_set_a (self, a);
+ return self;
+}
+
+Comp*
+comp_new (GType a_type,
+ GBoxedCopyFunc a_dup_func,
+ GDestroyNotify a_destroy_func,
+ gconstpointer a)
+{
+ return comp_construct (TYPE_COMP, a_type, a_dup_func, a_destroy_func, a);
+}
+
+gconstpointer
+comp_get_a (Comp* self)
+{
+ gconstpointer result;
+ gconstpointer _tmp0_;
+ g_return_val_if_fail (IS_COMP (self), NULL);
+ _tmp0_ = self->priv->_a;
+ result = _tmp0_;
+ return result;
+}
+
+static void
+comp_set_a (Comp* self,
+ gconstpointer value)
+{
+ gpointer _tmp0_;
+ g_return_if_fail (IS_COMP (self));
+ _tmp0_ = ((value != NULL) && (self->priv->a_dup_func != NULL)) ? self->priv->a_dup_func ((gpointer) value) : ((gpointer) value);
+ ((self->priv->_a == NULL) || (self->priv->a_destroy_func == NULL)) ? NULL : (self->priv->_a = (self->priv->a_destroy_func (self->priv->_a), NULL));
+ self->priv->_a = _tmp0_;
+}
+
+static void
+value_comp_init (GValue* value)
+{
+ value->data[0].v_pointer = NULL;
+}
+
+static void
+value_comp_free_value (GValue* value)
+{
+ if (value->data[0].v_pointer) {
+ comp_unref (value->data[0].v_pointer);
+ }
+}
+
+static void
+value_comp_copy_value (const GValue* src_value,
+ GValue* dest_value)
+{
+ if (src_value->data[0].v_pointer) {
+ dest_value->data[0].v_pointer = comp_ref (src_value->data[0].v_pointer);
+ } else {
+ dest_value->data[0].v_pointer = NULL;
+ }
+}
+
+static gpointer
+value_comp_peek_pointer (const GValue* value)
+{
+ return value->data[0].v_pointer;
+}
+
+static gchar*
+value_comp_collect_value (GValue* value,
+ guint n_collect_values,
+ GTypeCValue* collect_values,
+ guint collect_flags)
+{
+ if (collect_values[0].v_pointer) {
+ Comp * object;
+ object = collect_values[0].v_pointer;
+ if (object->parent_instance.g_class == NULL) {
+ return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
+ } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
+ return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
+ }
+ value->data[0].v_pointer = comp_ref (object);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ return NULL;
+}
+
+static gchar*
+value_comp_lcopy_value (const GValue* value,
+ guint n_collect_values,
+ GTypeCValue* collect_values,
+ guint collect_flags)
+{
+ Comp ** object_p;
+ object_p = collect_values[0].v_pointer;
+ if (!object_p) {
+ return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+ }
+ if (!value->data[0].v_pointer) {
+ *object_p = NULL;
+ } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
+ *object_p = value->data[0].v_pointer;
+ } else {
+ *object_p = comp_ref (value->data[0].v_pointer);
+ }
+ return NULL;
+}
+
+GParamSpec*
+param_spec_comp (const gchar* name,
+ const gchar* nick,
+ const gchar* blurb,
+ GType object_type,
+ GParamFlags flags)
+{
+ ParamSpecComp* spec;
+ g_return_val_if_fail (g_type_is_a (object_type, TYPE_COMP), NULL);
+ spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
+ G_PARAM_SPEC (spec)->value_type = object_type;
+ return G_PARAM_SPEC (spec);
+}
+
+gpointer
+value_get_comp (const GValue* value)
+{
+ g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_COMP), NULL);
+ return value->data[0].v_pointer;
+}
+
+void
+value_set_comp (GValue* value,
+ gpointer v_object)
+{
+ Comp * old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_COMP));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_COMP));
+ g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
+ value->data[0].v_pointer = v_object;
+ comp_ref (value->data[0].v_pointer);
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ comp_unref (old);
+ }
+}
+
+void
+value_take_comp (GValue* value,
+ gpointer v_object)
+{
+ Comp * old;
+ g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, TYPE_COMP));
+ old = value->data[0].v_pointer;
+ if (v_object) {
+ g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, TYPE_COMP));
+ g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
+ value->data[0].v_pointer = v_object;
+ } else {
+ value->data[0].v_pointer = NULL;
+ }
+ if (old) {
+ comp_unref (old);
+ }
+}
+
+static void
+comp_class_init (CompClass * klass,
+ gpointer klass_data)
+{
+ comp_parent_class = g_type_class_peek_parent (klass);
+ ((CompClass *) klass)->finalize = comp_finalize;
+ g_type_class_adjust_private_offset (klass, &Comp_private_offset);
+}
+
+static void
+comp_instance_init (Comp * self,
+ gpointer klass)
+{
+ self->priv = comp_get_instance_private (self);
+ self->ref_count = 1;
+}
+
+static void
+comp_finalize (Comp * obj)
+{
+ Comp * self;
+ self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_COMP, Comp);
+ g_signal_handlers_destroy (self);
+ ((self->priv->_a == NULL) || (self->priv->a_destroy_func == NULL)) ? NULL : (self->priv->_a = (self->priv->a_destroy_func (self->priv->_a), NULL));
+}
+
+static GType
+comp_get_type_once (void)
+{
+ static const GTypeValueTable g_define_type_value_table = { value_comp_init, value_comp_free_value, value_comp_copy_value, value_comp_peek_pointer, "p", value_comp_collect_value, "p", value_comp_lcopy_value };
+ static const GTypeInfo g_define_type_info = { sizeof (CompClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) comp_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Comp), 0, (GInstanceInitFunc) comp_instance_init, &g_define_type_value_table };
+ static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
+ GType comp_type_id;
+ comp_type_id = g_type_register_fundamental (g_type_fundamental_next (), "Comp", &g_define_type_info, &g_define_type_fundamental_info, 0);
+ Comp_private_offset = g_type_add_instance_private (comp_type_id, sizeof (CompPrivate));
+ return comp_type_id;
+}
+
+GType
+comp_get_type (void)
+{
+ static volatile gsize comp_type_id__once = 0;
+ if (g_once_init_enter (&comp_type_id__once)) {
+ GType comp_type_id;
+ comp_type_id = comp_get_type_once ();
+ g_once_init_leave (&comp_type_id__once, comp_type_id);
+ }
+ return comp_type_id__once;
+}
+
+gpointer
+comp_ref (gpointer instance)
+{
+ Comp * self;
+ self = instance;
+ g_atomic_int_inc (&self->ref_count);
+ return instance;
+}
+
+void
+comp_unref (gpointer instance)
+{
+ Comp * self;
+ self = instance;
+ if (g_atomic_int_dec_and_test (&self->ref_count)) {
+ COMP_GET_CLASS (self)->finalize (self);
+ g_type_free_instance ((GTypeInstance *) self);
+ }
+}
+
diff --git a/tests/delegates/anonymous-type-param.vala b/tests/delegates/anonymous-type-param.vala
new file mode 100644
index 000000000..b5485aa5c
--- /dev/null
+++ b/tests/delegates/anonymous-type-param.vala
@@ -0,0 +1,20 @@
+void main () {
+ f (t);
+}
+
+string t (Comp<string> a, Comp<string> b) {
+ return a.a + b.a;
+}
+
+
+void f (delegate(Comp<string>, Comp<string>) => string abc) {
+ assert (abc(new Comp<string> ("x"), new Comp<string> ("y")) == "xy");
+}
+
+class Comp<A> {
+ public A a { get; private set; }
+
+ public Comp (A a) {
+ this.a = a;
+ }
+}
diff --git a/tests/delegates/anonymous-variadic.test b/tests/delegates/anonymous-variadic.test
new file mode 100644
index 000000000..fabd3a422
--- /dev/null
+++ b/tests/delegates/anonymous-variadic.test
@@ -0,0 +1,19 @@
+Invalid Code
+
+/*
+ * 11.23-11.25: error: syntax error, expected identifier
+ * void f (delegate(int, ...) => int y) {
+ * ^^^
+ */
+
+void main () {
+ f (t);
+}
+
+void f (delegate(int, ...) => int y) {
+ y (1);
+}
+
+int t (int a, ...) {
+ return a;
+}
diff --git a/tests/delegates/anonymous.c-expected b/tests/delegates/anonymous.c-expected
new file mode 100644
index 000000000..68c369b39
--- /dev/null
+++ b/tests/delegates/anonymous.c-expected
@@ -0,0 +1,70 @@
+/* delegates_anonymous.c generated by valac, the Vala compiler
+ * generated from delegates_anonymous.vala, do not modify */
+
+#include <glib.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef gint (*__delegate0_) (gint p0, gint p1, gpointer user_data);
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+static void _vala_main (void);
+VALA_EXTERN void f (__delegate0_ abc,
+ gpointer abc_target);
+static gint __lambda4_ (gint a,
+ gint b);
+static gint ___lambda4____delegate0_ (gint p0,
+ gint p1,
+ gpointer self);
+
+static gint
+__lambda4_ (gint a,
+ gint b)
+{
+ gint result;
+ result = a + b;
+ return result;
+}
+
+static gint
+___lambda4____delegate0_ (gint p0,
+ gint p1,
+ gpointer self)
+{
+ gint result;
+ result = __lambda4_ (p0, p1);
+ return result;
+}
+
+static void
+_vala_main (void)
+{
+ f (___lambda4____delegate0_, NULL);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
+void
+f (__delegate0_ abc,
+ gpointer abc_target)
+{
+ _vala_assert (abc (1, 2, abc_target) == 3, "abc (1, 2) == 3");
+}
+
diff --git a/tests/delegates/anonymous.vala b/tests/delegates/anonymous.vala
new file mode 100644
index 000000000..eff97e298
--- /dev/null
+++ b/tests/delegates/anonymous.vala
@@ -0,0 +1,9 @@
+void main () {
+ f ((a, b) => {
+ return a + b;
+ });
+}
+
+void f (delegate(int, int) => int abc) {
+ assert (abc (1, 2) == 3);
+}
diff --git a/tests/methods/parameter-anonymous-delegate-optional.c-expected b/tests/methods/parameter-anonymous-delegate-optional.c-expected
new file mode 100644
index 000000000..5075818f3
--- /dev/null
+++ b/tests/methods/parameter-anonymous-delegate-optional.c-expected
@@ -0,0 +1,89 @@
+/* methods_parameter_anonymous_delegate_optional.c generated by valac, the Vala compiler
+ * generated from methods_parameter_anonymous_delegate_optional.vala, do not modify */
+
+#include <glib.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef gint (*__delegate0_) (gint p0, gpointer user_data);
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+VALA_EXTERN gint f (__delegate0_ d,
+ gpointer d_target);
+static void _vala_main (void);
+static gint __lambda5_ (gint a);
+static gint ___lambda5____delegate0_ (gint p0,
+ gpointer self);
+static gint _lambda4_ (gint a);
+static gint __lambda4____delegate0_ (gint p0,
+ gpointer self);
+
+gint
+f (__delegate0_ d,
+ gpointer d_target)
+{
+ gint result;
+ result = d (7, d_target);
+ return result;
+}
+
+static gint
+__lambda5_ (gint a)
+{
+ gint result;
+ result = a;
+ return result;
+}
+
+static gint
+___lambda5____delegate0_ (gint p0,
+ gpointer self)
+{
+ gint result;
+ result = __lambda5_ (p0);
+ return result;
+}
+
+static gint
+_lambda4_ (gint a)
+{
+ gint result;
+ result = 2 * a;
+ return result;
+}
+
+static gint
+__lambda4____delegate0_ (gint p0,
+ gpointer self)
+{
+ gint result;
+ result = _lambda4_ (p0);
+ return result;
+}
+
+static void
+_vala_main (void)
+{
+ _vala_assert (f (___lambda5____delegate0_, NULL) == 7, "f (a => a) == 7");
+ _vala_assert (f (__lambda4____delegate0_, NULL) == 14, "f () == 14");
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/methods/parameter-anonymous-delegate-optional.vala b/tests/methods/parameter-anonymous-delegate-optional.vala
new file mode 100644
index 000000000..dc6085b34
--- /dev/null
+++ b/tests/methods/parameter-anonymous-delegate-optional.vala
@@ -0,0 +1,8 @@
+int f (delegate(int) => int d = (a) => 2*a) {
+ return d (7);
+}
+
+void main () {
+ assert (f (a => a) == 7);
+ assert (f () == 14);
+}
diff --git a/tests/methods/parameter-anonymous-delegate.c-expected b/tests/methods/parameter-anonymous-delegate.c-expected
new file mode 100644
index 000000000..a4f4aa324
--- /dev/null
+++ b/tests/methods/parameter-anonymous-delegate.c-expected
@@ -0,0 +1,130 @@
+/* methods_parameter_anonymous_delegate.c generated by valac, the Vala compiler
+ * generated from methods_parameter_anonymous_delegate.vala, do not modify */
+
+#include <glib.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef gint (*__delegate0_) (gint p0, gint p1, gpointer user_data);
+typedef gint (*__delegate1_) (gint p0, gint p1, gpointer user_data);
+typedef gint (*__delegate2_) (gint p0, gint p1, gpointer user_data);
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
+
+VALA_EXTERN gint func (gint a,
+ gint b);
+VALA_EXTERN void foo (__delegate0_ p,
+ gpointer p_target,
+ gint r);
+VALA_EXTERN void bar (gint r,
+ __delegate1_ p,
+ gpointer p_target,
+ GDestroyNotify p_target_destroy_notify);
+VALA_EXTERN void manam (__delegate2_ p,
+ gpointer p_target,
+ gint r);
+static void _vala_main (void);
+static gint _func___delegate0_ (gint p0,
+ gint p1,
+ gpointer self);
+static gint _func___delegate1_ (gint p0,
+ gint p1,
+ gpointer self);
+static gint _func___delegate2_ (gint p0,
+ gint p1,
+ gpointer self);
+
+gint
+func (gint a,
+ gint b)
+{
+ gint result;
+ result = a + b;
+ return result;
+}
+
+void
+foo (__delegate0_ p,
+ gpointer p_target,
+ gint r)
+{
+ _vala_assert (p (23, 42, p_target) == r, "p (23, 42) == r");
+}
+
+void
+bar (gint r,
+ __delegate1_ p,
+ gpointer p_target,
+ GDestroyNotify p_target_destroy_notify)
+{
+ _vala_assert (p (23, 42, p_target) == r, "p (23, 42) == r");
+ (p_target_destroy_notify == NULL) ? NULL : (p_target_destroy_notify (p_target), NULL);
+ p = NULL;
+ p_target = NULL;
+ p_target_destroy_notify = NULL;
+}
+
+void
+manam (__delegate2_ p,
+ gpointer p_target,
+ gint r)
+{
+ _vala_assert (p (23, 42, p_target) == r, "p (23, 42) == r");
+}
+
+static gint
+_func___delegate0_ (gint p0,
+ gint p1,
+ gpointer self)
+{
+ gint result;
+ result = func (p0, p1);
+ return result;
+}
+
+static gint
+_func___delegate1_ (gint p0,
+ gint p1,
+ gpointer self)
+{
+ gint result;
+ result = func (p0, p1);
+ return result;
+}
+
+static gint
+_func___delegate2_ (gint p0,
+ gint p1,
+ gpointer self)
+{
+ gint result;
+ result = func (p0, p1);
+ return result;
+}
+
+static void
+_vala_main (void)
+{
+ foo (_func___delegate0_, NULL, 65);
+ bar (65, _func___delegate1_, NULL, NULL);
+ manam (_func___delegate2_, NULL, 65);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/methods/parameter-anonymous-delegate.vala b/tests/methods/parameter-anonymous-delegate.vala
new file mode 100644
index 000000000..da3e624be
--- /dev/null
+++ b/tests/methods/parameter-anonymous-delegate.vala
@@ -0,0 +1,21 @@
+int func (int a, int b) {
+ return a + b;
+}
+
+void foo (delegate(int, int) => int p, int r) {
+ assert (p (23, 42) == r);
+}
+
+void bar (int r, owned delegate(int, int) => int p) {
+ assert (p (23, 42) == r);
+}
+
+void manam ([CCode (has_target = false)] delegate(int, int) => int p, int r) {
+ assert (p (23, 42) == r);
+}
+
+void main () {
+ foo (func, 65);
+ bar (65, func);
+ manam (func, 65);
+}
diff --git a/vala/valacallabletype.vala b/vala/valacallabletype.vala
index 6ea2349d0..c2957a342 100644
--- a/vala/valacallabletype.vala
+++ b/vala/valacallabletype.vala
@@ -71,7 +71,11 @@ public abstract class Vala.CallableType : DataType {
// Append name
builder.append_c (' ');
- builder.append (override_name ?? this.to_string ());
+ if (symbol.anonymous) {
+ builder.append ("<anonymous>");
+ } else {
+ builder.append (override_name ?? this.to_string ());
+ }
builder.append_c (' ');
// Append parameter-list
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index f9f1fccd1..5887392fd 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -683,7 +683,11 @@ public class Vala.CodeWriter : CodeVisitor {
}
}
- write_type (param.variable_type);
+ if (param.variable_type is DelegateType && param.variable_type.type_symbol.anonymous) {
+ write_anonymous_delegate (param.variable_type as DelegateType);
+ } else {
+ write_type (param.variable_type);
+ }
write_string (" ");
write_identifier (param.name);
@@ -709,6 +713,10 @@ public class Vala.CodeWriter : CodeVisitor {
return;
}
+ if (cb.anonymous) {
+ return;
+ }
+
if (context.vapi_comments && cb.comment != null) {
write_comment (cb.comment);
}
@@ -1614,6 +1622,43 @@ public class Vala.CodeWriter : CodeVisitor {
stream.putc ('}');
}
+ private void write_anonymous_params (List<Parameter> params) {
+ write_string ("(");
+
+ int i = 1;
+ foreach (Parameter param in params) {
+ if (i > 1) {
+ write_string (", ");
+ }
+
+ write_attributes (param);
+
+ if (param.direction == ParameterDirection.REF) {
+ write_string ("ref ");
+ } else if (param.direction == ParameterDirection.OUT) {
+ write_string ("out ");
+ }
+
+ write_type (param.variable_type);
+ write_type_suffix (param.variable_type);
+
+ i++;
+ }
+
+ write_string (")");
+
+ }
+
+ private void write_anonymous_delegate (DelegateType cb) {
+ write_attributes (cb);
+
+ write_string ("delegate");
+ write_anonymous_params (cb.get_parameters ());
+
+ write_string (" => ");
+ write_return_type (cb.get_return_type ());
+ }
+
private bool check_accessibility (Symbol sym) {
switch (type) {
case CodeWriterType.EXTERNAL:
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 9ac94e4a5..1b1e51ac4 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -517,7 +517,7 @@ public class Vala.Parser : CodeVisitor {
return result;
}
- DataType parse_type (bool owned_by_default, bool can_weak_ref, bool require_unowned = false) throws ParseError {
+ DataType parse_type (bool owned_by_default, bool can_weak_ref, bool require_unowned = false, Symbol? parent=null, Method? method=null) throws ParseError {
var begin = get_location ();
bool is_dynamic = accept (TokenType.DYNAMIC);
@@ -552,6 +552,19 @@ public class Vala.Parser : CodeVisitor {
DataType type;
+ var begin_delegate_token = get_location ();
+ var is_delegate_token = accept (TokenType.DELEGATE);
+ rollback (begin_delegate_token);
+
+ if (is_delegate_token && method == null) {
+ throw new ParseError.SYNTAX ("anonymous delegate not allowed here");
+ } else if (is_delegate_token) {
+ type = parse_anonymous_delegate (parent, method);
+ type.value_owned = value_owned;
+ type.is_dynamic = is_dynamic;
+ return type;
+ }
+
bool inner_type_owned = true;
if (accept (TokenType.OPEN_PARENS)) {
type = parse_type (false, false, true);
@@ -3280,7 +3293,7 @@ public class Vala.Parser : CodeVisitor {
expect (TokenType.OPEN_PARENS);
if (current () != TokenType.CLOSE_PARENS) {
do {
- var param = parse_parameter ();
+ var param = parse_parameter (parent, method);
method.add_parameter (param);
} while (accept (TokenType.COMMA));
}
@@ -3815,7 +3828,8 @@ public class Vala.Parser : CodeVisitor {
}
}
- Parameter parse_parameter () throws ParseError {
+ Parameter parse_parameter (Symbol? parent=null, Method? method=null) throws ParseError {
+ var begin_attrs = get_location ();
var attrs = parse_attributes ();
var begin = get_location ();
if (accept (TokenType.ELLIPSIS)) {
@@ -3831,18 +3845,45 @@ public class Vala.Parser : CodeVisitor {
}
DataType type;
+ string pretty_direction = null;
if (direction == ParameterDirection.IN) {
// in parameters are unowned by default
- type = parse_type (false, false);
+ type = parse_type (false, false, false, parent, method);
} else if (direction == ParameterDirection.REF) {
// ref parameters own the value by default
- type = parse_type (true, true);
+ type = parse_type (true, true, false, parent, method);
+ pretty_direction = "ref";
} else {
// out parameters own the value by default
- type = parse_type (true, false);
+ type = parse_type (true, false, false, parent, method);
+ pretty_direction = "out";
}
+
string id = parse_identifier ();
+ var possibly_delegate = type as DelegateType;
+ if (possibly_delegate != null && possibly_delegate.delegate_symbol.anonymous) {
+ if (attrs != null) {
+ var here = get_location ();
+ rollback (begin);
+ Report.warning (get_src (begin_attrs), "Ambiguous attribute: does it belong to `%s` or parameter `%s`?"
+ .printf (possibly_delegate.to_prototype_string (), id));
+ rollback (here);
+ }
+
+ if (pretty_direction != null) {
+ Report.error (get_src (begin), "Anonymous delegates cannot be `" + pretty_direction + "` parameters");
+ }
+
+ if (possibly_delegate.is_dynamic) {
+ Report.error (get_src (begin), "Anonymous delegates cannot be dynamic types");
+ }
+
+ if (params_array) {
+ Report.error (get_src (begin), "Anonymous delegates cannot be param-arrays");
+ }
+ }
+
type = parse_inline_array_type (type);
var param = new Parameter (id, type, get_src (begin));
@@ -3975,6 +4016,92 @@ public class Vala.Parser : CodeVisitor {
}
}
+ static int next_anonymous_id = 0;
+
+ Parameter parse_anonymous_parameter (int id) throws ParseError {
+ var attrs = parse_attributes ();
+ var begin = get_location ();
+
+ if (accept (TokenType.PARAMS)) {
+ Report.error (get_last_src (), "Params-arrays not allowed in anonymous delegates");
+ }
+
+ var direction = ParameterDirection.IN;
+ if (accept (TokenType.OUT)) {
+ direction = ParameterDirection.OUT;
+ } else if (accept (TokenType.REF)) {
+ direction = ParameterDirection.REF;
+ }
+
+ DataType type;
+ var type_loc = get_location ();
+ if (direction == ParameterDirection.IN) {
+ // in parameters are unowned by default
+ type = parse_type (false, false);
+ } else if (direction == ParameterDirection.REF) {
+ // ref parameters own the value by default
+ type = parse_type (true, true);
+ } else {
+ // out parameters own the value by default
+ type = parse_type (true, false);
+ }
+
+ if (type.is_dynamic) {
+ Report.error (get_src (type_loc), "Dynamic types not allowed in anonymous delegates");
+ }
+
+ type = parse_inline_array_type (type);
+
+ if (accept (TokenType.ASSIGN)) {
+ Report.error (get_last_src (), "Optional paramters not allowed in anonymous delegates");
+ }
+
+ var param = new Parameter ("p%i".printf (id), type, get_src (begin));
+ set_attributes (param, attrs);
+ param.direction = direction;
+ return param;
+ }
+
+ DelegateType parse_anonymous_delegate (Symbol parent, Method method) throws ParseError {
+ var begin = get_location ();
+ expect (TokenType.DELEGATE);
+
+ expect (TokenType.OPEN_PARENS);
+ var param_list = new ArrayList<Parameter> ();
+ if (current () != TokenType.CLOSE_PARENS) {
+ int next_parameter_id = 0;
+ do {
+ var param = parse_anonymous_parameter (next_parameter_id++);
+ param_list.add (param);
+ } while (accept (TokenType.COMMA));
+ }
+ expect (TokenType.CLOSE_PARENS);
+
+ expect (TokenType.LAMBDA);
+ var type_loc = get_location ();
+ var type = parse_type (true, false);
+
+ if (type.is_dynamic) {
+ Report.error (get_src (type_loc), "Dynamic types not allowed in anonymous delegates");
+ }
+
+ var src = get_src (begin);
+ if (!context.experimental) {
+ Report.warning (src, "Anonymous delegates are experimental");
+ }
+
+ var d = new Delegate ("__delegate%i_".printf (next_anonymous_id++), type, get_src (begin), comment);
+ d.anonymous = true;
+ d.access = method.access;
+
+ foreach (var param in param_list) {
+ d.add_parameter (param);
+ }
+
+ parent.add_delegate (d);
+ return new DelegateType (d);
+ }
+
List<TypeParameter> parse_type_parameter_list () throws ParseError {
if (accept (TokenType.OP_LT)) {
var list = new ArrayList<TypeParameter> ();