changeset 30321:2ba4758654ca

deprecate ** and .** operators (bug #60882) * lex.h, lex.ll (base_lexer::warn_deprecated_operator): New function. (CMD_OR_DEPRECATED_OP): New macro. (".**", "**"): Use it. * basics.txi, expr.txi, vectorize.txi: Eliminate descriptions of the '**' and '.**' operators from the manual.
author John W. Eaton <jwe@octave.org>
date Mon, 22 Nov 2021 16:22:54 -0500
parents c41fec3367b0
children f69f749aad9b
files doc/interpreter/basics.txi doc/interpreter/expr.txi doc/interpreter/vectorize.txi libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll
diffstat 5 files changed, 47 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/basics.txi	Mon Nov 22 15:41:42 2021 -0500
+++ b/doc/interpreter/basics.txi	Mon Nov 22 16:22:54 2021 -0500
@@ -876,7 +876,7 @@
 have typed.  For example, if you misspell a keyword,
 
 @example
-octave:13> function y = f (x) y = x***2; endfunction
+octave:13> function z = f (x, y) z = x ||| 2; endfunction
 @end example
 
 @noindent
@@ -888,8 +888,8 @@
 
   syntax error
 
->>> function y = f (x) y = x***2; endfunction
-                              ^
+>>> function z = f (x, y) z = x ||| y; endfunction
+                                  ^
 @end group
 @end example
 
@@ -897,9 +897,9 @@
 For most parse errors, Octave uses a caret (@samp{^}) to mark the point
 on the line where it was unable to make sense of your input.  In this
 case, Octave generated an error message because the keyword for
-exponentiation (@code{**}) was misspelled.  It marked the error at the
-third @samp{*} because the code leading up to this was correct but the final
-@samp{*} was not understood.
+the logical or operator (@code{||}) was misspelled.  It marked the error
+at the third @samp{|} because the code leading up to this was correct
+but the final @samp{|} was not understood.
 
 Another class of error message occurs at evaluation time.  These
 errors are called @dfn{run-time errors}, or sometimes
--- a/doc/interpreter/expr.txi	Mon Nov 22 15:41:42 2021 -0500
+++ b/doc/interpreter/expr.txi	Mon Nov 22 16:22:54 2021 -0500
@@ -747,8 +747,6 @@
 by each corresponding element of @var{x}.
 
 @item  @var{x} ^ @var{y}
-@itemx @var{x} ** @var{y}
-@opindex **
 @opindex ^
 Power operator.  If @var{x} and @var{y} are both scalars, this operator
 returns @var{x} raised to the power @var{y}.  If @var{x} is a scalar and
@@ -761,8 +759,6 @@
 The implementation of this operator needs to be improved.
 
 @item  @var{x} .^ @var{y}
-@itemx @var{x} .** @var{y}
-@opindex .**
 @opindex .^
 Element-by-element power operator.  If both operands are matrices, the
 number of rows and columns must both agree, or they must be
@@ -836,7 +832,6 @@
 @opindex \
 @DOCSTRING(mldivide)
 
-@opindex **
 @opindex ^
 @DOCSTRING(mpower)
 
@@ -849,7 +844,6 @@
 @opindex +
 @DOCSTRING(plus)
 
-@opindex .**
 @opindex .^
 @DOCSTRING(power)
 
@@ -1535,7 +1529,7 @@
 These operators group right to left.
 
 @item transpose and exponentiation
-@samp{'} @samp{.'} @samp{^} @samp{**} @samp{.^} @samp{.**}
+@samp{'} @samp{.'} @samp{^} @samp{.^}
 
 @item unary plus, unary minus, prefix increment, prefix decrement, and logical "not"
 @samp{+} @samp{-} @samp{++}  @samp{--} @samp{~} @samp{!}
--- a/doc/interpreter/vectorize.txi	Mon Nov 22 15:41:42 2021 -0500
+++ b/doc/interpreter/vectorize.txi	Mon Nov 22 16:22:54 2021 -0500
@@ -389,7 +389,7 @@
       times     .*
       rdivide   ./
       ldivide   .\
-      power     .^  .**
+      power     .^
       lt        <
       le        <=
       eq        ==
@@ -406,7 +406,7 @@
       rem
       xor
 
-      +=  -=  .+=  .-=  .*=  ./=  .\=  .^=  .**=  &=  |=
+      +=  -=  .+=  .-=  .*=  ./=  .\=  .^=  &=  |=
 @end example
 
 Beware of resorting to broadcasting if a simpler operation will suffice.
--- a/libinterp/parse-tree/lex.h	Mon Nov 22 15:41:42 2021 -0500
+++ b/libinterp/parse-tree/lex.h	Mon Nov 22 16:22:54 2021 -0500
@@ -693,6 +693,10 @@
 
     void warn_deprecated_syntax (const std::string& msg);
 
+    void warn_deprecated_operator (const std::string& deprecated_op,
+                                   const std::string& recommended_op,
+                                   const std::string& version);
+
     void push_token (token *);
 
     token * current_token (void);
--- a/libinterp/parse-tree/lex.ll	Mon Nov 22 15:41:42 2021 -0500
+++ b/libinterp/parse-tree/lex.ll	Mon Nov 22 16:22:54 2021 -0500
@@ -183,6 +183,28 @@
      }                                                                  \
    while (0)
 
