Nand2Tetris（コンピュータシステムの理論と実装）のCourseraをやりきりました

# はじめに

「[「コンピュータシステムの理論と実装」をやりきりました](https://qiita.com/y-meguro/items/dc11c31cc2667aa20b3c)」という記事に影響を受け、自分も取り組んでみたいと思いました。調べてみるとこの書籍は講義の副読本的な立ち位置らしく、さらに講義はCourseraで受講できるということがわかりました。日本語の字幕が無いので受講するか迷いましたが、無理そうだったらいつでもやめるつもりで受講することにしました。  

- Nand2Tetrisの公式サイト:  https://www.nand2tetris.org/
- Coursera
   - Part1: https://www.coursera.org/learn/build-a-computer
   - Part2: https://www.coursera.org/learn/nand2tetris2

結果的には無事やりきることができました。Courseraのコースを受講して大正解だったと思います。この記事では「コンピュータシステムの理論と実装」、通称`Nand2Tetris`のCourseraのコースについて紹介と、受講の振り返りをしたいと思います。

# CourseraのNand2Tetrisのコースについて

こちらがNand2TetrisのCourseraの魅力的な紹介動画です。

<iframe width="560" height="315" src="https://www.youtube.com/embed/wTl5wRDT0CU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


このCourseraのコースではNand2Tetrisプロジェクトの製作者で本の著者でもあるNoam Nisan氏とShimon Schocken氏自らが講義をしてくれます。講義は大量のスライド・大量の図を使用しており、とても丁寧で非常にわかりやすい内容になっています。コースのレーティングは5点満点中の4.9で、Courseraの中でもかなり人気の高いコースです。

Nand2Tetrisは全部で12個のプロジェクトで構成されていますが、CourseraのコースはPart1とPart2に分かれていて、Part1(project01~project06)ではハードウェアを、Part2(project07~project12)ではソフトウェアを扱います。どちらも6Weekのコースになっています。ただし後述の通り、Part2はPart1の倍ぐらい時間がかかります。

残念ながら日本語の字幕は無いのですが、講義の英語はとても聞き取りやすかったです。上の紹介動画は講師のShimon氏がナレーションをしているので、この動画で話していることが概ね理解できれば問題なく受講できると思います。また講義のスライドにも詳細な説明が書いてあるので、英語を完全に聞き取らなくても進めることができると思います。

各週（プロジェクト）は２〜３時間の講義で構成され、最後に課題を提出します。コースを修了するためには全てのプロジェクトで合格点を取る必要があります。なお、講義だけであれば無料で視聴することができますが、課題を採点してもらうためにはCertificateを購入する必要があります。CertificateはPart1, Part2それぞれで購入する必要があります。自分が購入した時はどちらも6322円でした。書籍より高くなりますが、それでもコースのクオリティを考えれば全然安いと思います。またCeritificateを購入しておくとコース修了後にLinkedInのプロフィールに学習修了証明書を追加することができます。


# 講義の振り返り

自分が講義と課題に取り組んだ時間は、Part1は40時間ぐらい、Part2は90時間ぐらいでした。他の人の回答は参考にせず、全て自力でやりました。Part2は講義時間が長く課題も重くなり、動画速度を1.5倍にして視聴していましたが、それでもPart1の倍ぐらい時間がかかりました。特にPart2のProject9以降は、どの課題も完了させるのに2,3日かかりました。

Part1とPart2の両方やるのをおすすめしますが、Part2は非常に時間がかかるため、時間が無ければPart1だけでもやる価値が大いにあると思います。Part2はPart1で作ったハードウェア（Hack）の上にソフトウェアを構築するので、Part2だけをやるのは微妙かなと思います。


## Part1(ハードウェア)

Part1は紹介動画の通りで、Nandゲートのみを使って様々なチップを作成し、最終的にHackというコンピュータを作成します。とにかく各講義が面白いです。前提知識を必要としないので、コンピュータに興味のある全ての人におすすめしたいです。

なお、Hackは非常にシンプルなコンピュータアキテクチャなのでパイプライン処理や命令レベル並列性などは取り扱いません。またレジスタやメモリは存在しますがキャッシュについては一切触れていません。その辺りの知識を習得する場合は他の書籍などで補う必要があります（パタヘネの４章、５章あたり）


## Part2(ソフトウェア)

Part2ではVM翻訳機とコンパイラをスクラッチで自作し、その上で動くJackアプリケーションやJackOSを実装します。そのためPart2はある程度プログラミングを習得している人向けのコースになっています。（ちなみにPart2は全部Shimon先生が担当して、Noam先生は何故か登場しません。スケジュールが合わなかった？）

特に苦労したProject9以降についてもう少し振り返りたいと思います。

## Project9: Jackアプリケーションの作成

Jackという独自の高水準言語でアプリケーションを作成します。書籍で取り組んでいる場合、この章はJackの文法を確認してすぐ次に進むパターンが多いようなのですが、CourseraではJackで作成したアプリケーションを課題提出する必要があります（みんなゲームを作ります）。この課題はPeer-graded Assignment、すなわち受講者同士で採点を行う課題となっています。他の３〜４人の受講者の課題を採点した後、自分の課題を採点してもらえるようになります。採点は100点満点で60点以上が合格となります。自分は課題を提出してから１週間ぐらいで採点してもらえて、80点でした。100点は「他の生徒に見せるぐらいの珠玉の成果物」ということでかなり難しい・・・

非力なJack言語でゲームを作成するのは大変な作業でした。少し難しいことをやろうとするとすぐ壁にぶつかります。例えばゲーム開発ではしばしばランダム性を取り入れたくなります（テトリスで降ってくるブロックが毎回同じパターンにならないようしたい時など）。JackにはRandomクラスは用意されていないので自分で実装する必要があります。Randomクラスを実装するのにmodulo演算が必要となりますが、Jackにはmodulo演算が用意されていないので自分で実装する必要があります。などなど。。。

あとは普段はIDEでだいぶ楽をしているので、Jackでデバッグしながら開発するのはしんどかったです。for文が使えないのでwhile文でループさせる必要がありますが、iをインクリメントするのを忘れることがよくありました。また、他の受講者に採点してもらうのでコメントもある程度丁寧に（もちろん英語で）記述する必要があります。結局課題を完成させるのに３日ぐらいかかりました。ディスカッションフォーラムにも「この課題難しすぎない？」というスレが建っていたのでみんな苦労しているようです。今思えば、まずは自分の慣れている言語でJackで使える機能だけを使用して開発し、その後Jack言語に翻訳したほうが楽だったと思います。

Jackアプリケーションの開発は苦労しましたが、ここでJack言語に慣れておくと次のJackコンパイラの開発でいろいろな気づきを得ることができるのでやってよかったと思います（思いたい）。また、最後のJackOSの開発もJack言語で行うので進めやすくなります。


## Project10,11: Jackコンパイラの実装

自力で1からJack言語のコンパイラを実装します。やることが多いので時間はかなりかかりますが、逆に時間さえかければ実装できる課題だと思いました。Project11では、自作のコンパイラでテスト用のJackアプリケーションをコンパイルし、出力されたVM言語を付属のエミュレータで実行して、問題があればコンパイラを修正するという流れになっています。ただし実行結果から問題を発見・修正するのはかなり骨が折れます。そこで、ちょっとずるいようですが付属の公式Jackコンパイラを活用し、公式Jackコンパイラが出力したVM言語と自作Jackコンパイラが出力したVM言語を比較し、その差分から未実装の部分を見つけていくという方針で進めました。

Courseraでは最後に実装したコンパイラのプログラム本体を提出し、テストが通ると合格となります。注意点として、Coursera側では単純なビルドしかしないので、サードパーティのライブラリは使うことができません。 自分は慣れているJavaを使いましたが、JDK付属の基本ライブラリ（`java.util`など）だけで実装する必要がありました。したがってApache Commonsなどは使用できません。また、JDKのライブラリでも最近のJavaで追加された新機能は使えないことがあるようです。おそらく他の言語も同じ感じだと思います。

## Project12 Jack OSの実装

Jack言語で最低限のOSを作成します。全部で8個のクラスを実装します。Project10-11で作った自作コンパイラで開発するとエラーハンドリングが甘くて大変なので、開発中は公式のJackコンパイラを使用したほうが良いです。（完成後に自作Jackコンパイラでコンパイルできることも確認しました。）どのクラスもそれなりに頭を悩ませるので、Project11と同じぐらい時間がかかりました。自分は特にMemoryクラスとOutputクラスの実装に苦労しました。Courseraでは8個全てのクラスを提出する必要があります。書籍で進めていて全部やる時間がない場合でも、Memoryクラスの実装だけは取り組むことをおすすめします。

# 最後に

Courseraで受講することの一番のメリットは、修了するためには強制的に全ての課題をやる必要がある（スキップできない）ところかもしれません。実際Part2の後半はかなりしんどかったので、Courseraで進めていなかったらいくつかの課題はスキップしていたと思います。それゆえ、自分で実装したJackアプリケーションとJackOSを、自分で実装したJackコンパイラでコンパイルして、最後にアプリケーションが動いたときの達成感は非常に大きなものでした。Courseraで進めるか迷っている人がいたら是非チャレンジしてみて下さい！