TADS3: how to "cast" to avoid this warning.

Hi all. First post here. I did some stuff with TADS2 ages ago and I’m trying to get into TADS3 now.

Here is my problem:

I have an object of type Container.
I am trying to iterate over its contents and put some of them elsewhere.

The code snippet is like this:

foreach( local c in innerContainer.contents )
if( /* – complex check here that’s not relevant to this question – */ )
c.basicMoveInto( self );

(Before you chastise me for using basicMoveInto instead of moveInto, I have a very good reason for this. I’m doing it because this occurs inside a “notifyRemove” method, which I don’t want to re-trigger and cause a regressive recursion.)

The problem happens on that statement “c.basicMoveInto(self)”. If I compile with all the warnings enabled, and the “treat warnings as errors” enabled, which I definitely want to do, I get this warning and can’t compile:

warning: undefined symbol “basicMoveInto” - assuming this is a property name

Now, I know exactly why this is happening, but I don’t know how to fix it other than to turn off treating warnings as errors, which is not a good idea. It’s happening because TADS3 is only strongly typed at runtime and not at compile time, so until runtime it doesn’t realize that the variable ‘c’ is only ever going to be holding objects of type Thing or subclasses of Thing. It thinks that ‘c’, being taken from the contents which is a List type, could be literally any language object, not necessarily a Thing or subclass of Thing. I know it can only be a Thing because it’s taken from the list of contents of a Container, so I know this is a safe assumption to assume it has a basicMoveInto(), but the compiler doesn’t know that, so I get the warning.

How do I make the warning go away without dangerously making ALL warnings go away? I don’t think there is such a thing as “casting” in TADS3, so that’s not the answer. I can’t declare C to be of type Thing (can I?). All variables are untyped at compile time.

There are times when the “assuming this is a property name” has been a very important warning that let me discover I was misspelling something, so I don’t want to suppress it universally - just in this one case.

You want baseMoveInto instead of basicMoveInto, I think. :slight_smile:

As a general point of clarification, properties in T3 are in a global namespace - and if any object or class declares a property, every object has it. It may not have a defined or inherited value, in which case it’s nil, but it’s there.

The compiler will be happy to let you call it as a method even if it’s set to nil; the error will only come at runtime.


Yeah but I was hoping I could still let the compiler stop me when this warning occurs anywhere else, rather than having to turn off the warning-is-error flag entirely to get it to compile.

I want a way to tell the compiler, “Thank you for warning me about this, but in just this one instance it’s actually okay and I’ll flag it as such, but please do continue complaining about any other instances of this warning you see, mister compiler”

Although a late-binding language can do a lot of really cool things, one disadvantage it can have is that misspellings in the code don’t get caught until runtime, and often they don’t even cause a crash, just wrong behavior (i.e. that boolean variable you had set to true gets read as false at a crucial point because it was misspelled and the game engine returned nil for the misspelled name.)

I fear that turning the warning-is-error flag off means I’ll be making tons of misspellings that go uncaught until an end-user happens to exercise that bit of code.

It would be nice if there was a way to say, in similar ways to how ‘casts’ work in C and Java, “This is the class I expect to be holding in this variable even though it doesn’t look like it, so issue me error messages according to it being that class rather than it being wide-open and generic.”

But even if that doesn’t exist, is there a way to temporarily change the compile options in the midst of the code? Can I put in a preprocessor directive that says “turn off the -We flag” on the line above, and then another one that says “turn the -We flag back on now” in the line below? That would be perfect.

There is one interesting case where you can add type annotations to locals, and that’s with multi-methods.

Even with the added type information, the compiler wouldn’t complain about calling a non-method property as a method, since you could set the property to a dynamic method created at runtime.

In this case, you’ve misspelled “baseMoveInto” as “basicMoveInto”, and the compiler error you’re trying to disable is telling you that.

I’ve never seen the compiler issue that warning about a legitimate symbol. I’m not sure why it’s not a hard error since new properties can’t be created at runtime - if the compiler doesn’t know about the symbol, it almost certainly isn’t valid.

Except that I made that spelling error only when re-typing it into the forums post. In the code it was spelled right. (Not that you had any way to know that).
What you said would make sense, except that it was weirdly giving me the same error when I said “moveInto()”, which I know was spelled right. I did eventually discover that there was another unrelated error that made the message go away when I fixed it. I had accidentally created this class just inside the ‘;’ termination of the previous class rather than just after it and that made it think this class was meant to be contained lexically inside the earlier one, and that led to some odd behavior that could be related. At any rate, its gone now and the -we option is back on. Thanks for the help.