XL (プログラミング言語)

XLは（拡張可能言語）を表しており、コンセプトプログラミングに則り設計された、2016年時点で唯一のプログラミング言語である。
XLはプログラマによって再構成可能な構文と意味論を持つことを特徴としている。コンパイラ"プラグイン"を使って言語に新しい機能を追加できる。あるプラグインの基本セットは比較的標準的な命令型プログラミング言語を実装している。プログラマは独自のプラグインを書くことで、記号微分のように個々の応用に則した記法を実装し、組み込みの言語機能と同様に使用できる。
言語.
XLは4つの異なるレベルで定義されている:
XLにはプリミティブ型や予約語がない。整数や加算演算子といった、有用なデータ型と演算子は、すべて標準ライブラリ（XL2）で定義されている。XL1は異なる実行環境間で移植可能である。一方でXL2にはそのような保証はなく、もしCPUが浮動小数点数の乗算を実装していなければ、それに対応した演算子の定義は標準ライブラリから欠落しているかもしれず、また、浮動小数点数の乗算はコンパイル時エラーとなるかもしれない。
XLで書かれたHello Worldは次のようになる。
 use XL.TEXT_IO
 WriteLn "Hello World"
より大規模なプログラムにふさわしいスタイルで書かれた別のプログラムは次のようになる。
 import IO = XL.TEXT_IO
 IO.WriteLn "Hello World"
XLRでの階乗の再帰的な実装は次のようになる。
 0! -> 1
 N! -> N * (N-1)!
構文.
構文はXL0レベルで定義されている。コンパイラのXL0フェーズは、テキストの内部表現や演算子の優先順位といったプロパティが定義されている構文記述ファイルによって設定可能である。基本構文ファイルは、加算の+といった、一般的な数学の記法を、普段用いられる演算子の優先順位で定義している。
構文木は7種のノードから成る。4種の葉ノード（整数・実数・テキスト・シンボル）と、3種の内部ノード（中置・前置・ブロック）が存在する。
デフォルトの構文記述ファイルでは、意味論に関わらず、次のものはXL0による正しい記述とされる。
 A = B + "Hello"
これは、次のように構文解析される。
 infix("=",
 symbol("A"),
 infix("+",
 symbol("B"), text("Hello")))
XL1の意味論.
XL1フェーズはXL0構文木に対しての一連の操作として定義されている。操作は様々なコンパイラプラグインとして提供され、それぞれ構文木の形に従って呼び出される。
あるプラグインによって、他のプラグインを楽に記述できるようにするためにcodice_21とcodice_22という特別な構造が提供されている。codice_23構造は構文木を生成する。これらの構造を用いて、ZeroRemovalという意味のないゼロ加算とゼロ乗算を計算するプラグインを、以下に示す。
 translation ZeroRemoval
 when
 'X' + 0
 then
 return X
 when
 'X' * 0
 then
 return parse_tree(0)
プラグインはコマンドラインを使ってファイル全体に適用させることができる。また、以下のように"pragma"表記を使って、ソースコード内だけで完結させることができる。
 X := {Differentiate} d(sin(omega * T) * exp(-T/T0)) / dT
XL1フェーズはcodice_24に代表されるような、沢山のプラグインを持ち、それらはプログラミングでの主な概念であるサブルーチン、データ型、変数、宣言、定義に加えて、基本的な構造化プログラミングに使う条件分岐や繰り返しを提供する。
型システム.
XL1の型システムは静的型付けだが、ジェネリックプログラミングの方式がAbaやC++などの言語とは異なる。配列やポインタなどは、C++ではプリミティブ型であるが、XLではライブラリで定義される。以下に一次元配列の定義を例示する。
 generic [Item : type; Size : integer] type array
有効なジェネリック型（validated generic type）とは、その型がどのように使われるかを自身で表せる型であり、このような型にはジェネリック引数が必要ない。例として、不等号を含むときに型をcodice_25と宣言するものを示す。
 // A type is ordered if it has a less-than relationship
 generic type ordered if
 A, B : ordered
 Test : boolean := A < B
