Menu

#3554 where has the syntax error detection gone

obsolete: 8.5a5
closed-invalid
3
2008-01-12
2006-10-25
No

I was trying out 8.5a5 thinking that it's new compiled
switch feature would improve Tcl's detection of syntax
errors in switch arms, but instead found not only
is it unchanged, but that the basic error detection of
"if" is now gone. For example the following script
causes 8.3 and 8.4 to barf, but is perfectly legal
in 8.5:

proc bar var {
if {$var == "acorn"} {
set a b c
}
}
bar a

Ditto for

proc bar var {
if {$var == "acorn"} {
set a [b c
}
}

The "no errors til you execute it" policy means
you need nearly perfect code coverage testing
to use Tcl with any confidence.

Discussion

  • Donal K. Fellows

    Logged In: YES
    user_id=79902

    Because you can do some horrible hacks like this now:

    rename if if_
    proc if args {
    foreach a $args {puts $a}
    }
    bar var
    rename if {}
    rename if_ if

    OK, that's rather odd code, but it's legal. If you want
    static syntax checking, use a third-party tool like Nagelfar.

     
  • Donal K. Fellows

    • labels: --> 47. Bytecode Compiler
    • milestone: --> obsolete: 8.5a5
    • priority: 5 --> 3
    • assigned_to: nobody --> msofer
     
  • Peter MacDonald

    Peter MacDonald - 2006-10-26

    Logged In: YES
    user_id=190660

    Wonderful, Tcl will have even less checking.

    Any idea how hard it would be to optionally
    disable this lazy compile?

     
  • Peter MacDonald

    Peter MacDonald - 2006-10-26

    Logged In: YES
    user_id=190660
    Originator: YES

    I understand a little better now whats going on.
    Compilation is not being deferred but rather errors are
    being ignored.

    The main change seems to be in TclCompileScript() which
    no longer provides a return code.

    I looked at the two simple test cases in 8.5a5 and in both
    cases it is TclCompileScript() that is ignoring the compile
    errors.

    (Case 1):
    # set a [badcall c

    Line 1006:
    if (Tcl_ParseCommand(interp, p, bytesLeft, 0, &parse) !=
    TCL_OK)

    Just compiles a returnCmd which the invocation chain
    ignores. This is a syntax error which I think should be
    reported.

    (Case 2):
    # set a b c

    Line 1183:
    code = (cmdPtr->compileProc)(interp, &parse, envPtr);
    ...
    /* Restore numCommands and codeNext to their ... */

    Not sure what's the goal here. If you just wanted to
    redefine 'if' you can do that in 8.4 so long as 'proc if' is
    defined before this code is compiled.

    Oh, and Donal I think your code example is invalid.
    Did you mean:

    if bar var

    Also, static code checkers aren't really an option. On
    the second module I tried them on, frink core dumped and
    nagelfar generated an error for every 10th line of code.

     
  • Peter MacDonald

    Peter MacDonald - 2006-10-27

    Logged In: YES
    user_id=190660

    Right. But we could already do that as long as 'proc if' is define before compiling bar. eg. the following works
    in 8.3:

    proc bar var {
    if {$var == "acorn"} {
    set a b c
    }
    }
    catch {bar acorn}
    rename if if_
    proc if args {
    foreach a $args {puts $a}
    }

    bar var
    rename if {}
    rename if_ if

    I wonder if you didn't mean the following (which
    also works in 8.3)?

    proc bar var {
    if {$var == "acorn"} {
    set a b c
    }
    }
    catch {bar acorn}
    rename set set_
    proc set args {
    foreach a $args {puts $a}
    }

    bar acorn
    rename set {}
    rename set_ set

     
  • Don Porter

    Don Porter - 2006-10-28

    Logged In: YES
    user_id=80530

    > # set a [badcall c

    > Just compiles a returnCmd which the invocation chain
    > ignores.

    No, it compiles to bytecode that reports the
    syntax error at runtime.

     
  • Peter MacDonald

    Peter MacDonald - 2006-10-28

    Logged In: YES
    user_id=190660

    Hence: no errors till you execute it.

     
  • miguel sofer

    miguel sofer - 2008-01-12

    Logged In: YES
    user_id=148712
    Originator: NO

    This is per design. Tcl's has string interpretation semantics, the bytecompiler has to respect that. Tcl8.5 has fixed a number of bugs in that area.

    If we checked for syntax errors you couldn't run the following "perfectly valid" code. Tcl8.4 will return an error, which is a bug.

    proc foo bar {
    if {$bar == 0} {
    set a [badcall c
    } else {
    set a $bar
    }
    }
    foo 1 ;# returns 1
    proc if args {return $args}
    foo 0

    Not arguing that you would *want* to run code like that, only that a string interpretation language will run it.

     
  • miguel sofer

    miguel sofer - 2008-01-12
    • status: open --> closed-invalid