# HG changeset patch # User Arun Giridhar # Date 1654467088 14400 # Node ID 396f60e0b984cc90a1766cd99a1573e0f9265e23 # Parent 398a67a91798274c292b511701dfdfb50c66c5dd# Parent 277e31f0bb602a9a91c0bd6946a75eda2564170c maint: merge stable to default diff -r 398a67a91798 -r 396f60e0b984 etc/NEWS.7.md --- a/etc/NEWS.7.md Sat Jun 04 17:14:05 2022 -0400 +++ b/etc/NEWS.7.md Sun Jun 05 18:11:28 2022 -0400 @@ -148,19 +148,42 @@ between these operators and the variable they affect were allowed. That is no longer the case. -- When an expression involving operators could be interpreted ambiguously -either as command style syntax or function style syntax, it is -interpreted as command style syntax in more cases than in previous -versions. To still be interpreted as function style syntax, inplace -operators (`+=`, `-=`, `*=`, `.*=`, `/=`, `./=`, `\=`, `.\=`, `^=`, -`.^=`, `|=`, `&=`) must now either be followed by a whitespace character -or must not be preceded by a whitespace character. For ambiguous -expressions involving binary operators (`+`, `-`, `*`, `.*`, `/`, `./`, -`\`, `.\`, `^`, `.^`, `|`, `&`, `||`, `&&`), the same rules apply. -E.g., `a + b`, `a+ b`, or `a+b` are valid expressions if `a` is a -variable. In contrast, `a +b` will throw an error if `a` is a variable. -The latter example is now interpreted as a command syntax expression -(equivalent to the function syntax expression `a ("+b")`). +- Parsing of command-style function calls has changed to improve +consistency of behavior and compatibility with Matlab. This change +affects statements that begin with binary operator expressions when the +first operand is a plain symbol followed by a whitespace character and +the binary operator is not followed by a whitespace character. For +example, the statement `cmd -option` is parsed as a command-style +function call, not a binary subtraction operation. + + This change affects all binary operators: `+`, `-`, `*`, `/`, `\`, +`^`, `.*`, `./`, `.\`, `.^`, `|`, `&`, `||`, `&&`, `+=`, `-=`, `*=`, +`/=`, `\=`, `^=`, `.*=`, `./=`, `.\=`, `.^=`, `|=`, and `&=`. + + Previous versions of Octave would attempt to determine whether the +first operand in an expression was a variable, and if so, parse +expressions like `var -val` as an expression. However, this attempt to +"do the right thing" could cause trouble (for example, if a variable is +only defined conditionally). + + Now, parsing command-style function calls is purely based on syntax. + + Command-style function call syntax is only allowed at the beginning +of a statement. Expressions in other contexts are not affected, so an +expression like `a + b +c` will not be parsed as a command-style function +call. + + For compatibility with Matlab, a binary expression at the beginning +of a statement that starts with one of the symbols `I`, `i`, `J`, `j`, +`Inf`, `inf`, `NaN`, `nan`, or `pi` is never parsed as a command-style +function call. Octave also extends this behavior to `e`, which is not +present as a special numeric constant in Matlab. + + Note that full compatibility with Matlab, which does not have the +OP= operators, would require that even `a -= b` is parsed as a +command-style function call. As that would significantly hinder the use +of these operators, Octave treats them as the other binary operators +instead of providing fully compatible behavior. - The `mldivide` function (i.e., the `\` operator) now uses an LU decomposition to solve nearly singular full square matrices. This is diff -r 398a67a91798 -r 396f60e0b984 libinterp/parse-tree/pt-idx.cc --- a/libinterp/parse-tree/pt-idx.cc Sat Jun 04 17:14:05 2022 -0400 +++ b/libinterp/parse-tree/pt-idx.cc Sun Jun 05 18:11:28 2022 -0400 @@ -366,7 +366,26 @@ std::string nm = id->name (); if (is_var && is_word_list_cmd ()) - error ("%s used as variable and later as function", nm.c_str ()); + { + bool maybe_binary_op = false; + if ((*p_args) && (*p_args)->length () > 0) + { + // check if first character of first argument might be (the + // start of) a binary operator + std::string ops = "+-*/\\.^|&"; + string_vector arg_list = (*p_args)->get_arg_names (); + if (! arg_list.isempty () + && (ops.find (arg_list(0)[1]) != std::string::npos)) + maybe_binary_op = true; + } + + std::string advice; + if (maybe_binary_op) + advice = "\nCheck whitespace around potential binary operator."; + + error ("variable \"%s\" used as function in command style expression%s", + nm.c_str (), advice.c_str ()); + } if (! is_var) {