interpreter warning
by Ian Omroth Hardingham · in Torque Game Engine · 03/26/2003 (5:10 am) · 18 replies
Hi everyone.
Now, this is a scripting language, so not having to declare variables is the norm. However, surely the above behavoir is completely ridiculous?
In Python, attempting to reference (*not* assign) a variable that isn't defined in the current name space will produce a compiler error. Could we at least have it as an interpeter warning in TGE?
If I'm missing the usefullness of being able to reference a variable which doesn't exist, and having the interpreter make a value up for it which is type-correct, I apologise. However, I find it difficult to trust the scripting language because I know that a spelling mistake in *any* variable (not just assignments) will go unchecked.
For instance:
Anyway, could people look into interpreter warnings for this?
Thanks,
Ian
$a = 0; echo($a == $doesnt_exist); 1
Now, this is a scripting language, so not having to declare variables is the norm. However, surely the above behavoir is completely ridiculous?
In Python, attempting to reference (*not* assign) a variable that isn't defined in the current name space will produce a compiler error. Could we at least have it as an interpeter warning in TGE?
If I'm missing the usefullness of being able to reference a variable which doesn't exist, and having the interpreter make a value up for it which is type-correct, I apologise. However, I find it difficult to trust the scripting language because I know that a spelling mistake in *any* variable (not just assignments) will go unchecked.
For instance:
%moo = %base_moo_likelyhood + %cow_moo_perogative * %cow_moodWill work fine, whereas:
%moo = %base_moo_likelyhood + %cow_moo_perogitive * %cow_moodWill only have my cow mooing at the base likelyhood. Now, I see this behavoir in my game but I think it's an error with %cow_mood: maybe my cows are always in a good mood, which is why the multiplication always ends in 0. It then takes me absolutely ages to find what the actual problem is.
Anyway, could people look into interpreter warnings for this?
Thanks,
Ian
About the author
Designer and lead programmer on Frozen Synapse, Frozen Endzone, and Determinance. Co-owner of Mode 7 Games.
#2
$a = 0;
$doesnt_exist = NULL;
They are both a basically a Boolean FALSE
echo( FALSE == FALSE);
will return True....
03/26/2003 (10:55 am)
Umm... why would that be incorrect behaviour?$a = 0;
$doesnt_exist = NULL;
They are both a basically a Boolean FALSE
echo( FALSE == FALSE);
will return True....
#3
A declared but uninitialised variable is NULL, but an undeclared variable certainly isn't. And NULL is most certainly not equivalent to a boolean false.
And it isn't even true that an undeclared variable is NULL in TGE, because (1 + 5 * $doesnt_exist) will have $doesnt_exist as 0.
03/26/2003 (11:48 am)
I completely disagree with you Labrat, despite knowing full well that you are a good programmer from lots of posts of yours I've read.A declared but uninitialised variable is NULL, but an undeclared variable certainly isn't. And NULL is most certainly not equivalent to a boolean false.
And it isn't even true that an undeclared variable is NULL in TGE, because (1 + 5 * $doesnt_exist) will have $doesnt_exist as 0.
#4
This is mostly just a matter of preference. I agree that an option warning would be useful, though.
In C++, NULL is defined to be 0 which is defined to be a boolean false. Again, doesn't seem very strange to me, but maybe I've just gotten used to it.
03/26/2003 (12:22 pm)
I've dealt with other languages where an undefined variable is 0 before, so it doesn't seem particularly wrong to me.This is mostly just a matter of preference. I agree that an option warning would be useful, though.
In C++, NULL is defined to be 0 which is defined to be a boolean false. Again, doesn't seem very strange to me, but maybe I've just gotten used to it.
#5
They might not actually be the same, but they are used in the same way.
And I believe that 0 in C++ is essentially the same thing as NULL also (at least to some compilers).
03/26/2003 (12:23 pm)
NULL works in most (if not all) situations the same way Boolean false does.They might not actually be the same, but they are used in the same way.
And I believe that 0 in C++ is essentially the same thing as NULL also (at least to some compilers).
#6
PHP doesn't have declared or initialised variables.
If you try your first example in PHP you WILL get the same result.
RESULT:
The behaviour you are expecting is what you would get in C, C++
03/26/2003 (12:24 pm)
Torquescript doesn't have declared or initialised variables.PHP doesn't have declared or initialised variables.
If you try your first example in PHP you WILL get the same result.
<? $a=0; echo($a == $doesnt_exist); ?>
RESULT:
1
The behaviour you are expecting is what you would get in C, C++
#7
All standards compliant C++ compilers define NULL to be 0. Some older ones for funny architectures _might_ use something else, but it was never very common.
03/26/2003 (12:38 pm)
Quote:
And I believe that 0 in C++ is essentially the same thing as NULL also (at least to some compilers).
All standards compliant C++ compilers define NULL to be 0. Some older ones for funny architectures _might_ use something else, but it was never very common.
#8
In TorqueScript you don't have to declare or initialize a variable. Furthermore you don't have to keep a variable a specific type, because it is a loosely written language.
ie:
is perfectly fine syntax.
This is actually useful.
For instance, lets say you want to create a death messaging hud like that found in counter strike where it lists deaths in a game as they occur and then deletes the oldest death off the top of the message hud. You can create these death lines dynamically like so:
You can now refer to each of these death lines as objects in the scripting language:
03/26/2003 (1:22 pm)
I'm going with LabRat on this.In TorqueScript you don't have to declare or initialize a variable. Furthermore you don't have to keep a variable a specific type, because it is a loosely written language.
ie:
%stupidExample = 0x999; if(%stupidExample == 0x999) %stupidExample = "A stupid example";
is perfectly fine syntax.
This is actually useful.
For instance, lets say you want to create a death messaging hud like that found in counter strike where it lists deaths in a game as they occur and then deletes the oldest death off the top of the message hud. You can create these death lines dynamically like so:
// we'll have a max of 3 death lines
for(%i = 0; %i < 3; %i++)
{
%msgYCoord = (%i * 21);
%msgCoords = "2 " @ %msgYCoord;
// create our GUI object dynamically based upon
// the line number we are on
%addFilterLine = "addFilterLine" @ %i;
new GuiMLTextCtrl(%addFilterLine) {
profile = "GuiTextObjHudLeftProfile";
horizSizing = "right";
vertSizing = "bottom";
position = %msgCoords;
extent = "280 21";
minExtent = "8 8";
visible = "1";
};
FilterMsgHud.add(%addFilterLine);
}You can now refer to each of these death lines as objects in the scripting language:
if(isObject(addFilterLine0))
echo("This is fine");
if(isObject("addFilterLine1"))
echo("This is also fine");
for(int i = 0; i < 3; i++)
if(isObject(addFilterLine @ %i))
echo("This is fine as well");
#9
I stand by my opinion, however, that it's ridiculous behavoir, and I don't think Knuth would have liked it at all. I'm afraid I don't actually understand Robert blanchley Jr's post, or what's remarkable about his example code. Could someone please give an example where it is useful for the interpreter to make up values for variables which don't already exist in the name space?
(Just in case anyone's confused, I'm not taking issue with not having to declare variables, just being able to use non existant ones in statements.)
03/26/2003 (2:56 pm)
Okay, it appears I'm wrong about NULL and boolean false ;) And also about how unusual the interpreter making up variables is.I stand by my opinion, however, that it's ridiculous behavoir, and I don't think Knuth would have liked it at all. I'm afraid I don't actually understand Robert blanchley Jr's post, or what's remarkable about his example code. Could someone please give an example where it is useful for the interpreter to make up values for variables which don't already exist in the name space?
(Just in case anyone's confused, I'm not taking issue with not having to declare variables, just being able to use non existant ones in statements.)
#10
Then it is wonderful and essential to have Torque complain about undefined variables.
Scripting languages are awesome for rapidly developed, constantly changing code, but there comes a time when you want to fix the code, debug it, and finalize it; that is when you need help like Ian has pointed out.
This is not an issue of debate. The problem can be solved without affecting anyone or changing how the engine behaves.
I am right now testing a small patch that makes Torque print out a warning when you access a variable that isn't initialized. This is the Right Way to solve this problem; it's quick, fast, and very, very simple.
edit: [u] is not a tag.
03/26/2003 (4:21 pm)
This is all fine and dandy until you have to debug your code.Then it is wonderful and essential to have Torque complain about undefined variables.
Scripting languages are awesome for rapidly developed, constantly changing code, but there comes a time when you want to fix the code, debug it, and finalize it; that is when you need help like Ian has pointed out.
This is not an issue of debate. The problem can be solved without affecting anyone or changing how the engine behaves.
I am right now testing a small patch that makes Torque print out a warning when you access a variable that isn't initialized. This is the Right Way to solve this problem; it's quick, fast, and very, very simple.
edit: [u] is not a tag.
#11
At the end of Dictionary::getVariable(StringTableEntry name, bool *entValid), around line 365 of consoleInternal.cc, add these lines:
Except that this isn't catching local errors (ie, echo(%foo))... I'll see about that :)
-------------------------
It's actually even simpler, just go to console\compiledEval.cc, around line 319, and uncomment the two lines which go:
And there you are. Very, very simple. Is there a reason this isn't enabled in HEAD?
03/26/2003 (5:33 pm)
The patch:At the end of Dictionary::getVariable(StringTableEntry name, bool *entValid), around line 365 of consoleInternal.cc, add these lines:
if(entValid)
*entValid = false;
[b]
// Warn users when they access a variable that isn't defined.
Con::warnf(" *** Accessed undefined variable '%s'", name);
[/b]
return "";
}Except that this isn't catching local errors (ie, echo(%foo))... I'll see about that :)
-------------------------
It's actually even simpler, just go to console\compiledEval.cc, around line 319, and uncomment the two lines which go:
if(!currentVariable) Con::warnf(ConsoleLogEntry::Script, "Variable referenced before assignment: %s", name);
And there you are. Very, very simple. Is there a reason this isn't enabled in HEAD?
#12
03/27/2003 (2:16 am)
Thankyou!
#13
03/27/2003 (4:53 am)
Although I like torque's "loose" variables, that warning is quite nice to have.
#14
(and to avoid confusion agai: I'm not taking issue with not having to declare variables, just being able to use non existant ones in statements.)
03/27/2003 (5:58 am)
I still don't understand why anyone would want this particular example of looseness. Again, can anyone give me an example where actually useful?(and to avoid confusion agai: I'm not taking issue with not having to declare variables, just being able to use non existant ones in statements.)
#15
Take scripted pathfinding for example. You could save lots of memory if you don't have to set nonexisting paths to "0". Think about large arrays where only few, scattered elements are defined. Would you want errors while iterating through all the unused elements?
03/27/2003 (6:03 am)
Here's one, I hope it makes sense:Take scripted pathfinding for example. You could save lots of memory if you don't have to set nonexisting paths to "0". Think about large arrays where only few, scattered elements are defined. Would you want errors while iterating through all the unused elements?
#16
Frankly, it's debatable whether you should ever be accessing uninitialized variables, but it can be handy. Another example is if you have a callback that, say, increments a variable (such as the high score, or an animation status value); the first time the variable may not be defined, but TorqueScript is lazy and pretends it is zero, so you don't have to worry, and everything works.
My experience is when you are developing, using uninit'ed variables can be handy in that they save you effort - you don't have to set up infrastructure to set them up for you; when you are finalizing the code, you want to know about them so you don't shoot yourself in the foot. Occasionally there are neat tricks you can pull with them in production code.
Let's move on with our lives. This is one of those things you'll grok when you need it. :)
03/27/2003 (6:46 am)
(This example is more interesting when you bear in mind that _all_ arrays in TorqueScript are considered to be sparse; ie, $foo[3] is actually referencing $foo__3 or something like this, using the array operator does not a priori imply there is an actual array)Frankly, it's debatable whether you should ever be accessing uninitialized variables, but it can be handy. Another example is if you have a callback that, say, increments a variable (such as the high score, or an animation status value); the first time the variable may not be defined, but TorqueScript is lazy and pretends it is zero, so you don't have to worry, and everything works.
My experience is when you are developing, using uninit'ed variables can be handy in that they save you effort - you don't have to set up infrastructure to set them up for you; when you are finalizing the code, you want to know about them so you don't shoot yourself in the foot. Occasionally there are neat tricks you can pull with them in production code.
Let's move on with our lives. This is one of those things you'll grok when you need it. :)
#17
Ben, thanks for finding out what to change so we may receive this warning. I'd personally prefer to see what isn't being defined before being referenced and then go from there.
For those that prefer to not have these warnings in their release code, just surround the if statement with a #ifdef TORQUE_DEBUG.
- LightWave Dave
03/27/2003 (6:58 am)
Greetings!Ben, thanks for finding out what to change so we may receive this warning. I'd personally prefer to see what isn't being defined before being referenced and then go from there.
For those that prefer to not have these warnings in their release code, just surround the if statement with a #ifdef TORQUE_DEBUG.
- LightWave Dave
#18
03/27/2003 (7:17 am)
Ooh, good thought, Dave.
Associate Kyle Carter
Perhaps this would be worth a VB-style "Option Explicit" directive for the compiler/interpretive, which controls whether or not it bugs out when it tries to access a null variable.
I think that it's VERY handy not to have to always init things, but this is definitely a case where for debugging purposes, you want the ability to trap it! (witness use strict in PERL, Option Explicit, and similar things)
If I have the chance, I'll see about doing this, but I have a class coming up. :(