Elm/Compilerのコードリーティング
ElmのCode Reading
安全に設計されているElmは自作言語を作るときに参考になりそうなので、大まかなディレクトリ構造ぐらいのメモ
initial commitは2012/4/19
Elmの最初期ってたぶんFRPなので、全然実装が異なるものになっている
最初の方のコード、比べ物にならないほど汚い
Parsec使ってる
HaskellやParsec特有の記号が頻出している
github
docs
コードリーディングのためのdocsが用意されていた
エントリーポイントはsrc/Compile.hs
雑な感想
全体的にめちゃくちゃキレイ
コンパイラ関係なくHaskellの書き方として参考になりそう
Generateディレクトリ内で、ASTからJSやHTMLを生成するコードが書かれている
意外と小さくてびっくりした
Errorディレクトリはエラー文の集合
Elmはエラー文が親切であることで評判も良いので参考にしたい
高度なHaskell機能もあまり使われていないので読む難易度もそこまで高くなさそう
外部ライブラリも殆ど使われておらず全部自分で書いてるのすごすぎる
Parse/Primitives.hsがparserのcoreっぽい
自作のParserモナドの定義
つまり、他のファイルでParserが最終返り値の関数は全てparse用のもの
インデントやPositionなどを計算する関数が定義されている
Positionは今パース中のそれが何行目の何列目からみたいなやつ
Parserはparsecみたいに、字句解析と構文解析を同時にやる系の実装になっているのかな
全体
code:dir
├── ContributorAgreement.pdf
├── LICENSE
├── README.md
├── builder
│   └── src
│   ├── BackgroundWriter.hs
│   ├── Build.hs
│   ├── Deps
│   ├── Elm
│   ├── File.hs
│   ├── Generate.hs
│   ├── Http.hs
│   ├── Reporting
│   ├── Reporting.hs
│   └── Stuff.hs
├── cabal.config
├── compiler
│   └── src compilerのcore. 後述
├── docs
├── elm.cabal
├── hints elm/compilerに関するdocs
│   ├── bad-recursion.md
│   ├── comparing-custom-types.md
│   ├── comparing-records.md
│   ├── implicit-casts.md
│   ├── import-cycles.md
│   ├── imports.md
│   ├── infinite-type.md
│   ├── init.md
│   ├── missing-patterns.md
│   ├── optimize.md
│   ├── port-modules.md
│   ├── recursive-alias.md
│   ├── repl.md repl
│   ├── shadowing.md
│   ├── tuples.md
│   └── type-annotations.md
├── installers
├── reactor
├── terminal
└── worker
compiler/src
code:dir
├── AST 後述
├── Canonicalize 後述
├── Compile.hs エントリーポイント
├── Data
│   ├── Bag.hs
│   ├── Index.hs toHumanという関数でindexを1始まりにしてて、名前がおもろいなと思った()
│   ├── Map
│   │   └── Utils.hs
│   ├── Name.hs Envに使うMapのKeyに当たる箇所
│   ├── NonEmptyList.hs
│   ├── OneOrMore.hs
│   └── Utf8.hs
├── Elm
│   ├── Compiler
│   │   ├── Imports.hs
│   │   ├── Type
│   │   └── Type.hs
│   ├── Constraint.hs
│   ├── Docs.hs
│   ├── Float.hs
│   ├── Interface.hs
│   ├── Kernel.hs
│   ├── Licenses.hs
│   ├── Magnitude.hs
│   ├── ModuleName.hs
│   ├── Package.hs
│   ├── String.hs
│   └── Version.hs
├── Generate ASTからJSを生成する処理
│   ├── Html.hs HTML生成箇所。Text.RawString.QQで文字列としてのHTMLを書いている
│   ├── JavaScript JSを生成。JSの予約語がまとまっていたりする
│   │   ├── Builder.hs JSのAST定義がある
│   │   ├── Expression.hs
│   │   ├── Functions.hs
│   │   └── Name.hs
│   ├── JavaScript.hs
│   └── Mode.hs
├── Json
│   ├── Decode.hs
│   ├── Encode.hs
│   └── String.hs
├── Nitpick
│   ├── Debug.hs
│   └── PatternMatches.hs
├── Optimize
│   ├── Case.hs
│   ├── DecisionTree.hs
│   ├── Expression.hs
│   ├── Module.hs
│   ├── Names.hs
│   └── Port.hs
├── Parse
│   ├── Declaration.hs
│   ├── Expression.hs
│   ├── Keyword.hs
│   ├── Module.hs
│   ├── Number.hs
│   ├── Pattern.hs
│   ├── Primitives.hs Parserのcoreっぽい. Parserモナドの定義など
│   ├── Shader.hs
│   ├── Space.hs whitespaceやコメントなどのparse
│   ├── String.hs
│   ├── Symbol.hs
│   ├── Type.hs
│   └── Variable.hs
├── Reporting
│   ├── Annotation.hs
│   ├── Doc.hs かの有名な循環参照のエラー文とかこの中にある(circle)
│   ├── Error 配下にエラー文などが定義されている
│   │   ├── Canonicalize.hs
│   │   ├── Docs.hs
│   │   ├── Import.hs
│   │   ├── Json.hs
│   │   ├── Main.hs
│   │   ├── Pattern.hs
│   │   ├── Syntax.hs
│   │   └── Type.hs
│   ├── Error.hs
│   ├── Render
│   │   ├── Code.hs
│   │   ├── Type
│   │   └── Type.hs
│   ├── Report.hs
│   ├── Result.hs
│   ├── Suggest.hs
│   └── Warning.hs
└── Type // 後述
AST
Canonical.hs
型推論のためのアノテーションとコメントがある。よくわからん
関数のASTがLambda [Pattern] Exprになっているのは、引数のパターンが複数あるため
ex. 変数、リスト、タプル..
Optimized.hs
Source.hs
たぶんElmのAST
Utils
Binop.hs
Shader.hs
Type.hs
Canonicalize
ASTの正規化をして不要な情報を取り除く
Effects.hs
Environment
Dups.hs
Foreign.hs
Local.hs
Environment.hs
Envを操作する関数群
「local」は局所的な環境のことだと思う
addLocalで、元のEnvに新しいEnvを追加している
これは関数定義したときなどに呼び出される
Expression.hs
式の正規化
Module.hs
Pattern.hs
canonicalize
Lambdaの引数の種類によってごにょごにょする関数
関数の引数にはただの変数やリストが来ることがあるが、それによってどういうenvを作るのかを決定している
Type.hs
src/Compile
4つのフェーズがある
cannonicalize
正規化
typeCheck
型検査
nitpick
あら捜し?
optimize
最適化
Type
Constrain
Expression.hs
Module.hs
Pattern.hs
Error.hs
Instantiate.hs
Occurs.hs
Solve.hs
solveが型検査をする関数なのだろうか #??
Type.hs
Constraint型の定義
Unify.hs
単一化
UnionFind.hs
terminal
code:terminal
├── impl
│   ├── Terminal
│   │   ├── Chomp.hs
│   │   ├── Error.hs
│   │   ├── Helpers.hs
│   │   └── Internal.hs
│   └── Terminal.hs
└── src
├── Bump.hs
├── Develop
│   ├── Generate
│   │   ├── Help.hs
│   │   └── Index.hs
│   ├── Socket.hs
│   ├── StaticFiles
│   │   └── Build.hs
│   └── StaticFiles.hs
├── Develop.hs
├── Diff.hs
├── Init.hs
├── Install.hs
├── Main.hs
├── Make.hs
├── Publish.hs
└── Repl.hs // Replの実装
Replのコードなどがある
Hytlでも参考にした
/read-elm-js/生成コードの関数定義と関数適用
Elmの関数のコンパイル