Stackframe

Pythonは、inspectionが優れていて
関数,コード,スタックフレームのオブジェクトにまで
Pythonスクリプト上からアクセスできたりする。

 import inspect
 
 def show_var(varname):
   """
   呼出元のローカル変数を表示
   """
   try:
     frame = inspect.currentframe()
     print "%s : %s" % (varname, frame.f_back.f_locals[varname])
   finally:
     del frame

 if __name__ == "__main__":
   foo = "HiNa"
   show_var("foo") # foo : HiNa

エラーや例外時にでるメッセージは、このframeオブジェクトの情報を参照している。
これを使うと、Perlの caller みたいな関数も定義できる。

def caller(num=1):
  """
  引数は、幾つ前のスタックを辿るかを整数で指定。初期値は1。
  [ 呼出元の名前, 呼出元のファイル, 呼出元の行番号 ]
  """
  assert num > 0, "Stack depth number must be greater than zero."
  try:
    frame = inspect.currentframe()
    for _ in xrange(num-1):
      frame = frame.f_back
    code = frame.f_code
    return [ code.co_name, code.co_filename, frame.f_lineno ]
  finally:
    del frame

Python in parrotで心配になったのは、先にも書いたけど
この code や frame オブジェクトの互換性をどう解決するのか。
いずれも C で実装されていて、Pythonプログラムの実行に深く関わっている。

例えば、関数の引数のフォーマット情報を表示するinspectの関数などは、
関数オブジェクト内のコード・オブジェクトが持つバイトコードの情報を参照している。
当然ながら python bytecode -> parrot bytecodeになると、バイトコードが代わるので、
この部分の変更は避けられない。

また、parrot用に書き直されるとした場合でも、
branchになるので、CPythonとParrotPython版両方の保守が発生する。
開発者でもないのに余計な心配かなとは思うが、実装依存部分を取り除くには手間がかかりそうだ。