+#define CMD_OR_DEPRECATED_OP(PATTERN, REPLACEMENT, VERSION, TOK)        \
+   do                                                                   \
+     {                                                                  \
+       curr_lexer->lexer_debug (PATTERN);                               \
+                                                                        \
+       if (curr_lexer->looks_like_command_arg ())                       \
+         {                                                              \
+           yyless (0);                                                  \
+           curr_lexer->push_start_state (COMMAND_START);                \
+         }                                                              \
+       else                                                             \
+         {                                                              \
+           curr_lexer->warn_deprecated_operator (PATTERN, REPLACEMENT,  \
+                                                 #VERSION);             \
+           /* set COMPAT to true here to avoid warning about            \
+              compatibility since we've already warned about the        \
+              operator being deprecated.  */                            \
+           return curr_lexer->handle_op (TOK, false, true);             \
+         }                                                              \
+     }                                                                  \
+   while (0)
+
 #define CMD_OR_UNARY_OP(PATTERN, TOK, COMPAT)                           \
    do                                                                   \
      {                                                                  \
@@ -1628,7 +1650,7 @@
 "./"  { CMD_OR_OP ("./", EDIV, true); }
 ".\\" { CMD_OR_OP (".\\", ELEFTDIV, true); }
 ".^"  { CMD_OR_OP (".^", EPOW, true); }
-".**" { CMD_OR_OP (".**", EPOW, false); }
+".**" { CMD_OR_DEPRECATED_OP (".**", ".^", 7, EPOW); }
 "<="  { CMD_OR_OP ("<=", EXPR_LE, true); }
 "=="  { CMD_OR_OP ("==", EXPR_EQ, true); }
 "!="  { CMD_OR_OP ("!=", EXPR_NE, false); }
@@ -1658,7 +1680,7 @@
   }
 
 "^"   { CMD_OR_OP ("^", POW, true); }
-"**"  { CMD_OR_OP ("**", POW, false); }
+"**"  { CMD_OR_DEPRECATED_OP ("**", "^", 7, POW); }
 "&&"  { CMD_OR_OP ("&&", EXPR_AND_AND, true); }
 "||"  { CMD_OR_OP ("||", EXPR_OR_OR, true); }
 
@@ -3657,6 +3679,16 @@
   }
 
   void
+  base_lexer::warn_deprecated_operator (const std::string& deprecated_op,
+                                        const std::string& recommended_op,
+                                        const std::string& version)
+  {
+    std::string msg = "the '" + deprecated_op + "' operator was deprecated in version " + version + " and will not be allowed in a future version of Octave; please use '" + recommended_op + "' instead";
+
+    warn_deprecated_syntax (msg);
+  }
+
+  void
   base_lexer::push_token (token *tok)
   {
     YYSTYPE *lval = yyget_lval (m_scanner);