Smalltalk(Squeak と VisualWorks)の場合、メソッドオブジェクトに symbolic というメッセージを送ることで得られます。
(Integer compiledMethodAt: #factorial) symbolic
25 <70> self 26 <75> pushConstant: 0 27 <B6> send: = 28 <99> jumpFalse: 31 29 <76> pushConstant: 1 30 <7C> returnTop 31 <70> self 32 <75> pushConstant: 0 33 <B3> send: > 34 <9E> jumpFalse: 42 35 <70> self 36 <70> self 37 <76> pushConstant: 1 38 <B1> send: - 39 <D0> send: factorial 40 <B8> send: * 41 <7C> returnTop 42 <70> self 43 <22> pushConstant: 'Not valid for negative integers' 44 <E1> send: error: 45 <87> pop 46 <78> returnSelf
ちなみにメソッドオブジェクトに getSource を送るとソースコードが得られます。
(Integer compiledMethodAt: #factorial) getSource asString
factorial "Answer the factorial of the receiver." self = 0 ifTrue: [^ 1]. self > 0 ifTrue: [^ self * (self - 1) factorial]. self error: 'Not valid for negative integers'
getSource では、メソッド定義時のログ(.changes)があればそこからソースを引っ張って来ていますが、バイトコードのデコンパイルでソースを得ることも可能です。
Smalltalk では、メソッドもオブジェクトで、なおかつ Squeak では Python と違ってメソッドオブジェクトがイミュータブルでないことからソースをコンパイルして生成された時点でのメソッドと、現状のそれとが必ずしも一致しない場合もときとしてありえます。そんなときは、ログから引っ張ってきたソースと、デコンパイルしたソースを見比べる必要があります。
(Integer compiledMethodAt: #factorial) decompileString
factorial self = 0 ifTrue: [^ 1]. self > 0 ifTrue: [^ self * (self - 1) factorial]. self error: 'Not valid for negative integers'
メソッドオブジェクトに関して Squeak Smalltalk では #valueWithReceiver:arguments: のコールを介し、静的なコールも可能です。
| method | method := Integer compiledMethodAt: #factorial. method valueWithReceiver: 10 arguments: #(). "=> 3628800 " method valueWithReceiver: -1.0 arguments: #(). "=> Error: Not valid for negative integers"
後者のエラーは Integer>>#factorial によって出されている(上のソースの self error: '...' 部分)ところがポイントです。念のため、エラー時のコールスタックはこんな感じ。
Float(Object)>>error: Float(Integer)>>factorial CompiledMethod>>valueWithReceiver:arguments: UndefinedObject>>DoIt Compiler>>evaluate:in:to:notifying:ifFail:logged: [] in SmalltalkEditor(TextEditor)>>evaluateSelection BlockClosure>>on:do: SmalltalkEditor(TextEditor)>>evaluateSelection SmalltalkEditor(TextEditor)>>printIt ...
-1.0 factorial、つまり動的コールであればこうなります。
Float(Object)>>doesNotUnderstand: #factorial UndefinedObject>>DoIt Compiler>>evaluate:in:to:notifying:ifFail:logged: [] in SmalltalkEditor(TextEditor)>>evaluateSelection BlockClosure>>on:do: SmalltalkEditor(TextEditor)>>evaluateSelection SmalltalkEditor(TextEditor)>>printIt ...