`(Hello ,world)

ツッコミ、添削大歓迎です。いろいろ教えてください。

2010-05-01

.NET FrameworkのClispサンプル

WindowsC#を少し使い出して、なかなか便利だなぁと思い始めていたところ。.NETって動作結構速くてどうなってるのかなぁと調べてると、MSIL(Microsoft Intermediate Language)というらしい。

.NET SDKには、マネージド・コードを出力するLispコンパイラが、しかもソースコード付きで収録されている。

うおおぉぉ!てなわけで.NET Framework SDKを入れてみる。

  • CLISPサンプルは1.1じゃないとついてない
  • C:\Program Files\Microsoft.NET\SDK\v1.1\Tool Developers Guide\Samples\clisp
  • ilasm.exe とかがみつからない
  • フィボナッチサンプル:
(defun Fib (N)
  (if (<= N 0)
      0
    (if (= N 1)
        1
      (+ (Fib (- N 1))
         (Fib (- N 2))))))

(defun Fibo (N)
  (do ((count 0
              (+ count 1))
       (Fibo (car (Fib 0))
             (cons Fibo (car (Fib count)))))
      ((> count N)
       Fibo)))

(Fibo 25)
  • わけわからん
    • (car (Fib 0)) とかしてる
    • (Fib 0) と (car (Fib 0)) のどちらも 0
  • フィボナッチサンプルのコンパイルされたコードを逆アセンブルした結果:
//  Microsoft (R) .NET Framework IL Disassembler.  Version 3.5.30729.1
//  Copyright (c) Microsoft Corporation. All rights reserved.



// Metadata version: v1.1.4322
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 1:0:5000:0
}
.assembly extern Clisp
{
  .ver 0:0:0:0
}
.assembly fibo.exe
{
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module fibo.exe
// MVID: {B046BA20-D9BF-4DA6-90EF-EE12244D77E6}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x03210000


// =============== CLASS MEMBERS DECLARATION ===================

.class private auto ansi fibo
       extends [mscorlib]System.Object
{
  .method public static void  Main() cil managed
  {
    .entrypoint
    // コード サイズ       43 (0x2b)
    .maxstack  1
    IL_0000:  ldstr      "Fib"
    IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000a:  ldstr      "Fibo"
    IL_000f:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0014:  ldc.i4.s   25
    IL_0016:  call       class [Clisp]CList fibo::Fibo(int32)
    IL_001b:  call       void [Clisp]LispRuntime::Print(class [Clisp]CList)
    IL_0020:  ldstr      ""
    IL_0025:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_002a:  ret
  } // end of method fibo::Main

  .method public static int32  Fib(int32 A_0) cil managed
  {
    // コード サイズ       68 (0x44)
    .maxstack  9
    IL_0000:  ldarg.0
    IL_0001:  ldc.i4.0
    IL_0002:  ble        IL_000d

    IL_0007:  ldc.i4.0
    IL_0008:  br         IL_000e

    IL_000d:  ldc.i4.1
    IL_000e:  brfalse    IL_0019

    IL_0013:  ldc.i4.0
    IL_0014:  br         IL_0043

    IL_0019:  ldarg.0
    IL_001a:  ldc.i4.1
    IL_001b:  beq        IL_0026

    IL_0020:  ldc.i4.0
    IL_0021:  br         IL_0027

    IL_0026:  ldc.i4.1
    IL_0027:  brfalse    IL_0032

    IL_002c:  ldc.i4.1
    IL_002d:  br         IL_0043

    IL_0032:  ldarg.0
    IL_0033:  ldc.i4.1
    IL_0034:  sub
    IL_0035:  call       int32 fibo::Fib(int32)
    IL_003a:  ldarg.0
    IL_003b:  ldc.i4.2
    IL_003c:  sub
    IL_003d:  call       int32 fibo::Fib(int32)
    IL_0042:  add
    IL_0043:  ret
  } // end of method fibo::Fib

  .method public static class [Clisp]CList 
          Fibo(int32 A_0) cil managed
  {
    // コード サイズ       82 (0x52)
    .maxstack  4
    .locals init (int32 V_0,
             class [Clisp]CList V_1)
    IL_0000:  ldc.i4.0
    IL_0001:  stloc.0
    IL_0002:  ldc.i4.0
    IL_0003:  call       int32 fibo::Fib(int32)
    IL_0008:  call       class [Clisp]CList [Clisp]LispRuntime::ToList(int32)
    IL_000d:  call       class [Clisp]CList [Clisp]LispRuntime::Car(class [Clisp]CList)
    IL_0012:  stloc.1
    IL_0013:  br         IL_0033

    IL_0018:  ldloc.0
    IL_0019:  ldc.i4.1
    IL_001a:  add
    IL_001b:  stloc.0
    IL_001c:  ldloc.1
    IL_001d:  ldloc.0
    IL_001e:  call       int32 fibo::Fib(int32)
    IL_0023:  call       class [Clisp]CList [Clisp]LispRuntime::ToList(int32)
    IL_0028:  call       class [Clisp]CList [Clisp]LispRuntime::Car(class [Clisp]CList)
    IL_002d:  call       class [Clisp]CList [Clisp]LispRuntime::Cons(class [Clisp]CList,
                                                                     class [Clisp]CList)
    IL_0032:  stloc.1
    IL_0033:  ldloc.0
    IL_0034:  ldarg.0
    IL_0035:  bgt        IL_0040

    IL_003a:  ldc.i4.0
    IL_003b:  br         IL_0041

    IL_0040:  ldc.i4.1
    IL_0041:  brfalse    IL_004c

    IL_0046:  ldloc.1
    IL_0047:  br         IL_0051

    IL_004c:  br         IL_0018

    IL_0051:  ret
  } // end of method fibo::Fibo

  .method public specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // コード サイズ       7 (0x7)
    .maxstack  2
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method fibo::.ctor

} // end of class fibo


// =============================================================

// *********** 逆アセンブルが完了しました ***********************
  • C#のソースを見る
    • ILGeneratorというのでコード生成をしている
    • Emit 実行時にコード生成してさらに実行できる!

これを使って Compilers: Backend to Frontend and Back to Front Againとか、セルフホスティングとか作ったら面白いんじゃないかと思うのでいまさらながらやってみたい。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20100501