!EVAL
authorBen Pfaff <blp@cs.stanford.edu>
Fri, 11 Jun 2021 06:00:05 +0000 (23:00 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 11 Jun 2021 06:00:05 +0000 (23:00 -0700)
doc/flow-control.texi
src/language/lexer/macro.c
tests/language/control/define.at

index 7a95758a78b92cb4936dedc6d9b43e70395df59d..f0bf4fe10b77400ed999dd56672f9c1b84f93460 100644 (file)
@@ -492,7 +492,8 @@ extends to the end of @var{arg}.
 @example
 !SUBSTR(banana, 3)           @expansion{} nana
 !SUBSTR(banana, 3, 3)        @expansion{} nan
-!SUBSTR("banana", 3)         @expansion{} anana"
+!SUBSTR("banana", 3)         @expansion{} @r{error (@code{anana"} is not a valid token)}
+!SUBSTR(!UNQUOTE("banana"), 3) @expansion{} nana
 !SUBSTR("banana", 3, 3)      @expansion{} ana
 
 !SUBSTR(banana, 3, 0)        @expansion{} @r{empty}
index 95d86a6e9643adfec2030db68fc9bfdd15e0de41..e900a5e7d1a542f0ec1faedaa813b0bd9ac883dc 100644 (file)
@@ -142,6 +142,7 @@ macro_tokens_from_string (struct macro_tokens *mts, const struct substring src,
         {
           if (token->type != SCAN_SKIP)
             {
+              printf ("error\n");
               /* XXX report error */
             }
         }
@@ -995,6 +996,19 @@ expand_macro_function (struct parse_macro_function_ctx *ctx,
       free (upper);
       ds_destroy (&tmp);
     }
+  else if (parse_macro_function (ctx, &args, ss_cstr ("!eval"), 1, 1,
+                                 input_consumed))
+    {
+      struct macro_tokens mts = { .n = 0 };
+      macro_tokens_from_string (&mts, ss_cstr (args.strings[0]),
+                                SEG_MODE_INTERACTIVE /* XXX */);
+      struct macro_tokens exp = { .n = 0 };
+      macro_expand (&mts, ctx->nesting_countdown - 1, ctx->macros,
+                    ctx->me, ctx->expand, &exp);
+      macro_tokens_to_representation (&exp, output);
+      macro_tokens_uninit (&exp);
+      macro_tokens_uninit (&mts);
+    }
   else if (ctx->n_input > 0
            && ctx->input[0].token.type == T_MACRO_ID
            && ss_equals_case (ctx->input[0].token.string, ss_cstr ("!null")))
@@ -1015,13 +1029,6 @@ macro_expand (const struct macro_tokens *mts,
               const struct macro_expander *me, bool *expand,
               struct macro_tokens *exp)
 {
-  /* Macro expansion:
-
-     - Macro names in macro bodies are not expanded by default.  !EVAL()
-       expands them.
-
-     - Macro names in arguments to macro invocations (outside of macro bodies)
-       are expanded by default, unless !NOEXPAND. */
   if (nesting_countdown <= 0)
     {
       printf ("maximum nesting level exceeded\n");
index fce0e3f832ee2172f28a3a7f5fd54e77f42c9c58..bf5e2c4ae11dbaa0cabe39e9960bc1d83246e9aa 100644 (file)
@@ -391,6 +391,32 @@ xy.
 1234.
 123.])
 
+dnl Keep this test in sync with the examples for !EVAL in the manual.
+PSPP_CHECK_MACRO_EXPANSION([!EVAL],
+  [DEFINE !vars() a b c !ENDDEFINE.
+DEFINE !e()
+!vars.
+!QUOTE(!vars).
+!EVAL(!vars).
+!QUOTE(!EVAL(!vars)).
+!ENDDEFINE
+DEFINE !e2(!positional !enclose('(',')'))
+!1.
+!QUOTE(!1).
+!EVAL(!1).
+!QUOTE(!EVAL(!1)).
+!ENDDEFINE],
+  [!e.
+!e2(!vars)],
+  [a b c.
+'!vars'.
+a b c.
+'a b c'.
+a b c.
+'!vars'.
+a b c.
+'a b c'.])
+
 dnl Keep this test in sync with the examples for !HEAD in the manual.
 PSPP_CHECK_MACRO_EXPANSION([!HEAD],
   [DEFINE !h()
@@ -476,16 +502,18 @@ PSPP_CHECK_MACRO_EXPANSION([!SUBSTR],
 !SUBSTR(banana, 3).
 !SUBSTR(banana, 3, 3).
 !SUBSTR("banana", 3).
+!SUBSTR(!UNQUOTE("banana"), 3).
 !SUBSTR("banana", 3, 3).
 !SUBSTR(banana, 3, 0).
 !SUBSTR(banana, 3, 10).
 !SUBSTR(banana, 10, 3).
 !ENDDEFINE.],
   [!s.],
-  [nana.
+  [error
+nana.
 nan.
-anana". dnl"
-
+anana.
+nana.
 ana.
 .
 nana.