[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC] Scoped variables, supercharged
From: |
Jouke Witteveen |
Subject: |
[RFC] Scoped variables, supercharged |
Date: |
Thu, 26 Dec 2019 14:03:19 +0100 |
Hi,
I would like make to have scoped variables. Here, I will propose an
implementation of them. This implementation is currently without tests and
documentation. Hopefully, the proposal is acceptable and I can add the
tests and documentation.
Consider a situation in which we have macros F and G, and some variable X,
and our makefile includes:
$(call F,$(call G,$(X)),$(call G,$(X)))
Here, we duplicate the call to G. To make that more transparent (and
assuming G does not introduce side-effects), we could write the above as:
Y := $(call G,$(X))
$(call F,$(Y),$(Y))
undefine Y
However, this would interfere with any existing variable Y.
Alternatively, we could try:
$(foreach Y,$(call G,$(X)), \
$(call F,$(Y),$(Y)))
but that would not work if $(call G,$(X)) yields a list.
A solution would be a new function, 'let', which allows us to write
$(let Y,$(call G,$(X)), \
$(call F,$(Y),$(Y)))
This function can be implemented easily. It can even be given superpowers.
If the first argument to the new let-function is a single name, it is
assigned the full second argument. If it is multiple names, say n, we can
assign the first n-1 names to the first n-1 words of the second argument
and the final name to the remainder of the arguments (adding empty words
as necessary).
This also solves http://savannah.gnu.org/bugs/?51286 and makes something
like
reverse = $(let first rest,$1,$(if $(rest),$(call reverse,$(rest)) )$(first))
possible.
I have included an implementation bbelow, borrowing from the
implementation of foreach and call. Let me know if I can go forward with
this idea and prepare a patch including tests and documentation.
Regards,
- Jouke
---
src/function.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)
diff --git a/src/function.c b/src/function.c
index 4ebff16..1c1c38b 100644
--- a/src/function.c
+++ b/src/function.c
@@ -908,6 +908,53 @@ func_foreach (char *o, char **argv, const char *funcname
UNUSED)
return o;
}
+static char *
+func_let (char *o, char **argv, const char *funcname UNUSED)
+{
+ /* expand only the first two. */
+ char *varnames = expand_argument (argv[0], NULL);
+ char *list = expand_argument (argv[1], NULL);
+ const char *body = argv[2];
+
+ const char *list_iterator = list;
+ char *p;
+ size_t len;
+ size_t vlen;
+ const char *vp_next = varnames;
+ const char *vp = find_next_token (&vp_next, &vlen);
+
+ push_new_variable_scope ();
+
+ /* loop through LIST for all but the last VARNAME */
+ NEXT_TOKEN (vp_next);
+ while (*vp_next != '\0')
+ {
+ p = find_next_token (&list_iterator, &len);
+ if (*list_iterator != '\0')
+ {
+ ++list_iterator;
+ p[len] = '\0';
+ }
+ define_variable (vp, vlen, p ? p : "", o_automatic, 0);
+
+ vp = find_next_token (&vp_next, &vlen);
+ NEXT_TOKEN (vp_next);
+ }
+ if (vp)
+ define_variable (vp, vlen, next_token (list_iterator), o_automatic, 0);
+
+ /* Expand the body in the context of the arguments, adding the result to
+ the variable buffer. */
+
+ o = variable_expand_string (o, body, SIZE_MAX);
+
+ pop_variable_scope ();
+ free (varnames);
+ free (list);
+
+ return o + strlen (o);
+}
+
struct a_word
{
struct a_word *next;
@@ -2337,7 +2384,8 @@ func_abspath (char *o, char **argv, const char *funcname
UNUSED)
comma-separated values are treated as arguments.
EXPAND_ARGS means that all arguments should be expanded before invocation.
- Functions that do namespace tricks (foreach) don't automatically expand. */
+ Functions that do namespace tricks (foreach, let) don't automatically
+ expand. */
static char *func_call (char *o, char **argv, const char *funcname);
@@ -2373,6 +2421,7 @@ static struct function_table_entry function_table_init[] =
FT_ENTRY ("words", 0, 1, 1, func_words),
FT_ENTRY ("origin", 0, 1, 1, func_origin),
FT_ENTRY ("foreach", 3, 3, 0, func_foreach),
+ FT_ENTRY ("let", 3, 3, 0, func_let),
FT_ENTRY ("call", 1, 0, 1, func_call),
FT_ENTRY ("info", 0, 1, 1, func_error),
FT_ENTRY ("error", 0, 1, 1, func_error),
--
2.24.1
- [RFC] Scoped variables, supercharged,
Jouke Witteveen <=
- [RFC] Scoped variables, supercharged, thutt, 2019/12/26
- Re: [RFC] Scoped variables, supercharged, Jouke Witteveen, 2019/12/26
- Re: [RFC] Scoped variables, supercharged, Paul Smith, 2019/12/26
- Re: [RFC] Scoped variables, supercharged, Jouke Witteveen, 2019/12/27
- Re: [RFC] Scoped variables, supercharged, thutt, 2019/12/27
- Re: [RFC] Scoped variables, supercharged, Jouke Witteveen, 2019/12/27
- Re: [RFC] Scoped variables, supercharged, thutt, 2019/12/26