Which, when I look in vocab.997, I see that #title is 80, #button is 81, and #icon is 82, so that all makes sense. Can I reference those anywhere in code, including asm blocks, and the compiler will replace it with the index lookup value found in vocab.997? And then the interpreter will treat that as either a property/method index or an integer as appropriate? (It's not like there are any strongly typed variables here...)
A symbol that is preceded by a pound/hash sign (#) does a selector lookup and replaces the selector name with the number. So #title will evaluate to 80, #button to 81, and so on. It should work anywhere a value like a number (or a string, etc..) can be used. Literally all the compiler does is lookup the number of the selector and replace it with that number.
You'll see this used a lot in code that operates on lists. For example, "call this method on every object in this list":
; Call dispose on every member of the cast.
(gCast eachElementDo: #dispose)
... you use the # notation to pass the method number to the eachElementDo method.
The fact that these are used in the Print procedure is just kind of random. They could easily have used hard-coded enums too. There's no #at or #button or #title method ever being called. The Print procedure just uses them as identifiers to indicate what the next few parameters are.
Is it possible to add a tooltip that shows the index value when hovering over #selectors? Even if they're only used like constants for Print procedures, that's still a very commonly used procedure.
Yes, should be easy.
Then there's the "" vs {}. I read somewhere here that the original Sierra compiler would automatically convert "" strings into Text resources and leave {} string inline, but the last I read, SCICompanion did not duplicate that behaviour. Does this mean it does now?
I don't know if Sierra ever did that - I know you'll find quotes of me saying that, and claiming that in the documentation, because I heard it somewhere

. But we've seen no evidence of that in all the documentation that Omer has surfaces, as far as I know.
And yes, SCI Companion does support that now, but you have to turn it on explicitly for each script (since overwriting text resources when you compile a script is "risky" default behavior). Open the SCI Companion help and search for "auto generation". There should be one hit, and it's explained on that page. This isn't in the online help yet, because the official release from back in January does not have that functionality. So you have to use the help from the Help menu.
I assume Text resources are generated in the order they appear in script.So, does that mean that if I were patching a game (either my own release, or a Sierra game) and I had changed the order of some things in the script, I would need to distribute the new script.xxx and text.xxx files?
Yes, you would, if you enable the auto-generation of text resources. Or you could just leave it disabled as it is by default - then the strings will be compiled directly into the script of course, since the decompiler has replaced the resource/num tuple with a string (bloating the script resource, and potentially causing out of memory errors). Then the text resource won't even be used by the recompiled script.
Actually, enabling auto-generation of text resources is risky for a decompiled game, since I can't identify every place they are used. All the decompiler has to go on is two numbers in a row, and it only makes the assumption that they are a text resource tuple if the procedure call is "Print". So it'll miss some if they are used elsewhere, and then those tuples will be invalid once the text resource is auto-generated by compiling the script. So the game would show the wrong strings or crash.
Perhaps I should include an option in the decompiler to not replace the tuples - leave them as is. Maybe try to put a comment next to the Print call or something that contains the text, so it's still easy to follow a script's logic.