Home AMX User Forum NetLinx Studio

Another mysterious compiler issue

OK, scratching my head over this one ...

The following snippet generates a compiler (syntax) error:
DEFINE_DEVICE

dvTP =	10001:1:0

DEFINE_VARIABLE

VOLATILE INTEGER nVolume[3] ;

DEFINE_CALL 'Panel Update'
{
    LOCAL_VAR CHAR sOldTunerFreq[10] ;
    LOCAL_VAR CHAR sMainVolume[2][4] ;
    
    sMainVolume[1] = ITOA(nVolume[1]) ;
    SEND_LEVEL dvTP, 1, nVolume[1] ;
    
}

Move the SEND_LEVEL line so it's before the sMainVolume assignment line, and it compiles fine. Leave it as written, but remove the sOldTunerFreq declaration, and it compiles fine. Changing the order of the LOCAL_VAR declarations has no effect. Remove the semicolons after the LOCAL_VAR declarations, and it also compiles fine :(.

Why? Clearly the compiler is having trouble determining where the declarations end and the code begins, but I thought semicolons were the definitive answer to that particular problem.

Comments

  • jjamesjjames Posts: 2,908
    Oops - jumped to quick. Didn't read . . .
  • put the LOCAL_VAR assignments before the opening brace.
  • HedbergHedberg Posts: 671
    I don't know why it fails as written and the standard invalid syntax error message is about as useful as a rubber crutch. But, setting off the statements subsequent to the variable declarations in a subordinate code block seems to work. This, for example:
    DEFINE_CALL 'Panel Update'
        LOCAL_VAR CHAR sMainVolume[2][4] ;
        LOCAL_VAR CHAR sOldTunerFreq[10] ;
    {	
    	
        sMainVolume[1] = ITOA(nVolume[1]) ;
        SEND_LEVEL dvTP, 1, nVolume[1] ;
        
    }
    
    
    compiles without error as does this:
    DEFINE_CALL 'Panel Update'
    {
        LOCAL_VAR CHAR sMainVolume[2][4] ;
        LOCAL_VAR CHAR sOldTunerFreq[10] ;
    	{	
    			sMainVolume[1] = ITOA(nVolume[1]) ;
    			SEND_LEVEL dvTP, 1, nVolume[1] ;
    	}    
    }
    
    

    I was not aware that Netlinx would permit C style line terminations. Is there a technote or anything which explains when this is advisable?

    Harold
  • DHawthorneDHawthorne Posts: 4,584
    put the LOCAL_VAR assignments before the opening brace.
    That's an Axcent convention; standard NetLinx is to put your declarations inside the braces.
  • DHawthorneDHawthorne Posts: 4,584
    Hedberg wrote:

    I was not aware that Netlinx would permit C style line terminations. Is there a technote or anything which explains when this is advisable?

    Harold
    The NetLinx compiler has always supported them. Axcent does not.

    We had this discussion here a while ago; there are times when the compiler doesn't properly recognize the end of a declaration (generally when the next line is a DEVCHAN [] notation), and the semicolon forces it to recognize that wasn't intended as part of your declaration. We surmised that some other mysterious compiler errors might be due to something similar. Since that discussion, I have been using them on all my projects.
  • DHawthorne wrote:
    That's an Axcent convention; standard NetLinx is to put your declarations inside the braces.

    check the studio help file

    The keyword LOCAL_VAR specifies a variable that is static. A static variable?s value is initialized the first time the statement block in which it is declared is executed and retained after execution of the statement block has finished. To provide compatibility with the Axcess language, local variables may be declared right before the opening brace for DEFINE_CALL declarations only.
  • Maybe a better question is why you're enforcing the need for extra typing by using the Axcess holdover DEFINE_CALL instead of Netlinx's DEFINE_FUNCTION? :)

    - Chip (Was so very happy to nuke DEFINE_CALLs the day Netlinx came out)
  • Spire_JeffSpire_Jeff Posts: 1,917
    Chip Moody wrote:
    Maybe a better question is why you're enforcing the need for extra typing by using the Axcess holdover DEFINE_CALL instead of Netlinx's DEFINE_FUNCTION? :)

    - Chip (Was so very happy to nuke DEFINE_CALLs the day Netlinx came out)

    Is there a performance difference? I regularly use DEFINE_CALL whenever I don't need a value returned. Not exactly sure why this is, but I think it has to do with some of my early years programming experience.

    Jeff
  • DHawthorneDHawthorne Posts: 4,584
    I only use DEFINE_FUNCTION if I need a return value. I don't think there is any difference otherwise, except perhaps for the constant string for the call token. Not something I'm worried about ...
  • I'm with Chip on this one, I convert all DEFINE_CALLs to DEFINE_FUNCTIONs.
  • champchamp Posts: 261
    My first programming was Axcess so there are legacy DEFINE_CALLS still in my code though all new code uses DEFINE_FUNCTIONS.

    I found when I started to program in other languages I got lots of compilation errors because I wasn't used to using colons.

    using DEFINE_FUNCTIONS and colons are a good habbit to get into if you ever plan to program in other languages and make your code more portable.
  • Spire_Jeff wrote:
    Is there a performance difference? I regularly use DEFINE_CALL whenever I don't need a value returned. Not exactly sure why this is, but I think it has to do with some of my early years programming experience.

    Jeff

    I doubt it. I just can't stand having to put "CALL 'SOME_FUNCTION'" all over my program when I can do "Some_Function ()" instead.

    Just a personal taste thing with me. :)

    - Chip
  • DHawthorne wrote:
    OK, scratching my head over this one ...

    The following snippet generates a compiler (syntax) error:
    DEFINE_DEVICE
    
    dvTP =	10001:1:0
    
    DEFINE_VARIABLE
    
    VOLATILE INTEGER nVolume[3] ;
    
    DEFINE_CALL 'Panel Update'
    {
        LOCAL_VAR CHAR sOldTunerFreq[10] ;
        LOCAL_VAR CHAR sMainVolume[2][4] ;
        
        sMainVolume[1] = ITOA(nVolume[1]) ;
        SEND_LEVEL dvTP, 1, nVolume[1] ;
        
    }
    

    Move the SEND_LEVEL line so it's before the sMainVolume assignment line, and it compiles fine. Leave it as written, but remove the sOldTunerFreq declaration, and it compiles fine. Changing the order of the LOCAL_VAR declarations has no effect. Remove the semicolons after the LOCAL_VAR declarations, and it also compiles fine :(.

    Why? Clearly the compiler is having trouble determining where the declarations end and the code begins, but I thought semicolons were the definitive answer to that particular problem.

    We have a note in our database for Studio 1.20 which has a similar problem. It was a compiler bug where you have to end the LOCAL_VAR line with a semicolon if a Array-Element assignment was done directly after the LOCAL_VAR.

    But I found one more variation to get it to work:
    DEFINE_CALL 'Panel Update'
    {
        //LOCAL_VAR CHAR sOldTunerFreq[10] ;
        //LOCAL_VAR CHAR sMainVolume[2][4] ;
        LOCAL_VAR CHAR sOldTunerFreq[10], sMainVolume[2][4]
        sMainVolume[1] = ITOA(nVolume[1]) ;
        SEND_LEVEL dvTP, 1, nVolume[1] ;
        
    }
    
    This is the way I declare LOCAL_VARs or STACK_VARs if I have more than one of a type.
    In this notation it doesn't matter if a semicolon is used or not to end the LOCAL_VAR line.
  • DHawthorneDHawthorne Posts: 4,584
    The really odd thing in this case is that the semicolon is one of the things that breaks it. What I really worry about in these cases is the time when something is happening behind the scenes that the compiler doesn't generate an error for, yet still doesn't do what you thought it is doing.

    I have any number of ways to make that piece of code work, that's not what I am looking for. I want to understand why it didn't work the first time, to avoid problems in the future that aren't so easy to see are happening.
  • Joe HebertJoe Hebert Posts: 2,159
    We have a note in our database for Studio 1.20 which has a similar problem. It was a compiler bug where you have to end the LOCAL_VAR line with a semicolon if a Array-Element assignment was done directly after the LOCAL_VAR
    It looks like the compiler has done close to a 180 since Studio 1.20. Instead of having to end the declaration line with a semicolon if an Array-Element assignment is the first line of code ? now you must NOT end with a semicolon if an Array-Element assignment is the first line of code and if there is more than 1 declaration statement.
    [b]This incorrectly generates an [i]Illegal or Invalid syntax in code[/i] error.[/b]
    DEFINE_VARIABLE
    
    INTEGER a[1];
    
    DEFINE_FUNCTION test () {
    
       INTEGER b;
       INTEGER c;  //using semicolon for last declaration statement.
          
       a[1]=5;
       
    }
    
    [b]This compiles fine[/b]
    DEFINE_VARIABLE
    
    INTEGER a[1];
    
    DEFINE_FUNCTION test () {
    
       INTEGER b;
       INTEGER c //NOT using semicolon for last declaration statement.
       
       a[1]=5;
       
    }
    
    Why? Clearly the compiler is having trouble determining where the declarations end and the code begins, but I thought semicolons were the definitive answer to that particular problem.

    I agree the compiler is having trouble but I think it knows that the declarations have ended and the code begins because if you comment out the line INTEGER a[1]; the error Symbol [A] not defined is generated for the line a[1]=5;
    I have any number of ways to make that piece of code work, that's not what I am looking for. I want to understand why it didn't work the first time?
    I certainly can?t explain it and I hope it's looked into. A confused compiler is never a good thing.
    But I found one more variation to get it to work:
    DEFINE_CALL 'Panel Update'
    {
        //LOCAL_VAR CHAR sOldTunerFreq[10] ;
        //LOCAL_VAR CHAR sMainVolume[2][4] ;
        LOCAL_VAR CHAR sOldTunerFreq[10], sMainVolume[2][4]
        sMainVolume[1] = ITOA(nVolume[1]) ;
        SEND_LEVEL dvTP, 1, nVolume[1] ;
        
    }
    
    This is the way I declare LOCAL_VARs or STACK_VARs if I have more than one of a type. In this notation it doesn't matter if a semicolon is used or not to end the LOCAL_VAR line.
    IF you add a second declaration line like:
    STACK_VAR CHAR sOldTunerFreq2[10], sMainVolume2[2][4];
    and end it in a semicolon, the illegal syntax error will be generated.

    Isn?t programming fun? :)
  • Joe HebertJoe Hebert Posts: 2,159
    Define_function

    Regarding the DEFINE_CALL vs. DEFINE_FUNCTION debate, I?m in the Chip, champ, and cbaily camp. I was immediately converted the first time Chip voiced his opinion some time ago. I?ll never write another DEFINE_CALL again.
  • Not so fast.
    Joe Hebert wrote:
    Regarding the DEFINE_CALL vs. DEFINE_FUNCTION debate, I?m in the Chip, champ, and cbaily camp. I was immediately converted the first time Chip voiced his opinion some time ago. I?ll never write another DEFINE_CALL again.
    Perhaps you all like DEFINE_FUNCTION because that is what 'real' programmers use. But, I will argue that the code is much more readable using DEFINE_CALL because they are named as literal strings. And with my editor color code scheme literal strings are very easy to locate in a program. :)
Sign In or Register to comment.