a symmetry

雑な自己満足を残していくブログ 年度によってテンションが違うっぽい

セキュリティ・キャンプ全国大会2018応募用紙晒し

ポエム9割ポエム9割ポエム9割ポエム9割ポエム9割ポエム9割ポエム9割

まえがき

久々すぎて自分の文体が思い出せない・・・ので雑に殴り書きします. セキュリティ・キャンプ全国大会2018の選考が通ったのでほぼ全文の応募用紙を晒します.通らなかったら晒さなかったです. 締め切り当日の15:21くらいから書きました.もし昨日や一昨日が締め切りだったら完全にぶん投げてたし応募用紙は書けないですね,メンタル大事. www.ipa.go.jp

集中コースの Y【システムプログラミングトラック】Cコンパイラを自作してみよう!ゼミに応募しました. 凡人未満趣味太郎が書いた駄文ですが,セキュキャンの採点上加点方式が主らしいので書けることを書きました.気分を害した場合はブラウザバックを推奨します.あと文体が整ってないのもダメですね.9割ポエムです.間違っているところがあったらリプライなりコメントなりで激甘に優しく教えてください.いやもうマジでメンタル弱いんです.

という訳で以下の文章はフィクションです.実在の人物や団体および言語などとは関係ありません.ほんまか?

[問1] これまでのプログラミング歴(C言語に限りません)について好きなだけ語ってください。何か作ったものがあれば、それについても教えてください。

やっていった言語を順に書いていきたいと思います.言語自体が好きなので言語についてたくさん書いていることが多いです.

C言語

開始時期

大学に入ってから(8月とか)

動機

最初は授業で学ぶ予定だったので予習

所感

やっていくうちに自分の想像通りの動作をするとすごく楽しくなってきました. でもC言語で実際に何かの成果を上げようとするのは始めてすぐの人間には難しく,並行して勉強した後述するスクリプト言語たちをメインでやっていってました.

好き?

微妙,でもいろんな本読むとサンプルコードとして出てくるので必要性はとても感じる.

作ったもの

特になし(競プロだったり各種データ構造を実装したりはやりました)

Java

開始時期

学部1年の10月 ~ 12月

動機

オブジェクト指向を学ぶのに

所感:

入門書をちょっと読みました,CよりスタンダードなAPIが多いので色々触りやすそうだなと感じました.この時は構造体とクラスが具体的にどういう風に概念として違うのか他人に説明できるレベルではなかったと思います.

好き?

1.8以降で必要があれば書くぐらい

作ったもの

Ruby

開始時期

大学に入ってからC言語を少しやったあとに独学(少し) ~ Python触るまで

動機

入学してから知り合ったプロの友達がRubyistだったので布教されました.あと実際に実務でCを使うところはそんなに多くないしRubyの方が求人は多いと聞いたので

所感

この時は型宣言しなくて済むし任意のデータ構造を1つの変数で扱えて楽だな〜と思ってました.学部1年の時にExcelで大学の物理実験の数値計算を行うのですが,「せっかくプログラミングを学んだしRubyでもできないかな」といろいろ工夫 して実装しました.

好き?

シンタックスが柔らかくて好き #{} で文字列展開できるのとか(後述するPythonだとちょっとダルいので)

作ったもの

Python3

開始時期

学部1年の2月から

動機

Rubyで実験の数値計算を実装した後に「コード書いてお金もらいたい!そういうアルバイトはないのだろうか?」と調べたところインターンなどがあることを知り,熱意を買われてそこで学び始めました.

所感

おそらく一番書いた言語です. 主にそこではWebクローリング,スクレイピングDjangoを使ったWeb開発を行いました.書いていくうちに 内包表記やfor ... in <iterable> だったり構文が単調であったりライブラリと情報量が多いので作りたいものが最短かつ可読性が高いまま実装できる言語だと感じました. あとインデントをすごい気にするようになりました.別の言語でも無意識にインデントを気にするようになりましたし,見ててわかりやすいコードを書くことを意識するようになりました.

好き?

結構好き.出会えたおかげで今でもコードを書いている,そんな感じがします.

作ったもの

ECMAScript6~/TypeScript

開始時期

学部2年の夏休み辺りから

動機

アルバイトで必要になったため

所感

最初は嫌いでした. - 関数オブジェクトやPromiseがよくわからない - $ npm installをどのプロジェクトディレクトリでも打たないといけない - 打った後はめっちゃWARNING出る - Pythonみたいに $ pip installを打ったらインストールされてる処理系自体にそのライブラリから呼び出せるようにしたほうが手間暇がかからない気がしていた

