REBOL 3 Docs | Guide | Concepts | Functions | Datatypes | Errors |
TOC < Back Next > | Updated: 3-Aug-2010 Edit History |
Enables and disables evaluation tracing and backtrace.
Arguments:
mode [integer! logic!]
Refinements:
/back - Set mode ON to enable or integer for lines to display
/function - Traces functions only (less output)
See also:
Note this special requirement:
The trace lets you watch the evaluation of your script, expression by expression.
The three most common arguments to trace are shown here:
trace on ; turn on trace trace off ; turn off trace trace 5 ; turn on, but trace only 5 levels deep
Once enabled, when you evaluate an expression, you will see each step as a single line:
>> print 123 1: print : native! [value] 2: 123 --> print 123 <-- print == unset!
The trace format uses these formatting notations to indicate what your code is doing:
Notation | Meaning |
---|---|
(indent) | The indentation for each line indicates the depth of the code. |
N:
| The index number of the value in the code block (that is to be evaluated.) |
-->
| Entry into a function, followed by its formal argument list. |
<--
| Return from a function, followed by the value it returned (==). |
To help understand the format, here's a description for each line in the earlier example:
Code | Meaning |
---|---|
>> print 123
| Typed into the console to evaluate. |
1: print : native! [value]
| The value at block index 1 is the word print. It's value is looked up and found to be a native! function that takes value as an argument. |
2: 123
| The value at block index 2 is the integer 123. |
--> print
| The argument is valid and the print function is entered. The --> means "enter into the function." |
123
| Output is printed. |
<-- print == unset!
| The print function returns, but it has no return value (it is unset.) The <-- means "return from the function." |
Here is a user defined function to compute the average of a block of numbers.
ave: func [nums [block!] /local val][ val: 0 foreach num nums [val: val + num] val / length? nums ]
Tracing the evaluation, you will see how each new level is indented and begins a new sequence of index numbers. Notice also the foreach loop.
>> ave [1 2 3] 1: ave : function! [nums /local val] 2: [1 2 3] --> ave 1: val: 2: 0 3: foreach : native! ['word data body] 5: nums : [1 2 3] 6: [val: val + num] --> foreach 1: val: 2: val : 0 3: + : op! [value1 value2] 4: num : 1 --> + <-- + == 1 1: val: 2: val : 1 3: + : op! [value1 value2] 4: num : 2 --> + <-- + == 3 1: val: 2: val : 3 3: + : op! [value1 value2] 4: num : 3 --> + <-- + == 6 <-- foreach == 6 7: val : 6 8: / : op! [value1 value2] 9: length? : action! [series] 10: nums : [1 2 3] --> length? <-- length? == 3 --> / <-- / == 2 <-- ave == 2 == 2
At times the trace output will be a lot more than you want. The trick becomes how to cut it down without losing the information you need.. There are three methods:
Using the example above, set the trace depth to 2, and run it again. You will see:
>> trace 2 >> ave [1 2 3] 1: ave : function! [nums /local val] 2: [1 2 3] --> ave 1: val: 2: 0 3: foreach : native! ['word data body] 5: nums : [1 2 3] 6: [val: val + num] --> foreach <-- foreach == 6 7: val : 6 8: / : op! [value1 value2] 9: length? : action! [series] 10: nums : [1 2 3] --> length? <-- length? == 3 --> / <-- / == 2 <-- ave == 2 == 2
The output has been reduced. You no longer see the foreach loop operate.
Most of the time you don't need to trace your entire program, just part of it. So, it is useful just to put trace in your code where you need it.
Using the same example as above:
ave: func [nums [block!] /local val][ val: 0 trace on foreach num nums [val: val + num] trace off val / length? nums ]
You will now see:
>> ave [1 2 3] <-- trace == unset! 5: foreach : native! ['word data body] 7: nums : [1 2 3] 8: [val: val + num] --> foreach 1: val: 2: val : 0 3: + : op! [value1 value2] 4: num : 1 --> + <-- + == 1 1: val: 2: val : 1 3: + : op! [value1 value2] 4: num : 2 --> + <-- + == 3 1: val: 2: val : 3 3: + : op! [value1 value2] 4: num : 3 --> + <-- + == 6 <-- foreach == 6 9: trace : native! [mode /back] 10: off : false --> trace == 2
With the /function refinement you can trace just function calls and their returns. The evaluation of each code block value is not shown, saving a few lines.
>> trace/function on >> ave [1 2 3] --> ave [1 2 3] . . --> foreach num [1 2 3] [val: val + num] --> + 0 1 <-- + == 1 --> + 1 2 <-- + == 3 --> + 3 3 <-- + == 6 <-- foreach == 6 --> length? [1 2 3] <-- length? == 3 --> / 6 3 <-- / == 2 <-- ave == 2
In this mode, the function call lines will show the arguments passed to the functions. (A dot is used to show NONE value slots, such as those for unused refinements or local variables.)
At times it is important to know what your code was doing immediately before a crash. In such cases, you don't want to see trace output until after the crash. That is the purpose of the /back refinement: to tell trace to redirect its output to an internal buffer that you can examine later.
To enable backtrace:
>> trace/back on
Then, run your code. When your crash occurs, type:
>> trace/back 20
to see the last 20 lines (or however many lines you want to see.)
You can also modify your trace depth as you would normally. For example:
>> trace/back on >> trace 5
will only trace down five levels of code.
When you are done with the backtrace, you can disable it with:
>> trace/back off
and that will also free memory used by the backtrace buffer.
To use backtrace with the /function refinement:
>> trace/back/function on
This will also speed-up trace evaluation.
Here is an example session:
>> trace/back on >> test: func [a] [if integer? a [loop a [bug]]] >> test 10 ** Script error: bug has no value ** Where: loop if test ** Near: loop a [bug] >> trace/back 10 --> if 1: loop : native! [count block] 2: a : 10 3: [bug] --> loop 1: bug : unset! **: error : Script no-value 1: trace/back 2: 20 --> trace
So, it's not hard to see what was going on when the script crashed. Backtrace can be quite handy when you need it.
The stack function can also be used to show stack related backtrace information.
TOC < Back Next > | REBOL.com - WIP Wiki | Feedback Admin |