]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
parser: Allow declaration of static nested methods (local functions)
authorRico Tzschichholz <ricotz@ubuntu.com>
Fri, 15 Mar 2024 13:14:56 +0000 (14:14 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 18 Mar 2024 09:18:30 +0000 (10:18 +0100)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/1533

tests/Makefile.am
tests/methods/local-functions-to-delegate.c-expected [new file with mode: 0644]
tests/methods/local-functions-to-delegate.vala [new file with mode: 0644]
vala/valaparser.vala

index 806443855162d45afec00a12f9aad9f9bd726615..507b4e19cbdd406d105d26c97b2a80c0cf4b33a5 100644 (file)
@@ -209,6 +209,7 @@ TESTS = \
        methods/extern.vala \
        methods/iterator.vala \
        methods/local-functions.vala \
+       methods/local-functions-to-delegate.vala \
        methods/parameter-fixed-array-initializer.vala \
        methods/parameter-out-free-on-error.vala \
        methods/parameter-ref-array-resize.vala \
diff --git a/tests/methods/local-functions-to-delegate.c-expected b/tests/methods/local-functions-to-delegate.c-expected
new file mode 100644 (file)
index 0000000..56ff224
--- /dev/null
@@ -0,0 +1,160 @@
+/* methods_local_functions_to_delegate.c generated by valac, the Vala compiler
+ * generated from methods_local_functions_to_delegate.vala, do not modify */
+
+#include <glib.h>
+
+#if !defined(VALA_STRICT_C)
+#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
+#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
+#elif defined(__clang__) && (__clang_major__ >= 16)
+#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
+#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
+#endif
+#endif
+#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 (*Foo) (gint i, gpointer user_data);
+typedef gint (*Bar) (gint i);
+typedef gint (*_LocalFunc0_) (gint i, gpointer user_data);
+typedef gint (*_LocalFunc1_) (gint i);
+typedef struct _Block1Data Block1Data;
+#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 _Block1Data {
+       int _ref_count_;
+       gint j;
+};
+
+VALA_EXTERN void foo (Foo f,
+          gpointer f_target);
+VALA_EXTERN void bar (Bar b);
+static void _vala_main (void);
+static Block1Data* block1_data_ref (Block1Data* _data1_);
+static void block1_data_unref (void * _userdata_);
+static gint _vala_lambda0_ (Block1Data* _data1_,
+                     gint i);
+static gint __vala_lambda0___localfunc0_ (gint i,
+                                   gpointer self);
+static gint _vala_lambda1_ (gint i);
+static gint __vala_lambda1___localfunc1_ (gint i);
+
+void
+foo (Foo f,
+     gpointer f_target)
+{
+       _vala_assert (f (13, f_target) == 39, "f (13) == 39");
+}
+
+void
+bar (Bar b)
+{
+       _vala_assert (b (42) == 84, "b (42) == 84");
+}
+
+static Block1Data*
+block1_data_ref (Block1Data* _data1_)
+{
+       g_atomic_int_inc (&_data1_->_ref_count_);
+       return _data1_;
+}
+
+static void
+block1_data_unref (void * _userdata_)
+{
+       Block1Data* _data1_;
+       _data1_ = (Block1Data*) _userdata_;
+       if (g_atomic_int_dec_and_test (&_data1_->_ref_count_)) {
+               g_slice_free (Block1Data, _data1_);
+       }
+}
+
+static gint
+_vala_lambda0_ (Block1Data* _data1_,
+                gint i)
+{
+       gint result;
+       result = i * _data1_->j;
+       return result;
+}
+
+static gint
+__vala_lambda0___localfunc0_ (gint i,
+                              gpointer self)
+{
+       gint result;
+       result = _vala_lambda0_ (self, i);
+       return result;
+}
+
+static gint
+_vala_lambda1_ (gint i)
+{
+       gint result;
+       result = 2 * i;
+       return result;
+}
+
+static gint
+__vala_lambda1___localfunc1_ (gint i)
+{
+       gint result;
+       result = _vala_lambda1_ (i);
+       return result;
+}
+
+static void
+_vala_main (void)
+{
+       {
+               Block1Data* _data1_;
+               _LocalFunc0_ func = NULL;
+               gpointer func_target;
+               Foo f = NULL;
+               gpointer f_target;
+               GDestroyNotify f_target_destroy_notify;
+               _data1_ = g_slice_new0 (Block1Data);
+               _data1_->_ref_count_ = 1;
+               _data1_->j = 3;
+               func = __vala_lambda0___localfunc0_;
+               func_target = _data1_;
+               foo (func, func_target);
+               f = func;
+               f_target = func_target;
+               f_target_destroy_notify = NULL;
+               _vala_assert (f (23, f_target) == 69, "f (23) == 69");
+               (f_target_destroy_notify == NULL) ? NULL : (f_target_destroy_notify (f_target), NULL);
+               f = NULL;
+               f_target = NULL;
+               f_target_destroy_notify = NULL;
+               block1_data_unref (_data1_);
+               _data1_ = NULL;
+       }
+       {
+               _LocalFunc1_ func = NULL;
+               Bar b = NULL;
+               func = __vala_lambda1___localfunc1_;
+               bar (func);
+               b = func;
+               _vala_assert (b (23) == 46, "b (23) == 46");
+       }
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
diff --git a/tests/methods/local-functions-to-delegate.vala b/tests/methods/local-functions-to-delegate.vala
new file mode 100644 (file)
index 0000000..394080b
--- /dev/null
@@ -0,0 +1,35 @@
+delegate int Foo (int i);
+
+[CCode (has_target = false)]
+delegate int Bar (int i);
+
+void foo (Foo f) {
+       assert (f (13) == 39);
+}
+
+void bar (Bar b) {
+       assert (b (42) == 84);
+}
+
+void main () {
+       {
+               int j = 3;
+               int func (int i) {
+                       return i * j;
+               }
+               foo (func);
+
+               Foo f = func;
+               assert (f (23) == 69);
+       }
+       {
+               static int func (int i) {
+                       return 2 * i;
+               }
+               bar (func);
+
+               Bar b = func;
+               assert (b (23) == 46);
+       }
+}
+
index 33cb4843ee2dfab378c2f66444a84bf97032095f..0d0e0f7aaad1b6237ae357b8fc872f1bd04c3143 100644 (file)
@@ -1941,6 +1941,7 @@ public class Vala.Parser : CodeVisitor {
                var begin = get_location ();
 
                try {
+                       accept (TokenType.STATIC);
                        skip_type ();
                        if (accept (TokenType.IDENTIFIER) && accept (TokenType.OPEN_PARENS)) {
                                rollback (begin);
@@ -2173,6 +2174,7 @@ public class Vala.Parser : CodeVisitor {
 
        void parse_local_function_declaration (Block block) throws ParseError {
                var begin = get_location ();
+               var is_static = accept (TokenType.STATIC);
                var type = parse_type (true, false);
                var sym = parse_symbol_name ();
 
@@ -2188,6 +2190,7 @@ public class Vala.Parser : CodeVisitor {
                var src = get_src (begin);
 
                var d = new Delegate ("_LocalFunc%i_".printf (next_local_func_id++), type, src);
+               d.has_target = !is_static;
                foreach (var param in params) {
                        d.add_parameter (param);
                }