などがあったからです. やっていくうちに関数オブジェクトは考えてみたら便利だし$ npm installはプロダクト毎に使ってるライブラリのバージョンが違ったら辛い問題を緩和してくれているしこのスタイルの方がいい気がしてきました. あとVueとかReactとかAngularとかフロントエンドのフレームワークは多種多様で氾濫していてキャッチアップが辛そうという気持ちです.

好き?

ビジネスのお付き合いって感じです,ES~5 は・・・

作ったもの
  • 検閲削除(アルバイト)
  • 検閲削除(アルバイト)
  • 検閲削除(ハッカソン)

Swift3

開始時期

学部2年の10月から2月くらいまで

動機

個人的にiPhoneアプリを作ってみたかった + アルバイトで必要になったため

所感

XCodeに開発環境が縛られて辛かったです. 先述した通りiPhoneアプリを作るのに必要だったので書いていたのですがSwiftが難しかったのかXCodeが難しいのかiPhoneアプリが難しいのか分からないまま書いてました.今でもわからない・・・

好き?

今思えばそんな悪い言語ではない気がするがそれはそれとして後方互換性がないので2での情報が一瞬で消し飛んだりとかするのであの時期に評価するのは難しい気がしてきました.

作ったもの

トイレ内に人を感知するセンサがあって,それがWebサーバに情報を投げてそこにリクエストを送って,どこのトイレが空いているかを表示するアプリ

Go

開始時期

学部3年の6月くらいから

動機

マイクロなWebサービスを作る際の流行りだったので

所感

最初はとてつもなく書きづらかったのですが500行くらい書いてみるとだんだんとよくなってきました. クロスコンパイルが楽にできるのでハッカソンでRPiを会場でセットアップしてる時に最初はPythonでやろうとしたのですが処理系がなく,会場の回線がとっても遅くて詰んでいたのですがバイナリをMacで生成してRPiはバイナリ送るだけという風にしたら見事に動くものが作れました. この頃から型がある言語って実は良いのでは?と思うようになってきました. IDEなどがのオブジェクトが持つメソッドを補完してくれたり, 他人が書いた関数を読む際に返り値や引数の型を読んでどのような引数を渡せばいいか,そもそも型自体が説明になっていたりしていますね(例えばJSで仮引数名がurlという風になっていたらURLのオブジェクト or urlの文字列なのかぱっと見わからない気がします).少なくともアルバイトなどの業務や複数人で規模が大きいコードを書く際はあると嬉しいと思うようになりました.コンパイルが通ると(ロジックがあっているかどうかは別として)少なくとも動くのでスクリプト言語の「動いてはいるけど予期していない引数渡されて止まるか不安」みたいな懸念すべき要素を緩和してくれているんだなと思いました. また,Pythontry ~ exceptは予めエラーが起きることを先にエスパーして書かないといけないのですが Goのerr, hoge := ~~ は本当にエラーが起きてからエラーハンドリングができている感じが健全で良いと思います,あと _ で errをエスケープできるところも. 型がある言語ですが interface{}のおかげでダックタイピングができるのでスクリプト言語の手軽さを保ったままゴリゴリ書けるのもいいと思います. でもやはり規模が大きくなると設計がきっちりしてないと辛そうだなぁと思いました.(どの言語でもそうだと思いますが) あとジェネリクスがないので map, filter, reduceなど高階関数を使った関数型プログラミングの便利なメソッドがなかったりするのが辛いという気持ちです.

好き?

最後はちょっとだけ批判しましたが結構好きです.書くとしたらスクリプト言語代わりって感じの手軽さで書きたいものがあったらって感じですね.

作ったもの:
  • 社内向けにJVNをクローリングして自社が使っているライブラリの情報があるかないかを教えてくれるWebサービス
  • 検閲削除(ハッカソン)

Scala

開始時期

学部3年の11月あたりから

動機

アルバイト先で必要だったため

所感

シンタックスシュガーがすごくてDSLも半端ない. 型がとてもきっちりしていて,設計が綺麗だと型合わせパズルをするだけで大抵うまくいくコードが書けますし,Scalaで初めてOptionやEitherに触れたのですがパターンマッチでエラー処理が書けます. REPLもあるので比較的触りやすいし, 言語自体のライブラリもかなり充実しています.関数型言語としての側面でバズったように見えますがオブジェクト指向 + 関数型言語として綺麗に成立しているのがとてもScalaのいいところだと思います. でもコンパイルがめっちゃ遅かったり,学習コストが高いと思います.あとIDEIntelliJがメインになってしまうのが少し辛いところ

好き?

結構好きです.

作ったもの
  • 検閲削除(アルバイト)

Scheme

開始時期

学部3年の12月あたりから

動機

SICPを読むため

