# trace

Definition: | with trace trace(integer i)
Description: | If i is 1 or 2, turn on full-screen interactive statement tracing/debugging. If i is 3, turn on tracing of statements to a file called ctrace.out. If i is 0, turn off tracing. When i is 1 a color display appears. When i is 2 a monochrome trace display appears. See Debugging for a full discussion of tracing / debugging.
pwa/p2js: | Ignored, in other words transpilation behaves much like compilation as far as this routine is concerned. You can of course use the browser development tools to trace/debug the generated JavaScript code.
Comments: | Tracing can only occur in a with trace section of your program. Use trace(2) if the color display is hard to view on your system. The trace() function is only available during interpretation; it is not and cannot be part of a compiled application, other than in p[w].exe. Any thoughts of "trace a compiled application" suggest that there is a behavioural discrepancy (between compilation and interpretation) which should be directly addressed as a bug in Phix. I know of no such cases, but it is only reasonable to expect one to crop up every now and again, hopefully occuring quite rarely and promptly fixed. Tracing does not apply to inline assembly (#ilASM{}), only hll code.
Example: |
    if x < 0 then
        -- ok, here's the case I want to debug...
        trace(1)
        -- etc.
        ...
    end if
Implementation: | The trace() routine itself is implemented via :%opTrace in builtins\VM\pTrace.e (an autoinclude/part of the compiler) - be warned however this is hard-won ad-hoc code (often written one tiny disjointed step at a time) and it ain’t particularly clear what is really going on, even to me. See also technicalia below.
See Also: | profile, debugging and profiling
Technicalia | The trace() function itself does very little: just sets flags for subsequent opLnt (see builtins\VM\pTrace.e). In fact the implemention actually invokes the trace routine even when 'with trace' is not active; apart from being an utterly insignificant cost, it allows code the programmer would not normally wish to trace, such as the low-level general-purpose code in builtins\VM, to trigger tracing in the calling application-specific code. Perhaps you have a message handler which is called several million times and rather than trace that, you want it to start tracing when it gets back to whatever code triggered it to be invoked in a specific and unusual way (perhaps quite indirectly). One minor difference between Phix and Euphoria is that in the latter trace() has no effect when executed within a without trace section of code, whereas in the former it just doesn’t take effect until that section of code is exited (if at all). The internal routines that implement trace() must take great care over the handling of the stack and when referencing the symbol table: in 'p test' there are two symbol tables, one for p.exe, which was probably built months ago, and one for test.exw, which has just been built and only exists in memory. Furthermore, the very top entry on the stack, for pTrace.e/show_trace(), is alien to the 'current' symbol table (see :%pSetSymPtr and :%pGetSymPtr), which is not only ultimately restored from symtab[T_EBP][3] when interpretation/trace of test.exw finishes, but must also be and is temporarily restored over things like pemit2.e/rebuild_callback(), ie anything that uses routine_ids or call_backs for routines that are actually within p.exe rather than being part of the end user application. In the parlour trick that is 'p p test', the underlying assumption is that trace and diagnostics ought to apply to the first-level p.exw rather than the final test.exw, but that is not officially supported (tracewise) and neither are 'p p p test', 'p p p p test', etc. Of course in the latter there are five symbol tables knocking about, and it gets very difficult to guarantee the debugger is always using the right one for the code being executed, so any effort in that regard is strictly limited to juggling at most two. What is supported is 'p p test' with trace() statements in p.exw and no such thing in test.exw, but only up to the point just before the interpreted copy of p tries to run the binary that it just created for test.exw, with 'p p -norun test' being the safer way to do such things. While it remains a pretty good idea to first test any modifications to the compiler sources with 'p p test', (see also builtins\VM\_readme.txt) that does not generally extend to any trace/profile functionality.