苦労じゃー(3)

ブドウの葉もすっかり紅葉してきた。里の神社の境内にも落ち葉が目立つようになり、秋たけなわ と言った所だろうか。

リベンジを兼ねて、紅葉見物に行ってきた。行ってきたと言う程の事は無くて、車でひょいと 山の方へ向かうと、もうそこはRGBな世界ですよ。

Rはレッドと言う事で赤ね。Gはグリーン、そしてBはブルーで天高く秋の空。黄色は、合成色だな。 まあ、色気の無い事。

山を登って行くと、熊さん注意なんて標識が出て来る。こういう標識って道路交通法に定義された 由緒正しい標識なんだろうか?

この時期の熊さんは冬篭りの為、競って食べ物を漁っている。どんぐりが主食なのだろうか? 中には、どんぐりを食べる野性味たっぷりな人も居るようだけど、せいぜい、あけびぐらいで 止めておいた方が身のためだ。熊さんと戦っても勝てないからね。ちょっと前に、熊さんが 町の真ん中へさ迷い出てきて、殺されちゃいましたね。可愛そうにね、合掌。

で、あけびの話だけど、これちょっと卑猥な形をしてる。知らない人は想像してください。 ぱっくり割れた中に、舌を突っ込んで、実と言うか柔らかい部分をすくって食べる。黒い小さな 実が口の中に残るので、それを上手にペッペッと吐き出す。

子供の頃は、よくこの小さな実を口から吐き出して、忍法口から爆弾なんて言って遊んだっけ。 また、あけびの蔓は丈夫で、うまい事に樹に巻きついているんで、これを取ってきて、ターザン ごっことかもやったなあ。嗚呼、古き佳き時代だったわい。

佳き時代と言うと、神社の境内にある銀杏も冬の貴重なおやつだった。ウンチ臭い実を いっぱい集めてきて、土の中に埋めておくと、回りの柔らかい部分が腐って、中の堅い実だけが 取り出せる。それを干しておいて冬のおやつにするんだ。

火鉢で炙ってから食べる。気の利いた居酒屋へ行くとメニューに載ってたりするけど、昔は こんなの当たり前にそこらに有ったよ。こちらに来て、銀杏の樹があるか、それとなく探して いるんだけど、見つからんね。あの独特なにおいが敬遠されて、伐採してしまったと言うなら 何ともったい無い事かと、熊さん共々、怒っちゃうぞ。あれ? 熊さんは、銀杏食べるんかな? どんぐりって、確か木の実の総称だったはずだけどな。

disassembleは何処だ

田舎に引っ込んで、都内方面での催しものはワッチしなくなっちゃんだけど、この間の佳き日に Shibuya.lispが有ったのね。録画を見ましたよ。みんな 凄くバージョンアップしてるなあ。感心しますよ。

で、おいらは田舎で細々となんだけど、clojureと委員会Lispがどれぐらい似てるか調べてて、 あっちにあってclojureに無い(と思われる)のに出くわした。そう、disassembleが幾ら探しても 見つからんのよ。

Clojure 1.3 のパフォーマンスに驚いた話を 書いた某さんも、お探しのようでした。そうなんだよ。無いんだよ。この某さんは目的を達成する 為に探しておられたようだが、別のアプローチで解決された様子。折角なので、渋谷で演説して くればよかったんじゃないでしょうか。

で、思うに、clojureが吐き出したクラスファイルを裸に出来れば、おいらの目的は達成だよな。

クラス分解

クラスファイルがどうなっているか? きっと好きな人がやってるだろう。伊達にJavaが歴史を 積み重ねているわけじゃないから。

クラスファイル解析なんてのに、 行き当たった。いろいろ有って収拾が付かんなあ。もっと基礎的な所からやらんとだめか。

Java 仮想マシンで概要を掴んでから、 The JavaTM Virtual Machine Specification 仕様書を見ればいいんか。スタックマシンと言うことは、Forthを思い出せばいいんだな。 インテルの増築につぐ増築により迷路な石より、よっぽど見通しのよい石よ。 Koguroさんあたりが、JVMをFPGAに焼いてくれないかな。

筑波はACな所で、それっぽい授業もやってるな。 JAVA仮想機械 こちらはCamelがターゲットぽいけど、まあ、低いレーヤーをやれば、応用は利くわな。

javap

javapって言われると、Lisperは、きっと nil って反応すると思うんだ。clojure/scheme界隈だと java?だよね。きっと、falseとか #f なんて答えが返るに違いない。

まあ、java屋さんには必須なコマンドぽいな。 javapなんて解説が有りますな。 コマンドを叩くのが嫌な、Windowsマンには、 djなんてのがあるぞ。

そして、javapを題材にして、ディスアセンブラを作る なんてのも有る。

折角なので javapしてみる。題材は、

(ns o121.core
  (:gen-class))

(defn fact [n]
  (if (zero? n)
    1
    (* n (fact (- n 1)))))

(defn -main [& args]
  (println (fact 10)))

出来上がったクラスは、

[sakae@cdr ~/CLJ/o121/classes/o121]$ ls
core$_main.class                        core$loading__4414__auto__.class
core$fact.class                         core.class
core$loading__4410__auto__.class        core__init.class

クラス名とメソッド名が、$で分離されてるって言う、初心者お断りの匂いがしてますなあ。

