]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Add support for anonymous delegates wip/issue/658
authorNick Schrader <nick.schrader@mailbox.org>
Sun, 19 Jul 2020 20:13:37 +0000 (22:13 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Sun, 19 Mar 2023 11:55:01 +0000 (12:55 +0100)
  void foo (delegate(string, int) => int d) {
    ...
  }

Fixes https://gitlab.gnome.org/GNOME/vala/issues/658

32 files changed:
tests/Makefile.am
tests/delegates/anonymous-array.c-expected [new file with mode: 0644]
tests/delegates/anonymous-array.vala [new file with mode: 0644]
tests/delegates/anonymous-dynamic.test [new file with mode: 0644]
tests/delegates/anonymous-generics.test [new file with mode: 0644]
tests/delegates/anonymous-inner-dynamic-param.test [new file with mode: 0644]
tests/delegates/anonymous-inner-dynamic-return.test [new file with mode: 0644]
tests/delegates/anonymous-inner-owned-unowned.c-expected [new file with mode: 0644]
tests/delegates/anonymous-inner-owned-unowned.vala [new file with mode: 0644]
tests/delegates/anonymous-inner-params.test [new file with mode: 0644]
tests/delegates/anonymous-inner-ref-out.c-expected [new file with mode: 0644]
tests/delegates/anonymous-inner-ref-out.vala [new file with mode: 0644]
tests/delegates/anonymous-optional-param.test [new file with mode: 0644]
tests/delegates/anonymous-out.test [new file with mode: 0644]
tests/delegates/anonymous-param-attrs.c-expected [new file with mode: 0644]
tests/delegates/anonymous-param-attrs.vala [new file with mode: 0644]
tests/delegates/anonymous-params.test [new file with mode: 0644]
tests/delegates/anonymous-ref.test [new file with mode: 0644]
tests/delegates/anonymous-return-anonymous.test [new file with mode: 0644]
tests/delegates/anonymous-throws.test [new file with mode: 0644]
tests/delegates/anonymous-type-param.c-expected [new file with mode: 0644]
tests/delegates/anonymous-type-param.vala [new file with mode: 0644]
tests/delegates/anonymous-variadic.test [new file with mode: 0644]
tests/delegates/anonymous.c-expected [new file with mode: 0644]
tests/delegates/anonymous.vala [new file with mode: 0644]
tests/methods/parameter-anonymous-delegate-optional.c-expected [new file with mode: 0644]
tests/methods/parameter-anonymous-delegate-optional.vala [new file with mode: 0644]
tests/methods/parameter-anonymous-delegate.c-expected [new file with mode: 0644]
tests/methods/parameter-anonymous-delegate.vala [new file with mode: 0644]
vala/valacallabletype.vala
vala/valacodewriter.vala
vala/valaparser.vala

index 7b4317a18826e10cc9f266d83a890038db258c59..4824493c78c062f8d908a35239d12bfbba8f4a7a 100644 (file)
@@ -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 (file)
index 0000000..d38f7a4
--- /dev/null
@@ -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 (file)
index 0000000..b032b29
--- /dev/null
@@ -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 (file)
index 0000000..fdbf228
--- /dev/null
@@ -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 (file)
index 0000000..112e064
--- /dev/null
@@ -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 (file)
index 0000000..3d81996
--- /dev/null
@@ -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 (file)
index 0000000..0a2b6ad
--- /dev/null
@@ -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 (file)
index 0000000..53ac2b2
--- /dev/null
@@ -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 (file)
index 0000000..7c3381e
--- /dev/null
@@ -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 (file)
index 0000000..4dcb3e6
--- /dev/null
@@ -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 (file)
index 0000000..4ab8a12
--- /dev/null
@@ -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 (file)
index 0000000..b094d1c
--- /dev/null
@@ -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 (file)
index 0000000..4ac24c4
--- /dev/null
@@ -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 (file)
index 0000000..7313206
--- /dev/null
@@ -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 (file)
index 0000000..19961e2
--- /dev/null
@@ -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 (file)
index 0000000..4b0726b
--- /dev/null
@@ -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 (file)
index 0000000..4772114
--- /dev/null
@@ -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 (file)
index 0000000..e79835a
--- /dev/null
@@ -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 (file)
index 0000000..47be778
--- /dev/null
@@ -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 (file)
index 0000000..ff11a80
--- /dev/null
@@ -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 (file)
index 0000000..d4240d4
--- /dev/null
@@ -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 (file)
index 0000000..b5485aa
--- /dev/null
@@ -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 (file)
index 0000000..fabd3a4
--- /dev/null
@@ -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 (file)
index 0000000..68c369b
--- /dev/null
@@ -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 (file)
index 0000000..eff97e2
--- /dev/null
@@ -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 (file)
index 0000000..5075818
--- /dev/null
@@ -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 (file)
index 0000000..dc6085b
--- /dev/null
@@ -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 (file)
index 0000000..a4f4aa3
--- /dev/null
@@ -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 (file)
index 0000000..da3e624
--- /dev/null
@@ -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);
+}
index 6ea2349d0ed99f7d2b7ad05a34ff34adfdad8ee7..c2957a3421bd0184d3ca9ff2b710755ff69fe9c2 100644 (file)
@@ -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
index f9f1fccd1f175a00dcb328c480075061c8e50b33..5887392fd22779a43ab3e2333ef7691c48964185 100644 (file)
@@ -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:
index 9ac94e4a57b4cd0d7a8f547781c86f6f9a13855d..1b1e51ac41257e0503391febd10fe5c53444adb7 100644 (file)
@@ -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> ();