ならば

2010-05-30 ハッカーと作曲家

[]楽譜でプログラミングする言語Scorlang

はじめに

楽譜はソースコードというエントリを書いて以来、楽譜を使ったプログラミング言語という漠然とした考えが頭の片隅にあった。ModanShogiを見ていたら頭の片隅から開放したくなったので具体化した。

楽譜プログラミング言語Scorlang(Score language)。ジャンルとしてはビジュアル難解プログラミング言語*1になる。
Scorlangのプログラムは、楽譜のように見える図形で表現される。例えば、下の図は「Hello, world!」を出力するプログラムである。

f:id:naraba:20100530124734p:image:w600


言語仕様

最初に強調しておくが、Scorlangは音響プログラミング言語ではないので、音響信号を扱ったり音を入出力するための仕様は一切ない。扱えるデータは整数のみ、出力形式はテキストのみである。

ひとつのプログラムをシートと呼ぶ。シートは原則的に、音楽の楽譜と同じく左から右、上から下に向かって処理が描かれており、実行もその順に行われる。それぞれの要素(記号)の記法も特記しない限り音楽の楽譜と同じ。
以下ではシートを構成する要素に分けて、音楽用語を濫用しながらあくまで言語仕様をざっと説明する。単に「楽譜」と書いた場合は音楽の楽譜を意味する。

五線譜

空のシート。この上に処理を描く。音符の音高によっては五線の上や下に加線を引く必要がある。

f:id:naraba:20100530124902p:image

音部記号

音部記号によって、五線譜に置かれた音符の音高が決まる。五線譜の最初にト音記号(バイオリン記号)またはヘ音記号(バス記号)のどちらかで指定する。

f:id:naraba:20100530125010p:image

小節

拍子記号に従って、一定の拍(時間単位)の数(音符や休符が示す音の長さの合計値)でシートを区切ったかたまり。テキストで記述するプログラミング言語の「行」に似た概念だと思えばいいかもしれない。

小節の終わりには小節線を置く。シートの最後の小節であれば小節線の代わりに終止線を置く。反復記号で小節線や終止線を置き換えることもある。

f:id:naraba:20100530125054p:image

拍子記号

小節の始めに置いて、その小節内の拍の数を指定する。省略した場合は前の小節の指定を引き継ぐ。最初の小節では、音部記号に続いて必ず指定しなければならない。拍子と書いてはいるが、西洋音楽の強拍・弱拍に相当する言語的概念はなく、小節というかたまりを作るためだけの仕様。

f:id:naraba:20100530125139p:image

音符

音高に従って、数値リテラルをスタックにプッシュする命令。

各音符の音高はその音名の英語表記(C、D、E、F、G、A、Bのいずれか)を十七進法表記*2としたときの数を表す。つまり0や1を差し置いて、整数の10(A)から16(G)だけをリテラルとして表現できる。
スタックは複数あり、オクターブの違いによってプッシュするスタックを変えることができる。下の図はオクターブとスタックの対応関係を表す。例えば、ピアノの中央のCを表す音符(下の図でト音記号のすぐ右にある音符)はC4スタックに12をプッシュする命令である。

f:id:naraba:20100530125212p:image:w600

なお、音価(音の長さ)は楽譜と同様に指定できるが、処理には影響を与えない。この仕様は読みやすさや描きやすさ、見栄えを調整するために音価が使われることを想定している。テキストで記述するフリーフォーマットなプログラミング言語の「スペース」や「タブ」に似た役割を持つと思えばいいかもしれない。ただし、前述の通り、小節内の拍の数は拍子記号の指定に従う必要がある。

変化記号

演算子。変化記号を付した音符の音高が表す数値リテラルXと、その音高に対応するスタックからポップした値Yとで演算を行い、結果を元のスタックへプッシュする。演算子は2種類ある。

演算子のスコープというか効力は楽譜における変化記号の効力と同じであり、言語仕様としては怪奇的である。つまり、変化記号が付いた音符より後かつ同一小節内にある同じ音高の音符についても変化記号が付いているものと解釈され、演算が行われる。なお、この効力によって本来付けずに済む音符に変化記号を付けても動作に影響はない。
上記の効力を解消し、同一小節内に後続する同じ音高の音符を単一のプッシュ命令に戻すための命令としてナチュラルがある。

f:id:naraba:20100530125259p:image

休符

直前にプッシュまたはポップしたスタックからポップし、その値をUnicodeのコードポイントとしたときの文字を出力する命令。値がUnicodeのコードポイントの範囲にない場合の動作は未定義。休符の音価の扱いは音符のそれと同じである。

f:id:naraba:20100530125344p:image

反復記号

制御文。C言語のwhile文に相当する。小節線または終止線の代わりに置くことができる。ネストできる。

「||:」は、直前にプッシュまたはポップしたスタックのトップの値が0以外であれば処理を続行する。0の場合は「||:」に対応する「:||」の次の小節へジャンプする。
「:||」は、対応する「||:」に戻る。「:||」に対応する「||:」がない場合は楽譜と同様に最初に戻って処理を続ける。

f:id:naraba:20100530125414p:image

残念ながらこの仕様では、シートをScorlangのプログラムとして実行した場合と楽譜とみなして演奏した場合とでは繰り返し部分を通る回数が一般に一致しない。

タイトル、作曲者、歌詞

コメント。ここだけはテキストで記述できる。

タイトルにはシートに描かれた処理の名前、作曲者にはシート作成者の名前、歌詞には処理に関する注釈を書くことが推奨されるが、何を書いても処理自体に影響はないし、何も書かなくても良い。小節線をまたがる(文字が分割される)歌詞を書くことはできない。

おわりに

ここまで書いたら本当は処理系も用意しておくべきなんだろうけど、ない。かなり単純化してるとはいえ楽譜作成ソフト相当のものを作る時間と気力と能力がなかった。

Scorlangはチューリング完全だと思う(願望)。

*1:このジャンルには他にPietという言語がある

*2:十六進法だと綺麗(?)だったんだけど、音名がGまであるから仕方ない