Upload
yuta-sato
View
919
Download
5
Embed Size (px)
DESCRIPTION
セキュリティ・キャンプ2013のクラス内プレゼンで発表した、自作関数型言語「Fulyn」についての紹介です。
Citation preview
'Fulyn' The Functional
Programming Language
自己紹介
➲ 佐藤雄太(さとう・ゆうた)
➲ 16さい
➲ 高校一年生
➲ ライブラリやコンパイラを作るのが好き
➲ 好きな言語はC#とLispとML
➲ Monoのコミッターめざしてます
Fulynとは?
➲OSECPU用の初の高級言語
➲関数型言語
➲シンプル
➲豊富な表現力
OSECPU ASKA is キモい
➲ ほぼアセンブラ
➲ 変数にレジスタを割り当てる必要有
➲ 構文の使い勝手が悪い
➲ 関数呼び出しのネストができない
こんな感じ
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();
とてもじゃないけど、ASKAでアプリを書く気にはなれない
ので、自分で言語を作った
Fulynでは、リテラル、関数呼び出し、変数など、全てが式であり、
文は全てが代入文か宣言文のどちらかである
レジスタは変数に自動に割り当てられるのは当然として、
高階関数や、ラムダ、再帰、末尾再帰の最適化などをサポートしている
また、組み込み済の制御構文がパターンマッチしか存在せず、
余計な機能が一切ない
型も整数型と関数型以外は存在せず、将来は配列を配列型を追加することなく実装する予定
美しい再帰の例:
フィボナッチ数列を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
水玉の描画 コレ->
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
美しいパターンマッチの例:
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
ユークリッドの互除法
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
美しいラムダ(匿名関数)の例:
クロージャでもあることのテスト
ラムダでローカルに[int => int => int]型の関数オブジェクトを宣言し、同じスコープ内の値を利用して演算。
呼び出す側からは通常の関数ポインタと区別がつかない。
main b = 6 func = x :: int => y :: int => mul(b, add(x,y)) putnum(func(3, 4)) // output: 42end
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
美しい末尾再帰最適化の例:
ユークリッドの互除法(再掲)どんな大きい数を計算してもスタックを食いつぶさない
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
標準ライブラリの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
跳ね返るボール壁で跳ね返る、スタックを食いつぶさない
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
これらのバイナリは標準ライブラリ(約3KB)のコンパイルされた部分を含めても、全て5KB以内
に収まっている。もちろん、バイナリ生成時に
コンパイラの最適化が働いている
Fulyn is 美しい
Fulynにこれから実装すること
➲部分適用
➲ 配列サポート
➲ さらなる最適化
➲その他、「コレつけて!」というものがあったら
是非
Fulynは美しいので、他のアーキテクチャに移植しても美しいはず
次はCLI(Microsoft .NET Framework)をターゲットにしたコンパイラを作ろうと思っています。
FulynでiPhone開発も夢ではない
ちなみに、Fulynコンパイラの作成の過程で、セキュアOSなはずのOSECPUに脆弱性を2つも見つけました。
(一度目は存在しないラベルへのジャンプ、二度目は65536回の再帰によるス
タック食いつぶし)
ご清聴ありがとうございました