Skip to content

OpeLa Internal Design

uchan-nos edited this page Jul 20, 2021 · 23 revisions

OpeLa コンパイラの内部設計

OpeLa メインページ

C++ の機能をどこまで使うか

OpeLa コンパイラは、セルフホストを達成するまでは C++ で記述します。 C++ の素晴らしい機能、ライブラリを活用して作りたいところですが、最終的に OpeLa 言語に移植することを考えるとバランスが大切です。 移植をスムーズにするためには、OpeLa コンパイラを実装するのに利用した C++ の言語機能やライブラリを、OpeLa 言語でも実現する必要があるからです。

OpeLa 言語には、MikanOS を実装するために欲しい言語機能とライブラリを用意したいと考えています。 したがって、OpeLa コンパイラもその範囲で実装するのが良いだろうと思います。 OpeLa コンパイラ V1 は、何も制約を考えずに実装していましたが、V2 はこれらの制約を踏まえて実装します。

OpeLa コンパイラ V2 を実装するのに利用する C++ の機能を考えるために、MikanOS の実装に活用している機能、ライブラリを洗い出しました。

  • int や char 等の整数型、静的配列
  • ビット指定の整数型(uint8_t、uint64_t など)
  • グローバル変数、ローカル変数
  • 関数
  • ポインタ演算、関数ポインタ経由の関数呼び出し
  • 可変長引数 ...
  • 構造体、クラス、継承
  • ビットフィールド
  • 関数のオーバーロード
  • 演算子のオーバーロード
  • 配置new、普通のnew
  • alignas
  • インラインアセンブラ
  • 無名関数、クロージャ
  • sprintf
  • string, vector, map, deque
  • テンプレート

基本的には、上記の機能は MikanOS の実装に必要と考えられますので OpeLa 言語に搭載する方針です。一部機能は、バランスを考えて代替の機能とすることもあります。

C++ のテンプレートは複雑な機能なので、ちょっと違う形で実現しようと思っていましたが、考えを改めて実装することにしました。 →OpeLa のジェネリクスに登場する演算子の考察

したがって、これは古い記事です:C++ のテンプレートの使い方と OpeLa での代替手段の検討

Ver.2 の言語仕様

MikanOS の実装で使っている C++ の機能の洗い出し結果を踏まえ、Ver.2 の言語仕様をまとめます。 言語仕様は内部設計ではないので OpeLa 言語仕様 で扱います。

レジスタ割り当て

Ver.2 はレジスタマシンとして構成するため、どの値をどのレジスタに割り当てるかを決める「レジスタ割り当て」が重要です。 ナイーブなアルゴリズムではすぐにレジスタが足りなくなる可能性があります。 OpeLa Register Assignment で設計します。

整数のキャスト方法

整数のキャストとは uint8int64 などの整数型の間の型変換のことです。 OpeLa Type Cast で説明します。

Ver.2 の構文木データ構造

構文木のデータ構造 では、OpeLa コンパイラが内部で用いる各種のデータ構造を詳しく説明します。 AST ノードを表す Node や型を表す Type などについて知りたい方はご覧ください。

Ver.1 の設計

以下は V1 の設計です。V2 ではデータ構造が変わるかもしれません。

Type 構造体の仕様

直感的に分かるように、具体例により仕様を記述します。

配列型 kArray

配列型(kind: kArray)は、base に要素の型、num に要素数が設定される。

関数型 kFunc

関数型(kind: kFunc)は、next に引数型のリストの先頭要素、base に戻り値型が設定される。 引数型リストの最後には可変長引数を表す kVParam が来得る。

構造体型 kStruct

構造体型(kind: kStruct)は、next にフィールド型のリストの先頭要素が設定される。 フィールド型は name にフィールド名が設定される。

Clone this wiki locally