Community
SCI Programming => SCI Syntax Help => Topic started by: doomlazer on January 03, 2024, 09:44:25 PM
-
In the LSL5 SCI-Scripts decompile Interface.sc (https://github.com/sluicebox/sci-scripts/blob/c6fac2fa6806adb9e913f6cce8d47723a8932afc/lsl5-dos-1.000/src/Interface.sc#L250) line 250 is:
((or temp1025 temp1024) nsLeft:)
SCiCompanion will not compile the code, but:
(= temp0 0)
(= temp1 5)
(Printf {%d} (or temp0 temp1))
Results in 1, not 5. The following would work:
((if temp1025 else temp1024) nsLeft:)
But does 'or' ever?
-
That's not what or does. It doesn't return one value or the other, it returns true if one or the other given value is truthy. Or rather, if any of the given values is truthy, since you can have any amount of values to check if they're non-zero.
For comparison, and is true if all its arguments are truthy.
You must be talking about this line in the OG LSL5 source: ((or subI mainI) nsLeft?). Considering you must have a main text and may end up with a multi-language subtitle, mainI will always be a valid non-zero pointer and subI may be. (or subI mainI) will return the pointer to either DText object, and that control's nsLeft is then queried to pass on to editI. If there was a subtitle, it'll use the subtitle's nsLeft. If there wasn't, the pointer will be zero, false-y, and the guaranteed main text is used instead. The same trick is then used to move editI below the text (plus a bit) regardless of subI's existence.
... wait, hold up. That explanation doesn't track with observation. *checks the relevant original Sierra docs*.
(or e1 e2 [e3...])
Evaluates to TRUE if any of the expressions are non-zero, else FALSE.
I must've misunderstood what Print does there.
Edit: came back to do some more in-person testing. The manual is right.
;; Sanity checks.
(= theOne 42)
(= theOther 420)
(Printf "theOne = %d\ntheOther = %d" theOne theOther)
(Printf "one OR the other = %d" (or theOne theOther))
;; ^- should be TRUE
(= theOne 0)
(= theOther 420)
(Printf "theOne = %d\ntheOther = %d" theOne theOther)
(Printf "one OR the other = %d" (or theOne theOther))
;; ^- should be TRUE
(= theOne 42)
(= theOther 0)
(Printf "theOne = %d\ntheOther = %d" theOne theOther)
(Printf "one OR the other = %d" (or theOne theOther))
;; ^- should be TRUE
(= theOne 0)
(= theOther 0)
(Printf "theOne = %d\ntheOther = %d" theOne theOther)
(Printf "one OR the other = %d" (or theOne theOther))
;; ^- should be FALSE
(= theOne (DCIcon new:))
(theOne nsLeft: 100)
(= theOther 0)
(Printf "theOne = %d\ntheOther = %d" theOne theOther)
(Printf "one OR the other = %d" (or theOne theOther))
;; ^- should be TRUE
;; v-- Does not compile, "nsLeft is not a property or method on type 'bool'."
;;; (Printf "one OR the other's nsLeft = %d" ((or theOne theOther) nsLeft?))
(Printf "IF one ELSE the other's nsLeft = %d" ((if theOne else theOther) nsLeft?))
;; ^- should be 100
;; v-- Also does not compile, same reason. This is adapted straight from SCI10's Interface.
;;; (theOne
;;; moveTo:
;;; ((or theOne theOther) nsLeft?)
;;; ((or theOne theOther) nsBottom?)
;;; )
(theOne
moveTo:
((if theOne else theOther) nsLeft?)
((if theOne else theOther) nsBottom?)
)
; This tracks with the documentation: OR returns TRUE or FALSE, not the first valid pointer.
I would say that maybe Sierra's compiler handled things Differently?, but both the '88 and '94 manuals agree that what SCI 1.0 does here should not work.
-
Here's the snippet from the original source code:
; if editI we add it right under text item
(if editI
(editI
moveTo:
((or subI mainI) nsLeft?)
(+ MARGIN ((or subI mainI) nsBottom?))
)
; add edit item and resize the dialog
(theDialog add:editI, setSize:)
)https://github.com/historicalsource/leisure-suit-larry-5/blob/341bc91b5529c3243220a7fe77cc6b041c8022d4/SYSTEM/INTRFACE.SC#L1568C2-L1577C3
-
Note that, again, this original code won't compile in SCI Companion and has no business doing so in accordance with the original Sierra documentation.
(actually there's a bunch of things about the OG source that won't work in SCI Companion but that's not exactly on the level of "weird or behavior"...)
-
Note that, again, this original code won't compile in SCI Companion and has no business doing so in accordance with the original Sierra documentation.
Parts of the original documentation are outdated/inconsistent with reality. See, for example, the documentation of kernel calls that don't exist in any published SCI version. The changelogs are funny in places as well.
-
Even the 1994 SCI32 version?
Mind you, the observed behavior of or matches what you'd expect from most any other language. What it does in here Print makes no sense to begin with.
-
So maybe the interpreter knows to return the value instead of the bool when used with something that doesn't accept a bool? Weird.
-
It's not the interpreter's doing. I checked. After all, though there are and and or VM opcodes, those are for the binary math operations & and |.
(procedure (OrIsIt &tmp theOne theOther)
(= theOne 42)
(= theOther 420)
(Printf "theOne = %d\ntheOther = %d" theOne theOther)
(Printf "one OR the other = %d" (or theOne theOther))
); Manually cleaned up.
(procedure oneOrTheOther
link 2
; (= theOne 42)
ldi 42
sat theOne
; (= theOther 420)
ldi 420
sat theOther
; (Printf "theOne = %d\ntheOther = %d" theOne theOther)
pushi 3 ;argc
lofss "theOne = %d\ntheOther = %d"
lst theOne
lst theOther
calle 399 Printf 6
; (Printf "one OR the other = %d" (or theOne theOther))
push2
lofss "one OR the other = %d"
; THIS IS WHERE THE FUN BEGINS
lat theOne ; this MAY be zero/false.
bt itWasTrue
lat theOther
bnt orElse
itWasTrue:
ldi 1 ; True! So we replace theOne (42) with true (1).
orElse:
push ; push whatever's in the acc as the second arg, but hold up...
calle 399 Printf 4
ret
)You might notice there's no ldi 0 for the "other" case. But if I change the values to 0 and 420, I still get a 1/true result. But then, understanding ASM is not my strongest suit. Perhaps someone smarter can tell me how this works out.
But if I use (if theOne else theOther):
; (Printf "IF one ELSE the other = %d" (if theOne else theOther))
push2
lofss "IF one ELSE the other = %d"
; THIS IS WHERE THE FUN BEGINS... AGAIN!
lat theOne
bnt itWasNotTrue ; note: BNT, not BT.
jmp finally
itWasNotTrue:
lat theOther
finally:
push ; push one or the other, as seen in the acc, as the second arg
calle 399 Printf 4
In this case, it loads the one (42 here) into the accumulator, then if said acc happens to be false-y, it loads the other (420) instead.
-
Here is what Sluicebox had to say on the matter:
Sierra's compiler generates bt (branch if true) instructions for 'or'.
(or temp0 temp1)
lat 00 ; acc = temp0
bt label ; branch to label if acc != 0
lat 01 ; acc = temp1
label:
This is the behavior that the Interface script depends on, and that's what Sierra's compiler always did. But that's not what your Printf test did, because Companion did something different:
lat 00 ; acc = temp0
bt label1 ; branch to label1 if acc != 0
lat 01 ; acc = temp1
bnt label2 ; branch to label2 if acc == 0
label1:
ldi 01 ; acc = 1
label2:
also:
...I just peeked at Compiler.cpp:
if (Operator == BinaryOperator::LogicalAnd || Operator == BinaryOperator::LogicalOr)
{
// Handle && and || when not used in a condition.
// Basically, we write an "if statement" that evaluates to 1 or 0
return _WriteFakeIfStatement(context, *this);
}
So the answer is simply that SCICompanion is handling Or differently than Sierra's compiler. Not really a problem because SC decompiles the LSL5 Interface.sc code in question as an If statement. Also, the Sierra source code can be converted by hand before compiling to achieve the same functionality.
-
So... should SCI Companion be adjusted to mimic SC, which does not match its own official documentation nor any other language, or should we just let it be and use (if A else B) where other sources say (or A B)?
And if so, who's gonna do that? Cos I wouldn't know where to begin replacing that part Sluicebox found.
-
I had a brief look at the SCICompanion repo and it's certainly beyond my abilities to fix.
-
I mean I could figure it out maybe but my brain is the fried.
-
The closer SCICompanion matches SC the better IMO.
-
I don't like it, but I guess I'll put it on the list.
-
Feel free to ignore it completely. The code just stood out as odd when I saw it. SCICompanion already includes a workaround and my curiosity has been satiated.