これによって、codice_25自身がジェネリックとなるから、潜在的にジェネリックとなる関数を定義することが可能となる。
 // Generic function for the minimum of one item
 function Min(X : ordered) return ordered is
 ... compute Y of type ordered ... 
 return Y
さらに、codice_27のようなパラメータを持つジェネリック型にも適用できる。任意の配列(array)の和を計算する関数を以下に示す。
 function Sum(A : array) return array.Item is
 for I in 0..array.Size-1 loop
 result += A[I]
型安全な引数リスト.
関数は多重定義できる。関数は宣言時の引数リストにcodice_28を使うことで、可変引数を扱うことができる（当初はcodice_29がこの目的で使われていた）。この際、codice_28を使ってサブルーチンにそのまま引数を渡すことができる。これを可変引数テンプレートと呼ぶ。
 // Generic function for the minimum of N item
 function Min(X : ordered; ...) return ordered is
 result := Min(...)
 if X < result then
 result := X
このような関数が呼び出されたとき、コンパイラは引数リストに合うように再帰的に関数を作る。
 // Examples of use of the Min just declared
 X : real := Min(1.3, 2.56, 7.21)
 Y : integer := Min(1, 3, 6, 7, 1, 2)
演算子オーバーロード.
演算子は関数宣言のうちのcodice_31形式を使って定義することができる。以下に整数の足し算を定義するコードを示す。
 function Add(X, Y: integer) return integer written X+Y
writtenを使った定義には三つ以上の引数を取ることができる。例として線型変換の行列を示す。
 function Linear(A, B, C : matrix) return matrix written A+B*C
writtenは定数も扱える。これによってより特殊な演算子を定義できる。
 function Equal(A, B : matrix) return boolean written A=B
 function IsNull(A : matrix) return boolean written A=0
 function IsUnity(A : matrix) return boolean written A=1
基本的な演算子はすべてこのメカニズムで実装される。式はwrittenを用いた関数呼び出しに集約される。よってこのメカニズムは関数オーバーロードというよりも、式削減（expressin reduction）に近い。
イテレータ.
XLイテレータはジェネレータとイテレータの両方を扱える。
 import IO = XL.UI.CONSOLE
 iterator IntegerIterator (var out Counter : integer; Low, High : integer) written Counter in Low..High is
 Counter := Low
 while Counter <= High loop
 yield
 Counter += 1
 "// Note that I needs not be declared, because declared 'var out' in the iterator"
 "// An implicit declaration of I as an integer is therefore made here"
 for I in 1..5 loop
 IO.WriteLn "I=", I
開発状況と経緯.
XLは1992年頃から長い時間をかけて開発された。最初のバージョンはクリストフ・ド・ディネシャン ()が設計し、発表した。
XLのコンパイラは最初はC++で書かれていて、上に示すような機能のほとんどは正しく実装されていた。しかし、C++自身は拡張的でないため、プラグインを書くのは難しく、codice_21のような構造の実装は不可能であった。構文木はさらに複雑で、他のプログラミング言語でも扱えるようにするために非常に多くの木構造を実装する必要があった。Mokaは同様の仕組みを使ったJava-to-Javaの拡張可能なコンパイラである。
他プログラミング言語対応と複雑な構文木構造を諦めて、2003年にコンパイラの再開発が始まった。構文木は七つのタイプに大幅に簡略化された。2004年にXL自身で書かれたコンパイラが完成し、それ以降の開発はすべてXLで完結している。新たなコンパイラもXL1の実装がまだ不十分であるが、すでにいくつかの点でC++を上回っている。
影響を受けた言語.
XL1は多くのプログラミング言語から影響を受けている。
XLRの意味論.
XLRは動的言語だが、元々はXL Runtimeの略でXL1コンパイラのバックエンドとして存在した。XLRはXL0の文法をXL1と共有しているが、動作はむしろ関数言語に近い。逆にXL1は命令型言語に近い。XLRは実質的には"->"という一つのオペレータのみを持ち、その役割は書き換えである。左側の記述が右側の記述に変化させられる。
このメカニズムを使って、標準的な式を実装する。
 if true then TrueBody else FalseBody -> TrueBody
 if false then TrueBody else FalseBody -> FalseBody