所感

初めて触るS式は辛かったですが,インデントを意識したりparenthesis毎に色が変わるプラグインをエディタに入れたらとても書きやすくなりました.述語で条件分岐を書けるのが新鮮でSICPは読んでいて楽しいです.再帰が書けるようになりました.

好き?

そこそこ

作ったもの:

アセンブラ

開始時期

今年の4月くらいから

動機

なんとなく,知らずに大学を卒業するのが嫌だったので.

所感

使える変数が全部グローバル変数(レジスタ)なプログラミングがすごい新鮮というか・・・ ソースコードからこんなに分かりにくい形で吐き出されてめっちゃスタックだったりjumpしたりで構成されていて「僕の書いているソースコードはとてつもない抽象化の上で成立しているのだな」と思いました.

好き?

何とも言えない

作ったもの

"Hello, World!"と出力したりとかそんなレベルです.

[問2] コンパイラソースコードから実行バイナリを生成する過程について、現在知っている範囲で説明してください。ソースコードの言語については、好きなものでかまいません。

おおざっぱに以下のフェーズをたどってコンパイラソースコードから実行バイナリを生成します. - 字句解析 - 構文解析 - 意味解析 - 目的コード生成

字句解析

int main(void) {
    return 0;
}

とあったら

int
main
(
void
)
{
return
0
;
}

という風にソースコードトークンに分割する作業です. トークンはその言語内で意味を持つ最小単位の文字列を指します. 字句解析をする際は,オートマトンの考え方や正規表現を使うとうまくいくケースが多いです.

構文解析

