trinity
trinity copied to clipboard
GENERIC-WIRE-F doesn't work as intended
One trick Trinity uses in several places is that if multiple objects match the one you've typed, the GENERIC routine for those objects is set up to pick the object that matches P-IT-OBJECT, if any of them does. Usually (at least so far) it's just two objects, but with GENERIC-WIRE-F it gets a bit more complicated because it has four. This is how it does it:
<SET LEN <GET .TABLE 0>>
<COND (<ZERO? .LEN>
<RFALSE>)
(<INTBL? ,P-IT-OBJECT <REST .TABLE 1> .LEN>
<RETURN ,P-IT-OBJECT>)
(T
<RFALSE>)>>
But it doesn't work. It doesn't match the "it" wire, no matter what.
<INTBL? ,P-IT-OBJECT <REST .TABLE 1> .LEN> compiles to
ADD TABLE,1 >STACK
INTBL? P-IT-OBJECT,STACK,LEN >STACK \FALSE
I think that means that it passes the table, minus the first byte as parameter to INTBL?. But TABLE is a word table. If I change it to <REST .TABLE 2> it works. Unfortunately, REST isn't documented in any of the original ZIL manuals, as far as I can tell, but I assume this is a bug in Trinity, not a bug in ZILF or Frotz.
The "MDL Programming Language" (https://mdl-language.readthedocs.io/en/latest/07-structured-objects/#713-rest-1) states:
<REST structured fix> evaluates to structured without its first fix elements. fix is optional, 1 by default.
From "The Zork Implementation Language" (can be found on the http://www.ifwiki.org/index.php/PAX_USB_Drive file zil.doc):
Table Operations
GET V 2 Returns the nth (argument-2) element of
argument-1
PUT V 3 Set the nth (argument-2) element of argument-1
to argument-3
GETB V 2) Like NTH and PUT, but return the nth byte
PUTB V 3) of a table, rather than the nth word of a table
SIZEPT V 1 Returns the size of a property table, which
was returned by GETPT.
REST V 2 Rest the table (argument-1) by argument-2
BYTES! To rest a table by one element, the
second argument should be 2.
BACK V 2 Inverse of REST.
Ok, so my guess that <REST .TABLE 1> should be <REST .TABLE 2> seems to be correct, then? I thought I had checked the PAX drive stuff, but I guess the "REST" got lost in all the "RESTART" and "RESTORE" noise when I searched for it. Thanks for the pointer!
Ok, so my guess that
<REST .TABLE 1>should be<REST .TABLE 2>seems to be correct, then? I thought I had checked the PAX drive stuff, but I guess the "REST" got lost in all the "RESTART" and "RESTORE" noise when I searched for it. Thanks for the pointer!
If .TABLE is interpreted as a table of 2-byte entries, then you need in ZIL <READ .TABLE 2> to snipp the first off. The MDL semantics differs here. Try to use 2 instead of 1 in the original code.
At least in the case I tested, the table was a WORD table. I already tried changing it to <REST .TABLE 2> and it worked. I just wanted to make sure it was the Right Thing™ to do.
From "The Zork Implementation Language" (can be found on the http://www.ifwiki.org/index.php/PAX_USB_Drive file
zil.doc):Table Operations GET V 2 Returns the nth (argument-2) element of argument-1 PUT V 3 Set the nth (argument-2) element of argument-1 to argument-3 GETB V 2) Like NTH and PUT, but return the nth byte PUTB V 3) of a table, rather than the nth word of a table SIZEPT V 1 Returns the size of a property table, which was returned by GETPT. REST V 2 Rest the table (argument-1) by argument-2 BYTES! To rest a table by one element, the second argument should be 2. BACK V 2 Inverse of REST.
FWIW, I've extracted this file from the PAX USB archives and uploaded it to https://pastebin.com/htGaEuey
Thanks. That's the same information ZoBoRf posted earlier, though. I found out about the PAX drive fairly recently, and spent some time following the instructions on how to decode it. But somehow I missed that zil.doc file.
By the way, just to rule out Frotz and ZILF bugs once and for all here - not that I really thought there were any - I have now verified that the same bug happens in the official Trinity release, using Infocom's DOS interpreter.