Baffled by a compiler error
DHawthorne
Posts: 4,584
OK, this is driving me crazy. I'm modifying a Marantz UI module, and part of my mod is putting the feedback in a CALL from a TIMELINE. The following snippet is generating a syntax error in the compiler:
I might add, I hate the generic syntax error message with extreme prejudice. It seriously needs to at least provide the token that generated the error. It also pretty consistently highlights the wrong line when you double click the error message. Most of the time I have to comment out lines to pinpoint the real cause of the error because it's not even remotely close to the actual error. In this particular case, it highlights the blank line after the variable declarations; I only know it's the declarations that are causing the problem because commenting them out makes it go away.
DEFINE_CALL 'Panel Feedback' { LOCAL_VAR CHAR sOldFeedback[6][30] STACK_VAR CHAR cCount [dvMarantzTP, nButn[25]] = (nSurroundMode == 0) [dvMarantzTP, nButn[26]] = (nSurroundMode == 1) [dvMarantzTP, nButn[27]] = (nSurroundMode == 2) // ...and so on for remainder of call }If I comment out the variable declarations and put them in DEFINE_VARIABLE, there is no error. Any attempt to declare them in the CALL itself fails. I've declared variables in CALLs thousands of times, and I am completely baffled as to why I'm getting this error.
I might add, I hate the generic syntax error message with extreme prejudice. It seriously needs to at least provide the token that generated the error. It also pretty consistently highlights the wrong line when you double click the error message. Most of the time I have to comment out lines to pinpoint the real cause of the error because it's not even remotely close to the actual error. In this particular case, it highlights the blank line after the variable declarations; I only know it's the declarations that are causing the problem because commenting them out makes it go away.
0
Comments
Not sure what is causing the problem, but I had the same issue when pasting you code snippet into a running program. I was able to get the error to disappear by rearranging the code to this:
Hope this helps.
Jeff
DEFINE_CALL 'Panel Feedback'
{
LOCAL_VAR CHAR sOldFeedback[6][30]
STACK_VAR CHAR cCount
{
[dvMarantzTP, nButn[25]] = (nSurroundMode == 0)
[dvMarantzTP, nButn[26]] = (nSurroundMode == 1)
[dvMarantzTP, nButn[27]] = (nSurroundMode == 2)
}
// ...and so on for remainder of call
}
Or
DEFINE_CALL 'Panel Feedback'
{
LOCAL_VAR CHAR sOldFeedback[6][30]
STACK_VAR CHAR cCount
SEND_STRING 0,'something'
[dvMarantzTP, nButn[25]] = (nSurroundMode == 0)
[dvMarantzTP, nButn[26]] = (nSurroundMode == 1)
[dvMarantzTP, nButn[27]] = (nSurroundMode == 2)
// ...and so on for remainder of call
}
Joe
I have the reverse issue with Semicolons. I've always been so used to NOT needing them with AMX - so since C-tron came out with S+, I'm quite often forgetting to add them where they're required...
- Chip
And the readability plus is just too big to ignore, IMHO.
CALL 'DoMyFeedback'
vs.
DoMyFeedback ()
Eh, six and one-half dozen the other I suppose...
- Chip
I've seen this one before and never spent enough time to find out the problem. Did AMX Tech Support clue you in? If not, this should be reported.
No, I didn?t have any contact with AMX tech support regarding this. I don?t consider this a bug of any type since the compiler is doing its job correctly and terminating statements with a ; fixes any ?misunderstandings? like this. However, it would be nice to have the compiler generate some type of illegal dimension error instead of the generic syntax error message. Although in this particular case the illegal dimension error would have still been confusing since one might assume at first that it was nButn[25] causing the problem since the first feedback line is the one that gets flagged with the error.
I?ve seen several posts where people point out that the line that the compiler flags is one line off from where the error occurred. I don?t think that?s the case in many instances. For example in the code posted at the top of this thread, the compiler flags the first feedback line as the line with the error. And in this case it?s absolutely true. The compiler flagged the line where the illegal character is actually found.
About a year ago I had a problem very similar to this and I never figured it out. The only way I fixed it was to swap two lines of code around but it drove me nuts as to why the error disappeared when I did and why I had the error to begin with. So in all honesty it took me about a year to figure out this puzzle.
What it boils down to, though, is this: if you aren't going to mandate a line termination character, then you cannot universally consider a newline to be white space. I can see how this would be a bit of a nightmare to write into the compiler (and I am am feeling far to lazy to consider what the ruleset would need to be right now ); which is why termination characters came into being in the first place. Making the compiler "smarter" will also make it less efficient, and since we are (mostly) professionals here, I'm OK with the onus being on the programmer.
As for the highlight not appearing in the "right" place for the error - that is a bigger issue, and I likewise see no easy solution. My example snippet here left out 20 lines of comments after the variable declaration in question - it wasn't highlighting even remotely close to the error. But that was an easy case; I've seen far worse ones.
For example: you have a module with a bunch of parameters set in an include file. Errors are highligted based on what the line number would have been if the include was part of the module code. If you have multiple includes (not uncommon for me), it gets to be a royal pain. Throw in a few instances of code spanning multiple lines, and the compiler treating them as one, and then a generic error message, and you have a big problem figuring out what the problem really is. My workaround is very simply, compile often, and structure the way I write code so that I am filling in a legitimately syntaxed framework. That way when an error crops up, at least I know it was something I changed in the last hour if the error message is ambiguous. I would feel better about it all the same, if the compiler always told you exactly what token generated the error. It seems to me it once did - or does it only do so in some cases, and those aren't the kind of slip-ups I make very often? Another pet peeve I have is run-time errors that specify an array indexing error, but not the array name (I really wish NetLinx used zero-based indexing) and/or the the module that generated the error.
If the answer is yes to either of the two above questions and Netlinx supports using the ; as a line terminator, why isn't it taught in class to use the ";" to terminate lines?
Regardless, I think I'm going to untrain my untraining (used to program C and C++) and start using the ";" again. Even if it saves me the trouble of dealing with only one vague error in the future, I think it will be worth it.
Jeff
My guess is that when they developed the Axcent programming language, they wanted to make it more accessible to those new at programming. They did a good job at that I think; but the semicolon was one of the things they threw out to do that.
When NetLinx came along, they tried very hard to make it so that old Axcent code could be used with minimal modification, so they likewise left out the requirement for semicolons. Imagine the tedium of going through every snippet of old code and terminating the lines...yak. It would be even worse to add the requirement now, NetLinx code files tending to be much larger and more complex. But I'll be writing all my new code with them.
...which leads me to yet another thought: some kind of macro capability in Studio would be truly wonderful, even if only rudimentary. It would make such conversions considerably less onerous.
Jeff
I'm so used to NOT using semicolons, I wouldn't start unless the compiler was going to check up on me. Otherwise I'd just have <100% of my code with semicolons...
(And I'm too anal-retentive to allow that)
- Chip
I'm a "professional" developer. I write high performance, multithreaded servers for a living. When I develop code in C++ (my day job) "offline" (i.e. not regularly compiling), and then I go to compile, I get meaningful error messages, and it's easy for me to determine what the problem is - and where it is. I can get this code up and going quickly.
When I develop code in NetLinx, I *MUST* regularly compile. Even every dozen lines (or less). If I don't, then sometimes I'll get bizarre errors, and it'll be extraordinarily difficult to isolate.
When I get bizarre errors, they are generally related to one or more of:
1. An error message that, in no way, gives me a hint of the actual problem,
2. Sometimes a declaration (up top) causes a problem down below, in the implementation section. Not clear from error messages,
3. Line numbers that are inaccurate, forcing me to look at the wrong sections of code.
It's common for me to comment out blocks of code to help isolate changes when these sorts of things happen.
Bottom line: I don't think error detection for NetLinx is very good. In the past, I diligently reported these to AMX. Now I just don't bother anymore. I actually gave them *reproducable* issues where the line number was off (and they could reproduce at will), and these still weren't fixed. I just don't think this is a very important issue to AMX (at least judging on their lack of fixing these problems over time, even for easy to reproduce "simple" issues).
Now, that said: I tend to think that you should just regularly terminate lines with a semi-colon. This is very common in other languages (C, C++, Perl, and many many others). It's much easier for the token analyzer to understand what's coming in, and how to parse. The fact that it sometimes works properly and sometimes doesn't is no surprise to me ...
However, we fixed a similar problem for lines of code that don't start with an open bracket in v2.2, so if you do something like:
...it will compile just fine in Studio 2.2 and above - well actually, with the v2.2.0.108 compiler that Studio 2.2. installs.
I'll pass this along to the Engineers...
Anyone have any other thoughts on this idea?
Jeff
Jeff
Jeff, I think this would work, as the problem seems to be that the programmer and the compiler see the lines ending in different places.
If the compiler added the missing semicolons into the source code your idea would let the programmer look through the code that generated the error and show how the compiler saw the code. This should ideally be a compiler option. I never knew you could use semi-colons and always forget them when writing C. Most lines begin with a keyword or a previously declared (and therefore recognizable) variable, so it's easy to see where they start, but multiline DECLARE_VARIABLE statements are an exception. Perhaps semicolons should be obligatory in this case.
Another cure for the problem of not knowing where array declarations end might be to put in a comment - anyone tried this?
Jeff
Jeff
What I meant was to put a comment at the end of the array declaration instead of a semi-colon, so to tell the compiler where it ended.
John
Where I always seem to get burned is in returns without values. The compiler always takes the next statement as the value. I end up surrounding it with {} to get rid of errors.
I tried to play around with this block and found out curious thing:
DEFINE_CALL 'NO NAME'
STACK_VAR no_Name1
STACK_VAR no_Name2
{
//SO SOMETHING
//WITH NONAMES
}
works fine, also if there's only one declaration per call it works the way it was posted originally:
DEFINE_CALL 'NO NAME'
{
STACK_VAR no_Name1
//SO SOMETHING
//WITH NONAME
}
But if you have more than one, it doesn't
DEFINE_CALL 'NO NAME'
{
STACK_VAR no_Name1
STACK_VAR no_Name2
//SO SOMETHING
//WITH NONAME
}
will return compiler error. According to Netlinx Programming Language description:
"...Local
variables must be declared immediately after the opening brace of a block but before the
first executable statement."
So, compiler thinks, that second STACK_VAR is the "...first executable statement." Braces before STACK_VAR:
DEFINE_CALL 'NO NAME'
{
STACK_VAR no_Name1
STACK_VAR no_Name2
{
//SO SOMETHING
//WITH NONAMES
}
}
tell compiler where is the beginning of the first executable statement. It makes some sense to me, because it looks a little bit like other language elemnts, e.g. IF:
...
IF (SOMETHING_IS_WRONG)
SEND_STRING SOMEONE, "'DO SOMETHING'"
SEND_STRING SOMEONE, "'DO SOMETHING ELSE'"
first 'DO SOMETHING' is executed as a part of conditional because it's the first statement right after 'IF'.
Anyway, it's just my toughts.
Good luck everyone.
Paul
Best bit of thread necromancy I've seen in a long while!
I'm glad someone did dig this up. This caught me out the other day and wasted half an hour of my time. 3 years (at least) since the problem was identified and it still hasn't been fixed?!
Edit: Me no can add. Make that 4 years!
And I got caught with it today. This stuff is getting irritating.
--John
I think someone already mentioned this, but...
There is no required End-Of-Line delimiter in NetLinx, so to the compiler the two code snippets below are the same:
// start
STACK_VAR INTEGER nMyInt[<...additional code here>
// end
//start
STACK_VAR INTEGER nMyInt
[<...additional code here>
// end
My guess is this one of those things that doesn't have any easy or elegant fix that won't break someone else's existing code.