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

RPLは、ヒューレット・パッカード社が開発した小型電卓のオペレーティングシステム  の一部であり、アプリケーションプログラミング言語である。

"Reverse Polish"は逆ポーランド記法を意味しており、直訳するなら『逆ポーランド式LISP』となる。後置記法やスタック指向などという点ではForthとも類似している。

ヒューレット・パッカード社の科学技術計算グラフRPN電卓のHP 28 シリーズ、HP 48 シリーズ、HP 49/50 シリーズで使われた。

HP 38G、HP 39/40 シリーズのような非RPN電卓でも特殊なツールを使って使用可能であるが、後述のSystemRPLだけに限られる。

RPLはRPNに基づいた構造化プログラミング言語であるが、数値だけでなく代数式や方程式も扱える。RPLはスレッド化されたインタプリタとして実装されている。RPLはForth言語と多くの類似点がある。両言語はスタック指向であり、Lispのようなリスト指向だけではない。以前のHP社のRPN電卓に反して、RPLが使えるスタックは利用可能な電卓のRAMさえ余っていれば、スタックのレベル数を増やせる。

RPLは1984年にオレゴン州コーヴァリス市の開発拠点で誕生した。アセンブリ言語でOSを実装する以前の技術を置き換えるために開発された。RPLに対応した最後の電卓はHP 50gであり、2015年に製造終了となった。

1. RPLの種類
---------

RPLにはUser RPLとSystem RPLの2種類があり、一般的にRPLと言えば、User RPLを指す。

RPLの中でもシステムの低レベルから中レベルまでを扱うSystem RPL言語は、OSを実装する言語の一部として前述の機種だけでなくいくつかの初期のHP社電卓で使われた。HP 48 シリーズの場合、外部ツールを使わないとユーザーはSystem RPLを使用できない。しかし、HP 49/50 シリーズの場合、SysRPLを使うための内蔵コンパイラが搭載されている。誤りのあるSysRPLコードを実行すると深刻なクラッシュを引き起こす可能性がある。

RPLの一種である高レベル言語のUser RPLは、グラフィックスアプリケーションプログラムだけでなくテキスト型のプログラムを開発するために前述の電卓で利用できる。全てのUserRPLプログラムは内部的にはSysRPLで実装されている。しかし、利用可能なSysRPLコマンドの中の安全なサブセットだけを使う。UserRPLのコマンドはエラーチェックを行うので安全ではあるが、そのエラーチェックによってUserRPLプログラムはSysRPLプログラムよりも非常に動作が遅くなっている。

UserRPLコマンドのSYSEVALは、アドレスで指定された無名のオペレーティングシステムオブジェクトを評価・実行する。

2. newRPL
---------

newRPL は [1] が2014年から開発している User RPL を模倣した言語及び開発環境及びOSの総称である。HP社の正式なものではない。文法的には User RPL を拡張したものであるが、インタプリタ言語ではなくコンパイラ言語として動作するので、その実効速度は User RPL よりも圧倒的に高速である。

newRPL を使えるハードウェアは HP 48 シリーズ、HP 49/50 シリーズ ということになっていた。しかし、実際には HP 39gs/HP 40gs/HP 50g/PC が対象になっている。

newRPL を使用するにはファームウェアの全面的な書換が必要である。OSも書き換わるので、GUIも変更される。なお、HPGCC3.org 側は、HP社のファームウェアに書き戻すことができると主張している。

2017年12月15日に Build 1001 がリリースされ、α版ではなくなった。2019年1月現在CASは未対応である。

前述の対象ハードウェアが2015年に全て製造終了となっているので、別のハードウェアを開発対象に切替えるべきだという意見もある。

3. 制御構造
-------

//この節の内容は"[2]"に従っている。そのため、各項目ごとに脚注を明記しない。//

ここではUser RPLのみ解説する。System RPLはスタックベースであることを除けば、User RPLと文法が大幅に異なることに注意する必要がある。

RPLは厳密な後置記法ではなく、中置記法も取り入れており、いくつかの重要な例外は存在するものの、制御構造は標準的な中置記法の言語と類似している。これらの制御構造を実装することによって、必要な時にプログラムの内部で条件分岐やループを実行できる。

3.1. スタック
---------

RPLのスタックはインタプリタ上に実装されたソフトウェア的なものであり、CPUのスタックではない。スタックの底辺がスタックレベル1であり、電卓上では"1:"と表示される。スタックレベル番号が大きいほどスタックの上になる。スタックの出し入れ は基本的にスタックの底辺から行われる。

RPLは文中でオブジェクトに遭遇すると何も考えずにスタックにオブジェクトを入れることが動作の基本である。コマンドに遭遇したときはコマンドを実行する。条件式、数式、プログラムブロックのような実行できるオブジェクトは条件文などのコマンドが実行する場合と、EVALコマンドで意識的に実行することがある。

3.2. 条件文
--------

