Print context for debugging

Is there a method that returns the the current location of execution in a nice readable format ?

So if I called blah.postln it would print the enclosing method and object?

I want to write some debugging tools that’s why and I don’t want to type the execution context by hand with each postln.

1 Like

“Nice, readable” – that’s debatable :laughing:

thisMethod returns a Method object for the method that is currently executing. But you’d have to be a bit careful with that:

+ Object {
	debugWithLocation { |str ... args|
		... do something with thisMethod...
	}
}

If you write your debugging method this way, then thisMethod will always be Object:debugWithLocation = useless.

You could pass in the method as an argument (though I expect that would become annoying).

The other way is to this.getBackTrace and inspect the stack (in the form of a unidirectional linked list by way of .caller). This would slow down execution quite a lot if you call it often, but there is a lot of information in it. To make it nice and readable, though – that’s up to you.

(A potential caveat with the backtrace is that tail call optimization is enabled by default. If you call the debugging method as the return value of your function or method, then the stack frame you wanted to debug would be removed. That probably won’t happen very often, but may be helpful to be aware of it.)

hjh

I tried this, hoping to see something I could use to approximate “inside function f”, but I get the output below, which I can’t see how to use to get a human readable location. Any ideas? And thanks for the help!

f = {|i| 
	var x; 
	x = this.getBackTrace; 
	x.caller.context.dump;  // would like this to say something like "function 'f'" 
	1+i;
}
f.value(2);

Instance of DebugFrame {    (0x7f7ce9c776e8, gc=A4, fmt=00, flg=00, set=03)
  instance variables [6]
    functionDef : instance of Method Interpreter:interpretPrintCmdLine (0x7f7ce11c4480)
    args : instance of Array (0x7f7ccc3a41a8, size=1, set=2)
    vars : instance of Array (0x7f7ce9c770b8, size=5, set=3)
    caller : instance of DebugFrame (0x7f7ce9c77638, size=6, set=3)
    context : instance of DebugFrame (0x7f7ce9c776e8, size=6, set=3)
    address : RawPointer 0x7f7ce11c4480
}


I think the problem here is .context – this is unlikely to be useful.

(
f = {
	var stack = this.getBackTrace;
	stack  // use var to avoid tail call optimization
};
)

a = f.value;

a.functionDef.dump;

a.functionDef.varNames;  // SymbolArray[ stack ]

a.functionDef.dumpByteCodes;

In this specific case, it turns out that this in this.getBackTrace causes the function to be considered an open function, so the source code is not available. If f is a closed function, then it’s OK.

(
// environment variables will not break a closed function
~backTrace = {
	this.getBackTrace;
};

f = {
	var stack = ~backTrace.value;
	stack
};
)

a = f.value;  // this is ~backTrace, not interesting
a = a.caller; // let's try its caller

a.functionDef.sourceCode

a.functionDef.varNames;  // SymbolArray[ stack ]

a.functionDef.dumpByteCodes;

// decode local vars
[a.functionDef.varNames.as(Array), a.vars].flop.flat

“Human readable” cannot always be guaranteed, however (depending on your definition of human-readable, which you haven’t defined). If you mean human-readable in terms of source code, then the source code is available only for closed functions, not for open functions or methods. The only workaround I can imagine for that is too complicated to be practical. You could try to decompile the bytecodes (FunctionDef code variable) and print something resembling the source code. I don’t think this would be worth the effort, though.

hjh