[sakae@cdr ~/CLJ/o121/classes/o121]$ javap -c 'core$fact'
Compiled from "core.clj"
public final class o121.core$fact extends clojure.lang.AFunction{
public static final clojure.lang.Var const__0;

public static final java.lang.Object const__1;

public static final clojure.lang.Var const__2;

public static final clojure.lang.Var const__3;

final clojure.lang.IPersistentMap __meta;

public static {};
  Code:
   0:   ldc     #15; //String clojure.core
   2:   ldc     #17; //String zero?
   4:   invokestatic    #23; //Method clojure/lang/RT.var:(Ljava/lang/String;Ljava/lang/String;)Lclojure/lang/Var;
   7:   checkcast       #25; //class clojure/lang/Var
   10:  putstatic       #27; //Field const__0:Lclojure/lang/Var;
   13:  iconst_1
   14:  invokestatic    #33; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   17:  putstatic       #35; //Field const__1:Ljava/lang/Object;
   20:  ldc     #15; //String clojure.core
   22:  ldc     #37; //String *
   24:  invokestatic    #23; //Method clojure/lang/RT.var:(Ljava/lang/String;Ljava/lang/String;)Lclojure/lang/Var;
   27:  checkcast       #25; //class clojure/lang/Var
   30:  putstatic       #39; //Field const__2:Lclojure/lang/Var;
   33:  ldc     #15; //String clojure.core
   35:  ldc     #41; //String -
   37:  invokestatic    #23; //Method clojure/lang/RT.var:(Ljava/lang/String;Ljava/lang/String;)Lclojure/lang/Var;
   40:  checkcast       #25; //class clojure/lang/Var
   43:  putstatic       #43; //Field const__3:Lclojure/lang/Var;
   46:  return

public o121.core$fact(clojure.lang.IPersistentMap);
  Code:
   0:   aload_0
   1:   invokespecial   #49; //Method clojure/lang/AFunction."<init>":()V
   4:   aload_0
   5:   aload_1
   6:   putfield        #51; //Field __meta:Lclojure/lang/IPersistentMap;
   9:   return

public o121.core$fact();
  Code:
   0:   aload_0
   1:   aconst_null
   2:   invokespecial   #53; //Method "<init>":(Lclojure/lang/IPersistentMap;)V
   5:   return

public clojure.lang.IPersistentMap meta();
  Code:
   0:   aload_0
   1:   getfield        #51; //Field __meta:Lclojure/lang/IPersistentMap;
   4:   areturn

public clojure.lang.IObj withMeta(clojure.lang.IPersistentMap);
  Code:
   0:   new     #2; //class o121/core$fact
   3:   dup
   4:   aload_1
   5:   invokespecial   #53; //Method "<init>":(Lclojure/lang/IPersistentMap;)V
   8:   areturn

public java.lang.Object invoke(java.lang.Object)   throws java.lang.Exception;
  Code:
   0:   aload_1
   1:   invokestatic    #67; //Method clojure/lang/Numbers.isZero:(Ljava/lang/Object;)Z
   4:   ifeq    14
   7:   getstatic       #35; //Field const__1:Ljava/lang/Object;
   10:  goto    36
   13:  pop
   14:  aload_1
   15:  aload_0
   16:  checkcast       #69; //class clojure/lang/IFn
   19:  aload_1
   20:  aconst_null
   21:  astore_1
   22:  getstatic       #35; //Field const__1:Ljava/lang/Object;
   25:  invokestatic    #73; //Method clojure/lang/Numbers.minus:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Number;
   28:  invokeinterface #75,  2; //InterfaceMethod clojure/lang/IFn.invoke:(Ljava/lang/Object;)Ljava/lang/Object;
   33:  invokestatic    #78; //Method clojure/lang/Numbers.multiply:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Number;
   36:  areturn

いきなりのアセンブラはちとキツイか。ならば、もう少し抽象度の高いやつで。

decompiler

もう少しおだやかなやつを探してみた。そしたら、 Java Decompilerなんてのが出てきた。一世を風靡したjad とか言うのは、時代の進歩と共に使われなくなっちゃったのね。こやつ、WindowsとかLinuxとか MacOS用は出てるけど、BSD用は無し。すっかり、*BSDも世間から無視されるようになりましたね。 おいら、ちと寂しいよ。

/*   */ package o121;
/*   */ 
/*   */ import clojure.lang.AFunction;
/*   */ import clojure.lang.IObj;
/*   */ import clojure.lang.IPersistentMap;
/*   */ import clojure.lang.Numbers;
/*   */ import clojure.lang.RT;
/*   */ import clojure.lang.Var;
/*   */ 
/*   */ public final class core$fact extends AFunction
/*   */ {
/* 4 */   public static final Var const__0 = (Var)RT.var("clojure.core", "zero?");
          public static final Object const__1 = Integer.valueOf(1);
          public static final Var const__2 = (Var)RT.var("clojure.core", "*");
          public static final Var const__3 = (Var)RT.var("clojure.core", "-");
/*   */   final IPersistentMap __meta;
/*   */ 
/*   */   public core$fact(IPersistentMap paramIPersistentMap)
/*   */   {
/* 4 */     this.__meta = paramIPersistentMap; } 
/*   */   public core$fact() { this(null); } 
/*   */   public IPersistentMap meta() { return this.__meta; } 
/*   */   public IObj withMeta(IPersistentMap paramIPersistentMap) { 
                       return new fact(paramIPersistentMap);
                 } 
/* 5 */   public Object invoke(Object n) throws Exception {
                       if (Numbers.isZero(n)) tmpTernaryOp = const__1;
/*   */   }
/*   */ }

/* Location:           C:\homes\CLJ\o121\classes\
 * Qualified Name:     o121.core.fact
 * JD-Core Version:    0.6.0
 */

これも解ったような解らないような。。やっぱり、Javaは分からんと言う結論かな?

Lispの父、天国へ

Lispの生みの親、John McCarthy が、天国へ召された。 今月はいやに、コンピュータの関係者が居なくなるなあ。

天国でゆっくりなさって下さい。合掌!