177 lines
6.3 KiB
Text
177 lines
6.3 KiB
Text
|
title:: Internal Snooping
|
||
|
summary:: Snooping around SuperCollider
|
||
|
categories:: Debugging
|
||
|
|
||
|
You can inspect much of the internal structure of the class library and other data structures.
|
||
|
This can often be useful for research and debugging purposes.
|
||
|
|
||
|
warning:: The keyboard shortcuts mentioned here only applies to the Mac SC.app. This document should probably be updated. ::
|
||
|
|
||
|
section:: Class Definitions, Implementations, and References
|
||
|
|
||
|
Selecting the name of any Class (e.g. Object) and typing cmd-j will open its class definition file.
|
||
|
|
||
|
note:: Any keypresses that open files identify the files using SuperCollider strings, which may contain only ASCII characters up to code point 127. If any part of the path to your SuperCollider installation contains character codes greater than 127 (such as the old Mac convention of identifying program folders with option-F), automatic file opening will fail. ::
|
||
|
|
||
|
Selecting the name of any method (e.g. play) and typing cmd-y will open a window showing all implementations of that method and their arguments. Selecting one of those classes and methods (e.g. Sample:play) and typing cmd-j will open the class definition at that method. (Note that cmd-y only shows implementations, and does not indicate inheritance).
|
||
|
|
||
|
Selecting any text (e.g. Window or asStream) and typing shift-cmd-y will open a window showing all references to the selected text, i.e. each place it is used within the class library. (This will not find methods calls compiled with special byte codes like 'value'.)
|
||
|
|
||
|
SC has a graphical Class browser which will show all methods, arguments, subclasses, instance variables and class variables. Using the browser's buttons you can easily navigate to the class' superclass, subclasses, class source, method source, helpfile (if there is one), check references or implementation of methods.
|
||
|
code::
|
||
|
SequenceableCollection.browse;
|
||
|
::
|
||
|
|
||
|
subsection:: Snooping in Classes
|
||
|
|
||
|
The link::Classes/Class:: help file documents some of these snooping methods.
|
||
|
Even though you may access these data structures, if you store things into them, you may break something.
|
||
|
code::
|
||
|
Collection.dumpInterface; // print all instance methods defined for this class
|
||
|
|
||
|
Collection.class.dumpInterface; // print all class methods defined for this class
|
||
|
|
||
|
|
||
|
// The following three include inherited methods
|
||
|
|
||
|
Collection.methods.collect(_.name); // print all instance methods that instances of this class respond to
|
||
|
|
||
|
Collection.class.methods.collect(_.name); // print all class methods that this class responds to
|
||
|
|
||
|
Collection.dumpFullInterface; // print all instance and class methods that this class responds to
|
||
|
|
||
|
Collection.dumpMethodList; // print instance methods of this class and superclasses, in alpha order
|
||
|
// also shows from which class the method is inherited
|
||
|
// does not include Object or Class methods
|
||
|
// for class methods, do Meta_Collection.dumpMethodList
|
||
|
|
||
|
Collection.dumpClassSubtree; // dump all subclasses of this class
|
||
|
|
||
|
Collection.dumpSubclassList; // dump all subclasses, in alphabetical order
|
||
|
|
||
|
Server.instVarNames.dump; // dump all instance variable names of this class
|
||
|
|
||
|
Server.classVarNames.dump; // dump all class variable names of this class
|
||
|
|
||
|
Server.filenameSymbol.postln; // the path to the file that defined this class
|
||
|
|
||
|
(
|
||
|
// print all classes whose names start with 'F'
|
||
|
Class.allClasses.do({ arg class;
|
||
|
if (class.name.asString.at(0) == $F, { class.name.postln; });
|
||
|
})
|
||
|
)
|
||
|
|
||
|
(
|
||
|
// find and print all class variable names defined in the system
|
||
|
Class.allClasses.do({ arg class;
|
||
|
if (class.classVarNames.notNil, {
|
||
|
// classVarNames is an Array of Symbols
|
||
|
class.classVarNames.do({ arg varname;
|
||
|
(class.name.asString ++ " " ++ varname.asString).postln;
|
||
|
})
|
||
|
});
|
||
|
});
|
||
|
)
|
||
|
|
||
|
(
|
||
|
// find and print all methods that contain "ascii"
|
||
|
Class.allClasses.do({ arg class;
|
||
|
class.methods.do({ arg sel;
|
||
|
if(sel.name.asString.find("ascii").notNil) {
|
||
|
(class.name.asString + "-" + sel.name).postln;
|
||
|
}
|
||
|
});
|
||
|
}); ""
|
||
|
)
|
||
|
::
|
||
|
|
||
|
subsection:: Snooping in Methods
|
||
|
|
||
|
Same thing goes here, if you store things into Methods, you may break something.
|
||
|
code::
|
||
|
Collection.findMethod('select'); // does it have this method?
|
||
|
|
||
|
Array.findMethod('select'); // this class doesn't
|
||
|
|
||
|
Array.findRespondingMethodFor('select'); // climb the class tree to find the method
|
||
|
|
||
|
Collection.findMethod('select').dump; // find a method object
|
||
|
|
||
|
Collection.findMethod('select').argNames.dump; // dump its argument names
|
||
|
|
||
|
Collection.findMethod('select').varNames.dump; // dump its local variable names
|
||
|
|
||
|
// dump its code. mostly for debugging the compiler.
|
||
|
Collection.findMethod('select').dumpByteCodes;
|
||
|
|
||
|
Collection.dumpByteCodes('select'); // a shorter version of the above
|
||
|
|
||
|
{ 1 + 2 }.dump; // this is a Function
|
||
|
|
||
|
{ 1 + 2 }.def.dump; // get its FunctionDef
|
||
|
|
||
|
{ 1 + 2 }.def.dumpByteCodes; // dump its code.
|
||
|
::
|
||
|
|
||
|
subsection:: Snooping in Windows
|
||
|
code::
|
||
|
(
|
||
|
// create some windows to snoop in
|
||
|
5.do({ arg i;
|
||
|
var w, b;
|
||
|
w = Window.new("snoop " ++ i.asString,
|
||
|
Rect.new( 200 + 400.rand, 69 + 300.rand, 172, 90 ));
|
||
|
w.front;
|
||
|
b = Button.new( w, Rect.new( 23, 28, 127, 25 ));
|
||
|
b.states = [["BLAM-O", Color.red]];
|
||
|
}))
|
||
|
|
||
|
Window.allWindows.dump; // dump a list of all open SCWindows
|
||
|
|
||
|
// a little more helpful, dump their names
|
||
|
Window.allWindows.collect({ arg w; w.name }).postln;
|
||
|
|
||
|
(
|
||
|
// change background colors of all open windows
|
||
|
Window.allWindows.do({ arg window;
|
||
|
window.view.background = Color.new(0.5 + 0.5.rand, 0.5 + 0.5.rand, 0.5 + 0.5.rand);
|
||
|
}))
|
||
|
|
||
|
Window.closeAll; // close all the windows (This will close the server windows)
|
||
|
::
|
||
|
|
||
|
subsection:: Snooping in SynthDefs
|
||
|
code::
|
||
|
// First execute this:
|
||
|
(
|
||
|
f = SynthDef("Help-SnoopSynthDef",
|
||
|
{ arg out=0;
|
||
|
Out.ar(out, PinkNoise.ar(0.1))
|
||
|
});
|
||
|
)
|
||
|
|
||
|
f.dumpUGens; // get the ugens, listed in order of execution, with rate, index and
|
||
|
// inputs
|
||
|
::
|
||
|
|
||
|
subsection:: Snooping in the Interpreter
|
||
|
|
||
|
When evaluating text in the interpreter, the variable 'this' always refers to the interpreter.
|
||
|
code::
|
||
|
this.dump; // display the values of all the interpreter variables a-z
|
||
|
|
||
|
this.clearAll; // set all variables a-z to nil
|
||
|
|
||
|
g = this.compile("(1 + 2).postln"); // compile some text into a Function
|
||
|
|
||
|
g.postln; // see, g is a Function
|
||
|
|
||
|
g.value; // evaluate g
|
||
|
|
||
|
this.interpret("(1 + 2).postln"); // interpret some text
|
||
|
|
||
|
this.interpretPrint("1 + 2"); // interpret some text and print the result
|
||
|
::
|
||
|
|