Wiki
Version 4 (modified by todd.a, 14 years ago)

--

The trace statement is a debugging aid to log points of execution in the source code and/or values of expressions.

Grammar

trace
trace <expr1>, <expr2>, ... <expr3>
trace all
trace off
trace on

A simple trace gives the filename, line number, declaring class name and declaring method name that the trace is located in. If the current object's class is a subclass of the declaring class then the subclass name is reported as well.

When given one or more expressions, trace gives the same information plus the source code and value of each expression.

The trace all statement is a convenience for logging this, every method argument and every local variable.

The trace off statement turns off the subsequent trace statements in the declaring method. The trace on statement turns them back on.

Sprinkling trace statements in methods can help diagnose bugs by showing program flow and values during execution, as seen here:

class Foo 

    var _z as int 

    def computeStuff(x as int, y as int)
        if x > y
            trace return 
        _z = x * y 
        trace all 
        trace _z 
trace: this=Foo; x=2; y=4; at Foo.cobra:10; in Foo.computeStuff
trace: this=Foo; _z=8; at Foo.cobra:11; in Foo.computeStuff

An alternative to a trace would be a print statement:

...
print 'trace: x=[x]; y=[y]' 

But that won't report source information such as line number, and writing such a print statement is more work than:

trace x,y

Also, trace statements are easy to locate and remove—or turn off via trace off—while leaving application print statements in tact. And trace output is flushed with each trace, by default.

Note that the trace statement is backed by a supporting class called Tracer:

class Tracer 
    inherits Object
    """ 
    Used to implement the trace statement. 
    """ 

    cue init 
        """ 
        Initializes the tracer with Console.out as the destination. 
        """ 

    cue init(dest as System.IO.TextWriter) 

    pro isActive as bool 
        """ 
        When false, the `trace` methods will produce no output. 
        """ 

    pro willAutoFlush as bool 
        """ 
        When true, `destination.flush` is invoked after every trace. 
        Defaults to `true`. 
        """ 

    pro destination as String 
        """ 
        The TextWriter where all trace output is sent to. 
        """ 

    pro separator as String 
        """ 
        The separator string used between items of both name/value pairs and source information. 
        Default is '; '. 
        """ 

    pro prefix as String 
        """ 
        The prefix string used at the beginning of every trace. 
        Default is 'trace: '. 
        """ 

    def trace(source as SourceInfo) 

    def trace(source as SourceInfo, nameValues as vari Object)
        require nameValues.length % 2 == 0 

You can get access to the current tracer with the shared property, CobraCore.tracer. In fact, you can use that same property to set the Tracer instance that the trace statements use, although modifying the default instance is normally sufficient. For example:

    class Program 
        def main is shared
        tracer = CobraCore.tracer 
        tracer.prefix = '' 
        tracer.separator = ', ' 
        tracer.destination = File.createText('trace.text') 

Don't confuse trace on/off with Tracer.isActive. The trace on/off statements are purely compile-time directives that affect only the method that contains them. The Trace.isActive property is purely a run-time property and will deactive the output of all trace statements when set to false.