Shop OBEX P1 Docs P2 Docs Learn Events
SPIN: A byte or word can never equal -1 and TRUE — Parallax Forums

SPIN: A byte or word can never equal -1 and TRUE

I have some projects that never worked right until I finally got it through my thick head that a byte or word can never equal -1 and TRUE. TRUE is defined to be -1.

Under normal circumstances, equating a byte or word to a long will truncate and assign the least significant 8 or 16 bits of the long to the byte or word. For example:
Byte:  C := -1    ' assign 255 to C
Byte:  C := TRUE  ' assign 255 to C
Word:  C := -1    ' assign 65535 to C
Word:  C := TRUE  ' assign 65535 to C
The following logical tests can never be true when C is a byte or word:
  C == -1
  C == TRUE
The following logical tests can be true when C is a byte or word:
Byte:  C == 255  
Word:  C == 65535
The least significant 8 or 16 bits of -1 and TRUE are equal to 255 (byte) and 65535 (word), but in logical tests, a byte or word can never equal -1 and TRUE.

I would love to read your comments.



Comments

  • True that TRUE isn't true when it's not a long but I never bother to tell Spin to check if it is truly TRUE :)

    If you said "if C == TRUE" then it would always fail but you can just as easily say "if C" without the condition as the "if" is equivalent to a "jump if zero" and doesn't care about the actual value other than whether it's zero or not zero, or is that FALSE ? :)
  • That's correct. If C is not zero, C is promoted to TRUE before the logical test, and "if C" will be TRUE, whereas, "if C == TRUE" will always be FALSE.
  • Mike GreenMike Green Posts: 23,101
    edited 2017-01-05 17:57
    However, if you write "if C" (in SPIN), the code generated tests for non-zero rather than -1.
  • AribaAriba Posts: 2,682
    Never say never...

    You can force Spin to sign extend the byte or word for the logical test:

    Byte: if ~C == TRUE
    Word: if ~~C == TRUE

    But as others already said: All values <> zero are defined as true, not only -1. So comparing to one of the many possible TRUE values makes not much sense.

    Andy
  • dbpagedbpage Posts: 217
    edited 2017-01-06 01:50
    I'm glad you mentioned that! I didn't think about ~C and ~~C.

    Both work. It's a silly construct, but, you're right, when C := TRUE, the logical tests ~C == TRUE and ~~C == TRUE evaluate to be TRUE. Same when C := -1 (because TRUE is -1).

    Curious, but when C is defined as a word and C := TRUE, both ~C == TRUE and ~~C == TRUE evaluate to be TRUE:
    byte C
    C := TRUE
    if ~C == TRUE      ' Evaluates as TRUE
    if ~~C == TRUE     ' Evaluates as FALSE
    
    and
    word C
    C := TRUE
    if ~C == TRUE      ' Evaluates as TRUE
    if ~~C == TRUE     ' Evaluates as TRUE
    
    The point of my post is to be conscious of type mismatch. SPIN lets us be lazy in some instances, but we must be on our toes in other instances. The compiler doesn't protect us with type mismatches.

    This is where I get into trouble. With regard to "All values <> zero are defined as true, not only -1", the Propeller manual says for AND and OR, "..the value of X is promoted to TRUE if it is non-zero, then is compared with TRUE and the Boolean result (TRUE / FALSE, -1 / 0) is stored back in X." I erroneously extended that statement to logical tests other than AND and OR.

    You smarter people know better!
  • dbpage wrote: »
    This is where I get into trouble. With regard to "All values <> zero are defined as true, not only -1", the Propeller manual says for AND and OR, "..the value of X is promoted to TRUE if it is non-zero, then is compared with TRUE and the Boolean result (TRUE / FALSE, -1 / 0) is stored back in X." I erroneously extended that statement to logical tests other than AND and OR.

    "==" is a numerical test, not a logical test.
  • AribaAriba Posts: 2,682
    edited 2017-01-06 06:18
    dbpage wrote: »
    ...
    Curious, but when C is defined as a word and C := TRUE, both ~C == TRUE and ~~C == TRUE evaluate to be TRUE:
    byte C
    C := TRUE
    if ~C == TRUE      ' Evaluates as TRUE
    if ~~C == TRUE     ' Evaluates as FALSE
    
    and
    word C
    C := TRUE
    if ~C == TRUE      ' Evaluates as TRUE
    if ~~C == TRUE     ' Evaluates as TRUE
    
    The point of my post is to be conscious of type mismatch. SPIN lets us be lazy in some instances, but we must be on our toes in other instances. The compiler doesn't protect us with type mismatches.
    ...
    That's a logical result ;-)
    ~C sign extends from bit 7 and ~~C sign extends from bit 15, that is: all higher bits are set to the state of bit 7 or 15.
    So if you set a word variable to TRUE, all the bits from 0 to 15 are set, and a signextend from bit 7 also gives -1. If you set a byte variable to TRUE, only bit 0..7 get set, and a sign extend from bit 15 will result in 255, because bit 15 is low.

    I like the lazyness of Spin in respect to types, it does just what I code. While the type checking of C compilers is really annoying sometimes.

    Andy
  • As Electrodude and the Propeller Manual points out, "Since the Spin language performs all mathematic operations using 32-bit signed math, any byte-sized values will be internally treated as positive long-sized values." and similarly, "Since the Spin language performs all mathematic operations using 32-bit signed math, any word-sized values will be internally treated as positive long-sized values."

    All this time I thought "if C == TRUE" was a logical test, and I now know it's a mathematical operation.

    Hence, Ariba's strategy is the spot on. Without sign extending (~C for byte, ~~C for word), a byte or word can never equal -1 and TRUE.

    Thank you all for the clarification. It was fun!

  • I think to define TRUE as -1 is wrong.

    The correct definition is that FALSE is defined as 0 and TRUE is defined as NOT FALSE.

    So instead of "if C==TRUE" check "if C<>FALSE"

    Enjoy!

    Mike
  • Heater.Heater. Posts: 21,230
    edited 2017-01-07 21:30
    msrobots,
    The correct definition is that FALSE is defined as 0 and TRUE is defined as NOT FALSE.
    Yeah but. That is ambiguous.

    Does "NOT FALSE" mean anything that is not 0.

    Or does it mean the logical bitwise NOT of zero. Which is -1 in two-complement representation?

    Or even, given that FALSE is 0 does it mean TRUE is just 1?

    Every language I have ever worked with has made a mess of this.








  • All the languages that treat 0 as false and [not zero value] as true have this problem. Very few languages actually have a boolean type where the two possible values are unambiguously either true or false. (Lua is one of these.) Given the ambiguity it's best to treat zero as false, anything other than zero as true, and not do logical operations like AND, OR, XOR, and what unless you are certain the true values are -1 ("all bits on"). Spin actually provides better tools for this than most languages, since it has both bitwise and logical operators; the bitwise operators will do what you're used to, but the logical operators coerce all nonzero values to -1 before doing the logical math operation, and they always return 0 or -1.
  • dbpagedbpage Posts: 217
    edited 2017-01-08 18:29
    That was exactly my thinking, but SPIN does *not* coerce all nonzero values to -1 before doing the logical math operation.

    SPIN promotes non-zero values to -1 *only* for AND, OR and NOT. For IF, UNTIL and WHILE (for example), bytes and words can never equal TRUE and -1 without sign extending. This is because SPIN defines TRUE to be equal to -1, and treats all bytes and words as unsigned.

    That leaves us with zero or non-zero as the only tests for operations, except AND, OR and NOT in SPIN.

    Regarding bitwise "!", I got into trouble thinking that when X is non-zero, !X will always be zero. !X is zero only when X = TRUE or X = -1. In all other cases, the bits are toggled and a non-zero X will remain non-zero.
  • The problem here is that one wants to believe that False and True are enumerations of type Boolean, but Spin has no types and False and True are simply predefined named numbers with values 0 and -1, respectively.

    While it's true that 0 and 1 would have been better choices in most cases, there is no good choice given the absence of any typing in the language.

    Given the untyped nature of the language, it's best to not think of relational operators as yielding Boolean results as there is no Boolean type. Similarly, and, or and not are also best considered as arithmetic operators and if is best considered to be if-not-zero.

    That perversion is the only consistent approach that will lead to understanding of why the perversion of "if 3" doesn't cause semantic errors at compilation time.
Sign In or Register to comment.