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

XL1の意味論

XL1フェーズはXL0構文木に対しての一連の操作として定義されている。操作は様々なコンパイラプラグインとして提供され、それぞれ構文木の形に従って呼び出される。
あるプラグインによって、他のプラグインを楽に記述できるようにするためにtranslateとtranslationという特別な構造が提供されている。quote構造は構文木を生成する。これらの構造を用いて、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フェーズはXLSemanticsに代表されるような、沢山のプラグインを持ち、それらはプログラミングでの主な概念であるサブルーチン、データ型、変数、宣言、定義に加えて、基本的な構造化プログラミングに使う条件分岐や繰り返しを提供する。

型システム

XL1の型システムは静的型付けだが、ジェネリックプログラミングの方式がAbaやC++などの言語とは異なる。配列やポインタなどは、C++ではプリミティブ型であるが、XLではライブラリで定義される。以下に一次元配列の定義を例示する。

generic [Item : type; Size : integer] type array
有効なジェネリック型（validated generic type）とは、その型がどのように使われるかを自身で表せる型であり、このような型にはジェネリック引数が必要ない。例として、不等号を含むときに型をorderedと宣言するものを示す。

// A type is ordered if it has a less-than relationship
generic type ordered if
  A, B : ordered
  Test : boolean := A < B
これによって、ordered自身がジェネリックとなるから、潜在的にジェネリックとなる関数を定義することが可能となる。

// Generic function for the minimum of one item
function Min(X : ordered) return ordered is
  ... compute Y of type ordered ... 
  return Y
さらに、arrayのようなパラメータを持つジェネリック型にも適用できる。任意の配列(array)の和を計算する関数を以下に示す。

function Sum(A : array) return array.Item is
  for I in 0..array.Size-1 loop
    result += A[I]

型安全な引数リスト

関数は多重定義できる。関数は宣言時の引数リストに...を使うことで、可変引数を扱うことができる（当初はothetがこの目的で使われていた）。この際、...を使ってサブルーチンにそのまま引数を渡すことができる。これを可変引数テンプレートと呼ぶ。

// 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)

演算子オーバーロード

演算子は関数宣言のうちのwritten形式を使って定義することができる。以下に整数の足し算を定義するコードを示す。

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 herefor I in 1..5 loop
    IO.WriteLn "I=", I

開発状況と経緯

XLは1992年頃から長い時間をかけて開発された。最初のバージョンはクリストフ・ド・ディネシャン (en:Christophe de Dinechin)が設計し、発表した。
XLのコンパイラは最初はC++で書かれていて、上に示すような機能のほとんどは正しく実装されていた。しかし、C++自身は拡張的でないため、プラグインを書くのは難しく、translateのような構造の実装は不可能であった。構文木はさらに複雑で、他のプログラミング言語でも扱えるようにするために非常に多くの木構造を実装する必要があった。Mokaは同様の仕組みを使ったJava-to-Javaの拡張可能なコンパイラである。
他プログラミング言語対応と複雑な構文木構造を諦めて、2003年にコンパイラの再開発が始まった。構文木は七つのタイプに大幅に簡略化された。2004年にXL自身で書かれたコンパイラが完成し、それ以降の開発はすべてXLで完結している。新たなコンパイラもXL1の実装がまだ不十分であるが、すでにいくつかの点でC++を上回っている。

XLRの意味論

XLRは動的言語だが、元々はXL Runtimeの略でXL1コンパイラのバックエンドとして存在した。XLRはXL0の文法をXL1と共有しているが、動作はむしろ関数言語に近い。逆にXL1は命令型言語に近い。XLRは実質的には"->"という一つのオペレータのみを持ち、その役割は書き換えである。左側の記述が右側の記述に変化させられる。
このメカニズムを使って、標準的な式を実装する。

 if true then TrueBody else FalseBody -> TrueBody
 if false then TrueBody else FalseBody -> FalseBody