2 classvar <>handling = false;
3 classvar <>debug = false;
4 classvar <>inProtectedFunction = false;
6 var <>what, <>protectedBacktrace, <>path;
9 var protectedBacktrace, instance;
10 if (debug || inProtectedFunction, {
11 protectedBacktrace = this.getBackTrace.caller;
12 inProtectedFunction = false;
14 ^super.newCopyArgs(what ? this.name, protectedBacktrace, thisProcess.nowExecutingPath);
17 ^"EXCEPTION: " ++ what
20 this.errorString.postln;
21 if(protectedBacktrace.notNil, { this.postProtectedBacktrace });
23 this.adviceLink.postln;
26 ^("For advice: [http://supercollider.sf.net/wiki/index.php/%]"
27 .format(this.adviceLinkPage));
30 ^this.errorString.tr($ , $_).tr($\n, $_);
32 postProtectedBacktrace {
33 var out, currentFrame, def, ownerClass, methodName, pos;
35 "\nPROTECTED CALL STACK:".postln;
36 currentFrame = protectedBacktrace;
37 while({currentFrame.notNil}, {
38 def = currentFrame.functionDef;
39 if(def.isKindOf(Method), {
40 ownerClass = def.ownerClass;
41 methodName = def.name;
42 if(ownerClass == Function && { #['protect', 'try'].includes(methodName) }, {
45 out << "\t%:%\t%\n".format(ownerClass, methodName, currentFrame.address);
47 out << "\ta FunctionDef\t%\n".format(currentFrame.address);
48 out << "\t\tsourceCode = %\n".format(def.sourceCode ? "<an open Function>");
50 def.argNames.do({|name, i|
51 out << "\t\targ % = %\n".format(name, currentFrame.args[i]);
53 def.varNames.do({|name, i|
54 out << "\t\tvar % = %\n".format(name, currentFrame.vars[i]);
56 currentFrame = currentFrame.caller;
58 // lose everything after the last Function:protect
59 // it just duplicates the normal stack with less info
60 // but, an Error in a routine in a Scheduler
61 // may not have a try/protect in the protectedBacktrace
62 // then, pos is nil and we should print everything
65 out.collection.copyFromStart(pos)
80 ^if(path.isNil) { "" } { "PATH:" + path ++ "\n" }
87 *new { arg what, receiver;
88 ^super.new(what).receiver_(receiver)
91 this.errorString.postln;
94 this.errorPathString.post;
95 if(protectedBacktrace.notNil, { this.postProtectedBacktrace });
97 this.adviceLink.postln;
105 PrimitiveFailedError : MethodError {
106 var <>failedPrimitiveName;
109 ^super.new(Thread.primitiveErrorString, receiver)
110 .failedPrimitiveName_(thisThread.failedPrimitiveName)
113 ^"ERROR: Primitive '%' failed.\n%".format(failedPrimitiveName, what ? "")
117 SubclassResponsibilityError : MethodError {
118 var <>method, <>class;
119 *new { arg receiver, method, class;
120 ^super.new(nil, receiver).method_(method).class_(class)
123 ^"ERROR: '" ++ method.name ++ "' should have been implemented by "
128 ShouldNotImplementError : MethodError {
129 var <>method, <>class;
130 *new { arg receiver, method, class;
131 ^super.new(nil, receiver).method_(method).class_(class)
134 ^"ERROR: '" ++ method.ownerClass.name ++ "-" ++ method.name
135 ++ "' Message not valid for this subclass: "
140 DoesNotUnderstandError : MethodError {
141 var <>selector, <>args;
142 *new { arg receiver, selector, args;
143 ^super.new(nil, receiver).selector_(selector).args_(args)
146 ^"ERROR: Message '" ++ selector ++ "' not understood."
149 this.errorString.postln;
154 this.errorPathString.post;
155 if(protectedBacktrace.notNil, { this.postProtectedBacktrace });
157 this.adviceLink.postln;
160 ^"%#%".format(this.class.name, selector)
165 MustBeBooleanError : MethodError {
167 ^"ERROR: Non Boolean in test."
171 NotYetImplementedError : MethodError {
174 OutOfContextReturnError : MethodError {
175 var <>method, <>result;
176 *new { arg receiver, method, result;
177 ^super.new(nil, receiver).method_(method).result_(result)
180 ^"ERROR: '" ++ method.ownerClass.name ++ "-" ++ method.name
181 ++ "' Out of context return of value: " ++ result
185 ImmutableError : MethodError {
187 *new { arg receiver, value;
188 ^super.new(nil, receiver).value_(value)
191 ^"ERROR: Object is immutable: " ++ receiver
195 BinaryOpFailureError : DoesNotUnderstandError {
197 ^"ERROR: binary operator '" ++ selector ++ "' failed."
201 DeprecatedError : MethodError {
202 var <>method, <>class, <>alternateMethod;
204 *new { arg receiver, method, alternateMethod, class;
205 ^super.new(nil).receiver_(receiver).method_(method).class_(class).alternateMethod_(alternateMethod)
208 var methodSignature = { arg m;
209 var c = m.ownerClass;
210 var str = c.name.asString;
212 { str = str.drop( str.indexOf($_) + 1 ) ++ ":*" ++ m.name }
213 { str = str ++ ":-" ++ m.name };
216 var searchForCaller = { arg backtrace, m;
218 backtrace.notNil and: {
219 backtrace.functionDef !== m
222 backtrace = backtrace.caller;
224 // backtrace.caller may now be a FunctionDef,
225 // useless for troubleshooting
226 // so roll back to the last real method
228 backtrace.notNil and: {
229 backtrace = backtrace.caller;
230 backtrace.functionDef.isKindOf(Method).not
233 if(backtrace.notNil) { backtrace.tryPerform(\functionDef) };
236 if(protectedBacktrace.notNil) {
237 caller = searchForCaller.value(protectedBacktrace, method);
240 caller = searchForCaller.value(this.getBackTrace, method);
245 if(caller.isKindOf(Method)) {
246 caller = methodSignature.value(caller);
248 caller = caller.asString;
251 string = "WARNING: Called from %, method % is deprecated and will be removed.".format(
253 methodSignature.value(method)
255 if(alternateMethod.notNil, {
256 string = string + "Use" + methodSignature.value(alternateMethod) + "instead.";
262 this.errorString.postln;
263 this.errorPathString.post;
264 this.adviceLink.postln;
268 Error.handling = true;
271 if(protectedBacktrace.notNil, { this.postProtectedBacktrace });
273 Error.handling = false;
276 Error.handling = false;