読者です 読者をやめる 読者になる 読者になる

カリー化 続々

プログラム

クロージャを実装できた
関数外の変数に手を出している関数をマークして
関数外の変数を一個のframeにまとめる

var a = 1
var b = 2
sub f(c: Int)
    print(a + b + c)
f(3)

↑これを↓こう変換する

var a = 1
var b = 2
sub f_(frame, c: Int)
    print(frame.a + frame.b + c)

var frame # この辺が変換部分
frame.a = a
frame.b = b
f = f_.bind(frame)

f(3)

CILに変換するときは前回の部分適用でなんとかする
今のつくりはクロージャがネストすると1関数1frameで作っているので、どんどん引数が増える
まぁいっか

f:id:zenu:20160224232120p:plain

ILは笑っちゃうほど長い

//  Microsoft (R) .NET Framework IL Disassembler.  Version 4.6.81.0
//  Copyright (c) Microsoft Corporation. All rights reserved.



// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly Global
{
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module Global
// MVID: {3B864071-7E41-437A-9EDF-B63D9808492F}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x00CA0000


// ================== GLOBAL METHODS =========================

.method public static class [mscorlib]System.Action`1<int32> 
        f1(int32 A_0) cil managed
{
  // コード サイズ       38 (0x26)
  .maxstack  2
  .locals init (class '##f1' V_0,
           class [mscorlib]System.Action`1<int32> V_1)
  IL_0000:  newobj     instance void '##f1'::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  ldarg.0
  IL_0008:  stfld      int32 '##f1'::w
  IL_000d:  ldloc.0
  IL_000e:  ldc.i4.5
  IL_000f:  stfld      int32 '##f1'::z
  IL_0014:  ldloc.0
  IL_0015:  ldc.i4     0x14
  IL_001a:  nop
  IL_001b:  nop
  IL_001c:  nop
  IL_001d:  nop
  IL_001e:  call       class [mscorlib]System.Action`1<int32> f2(class '##f1',
                                                                 int32)
  IL_0023:  stloc.1
  IL_0024:  ldloc.1
  IL_0025:  ret
} // end of global method f1

.method public static class [mscorlib]System.Action`1<int32> 
        f2(class '##f1' A_0,
           int32 A_1) cil managed
{
  // コード サイズ       70 (0x46)
  .maxstack  3
  .locals init (class '##f2' V_0,
           class [mscorlib]System.Action`1<int32> V_1)
  IL_0000:  newobj     instance void '##f2'::.ctor()
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  ldarg.1
  IL_0008:  stfld      int32 '##f2'::x
  IL_000d:  ldloc.0
  IL_000e:  ldloc.0
  IL_000f:  ldfld      int32 '##f2'::x
  IL_0014:  stfld      int32 '##f2'::y
  IL_0019:  newobj     instance void Bind_f3::.ctor()
  IL_001e:  stloc.1
  IL_001f:  ldloc.1
  IL_0020:  ldftn      void f3(class '##f1',
                               class '##f2',
                               int32)
  IL_0026:  stfld      native int Bind_f3::f
  IL_002b:  ldloc.1
  IL_002c:  ldarg.0
  IL_002d:  stfld      class '##f1' Bind_f3::'##f1'
  IL_0032:  ldloc.1
  IL_0033:  ldloc.0
  IL_0034:  stfld      class '##f2' Bind_f3::'##f2'
  IL_0039:  ldloc.1
  IL_003a:  ldftn      instance void Bind_f3::Invoke(int32)
  IL_0040:  newobj     instance void class [mscorlib]System.Action`1<int32>::.ctor(object,
                                                                                   native int)
  IL_0045:  ret
} // end of global method f2

.method public static void  f3(class '##f1' A_0,
                               class '##f2' A_1,
                               int32 A_2) cil managed
{
  // コード サイズ       65 (0x41)
  .maxstack  2
  .locals init (int32 V_0,
           int32 V_1,
           int32 V_2,
           int32 V_3,
           int32 V_4)
  IL_0000:  ldc.i4     0xa
  IL_0005:  nop
  IL_0006:  nop
  IL_0007:  nop
  IL_0008:  nop
  IL_0009:  ldarg.1
  IL_000a:  ldfld      int32 '##f2'::x
  IL_000f:  add
  IL_0010:  stloc.0
  IL_0011:  ldloc.0
  IL_0012:  ldarg.1
  IL_0013:  ldfld      int32 '##f2'::y
  IL_0018:  add
  IL_0019:  stloc.1
  IL_001a:  ldloc.1
  IL_001b:  ldarg.0
  IL_001c:  ldfld      int32 '##f1'::z
  IL_0021:  add
  IL_0022:  stloc.2
  IL_0023:  ldloc.2
  IL_0024:  ldarg.0
  IL_0025:  ldfld      int32 '##f1'::w
  IL_002a:  add
  IL_002b:  stloc.3
  IL_002c:  ldloc.3
  IL_002d:  ldarg.2
  IL_002e:  add
  IL_002f:  stloc      V_4
  IL_0033:  nop
  IL_0034:  nop
  IL_0035:  ldloc      V_4
  IL_0039:  nop
  IL_003a:  nop
  IL_003b:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_0040:  ret
} // end of global method f3

.method public static void  '###.ctor'() cil managed
{
  // コード サイズ       15 (0xf)
  .maxstack  2
  .locals init (class [mscorlib]System.Action`1<int32> V_0)
  IL_0000:  ldc.i4.1
  IL_0001:  call       class [mscorlib]System.Action`1<int32> f1(int32)
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldc.i4.2
  IL_0009:  callvirt   instance void class [mscorlib]System.Action`1<int32>::Invoke(!0)
  IL_000e:  ret
} // end of global method '###.ctor'

.method family static void  __EntryPoint() cil managed
{
  .entrypoint
  // コード サイズ       6 (0x6)
  .maxstack  0
  IL_0000:  call       void '###.ctor'()
  IL_0005:  ret
} // end of global method __EntryPoint


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


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

.class private auto ansi '##f1'
       extends [mscorlib]System.Object
{
  .field public int32 w
  .field public int32 z
  .method public specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // コード サイズ       1 (0x1)
    .maxstack  0
    IL_0000:  ret
  } // end of method '##f1'::.ctor

} // end of class '##f1'

.class private auto ansi '##f2'
       extends [mscorlib]System.Object
{
  .field public int32 x
  .field public int32 y
  .method public specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // コード サイズ       1 (0x1)
    .maxstack  0
    IL_0000:  ret
  } // end of method '##f2'::.ctor

} // end of class '##f2'

.class private auto ansi Bind_f3
       extends [mscorlib]System.Object
{
  .field public native int f
  .field public class '##f1' '##f1'
  .field public class '##f2' '##f2'
  .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 Bind_f3::.ctor

  .method public instance void  Invoke(int32 A_1) cil managed
  {
    // コード サイズ       30 (0x1e)
    .maxstack  4
    IL_0000:  ldarg.0
    IL_0001:  ldfld      class '##f1' Bind_f3::'##f1'
    IL_0006:  ldarg.0
    IL_0007:  ldfld      class '##f2' Bind_f3::'##f2'
    IL_000c:  ldarg      A_1
    IL_0010:  nop
    IL_0011:  nop
    IL_0012:  ldarg.0
    IL_0013:  ldfld      native int Bind_f3::f
    IL_0018:  calli      void(class '##f1',class '##f2',int32)
    IL_001d:  ret
  } // end of method Bind_f3::Invoke

} // end of class Bind_f3


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

// *********** 逆アセンブルが完了しました ***********************


ところで得正のカレーうどんはうまかった

f:id:zenu:20160220152357j:plain