Syntax Checking

Reason for syntax checking in Tcl/XOTcl

Tcl has no types and and this is good. One disadvantage is that ugly syntax errors (typically typos) crash your program the first time you run it. Therefore you must care about running every piece of your code through interpreter by writing special test procedures. Syntax checking with XOTclIDE can find most of these errors (syntax errors) at editing time by simulating the interpreter. The syntax checker can parse and interpret code without running it.

Syntax checker implementation

XOTclIDE implements a static syntax checker. It parses Tcl/XOTcl procedures and finds errors that normally appear only at run time. Because XOTclIDE does not manage source code but manages a Tcl/XOTcl interpreter it always checks a method in the actual interpreter context. You cannot check your Tcl files without loading (source $your_file) the procedures into the interpreter. The following syntax checks are processed.

  • check all called procedures

  • check the count of arguments

  • simulate quote and command substitution

  • simulate evaluation of control structure commands (if, for, foreach, ...)

  • check variable visibility

  • check XOTcl self method calls. (my callMe; [self] callMe)

Syntax Checking can be used in two ways

  • Syntax check while editing or accepting code.

  • Run the syntax checker on projects, so you can check existing Tcl/XOTcl sources.

Example Tcl procedures

procs example {a} {
     set b [lindex $a 0]
     puts "$a $c"
     set e [lindex $a end dummy]
     foreach d $a {
         if {$d==a} {
              putd $d
         }
     }		
}

The syntax checker will find the following errors:

procs example {a} {
      set b [lindex $a 0]
      puts "$a $c"
      # unknown variable c
      set e [lindex $a end dummy]
      # await (2,2) arguments
      foreach d $a {
          if {$d==a} {
                putd $d
                # unknown proc
          }
      }		
}

Example XOTcl methods

Class Test -parameter {par1}
Test instproc foo1 {a {b 1}} {
     puts "[self] $a $b"
}
# Method to check
Test instproc foo2 {b} {
     my foo1 test
     my foo1 test 1 2
     # await (1,2) arguments
     foreach elem $b {
          puts "[my par1] $elem"
          my par1 $elem
          my foo3
          # unknown instproc
     }
     set c $d
     # unknown variable d			
}

Syntax Checking while editing

To enable syntax checking while editing, click on the check-box in menu Edit->Syntaxcheck on Save. All accepted (saved) code will be syntax-checked. If errors are found a new window with syntax messages are displayed. You can see the corresponding code in the editor by clicking on the list items. (see Figure 4.4, “Syntax Checker Dialog”)

If the errors shown by the syntax checker are not really errors or you have already corrected the errors you can press the button Force Saving. The code shown in the editor will be accepted without syntax checking.

If you want to force syntax checking without accepting choose menu Edit->Syntax Highlight->Force Syntax Check.

Figure 4.4. Syntax Checker Dialog

Syntax Checker Dialog

Syntax Checker Browser

You can launch this tool from the menu System->Syntax Checker. Choose the components you will check and run the check with button Check Selected. You can browse the errors by clicking the other two lists.

Figure 4.5. Syntax Checker Tool

Syntax Checker Tool

You can produce a protocol of checking as text file with menu Syntax Check->Protocol to file.

Tcl/XOTcl Parser

The XOTclIDE syntax checker works by using its Tcl parser programmed in XOTcl (see component IDETclParser). It produces a parser tree that can also be used for other purposes. At this time the syntax highlighting is also based on this parser.

Other ways of using Tcl parser in Tcl.

  • Normalize source code (pretty print)

  • convert source codes from or to another object oriented Tcl. (ITcl)

  • Refactoring tools in the manner of Smalltalk.

How to extend syntax interpretation

See the PrsContext>checkTclCommand method. The syntax of all Tcl control command are coded as simple pieces of code.

# while proc
[$command getElem 1] substituteContents
[$command getElem 2] evalContents
# set proc
if {$count==2} {
    my addVariableFrom [$command getElem 1]
} else {
    my checkVariableFrom [$command getElem 1] $notifier
}

It should not be difficult to extend the semantics for more commands.

Problems

The syntax checker cannot simulate the full power of a Tcl interpreter. For example, it interprets double substitution as:

set a putd
$a hallo
set a c
set $a 2
puts $c

"$a hallo" will be not reported as an error but "puts $c" will report the error "unknown variable c".

Magic strings for checker

If you want to avoid syntax checking for one method place the string "no syntax check" in the method (probably as a comment).

If you want to force the checker to accept a variable use "add variables (varName varName2)"

# add variables (c)
set a c
set $a 3
puts $c

Checking Referenced Object Calls

It is also not possible to check referenced object calls:

set a [MyClass new]
$a doJob
# also direct call by object name
MyClass myObject
myObject doJob

The first method call will be not checked. The checker has no information about what is $a. The second method call will be reported with the error "no such proc" (myObject). This second type of call should be very rare in XOTcl programs (besides global singleton objects).

To solve the problem the checker would need more type information. Type information could be coded as meta information in the class. For example:

Class A
A addMetaVariable drawContext DrawContext
A instproc draw {} {
my instvar drawContext
$drawContext drawLine 0 2 0 50
}

In this case the Syntax Checker would know that "drawContext" references an object of class "DrawContext". The same thing could be done for method arguments or even all variables by using special in-line directives

set a [MyClass new]
# variableType a MyClass
$a doJob

This could be a back door to make Tcl type-safe if you want. In fact, the meta type information could be collected by doing analysis of a running system (for example by using XOTcl filters). This type informations could also be used to build XOTcl assertions.

There is a chance of making a very powerful Tcl development system even with type safe syntax checking.