Menu ▾ ▴

#2117 The message "\" sent to .true or .false returns the value itself, not its negation

5.3.0
pending
None
none
5
2026-10-17
2026-10-16
No

Summary

Sending the logical NOT message "\" explicitly to a string that is internally
a RexxInteger, such as .true, .false, the result of a comparison, or a
small whole number, returns the truth value itself instead of its
negation. The prefix operator (\x) is not affected. Neither is a string that
is internally a RexxString. A literal "1" or "0" may be either,
depending on whether the same program also uses 1 or 0 as a number, so
"1"~"\" is right in one program and wrong in another.

How to reproduce

say .true~"\"          -- 1   (should be 0)
say .false~"\"         -- 0   (should be 1)
say (1=1)~"\"          -- 1   (should be 0)
c = 1 + 0; say c~"\"   -- 1   (should be 0)

s = "1" || ""
say s~"\"              -- 0   correct (a RexxString)
say \.true             -- 0   correct (the prefix operator)

Where it shows

Code that forwards messages to a logical value gets the wrong answer, even
though it never sends "\" itself. That is the usual way to write an object
that behaves like a logical value: an UNKNOWN method that forwards every
message to the value. json.cls and yaml.cls, both in the distribution, do
exactly that, so:

say \.json~true        -- 1   (should be 0): JsonBoolean's UNKNOWN forwards "\" to .true
say \.json~false       -- 0   (should be 1)
::requires "json.cls"

The same happens with .YamlBoolean~true and ~false from yaml.cls.

Cause

Setup.cpp binds the message "\" of the Integer behaviour to
RexxInteger::notOp:

AddMethod("\\", RexxInteger::notOp, 0);      // interpreter/memory/Setup.cpp

and RexxInteger::notOp lacks the !:

RexxObject *RexxInteger::notOp()
{
    return booleanObject(truthValue(Error_Logical_value_method));
}

The operator entry of the same class, RexxInteger::operatorNot, which the
prefix operator uses, has it. So do RexxString::notOp and
RexxString::operatorNot. That is why \.true and "1"~"\" are right.

Patch

notop.patch (one character):

--- a/interpreter/classes/IntegerClass.cpp
+++ b/interpreter/classes/IntegerClass.cpp
@@ -1429,7 +1429,7 @@
  */
 RexxObject *RexxInteger::notOp()
 {

-    return booleanObject(truthValue(Error_Logical_value_method));
+    return booleanObject(!truthValue(Error_Logical_value_method));
 }

Test

notop-test.rex checks the message and the operator on integer-backed and
string-backed values, and through a forwarding object like JsonBoolean.
Results:

Build notop-test.rex Test suite, ooRexx/base (14369 tests, 244723 assertions)
r13271, official Ubuntu 24.04 package, unpatched 4 passed, 12 failed 5 failures
r13265 source tarball + this patch (IntegerClass.cpp is identical in r13265 and r13271) 16 passed, 0 failed the same 5 failures

The 5 failures are the same tests before and after
(File.testGroup: TEST_FILE_READWRITE_DIRECTORY_EXIST,
TEST_FILE_READWRITE_FILE_EXIST; Stream.testGroup: TEST_RELATIVE_EXISTS2,
TEST_RELATIVE_EXISTS3, TEST_STATE_ERROR). They are about file
permissions: the suite ran as root in a container. Linux x86_64, gcc 13.

Suggested addition to the test suite: the checks in notop-test.rex, in
ooRexx/base/class/RexxInteger.testGroup (message "\" on .true, .false,
a comparison result and a computed integer).

2 Attachments

Discussion

  • Josep Maria Blasco

    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -93,5 +93,5 @@
     permissions: the suite ran as root in a container. Linux x86_64, gcc 13.
    
     Suggested addition to the test suite: the checks in `notop-test.rex`, in
    -`ooRexx/base/class/RexxInteger.testGroup` (message `""` on `.true`, `.false`,
    +`ooRexx/base/class/RexxInteger.testGroup` (message `"\"` on `.true`, `.false`,
     a comparison result and a computed integer).
    
     
  • Josep Maria Blasco

     
  • Josep Maria Blasco

    Fixed in r13272 (interpreter: RexxInteger::notOp now returns the negation, as RexxInteger::operatorNot already did) and r13273 (tests: ooRexx/base/class/RexxInteger.testGroup, test_integer_not_message and test_integer_not_forwarded).

    With the fix, the whole ooRexx/base suite gives the same results as before, plus the two new tests.

     
  • Josep Maria Blasco

    • status: open --> pending
    • assigned_to: Josep Maria Blasco
     

Anonymous
Anonymous

Add attachments
Cancel