fulyn - the functional language

32
'Fulyn' The Functional Programming Language

Upload: yuta-sato

Post on 24-May-2015

919 views

Category:

Technology


5 download

DESCRIPTION

セキュリティ・キャンプ2013のクラス内プレゼンで発表した、自作関数型言語「Fulyn」についての紹介です。

TRANSCRIPT

Page 1: Fulyn - The Functional Language

'Fulyn' The Functional

Programming Language

Page 2: Fulyn - The Functional Language

自己紹介

➲ 佐藤雄太(さとう・ゆうた)

➲ 16さい

➲ 高校一年生

➲ ライブラリやコンパイラを作るのが好き

➲ 好きな言語はC#とLispとML

➲ Monoのコミッターめざしてます

Page 3: Fulyn - The Functional Language

Fulynとは?

Page 4: Fulyn - The Functional Language

➲OSECPU用の初の高級言語

➲関数型言語

➲シンプル

➲豊富な表現力

Page 5: Fulyn - The Functional Language

OSECPU ASKA is キモい

➲ ほぼアセンブラ

➲ 変数にレジスタを割り当てる必要有

➲ 構文の使い勝手が悪い

➲ 関数呼び出しのネストができない

Page 6: Fulyn - The Functional Language

こんな感じ

beginFunc(L_print_board); do { int32s i:R00, x:R02, y:R03; junkApi_fillRect(0, 360, 360, 0, 0, 0x008000); x = 18; y = 18; for ( i = 0; i < 9; i++ ) { junkApi_fillRect(0, 324, 4, 18, y, 0); junkApi_fillRect(0, 4, 324, x, 18, 0); x += 40; y += 40; } }endFunc();

Page 7: Fulyn - The Functional Language

とてもじゃないけど、ASKAでアプリを書く気にはなれない

Page 8: Fulyn - The Functional Language

ので、自分で言語を作った

Page 9: Fulyn - The Functional Language

Fulynでは、リテラル、関数呼び出し、変数など、全てが式であり、

文は全てが代入文か宣言文のどちらかである

Page 10: Fulyn - The Functional Language

レジスタは変数に自動に割り当てられるのは当然として、

高階関数や、ラムダ、再帰、末尾再帰の最適化などをサポートしている

Page 11: Fulyn - The Functional Language

また、組み込み済の制御構文がパターンマッチしか存在せず、

余計な機能が一切ない

Page 12: Fulyn - The Functional Language

型も整数型と関数型以外は存在せず、将来は配列を配列型を追加することなく実装する予定

Page 13: Fulyn - The Functional Language

美しい再帰の例:

Page 14: Fulyn - The Functional Language

フィボナッチ数列を1000まで表示

fibonatti :: [int => int => int]

main fibonatti(0, 1)end

fibonatti(left, right) r = right next = add(left, right) putnum(next, 0x0a) ? les(next, 1000) | true -> fibonatti(r, next) | false -> 0end

Page 15: Fulyn - The Functional Language

水玉の描画 コレ->

indx :: int; indy :: int; color :: int

main ? eql(0, color) | true -> openwin(256, 256) | false -> 0 color = add(add(mul(indx, 21760), mul(indy, 85)), 0xFF0000) filloval(add(2, mul(64, indx)), add(2, mul(64, indy)), 60, 60, color) indx = ? les(indx, 3) | true -> add(indx, 1) | false -> 0 indy = ? eql(indx, 0) | true -> add(indy, 1) | false -> indy ? les(indy, 4) | true -> main() | false -> 0end

Page 16: Fulyn - The Functional Language

美しいパターンマッチの例:

Page 17: Fulyn - The Functional Language

FizzBuzzfizz,buzz,fizzbuzzは

文字列を表示する関数なので省いてあります~は次の行を直後に結合する記号です

solve :: [int => int]write4 :: [int => int => int => int => int]

main for(1, x :: int => loq(x, 100), y :: int => add(y, 1), ~ z :: int => solve(z))end

solve(x) xfz = x ? 0xFFFFFFFF // trueの整数値 | eql(mod(xfz, 15), 0) -> fizzbuzz() | eql(mod(xfz, 3), 0) -> fizz() | eql(mod(xfz, 5), 0) -> buzz() | () -> putnum(xfz, 0x0a)end

Page 18: Fulyn - The Functional Language

ユークリッドの互除法

gcd :: [int => int => int]

main putnum(gcd(1547, 2093), 0x0a)end

