レポジトリ:https://doss-gitlab.eidos.ic.i.u-tokyo.ac.jp/utability
slide: 未作成
プロジェクト概要
TypeScriptに「====」の評価を実装する。
動作イメージはjson的なオブジェクトの中身の比較(暫定)
現在はTypeScriptコードベースのデバッグ環境構築段階。
TypeScript V4.5.0 -devをインストールした。
Microsoft/TypeScriptのmainブランチ:https://github.com/microsoft/TypeScript
TypeScript フォルダ内のREADMEにしたがってビルドした。
推奨されているコマンドを使用すると、TypeScript/built/local内にビルドされる。
ビルドには成功したので、次はvscodeにtypescript用のデバッガーを準備する。
https://github.com/denoland/deno/issues/1404
上のissueによるとTypescriptはgdbでデバッグできないので、vscodeにビルドインされているTypescriptのデバッグ機能を使用する。
Debugging Typescript(公式ドキュメント):
https://code.visualstudio.com/docs/typescript/typescript-debugging
Debugging the TypeScript Codebase(Typescriptのコンパイラをデバッグする方法について): https://blog.andrewbran.ch/debugging-the-type-script-codebase/
お互いデバッグ環境を構築するのに苦戦したので次回までに終わらせたい。
(10/13追記) コンパイラをデバッグできるようになった。
.vscodeフォルダ内のlaunch.template.jsonファイルをコピーし、launch.jsonとして.vscodeフォルダ内に配置
下記bashコードによりデバッガーlisten状態にする
vscodeの虫マークのデバッグツールタグから、"Attach to VS Code TS Server via Port"を選択して実行。これはlaunch.jsonに記述されているもの。
よくわかんないけどなにかが動く。動いてるものが本当にコンパイル過程なのかは知らない。
デバッグできるようになったので今日から実際にコンパイラの中身を見ていくことにする。
scanner.ts 165行目 textToTokenが怪しい?
1609行目 scan関数で文章解析?
tsc.ts で実行される
performCompilation()
字句解析と構文解析の該当場所を意識。
字句解析→Token, 構文解析→Parserがキーワードか。
コード全体に対し、"EqualsEqualsEqualsToken"と検索すると、該当しそうな箇所がたくさん出てきた。
types.ts :
scanner.ts :
parser.ts :
src>services>classifier.ts
src>services>codefixs>interFromUsage.ts
src>compiler>factory>utilities.ts
src>compiler>utilities.ts
src>services>utilities.ts
createStrictEquality"も大事そう。
nodefactory.ts :
462行目 factory methodの呼び出し
getってどういう意味だっけ。あとcreateStrictEquality()どこで使ってるのかあとで確認
asTokenの中身はCreateToken
973行目 CreateToken()
中身はcreateBaseToken()
CreateBaseTokenの中身はCreateBaseTokenNode
createStrictEqualityの使いどころ
typescript独自のclass構文をfunction構文に書き換えてる部分
src>compilers>transformers>classFields.ts
よくわかんないけど
src>services>refactors>convertToOptionalChainExpressions.ts
上記で列挙した場所が全てではない。
ソースコード内で"EqualsEqualsEqualsToken"と検索して、出てきたsrcファイルないのすべての場所で"EqualsEqualsEqualsEqualsToken"を追加した。
またscannerでは、====を一つのTokenとして認識できるように書き換え
さらに、Token定義では、数字を割り当て。
あとは、tsにおける====文を、適切なjsテンプレートに置き換える。
class構文→function構文の変換を参考にしたい
調べると、??はQuestionQuestionTokenとして定義されているようだ
nodeFactory.ts 2784行目
propagateChildFlagsとはなにか、es2020の中身、Transformflagsオブジェクトの中身が気になる。
まずはES2020に関連ありそうなものを見る。
src>compiler>transformers>es2020.ts 38行目
transformNullishCcoalescingExpression()怪しい
同es2020.ts 196行目
createNotNullConditionが怪しい
同じくes2020.ts 180行目
全体の流れとして、
emit()がtransformES2020()を呼び出し
transformES2020()が内部関数visitor()を呼び出し
visitor()が条件分岐の中で、transformNullishCoalescingExpression()を呼び出している。
transformNullishCoalescingExpression -> visitor -> transformES2020 ->
getScriptTransformers -> scriptTransformers in getTransformers -> emitFiles in emitter.ts
nodefactory.ts のcreateBinaryExpressionを編集。operatorKindがEqualsEqualsEqualsEqualsTokenのときにES2020を参照するよう結びつける
es2020.ts内のtransformES2020関数内のvisitor関数を編集。EqualsEqualsEqualsEqualsTokenの時に、transformObjectEqualsExpressionを行うと定義。
es2020.ts内のtransformES2020関数内に、新たな内部関数として前述のtransformObjectEqualsExpression()を追加。とりあえず中身は、"??"の処理を行うtransformNullishCoalescingExpression()と全く同じにした。
目標は、自分たちが欲しいかたちを自由に出力することだが、まだ関数の構造がわからないので試行錯誤
上記のように関数を変更すると、コンパイルは以下のようになった
実際に「====」を目的の処理ができる形にコンパイルできるように、transformObjectEqualsExpression()を変更していく。
構文木が実際にどのようにしてjsファイルに出力されているかは完全にわかっているわけではないが、中身はNodeという単位で管理されており、出力されるコードとNodeは一対一に対応していることがわかった。
(例)
createVariableStatement: 変数定義
createForStatement: for文生成
createPrefixIncrement: インクリメント
createReturnStatement: return文生成
createTrue: True生成
これらNodeを生成するAPIを活用し、実際に出力したいコードに対応する
入れ子構造を作った。
生成されるコードは以下