3.2.1. IF/THEN/ELSE/END
-----------------------

IF/THEN/ELSE/END構造は、基本的な条件分岐をサポートする。この制御構造の基本的な文法は以下のようになる。

以下の例はスタックの底辺の値が"1"であるかどうかをテストし、そうであれば、スタックの底辺を"Equal to one"に置き換える。

'////

3.2.2. IFT/IFTE
---------------

IFT 文とIFTE 文を使うことによって後置条件式を実現できる。IFTとIFTEはそれぞれ2つまたは3つのオブジェクトをスタックから取り出す。取り出した2つまたは3つのオブジェクトの最上位のオブジェクトは真偽値として評価される。もしも真ならば、上から2番目のオブジェクトはスタックに戻される。IFTEは上から3番目の"else"に相当するオブジェクトを必要とする。偽の場合、そのオブジェクトがスタックに戻される。

以下の例は、IFT文の例である。スタックの底辺から1つのオブジェクトを取り出し、それが1ならば、1を"One"に置き換える。

'//2: 0 or 11: "One"そして、IFTコマンドが上の状態のスタックから2つのオブジェクトを取り出して、上のスタックレベル2が真ならば、"One"を実行するが、"One"はただのオブジェクトなので、またスタックに入れられる。以下の例はIFTE文の例である。スタックの底辺からオブジェクトを取り出し、それが1と等しいならば、1を"One"に置き換える。それが1でない場合は、それを"Not one"に置き換える。

IFTとIFTEは引数として与えられたプログラムブロックを条件によって評価・実行することがある。その動作を利用することによって、IF/THEN/ELSE/END構造よりもさらにコンパクトな条件文を作ることができる。

以下の例はスタックの底辺からオブジェクトを取り出して、それが1と等しいのか、1より小さいのか、1より大きいのかを判断してからそれを"One"、"Less"、"More"のどれかに置き換える。

'//プログラムブロックでも実行しないでスタックに入れる。そのため、プログラムブロックは評価されるまで実行されない。そのため、IFTEが実行される直前のスタックの状態は以下のようになる。3: 0 or 12: « DROP "One" »1: « 1 < "Less" "More" IFTE »IFTE文はスタックから3つのオブジェクトを取り出す。条件式の結果が真のときは"then"に対応するプログラムブロックを評価する。その結果、オブジェクトはプログラムブロックなので実行される。結果が偽の場合は、"else"に対応するプログラムブロックを評価し、プログラムブロックなので実行する。

3.2.3. CASE/THEN/END
--------------------

CASE/THEN/END構造を用いて、複数の条件から排他的に1つの条件を選ぶ、より複雑な条件論理式を実行できる。CASE文の中の1つだけの選択肢が実行される。この構造の基本文法は以下のようになる。

以下のコードはCASE/THEN/END構造の使用方法の例である。スタックの底辺にある1文字を取得して、それに対応する文字列をそれと置き換える。対応する文字がない場合は"Unknown letter"で置き換える。 上記のコードは以下の入れ子になったIF/THEN/ELSE/END構造と完全に等価である。

3.3. ループ文
---------

3.3.1. FOR/NEXT
---------------

FOR/NEXT構造は、あるインデックス値から他のインデックス値までのループをサポートする。ループ用のインデックス値はループ内でプログラムからアクセス可能な一時的ローカル変数に格納される。FOR/NEXT構造の文法は以下のようになる。

以下の例は1から10までの数値を合計するためにFORループを使っている。FORループのインデックス変数は"I"である。

'//

3.3.2. START/NEXT
-----------------

START/NEXT構造は、開始インデックスから終了インデックスまでの単純なループをサポートする。FOR/NEXT構造と違って、インデックス変数はプログラムから利用できない。しかし、インデックス変数は内部的に存在する。NEXTコマンドはインデックス変数を+1するだけである。START/NEXT構造の文法は以下のようになる。

3.3.3. FOR/STEPとSTART/STEP
--------------------------

FOR/NEXTとSTART/NEXTは1回のループでインデックス変数を+1することしかできない。しかし、NEXTを増分値とSTEPで置き換えると、インデックス変数は+1以外の値で増やしたり減らしたりできる。例えば、以下のループはインデックス変数を1回のループ毎に-2加算することによって、10から2へ逆行するようにループする。

3.3.4. WHILE/REPEAT/END
-----------------------

WHILE/REPEAT/END構造は、ループの開始地点で条件テストをする回数未定のループをサポートする。WHILE/REPEAT/END構造の文法は以下のようになる。

3.3.5. DO/UNTIL/END
-------------------

DO/UNTIL/END構造は、ループの最後で条件テストをする回数未定のループをサポートする。DO/UNTIL/END構造の文法は以下のようになる。

4. 出典
-----

5. 参考文献
-------

author= [3]
author= [4]
author= 

6. 外部リンク
--------

url=http://www.rpl2.net 
url=http://hpgcc3.org/projects/newrpl