if i == 1) {

といった明らかにC言語の文法的に正しくない行を例として考えます.この場合は ( と }がないですね. 字句解析のフェーズでは

if
i
==
1
)
{

トークンに分割することはできるが,誤りを検知できません.そこで構文解析の出番です. トークンが正しい順番で並んでいるかどうかをあらかじめ定義されたBNFなどの文法規則と照らし合わせて検証します. 構文解析に成功した後,トークンを構文木と呼ばれる再帰的な木構造を生成します. 構文解析

で表現すると良い感じの実装になるケースがあります.

意味解析

int ten(void) {
    return 10;
}

int main(void) {
    char i = ten();
    return 0;
}

という風に構文的にあっているけど iの型があってないソースコードに対して誤りを検知できるのが意味解析です.

name type scope .....
ten int 0 .....
i char 1 .....

上のような表が用意されていてハッシュ法などを用いて表にアクセスして照らしあわせます. また,上の表は左から順に

を指しています. 他にも,意味解析ではローカル変数がスコープの外で呼び出されていないかなどの誤りも検知できます.

コード生成

構文解析した結果得られる抽象構文木から対象の機械で動かすことのできるコードを生成します. アセンブラ機械語は一対一対応であるためこの時点でアセンブラを吐き出せればCでは完成であると言っても良いのではないのでしょうか.

最終的に

1 + 2 * 3

が字句解析をへて

1
+
2
*
3

となり,構文解析を経て

   +
 /   \
1     *
    /   \
   2     3

となり,コード生成で

MOV eax, 2
MOV edx, 3
MUL edx
ADD eax, 1

といった風に機械が解釈できる言語に変換されるのがコンパイルの一連の流れです.

[問3] C言語コンパイラを書く際に、最も難しいポイントはどこだと思いますか?考えたことや、これまでのプログラミング経験をもとに、具体的に教えてください。

最も難しいを判断するのは難しいのでいくつか書かせていただきます.(あとがきですが書いたことがないものの最も難しいポイントを当てるの難しくないですか?)

yaccなどのlexerを使わない構文解析

過去にコンパイラを作ろうとチャレンジした際に構文解析でつまづきました. 任意の個数のトークンを戻ったり,先読みするのを表現するのはとても難しそうだし,そもそもの構文が再帰的であるため,任意にトークンを行ったり来たりしたいのに構文が再帰的なのでこれを表現するのは難しそうに感じます.これはSICPでの再帰をある程度やった後の経験に基づく文章です.また,Lexerはいろいろな言語のライブラリで実装されていますがそれは多数の人が「自動化できるにもかかわらず煩雑な内容である」と判断して実装した.というのも考えられると思います.

型を前置して宣言すること

型を前置すると,その変数が関数なのか値なのかが実行するまで分からないのも辛いところだと思います.意味解析で使う記号表に登録するための処理やタイミングが難しそうに見受けられます. これは,今まで触ってきたScala, GoやRustのモダンな言語とCのシンタックスを比べて考えました.

マクロの実装

マクロは定義されている構文や意味を加算的に追加できます.あらかじめ定義された構文を実装するのも僕にとってはとてもハードなことなのにマクロを実装するとなると完全にどこでどういう処理が行われるのか見当がつかないです・・・

goto

gotoは正しく使うと便利なのですが,人間が正しく使うには難しいところがあるのでgotoの実装やテストのケースは膨大になるのではないのかと思いました.

コード生成

例えばスタックマシン向けにコードを生成するのであれば,そもそものスタックマシンがどのように動作するのかを知っていないのといけないし,それだけでコンパイラから十分逸脱できる内容だと考えられます. LLVMなどを用いるとある程度アーキテクチャの後ろ側を無視して書けるとは思いますが,ブラックボックスブラックボックスのままにするのは良くないと思いました.

[問4]. 何か他にアピールしたいことがあれば、自由に書いてください。この設問も含め、誤ったことを書いていても減点はしません。書いておきたいことはなんでも書いてください。

問1でいろいろな言語について書いて気づいたのが業務で触るのと個人で触るのは違うなーとは思いました. 業務で使うとしたらScalaやTypeScriptなどといった型がしっかりしてる言語でやっていきたいですが, 個人だったら好きなようにすればいいのかなーと思いました.いい言語が増えてきていますし.

問1を読んでいただけるとわかる通り,僕の学ぶ動機として一番最初は「面白そう」でしたが最近は「アルバイトで必要に駆られて」となることがとても多いです. コードを書くことは楽しいですが,やっていくうちに

  • お金とのトレードオフで業務で必要なことを学ぶ
  • ハッカソンで勝てる派手な技術だったり色々レイヤが高い技術だったりそれを活かせるアイデア
  • 就活のために人事とかの人から見ても分かるような技術や動くプロダクトを作りたい

ばかりで本当に興味があるプログラミング言語自体だったりコンピュータサイエンスだったりができてなくメンタルがすり減ってることに気づきました. それらを学ぶための機会や興味が,やらなければいけないことで埋め尽くされたまま大学生活が終わりかけていました.

学部3年の終わりの時,バイト先の人と進路がどうなるのかという話になって「もっと自分の興味があることについてたくさん知りたい」と思ってSICPを読み始めました. SICPを読んでいるうちに「なんとなく再帰を理解していたつもりだったが自分はこんなにも再帰がかけないのか,こんなに知っていることが少ないのか」と愕然としましたが,それでも自分がもがきながらも一生懸命解いていくうちに再帰がちゃんと書けるようになったり知っていることが何となく増えたような気がします.それと同時に「即時的なお金にならないけど,コンピュータサイエンスやプログラミング自体の学習はやっぱり楽しいな」と最近やっと思えるようになりました. そこで,「お金にならないけど夏休みに1週間同じ志であるコンパイラプログラミング言語について興味や知識を持つ仲間やたくさんのことを知っている講師達に積極的に質問できる機会がある,純粋に自分が興味がある分野を学ぶことに全力になれそうなセキュキャンに行きたい」と思うようになっていました.

僕は電通大の夜間主に所属していて夜間主では研究室配属が必須でないため,楽をしたかった当時の僕は研究室配属をしなかったので誰かと一緒にコンパイラについて学ぶ/教わる機会だったりがないです. 数が少ないとは言え,いろいろな言語を触ったつもりはあります.未だに新しい言語に触れることは飽きていませんし,やはりコンパイラは言語が好きなら通るべき道だと思いました. 学部4年になってやっと知りたいことを知るための機会や意志がマッチしました.この応募が通らなくてもSICPや様々な本を読み,自力でコンパイラについて学んでやっていくと思います. それでも,自分よりたくさんの事を知っている講師の方や同じ志を持った仲間と共に一緒に学び,苦悩し,実装をやっていくことは絶対にこれからの僕のエンジニアリング人生の大きな思い出や一歩になると信じています. というか,こんな機会は僕にはもうないと思います. 参加できたら誰よりも受講学生の中で一番年上になりますが,そんなの関係なしに年上であることのメリット,デメリットやプライドを捨てて誰に対してもリスペクトを支払いつつも,全力で取り組みたいと思っています.

どうかよろしくお願い致します.

あとがき

セキュキャンの締め切りツイートを見なきゃ完全に忘れてました. 去年は同じハッカソンチームのメンバーの id:kden が行ってたのですが,まさか今年は自分が行けるようになるとは思いませんでした. 22時にラーメン食べながら問1と問4を校正してくれた同期,締め切りツイートをしていた各位,こんな駄文を読んで良いと判断していただいた講師の方々,その他諸々各位に感謝します. 受かったからにはちゃんとメンタル調整して全力でやって行きたいと思います,何卒よろしくお願いいたします.