annotate paper/chapter/02-perl.tex @ 8:4eb9702d1ed7

...
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Tue, 26 Jan 2021 16:44:45 +0900
parents ff17a9f0ea9a
children 6e33e74d378f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
1 \chapter{GearsOSのトランスコンパイラ}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
2
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
3 GearsOSはCbCで実装を行う。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
4 CbCはC言語よりアセンブラに近い言語であるため、 すべてを純粋なCbCで記述しようとすると記述量が膨大になってしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
5 またノーマルレベルの計算とメタレベルの計算を、全てプログラマが記述する必要が発生してしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
6 メタ計算では値の取り出しなどを行うが、 これはノーマルレベルのCodeGearのAPIが決まれば一意に決定される。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
7 したがってノーマルレベルのみ記述すれば、 機械的にメタ部分の処理は概ね生成可能となる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
8 また、メタレベルのみ切り替えたいなどの状況が存在する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
9 ノーマルレベル、メタレベル共に同じコードの場合は記述の変更量が膨大であるが、 メタレベルの作成を分離するとこの問題は解消される。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
10
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
11 GearsOSではメタレベルの処理の作成にPerlスクリプトを用いており、 ノーマルレベルで記述されたCbCから、 メタ部分を含むCbCへと変換する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
12 変換前のCbCをGearsCbCと呼ぶ。
2
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13
8
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
14 \section{トランスコンパイラ}
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
15 プログラミング言語から実行可能ファイルやアセンブラを生成する処理系のことを、一般的にコンパイラと呼ぶ。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
16 特定のプログラミング言語から別のプログラミング言語に変換するコンパイラのことを、 トランスコンパイラと呼ぶ。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
17 トランスコンパイラとしてはJavaScriptを古い規格のJavaScriptに変換するBabel\cite{babel}がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
18
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
19 またトランスコンパイラは、変換先の言語を拡張した言語の実装としても使われる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
20 JavaScriptに強い型制約をつけた拡張言語であるTypeScriptは、 TypeScriptから純粋なJavaScriptに変換を行うトランスコンパイラである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
21 すべてのTypeScriptのコードはJavaScriptにコンパイル可能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
22 JavaScriptに静的型の機能を取り込みたい場合に使われる言語であり、 JavaScriptの上位の言語と言える。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
23
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
24 GearsOSはCbCを拡張した言語となっている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
25 ただしこの拡張自体はCbCコンパイラであるgcc、 llvm/clangには搭載されていない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
26 その為GearsOSの拡張部分を、等価な純粋なCbCの記述に変換する必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
27 現在のGearsOSでは、 CMakeによるコンパイル時にPerlで記述された\texttt{generate\_stub.pl}と\texttt{generate\_context.pl}の2種類のスクリプトで変換される。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
28
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
29
2
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 \section{GearsCbCの雛形生成}
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 Interfaceとそれを実装するImplの型が決定すると、最低限満たすべきCodeGearのAPIは一意に決定する。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 ここで満たすべきCodeGearは、Interfaceで定義したCodeGearと、 Impl側で定義した privateなCodeGearとなる。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 例えばStack Interfaceの実装を考えると、各Implで\texttt{pop}, push, shift, isEmptyなどを実装する必要がある。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 従来はプログラマが手作業でヘッダーファイルの定義を参照しながら\texttt{.cbc}ファイルを作成していた。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 手作業での実装のため、 コンパイル時に次のような問題点が多発した。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 \begin{itemize}
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 \item CodeGearの入力のフォーマットの不一致
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 \item Interfaceの実装のCodeGearの命名規則の不一致
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 \item 実装を忘れているCodeGearの発生
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 \end{itemize}
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 特にGearsOSの場合はPerlスクリプトによって純粋なCbCに一度変換されてからコンパイルが行われる。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 実装の状況とトランスコンパイラの組み合わせによっては、 CbCコンパイラレベルでコンパイルエラーを発生させないケースがある。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 この場合は実際に動作させながら、gdb, lldbなどのCデバッガを用いてデバッグをする必要がある。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 またCbCコンパイラレベルで検知できても、すでに変換されたコード側でエラーが出てしまうので、トランスコンパイラの挙動をトレースしながらデバッグをする必要がある。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 Interfaceの実装が不十分であることのエラーは、 GearsOSレベル、最低でもCbCコンパイラのレベルで完全に検知したい。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 Interfaceを機能として所持している言語の場合、これらはコンパイルレベルか実行時レベルで検知される。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 例えばJavaの場合はInterfaceを満たしていない場合はコンパイルエラーになる。
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 InterfaceのAPIを完全に実装するのを促す仕組みとして、Interfceの定義からエディタやツールが満たすべき関数と引数の組を自動生成するツールがある。
6
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
58
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
59 Javaでは様々な手法でこのツールを実装している。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
60 Microsoftが提唱しているIDEとプログラミング言語のコンパイラをつなぐプロトコルにLanguage Serverがある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
61 Language Serverはコーディング中のソースコードをコンパイラ自身でパースし、 型推論やエラーの内容などをIDE側に通知するプロトコルである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
62 主要なJavaのLanguage Serverの実装であるeclipse.jdt.ls\cite{eclipse.jdt.ls}では、 LanguageServerの機能として未実装のメソッドを検知する機能が実装されている。\cite{eclipse.jdt.pull322}
8
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
63 この機能を応用してvscode上から未実装のメソッドを特定し、 雛形を生成する機能がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
64 他にもIntelliJ IDEなどの商用IDEでは、 IDEが独自に未実装のメソッドを検知、雛形を生成する機能を実装している。
6
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
65
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
66
2
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 golangの場合は主に\texttt{josharian/impl}\cite{golang_impl}が使われている。
6
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
68 これはインストールすると\texttt{impl}コマンドが使用可能になり、 実装したいInterfaceの型と、 Interfaceを実装するImplの型(レシーバ)を与えることで雛形が生成される。
2
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 主要なエディタであるvscodeのgolangの公式パッケージである\texttt{vscode-go}\cite{vscode-go}でも導入されており、 vscodeから呼び出すことが可能である。
6
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
70 vscode以外にもvimなどのエディタから呼び出すことや、 シェル上で呼び出して標準出力の結果を利用することが可能である。
2
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72
4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
73 GearsOSでも同様のプログラマ支援ツールを導入したい。
6
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
74 LanguageServerの導入も考えられるが、 今回の場合はC言語のLanguageServerをCbC用にまず改良し、 さらにGearsOS用に書き換える必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
75 現状のGearsOSが持つシンタックスはCbCのシンタックスを拡張しているものではあるが、これはCbCコンパイラ側には組み込まれていない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
76 LanguageServerをGearsOSに対応する場合、 CbCコンパイラ側にGearsOSの拡張シンタックスを導入する必要がある。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
77 CbCコンパイラ側への機能の実装は、 比較的難易度が高いと考えらる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
78 CbCコンパイラ側に手をつけず、 Interfaceの入出力の検査は既存のGearsOSのビルドシステム上に組み込みたい。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
79
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
80 対してgolangの\texttt{impl}コマンドのように、 シェルから呼び出し標準出力に結果を書き込む形式も考えられる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
81 この場合は実装が比較的容易かつ、 コマンドを呼び出して標準出力の結果を使えるシェルやエディタなどの各プラットフォームで使用可能となる。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
82 先行事例を参考に、コマンドを実行して雛形ファイルを生成するスクリプトをGearsOSに導入した。
4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
83
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
84
2
e543ba9a8e5c from git
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 Interfaceでは入力の引数がImplと揃っている必要があるが、 第一引数は実装自身のインスタンスがくる制約となっている。
4
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
86 実装自身の型は、Interface定義時には不定である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
87 その為、 GearsOSではInterfaceのAPIの宣言時にデフォルト型変数\texttt{Impl}を実装の型として利用する。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
88 デフォルト型\texttt{Impl}を各実装の型に置換することで自動生成が可能となる。
6
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
89
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
90
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
91 実装すべきCodeGearはInterfaceとImpl側の型を見れば定義されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
92 \texttt{\_\_code}で宣言されているものを逐次生成すればよいが、 継続として呼び出されるCodeGearは具体的な実装を持たない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
93 GearsOSで使われているInterfaceには概ね次の継続である\texttt{next}が登録されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
94 \texttt{next}そのものはInterfaceを呼び出す際に、入力として与える。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
95 その為各Interfaceに入力として与えられた\texttt{next}を保存する場所は存在するが、 nextそのものの独自実装は各Interfaceは所持しない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
96 したがってこれをInterfaceの実装側で明示的に実装することはできない。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
97 雛形生成の際に、入力として与えられるCodeGearを生成してしまうと、プログラマに混乱をもたらしてしまう。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
98
7
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
99 入力として与えられているCodeGearは、Interfaceに定義されているCodeGearの引数として表現されている。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
100 コードに示す例では、\texttt{whenEmpty}は入力して与えられているCodeGearである。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
101 雛形を生成する場合は、入力として与えられたCodeGearを除外して出力を行う。
6
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 4
diff changeset
102
7
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
103
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
104 雛形生成では他にコンストラクタの生成も行う。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
105 コンストラクタはデフォルトでは変数は0、またはNULLで初期化される。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
106 このスクリプトで生成されたコンストラクタは\texttt{generate\_stub.pl}内でも自動的に生成することが可能である。
anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
107 そのため、 オーバーライドする必要がない場合は削除しても問題なく動作するようになっている。