gcd(x, y) : tailcall tmp = x xg = x yg = y xg = ? les(xg, yg) | true -> yg | false -> xg yg = ? eql(xg, tmp) | true -> yg | false -> tmp ? mod(xg, yg) | 0 -> yg | () -> gcd(yg, mod(xg, yg))end

Page 19: Fulyn - The Functional Language

美しいラムダ(匿名関数)の例:

Page 20: Fulyn - The Functional Language

クロージャでもあることのテスト

ラムダでローカルに[int => int => int]型の関数オブジェクトを宣言し、同じスコープ内の値を利用して演算。

呼び出す側からは通常の関数ポインタと区別がつかない。

main b = 6 func = x :: int => y :: int => mul(b, add(x,y)) putnum(func(3, 4)) // output: 42end

Page 21: Fulyn - The Functional Language

FizzBuzz(再掲)for関数に、ラムダで記述した関数を直接渡しています。

高階関数をサポートしているので、関数を取ったり関数を返したりする関数が構築可能です。

solve :: [int => int]write4 :: [int => int => int => int => int]

main for(1, x :: int => loq(x, 100), y :: int => add(y, 1), ~ z :: int => solve(z))end

solve(x) xfz = x ? 0xFFFFFFFF // trueの整数値 | eql(mod(xfz, 15), 0) -> fizzbuzz() | eql(mod(xfz, 3), 0) -> fizz() | eql(mod(xfz, 5), 0) -> buzz() | () -> putnum(xfz, 0x0a)end

Page 22: Fulyn - The Functional Language

美しい末尾再帰最適化の例:

Page 23: Fulyn - The Functional Language

ユークリッドの互除法(再掲)どんな大きい数を計算してもスタックを食いつぶさない

gcd :: [int => int => int]

main putnum(gcd(1547, 2093), 0x0a)end

gcd(x, y) : tailcall tmp = x xg = x yg = y xg = ? les(xg, yg) | true -> yg | false -> xg yg = ? eql(xg, tmp) | true -> yg | false -> tmp ? mod(xg, yg) | 0 -> yg | () -> gcd(yg, mod(xg, yg))end

Page 24: Fulyn - The Functional Language

標準ライブラリのfor関数高階関数でもある

for :: [int => [int => int] => [int => int] => [int => int] => int]

for(x, comp, next, exec) : tailcall xf = x cmpf = comp nxtf = next excf = exec flag = comp(xf) ? flag | true -> excf(xf) | false -> 0 ? flag | true -> for(nxtf(xf), cmpf, nxtf, excf) | false -> 0end

Page 25: Fulyn - The Functional Language

跳ね返るボール壁で跳ね返る、スタックを食いつぶさない

draw :: [int]ballx :: intbally :: intrangex :: intrangey :: int

main openwin(256, 256) bally = 0; ballx = 90 rangex = 1; rangey = 1 draw()end

draw() : tailcall rangex = ? -1 | les(ballx, 1) -> 1 | goq(ballx, 240) -> -1 | () -> rangex rangey = ? -1 | les(bally, 1) -> 1 | goq(bally, 240) -> -1 | () -> rangey filloval(ballx, bally, 16, 16, 0xFF0000) sleep(10) filloval(ballx, bally, 16, 16, 0x000000) ballx = add(ballx, rangex) bally = add(bally, rangey) draw()end

Page 26: Fulyn - The Functional Language

これらのバイナリは標準ライブラリ(約3KB)のコンパイルされた部分を含めても、全て5KB以内

に収まっている。もちろん、バイナリ生成時に

コンパイラの最適化が働いている

Page 27: Fulyn - The Functional Language

Fulyn is 美しい

Page 28: Fulyn - The Functional Language

Fulynにこれから実装すること

➲部分適用

➲ 配列サポート

➲ さらなる最適化

➲その他、「コレつけて!」というものがあったら

是非

Page 29: Fulyn - The Functional Language

Fulynは美しいので、他のアーキテクチャに移植しても美しいはず

Page 30: Fulyn - The Functional Language

次はCLI(Microsoft .NET Framework)をターゲットにしたコンパイラを作ろうと思っています。

FulynでiPhone開発も夢ではない

Page 31: Fulyn - The Functional Language

ちなみに、Fulynコンパイラの作成の過程で、セキュアOSなはずのOSECPUに脆弱性を2つも見つけました。

(一度目は存在しないラベルへのジャンプ、二度目は65536回の再帰によるス

タック食いつぶし)

Page 32: Fulyn - The Functional Language

ご清聴ありがとうございました