Pxem
この記事の主題はウィキペディアにおける独立記事作成の目安を満たしていないおそれがあります。 (2017年10月) |
Pxemは2008年にぬこ[1][注釈 1]によって作られたジョーク向け難解プログラミング言語である。実用言語ではない。 なお、「Pxem」と言う名前については、特に意味は無く、ただキーボードで打ちやすいというだけである[要出典]。
ファイル名をもコードとして解釈する特徴により、0バイトでのプログラミングを可能にするとして紹介されている[1]。元々はコードゴルフ用に設計された[2]。
本家ページにアクセスできなくなる2012年頃までは本家ページでC++により開発されたインタプリタが公開されていた。その後約6年間、そのインタプリタの入手が不可能となっていたが、2018年9月に、作者のブログにおいてオリジナルインタプリタのソースコードが再公開された[2]。
言語仕様
[編集]Pxemのプログラムは、二つのレジスタを持つ仮想機械で処理される。片方は整数型のスタック、もう片方は同じく整数型で、データを保持しているかどうかを区別し、ただ一つの値を保持する一時領域用のレジスタである。プログラム起動時、どちらも空の状態で初期化される。
このプログラミング言語はファイル名をメインルーチン、ファイルの中身をサブルーチンとして解釈する。そのため最初はファイル名の最初の文字から順に実行される。ファイル名の最後まで実行、またはファイル名上の終止コマンド.d
を実行した際にプログラムが終了される。この際ファイルの中身を処理するコマンドがファイル名にない、または実行されないとファイルの中身は無視される。
ファイル名上でサブルーチン実行コマンド.e
を実行すると新たな仮想機械が作成され、その機械上でサブルーチンが実行される[注釈 2]。この際、その機械のレジスタについて、
- スタックは元の機械のスタックからコピーされる。
- 一時領域用のレジスタは何も保持されない状態で初期化される。
サブルーチンの処理終了は終止コマンド.d
が実行される場合、またはファイルの中身を解釈し終えた場合に行われる。サブルーチン終了時、前の仮想機械上でサブルーチン呼び出し元のルーチンを処理する。この際、呼び出されたサブルーチンを処理していた仮想機械について、
- スタック内のデータは元の機械のスタックに、底から最上位までの順にプッシュされる。
- 一時領域用のレジスタのデータは破棄される。
コマンドである部分が解釈される際、それより前にコマンド以外の部分がある場合、その部分が文字列として解釈され、スタックに逆順にプッシュされる。
例えばファイル名がHello, world!.pxe
であるファイルでインタプリタを実行した場合は、コマンドである部分は.p
の部分で、それより前のHello, world!
という部分が文字列として解釈され、スタックに!
、d
、l
、r
、o
、w
、
、,
、o
、l
、l
、e
、H
、の順にプッシュされる。その後、.p
というコマンドは「スタックが空になるまでポップし、ポップした値を文字として出力する」ため、結果として"Hello, world!"と出力される[1]。なお、.pxe
のxe
もスタックにプッシュされるが、そのままプログラムが終了する。
制御構造
[編集]制御構造として条件制御ループのみが使用できる。それらの内容は次の通りである。
コマンド | 処理内容 | C言語での表現 |
---|---|---|
.w 、.a |
スタック内に何もない、またはスタックから値を一つポップしてその値がゼロでない間、その二コマンド間の処理内容を実行し続ける。 | while(stackIsEmpty()||stackPop()!=0){
// 処理内容
}
|
.x 、.a |
スタック内に値が一つだけある、スタック内に何もない、またはスタックから値を二つポップ(ポップした順にx、yとする)してxがyより小さい間、その二コマンド間の処理内容を実行し続ける。 | while(1){
if(stackHasMoreThanTwo()){
int x=stackPop();
int y=stackPop();
if(!(x<y))
break;
}
// 処理内容
}
|
.y 、.a |
スタック内に値が一つだけある、スタック内に何もない、またはスタックから値を二つポップ(ポップした順にx、yとする)してxがyより大きい間、その二コマンド間の処理内容を実行し続ける。 | while(1){
if(stackHasMoreThanTwo()){
int x=stackPop();
int y=stackPop();
if(!(x>y))
break;
}
// 処理内容
}
|
.z 、.a |
スタック内に値が一つだけある、スタック内に何もない、またはスタックから値を二つポップ(ポップした順にx、yとする)してxがyと等しくない間、その二コマンド間の処理内容を実行し続ける。 | while(1){
if(stackHasMoreThanTwo()){
int x=stackPop();
int y=stackPop();
if(x==y)
break;
}
// 処理内容
}
|
演算
[編集]算術演算を行う五つのコマンドが利用可能で、それらは.+
、.-
、.!
、.$
、.%
(順に加算、減算、乗算、除算(商を得る)、剰余演算)である。どれも、スタック最上位二つのデータに関して行われ、結果がスタックにプッシュされる。このうち減算、除算、剰余演算はどちらが上位にあるのかに関係なく、大きい値を小さい値で減算、除算、剰余演算する。またゼロ除算については明確な仕様がない。
乱数
[編集]乱数を生成するコマンドとして.r
が利用可能である。
実例
[編集]Hello, worldを出力する場合
[編集]Hello world を出力するには、ファイル名をHello, world!.pxe
とする[1]。ファイルの中身は任意。このためファイルのサイズを0とすることも可能である。
Fizzbuzzを出力する場合
[編集]Fizzbuzz を出力するには、ファイル名をak.-akbuzz.-ak4.-akfizz.-ak2.-1.p05.-.tab.z01.-.c.m.+.c.t05.-.%.w.s01.-.m03.-.%.W.s.m.nak.-.p00.-.c.c.c.a.wak.-fizz.p00.-.c.c.a.a.w01.-.m03.-.%.w.sak.-buzz.p00.-.c.c.a.wak.-fizzbuzz.p00.-.c.a.a.md2.-02.-.!.a.d.pxe
とする[1][3]。ファイルの中身は任意である。
実装
[編集]Pxemのインタプリタはもともと、設計者のページ[1]で"pxemi.exe"として公開されていた。同ページのサイト消失後は新たなサイトでソースコードが配布されている[2]。
また、コードジェネレータ"text2pxem.pl"[4]も配布されていた。こちらはテキストファイルをPxemのコードファイルに変換するツールである。こちらも、新たなサイトで配布されている[2]。
脚注
[編集]注釈
[編集]出典
[編集]- ^ a b c d e f Pxem(web.archieve.org、2012年6月5日) - http://cfs.maxn.jp/neta/pxem.php
- ^ a b c d Pxemの思い出
- ^ fizzbuzz in pxem(web.archive.org、2016年7月31日) - http://www.owlab.org/pxem/fizzbuzz.html
- ^ pxem(Wayback Machine、2016年8月9日) - http://www.owlab.org/pxem/
外部リンク
[編集]- Pxem(web.archieve.org、2012年6月5日) - http://cfs.maxn.jp/neta/pxem.php - 元の紹介ページ。言語の仕様が紹介されているが、所々が曖昧にされている。
- Pxemの思い出 - 新しい紹介ページ。このページにおいて"pxemi.7z"、"text2pxem.pl"の名でインタプリタのソースコードと、テキストファイルをPxemのファイルに変換するツールが公開されている。