ローカル関数

なんとかローカル関数を実装した。
無理矢理っぽくてあんまり納得いかないけど。


自由変数を本物の引数の前に並べるような
lambda-liftingしただけなので、
関数が定義されたスコープを抜けたらコール不能になる。
(引数として使う自由変数の存在が保証できなくなるから)
従ってfirst classの関数はまだできない。
まあ、ここまでやってあればそう難しくはないと思うけど。
自由変数とスタブ関数(シグネチャがユーザの定義通りの関数)を組にした構造体
(すなわちこれがクロージャ)を作って
スタブ関数の中から本物の関数(シグネチャが自由変数込みのもの)を
呼び出すようにすれば
あとはLLVMオプティマイザが
そこそこよろしくやってくれるんじゃないかと思う。


つまりこうすると言いたい:

int foo_internal( int l, int m, int n )
{
    do something
}

struct closure {
    int foo( int n )
    {
        foo_internal( l, m, n );
    }
    int l;
    int m;
};


ちなみに現状では、

require leaf;

fun main(): int
{
	var m = 3 + 2;

	fun foo( n: int ): int
	{
		m * n ;
	}

	puti( foo(4) );
	0;
}

こんなソースが

define i32 @main() {
ENTRY:
	%reg28 = add i32 3, 2
	%ret50 = call i32 @foo( i32 %reg28, i32 4 )
	%ret55 = call i32 @puti( i32 %ret50 )
	ret i32 0
}

define i32 @foo(i32 %env_m, i32 %arg_n) {
ENTRY:
	%reg41 = mul i32 %env_m, %arg_n
	ret i32 %reg41
}

こんな風になって出てきます。