見出し画像

【日記を書く33日目】mini-typescriptのコードを眺めてみる2

れみです。

昨日に続いてコードを眺めていきます。

昨日の記事

昨日は、字句解析と構文解析の処理からASTを取得するところまで見ることができました。そして、その次の処理は、ASTを受け取って何かをチェックするbindという処理から見ていきます。

bind.ts

bindの処理も比較的簡単です。ASTのトップレベルはModuleであり、ModuleはStatementのArrayを持っていることは、昨日確認しました。そのStatementのArrayの要素、つまり、Moduleに含まれるStatement1つ1つに対し、bindStatementという処理を実行しています。

では、bindStatementで何をしているかですが、Moduleに含まれるlocalsを更新しています。localsはMap<string, Symbol>という型になっています。Symbolはプリミティブ型のsymbolではなく、以下のような定義となっています。

type Symbol = { 
    valueDeclaration: Declaration | undefined
    declarations: Declaration[] 
}

これがなんなのかですが、おそらくは環境だと思います。環境というのは、それ以降で式を評価する際に使う環境です。ただし、今のままの言語ではスコープという概念が存在しないため、すべての式の評価で使える環境でしょうか。

対象となるModuleに含まれるすべての宣言とそれに対応する値が、localsに含まれます。また、スコープ内に同名の変数宣言が存在するかどうかも、bindの処理の中でわかります。コードでは、errorとして、その場所とエラー内容が記録されるようです。

bindではASTの中に環境を作る、ということをやっていました。

check.ts

次はcheckという処理です。やはりやっていることは型チェックですね。ただ、この処理は、Moduleを受け取って、TypeのArrayを返す関数になっていました。

export function check(module: Module) {
    return module.statements.map(checkStatement)

    function checkStatement(statement: Statement): Type {
        // ...
    }
}

ということは、すべてのstatementに対応する型がここで手に入ることになります。初めての発見は、変数宣言というstatementに対応する型は、その変数の型が返ってくるようです。まあわかります。ただ、この後出てくるであろうif statement(そもそもstatementなのか?)とかの型はそうやって扱うんだろう。ちょっと考えてみます。

注意点としては、現状のコードでは、checkの呼び出しもと、つまりcompileの処理の中で、このcheckの結果を捨てていることです。エラーは記録されているので、型に不整合があればそれが記録されますが、これら確認済みの型情報は使われてないことになります。確かに、この後の処理のことを考えたら、必要ないのかもしれませんが、実際のTypeScriptではどうなってるんでしょう。

transform.ts

次はtransformの処理です。構文解析を終えて、環境を持ったASTがtransformの対象になります。

やっていることは簡単で、やはりTypeScriptのASTから純粋なJavaScriptのASTを作っているようです。具体的には型定義と型注釈を取り除くようです。コメントに書いてありますし、コードを読んでも確かにそうなっているようです。現段階での言語の仕様的に、まだ型定義しか存在せず、型定義を取り除く処理となっていました。

注意点としては、StatementのArrayを受け取り、StatementのArrayを返しています。つまり、環境は必要としていません。当然といえば当然ですが。環境は、今の所、1つ前の処理、checkで変数に対応する値を解決するために使われてましたが、AST上は不要の情報です。

emit.ts

最後は、transformした結果、つまりStatementのArrayを受け取って、JavaScriptのコードを返す処理です。

中を読んでも、ASTからコードを作っているだけでした。

ただ、この処理はJavaScriptのコードを作るのではなく、TypeScriptのコードを作る処理になってました。この段階ではASTに型注釈や型定義は含まれないはずなので、入ってても通ることはないと思うのですが、おそらく何かと共用なんでしょう。



まだ、変数定義しかできない言語のcompile処理を読んできましたが、面白かったです。ここからどんどん追加していくことになるのは、ワクワクしますね。コツコツ遊びながらやってみようと思います。

では今日はここまで。


この記事が気に入ったらサポートをしてみませんか?