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

RPLは、ヒューレット・パッカード社（HP社）が開発した小型電卓のオペレーティングシステム (OS) の一部であり、アプリケーションプログラミング言語である（初期開発者によるとReverse Polish Lispに由来する。一方、HP社のマーケティングは1987年の短い期間の間、RPLから逆にROM-based Procedural Languageという意味をこじつけで作り出そうとした）。 "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電卓（4レベル固定スタック）に反して、RPLが使えるスタックは利用可能な電卓のRAMさえ余っていれば、スタックのレベル数を増やせる。 RPLは1984年にオレゴン州コーヴァリス市の開発拠点で誕生した。アセンブリ言語でOSを実装する以前の技術を置き換えるために開発された。RPLに対応した最後の電卓はHP 50gであり、2015年に製造終了となった。 RPLにはUser RPLとSystem RPLの2種類があり、一般的にRPLと言えば、User RPLを指す。 RPLの中でもシステムの低レベルから中レベルまでを扱うSystem RPL（もしくはSysRPL）言語は、OSを実装する言語の一部として前述の機種だけでなくいくつかの初期のHP社電卓で使われた。HP 48 シリーズの場合、外部ツールを使わないとユーザーはSystem RPLを使用できない。しかし、HP 49/50 シリーズの場合、SysRPLを使うための内蔵コンパイラが搭載されている。誤りのあるSysRPLコードを実行すると深刻なクラッシュを引き起こす可能性がある。 RPLの一種である高レベル言語のUser RPL（もしくはUserRPL）は、グラフィックスアプリケーションプログラムだけでなくテキスト型のプログラムを開発するために前述の電卓で利用できる。全てのUserRPLプログラムは内部的にはSysRPLで実装されている。しかし、利用可能なSysRPLコマンドの中の安全なサブセットだけを使う。UserRPLのコマンドはエラーチェックを行うので安全ではあるが、そのエラーチェックによってUserRPLプログラムはSysRPLプログラムよりも非常に動作が遅くなっている。 UserRPLコマンドのSYSEVALは、アドレスで指定された無名のオペレーティングシステムオブジェクトを評価・実行する。 newRPL は HPGCC3.org が2014年から開発している User RPL を模倣した言語及び開発環境及びOSの総称である。HP社の正式なものではない。文法的には User RPL を拡張したものであるが、インタプリタ言語ではなくコンパイラ言語として動作するので、その実効速度は User RPL よりも圧倒的に高速である。 newRPL を使えるハードウェアは HP 48 シリーズ、HP 49/50 シリーズ ということになっていた。しかし、実際には HP 39gs/HP 40gs/HP 50g/PC(Windows) が対象になっている。 newRPL を使用するにはファームウェアの全面的な書換が必要である（データも全て消える）。OSも書き換わるので、GUIも変更される。なお、HPGCC3.org 側は、HP社のファームウェアに書き戻すことができると主張している。 2017年12月15日に Build 1001 がリリースされ、α版ではなくなった。2019年1月現在CAS（数式処理システム）は未対応である。 前述の対象ハードウェアが2015年に全て製造終了となっているので、別のハードウェアを開発対象に切替えるべきだという意見もある。 この節の内容は"HP 50g / 49g+ / 48gII graphing calculator advanced user’s reference manual"に従っている。そのため、各項目ごとに脚注を明記しない。 ここではUser RPLのみ解説する。System RPLはスタックベースであることを除けば、User RPLと文法が大幅に異なることに注意する必要がある。 RPLは厳密な後置記法ではなく、中置記法も取り入れており、いくつかの重要な例外は存在するものの、制御構造は標準的な中置記法の言語と類似している。これらの制御構造を実装することによって、必要な時にプログラムの内部で条件分岐やループを実行できる。 RPLのスタックはインタプリタ上に実装されたソフトウェア的なものであり、CPUのスタックではない。スタックの底辺がスタックレベル1であり、電卓上では"1:"と表示される。スタックレベル番号が大きいほどスタックの上になる。スタックの出し入れ (POP/PUSH)は基本的にスタックの底辺から行われる。 RPLは文中でオブジェクト（数値、数式、文字列、条件式、プログラムブロックなど）に遭遇すると何も考えずにスタックにオブジェクトを入れることが動作の基本である。コマンドに遭遇したときはコマンドを実行する。条件式、数式、プログラムブロックのような実行できるオブジェクトは条件文などのコマンドが実行する場合と、EVALコマンドで意識的に実行することがある。 IF/THEN/ELSE/END構造は、基本的な条件分岐をサポートする。この制御構造の基本的な文法は以下のようになる。  IF condition THEN if-true [ELSE if-false] END 以下の例はスタックの底辺（スタックレベル1）の値が"1"であるかどうかをテストし、そうであれば、スタックの底辺を"Equal to one"に置き換える。  « IF 1 == THEN "Equal to one" END » （説明）上のコードの条件式は '1 ==' である。IF文はこの条件式を実行する。1はオブジェクトなのでスタックに入れられる。==はコマンドである（一般的な言語の場合、==は演算子だが、RPLではコマンドである）。==コマンドはスタックから2つのオブジェクトを取り出すので、このプログラムを実行する前にユーザーが手動でスタックに値を入れておく必要がある。そうしないとスタックに1しかオブジェクトがないので、==コマンドが2つのオブジェクトを取り出せない。==コマンドは2つのオブジェクトが同じ時は真(1)、異なる時は偽(0)をスタックに入れる。IF文は条件式を実行した後、スタックの底辺から条件式の実行結果を取り出し、その数値が真(1)ならば、THEN文が実行される。上のコードではELSE文はないが、ELSE文がありその数値が偽(0)であれば、ELSE文が実行される。 IF文はcondition(条件式)を評価するとその結果（0:偽あるいは1:真）をスタックの底辺に残す。そして、その条件式の結果を得るためにスタックの底辺を検証する。この動作を利用すると、RPLはForth形式のIF文をオプションでサポートすることができる。つまりIF文の前に評価される条件式を書くことができる。IF文の条件式を空にすることによって、IF文は条件式実行の間にスタックの変更を行わない。そして、THENを実行する前にスタックの底辺にある既存の結果（IF文の前に書いた条件の結果のこと。0:偽あるいは1:真）を取り出して使う。 IFT ("if-then")文とIFTE ("if-then-else")文を使うことによって後置条件式を実現できる。IFTとIFTEはそれぞれ2つまたは3つのオブジェクトをスタックから取り出す。取り出した2つまたは3つのオブジェクトの最上位のオブジェクトは真偽値として評価される。もしも真ならば、上から2番目のオブジェクト（"then"に相当）はスタックに戻される。IFTEは上から3番目の"else"に相当するオブジェクトを必要とする。偽の場合、そのオブジェクトがスタックに戻される。 以下の例は、IFT文の例である。スタックの底辺から1つのオブジェクトを取り出し、それが1ならば、1を"One"に置き換える。  « 1 == "One" IFT » （説明）上のコードの 1 はオブジェクトなので、すぐにスタックに入れられる。そして、==コマンドがスタックから2つのオブジェクトを取り出す。もちろん1を先にスタックに入れているので、1の上のスタックレベルにもオブジェクトがないとオブジェクトが不足する。そのオブジェクトはプログラム実行前にユーザーが自分でスタックに入れる必要がある。==コマンドは2つのオブジェクトを比較して、同じ場合は真(1)を、異なる場合は偽(0)をスタックに入れる。次に"One"もオブジェクトなので、スタックに入れられる。つまりスタックの状態は以下のようになる。 2: 0 or 1（条件式の結果） 1: "One"（thenに相当するオブジェクト） そして、IFTコマンドが上の状態のスタックから2つのオブジェクトを取り出して、上のスタックレベル2が真(1)ならば、"One"を実行するが、"One"はただのオブジェクトなので、またスタックに入れられる。 以下の例はIFTE文の例である。スタックの底辺からオブジェクトを取り出し、それが1と等しいならば、1を"One"に置き換える。それが1でない場合は、それを"Not one"に置き換える。  « 1 == "One" "Not one" IFTE » IFTとIFTEは引数として与えられたプログラムブロック（下のコードの最初の行と最後の行以外の« »で囲まれたところ）を条件によって評価・実行することがある。その動作を利用することによって、IF/THEN/ELSE/END構造よりもさらにコンパクトな条件文を作ることができる。 以下の例はスタックの底辺からオブジェクトを取り出して、それが1と等しいのか、1より小さいのか、1より大きいのかを判断してからそれを"One"、"Less"、"More"のどれかに置き換える。 « DUP 1 == « DROP "One" » « 1 < "Less" "More" IFTE » IFTE » （説明）RPLはオブジェクトと見なしたものはそれがプログラムブロックでも実行しないでスタックに入れる。そのため、プログラムブロックは評価(evaluate)されるまで実行されない。そのため、IFTEが実行される直前のスタックの状態は以下のようになる。 3: 0 or 1（条件式の結果） 2: « DROP "One" » 1: « 1 < "Less" "More" IFTE » IFTE文はスタックから3つのオブジェクトを取り出す（つまり上の3つのオブジェクトはスタックから取り除かれる）。条件式の結果が真(1)のときは"then"に対応するプログラムブロック（« DROP "One" »）を評価する。その結果、オブジェクトはプログラムブロックなので実行される。結果が偽(0)の場合は、"else"に対応するプログラムブロック（« 1 < "Less" "More" IFTE »）を評価し、プログラムブロックなので実行する。 CASE/THEN/END構造を用いて、複数の条件から排他的に1つの条件を選ぶ、より複雑な条件論理式を実行できる。CASE文の中の1つだけの選択肢が実行される。この構造の基本文法は以下のようになる。 CASE condition_1 THEN if-condition_1 END ... condition_n THEN if-condition_n END if-none END 以下のコードはCASE/THEN/END構造の使用方法の例である。スタックの底辺にある1文字を取得して、それに対応する文字列をそれと置き換える。対応する文字がない場合は"Unknown letter"で置き換える。 «  CASE DUP "A" == THEN "Alpha" END DUP "B" == THEN "Beta" END DUP "G" == THEN "Gamma" END "Unknown letter" END SWAP DROP @ Get rid of the original letter  » 上記のコードは以下の入れ子になったIF/THEN/ELSE/END構造と完全に等価である。 « IF DUP "A" == THEN "Alpha" ELSE IF DUP "B" == THEN "Beta" ELSE IF DUP "G" == THEN "Gamma" ELSE "Unknown letter" END END END SWAP DROP @ Get rid of the original letter  » FOR/NEXT構造は、あるインデックス値から他のインデックス値までのループをサポートする。ループ用のインデックス値はループ内でプログラムからアクセス可能な一時的ローカル変数（インデックス変数）に格納される。FOR/NEXT構造の文法は以下のようになる。  index_from index_to FOR variable_name loop_statement NEXT 以下の例は1から10までの数値を合計するためにFORループを使っている。FORループのインデックス変数は"I"である。 «  0 @ Start with zero on the stack 1 10 @ Loop from 1 to 10 FOR I @ "I" is the local variable I + @ Add "I" to the running total NEXT @ Repeat...  » （説明）プログラムの最初の0は実行されて、スタックに入れられる。次の行の '1 10' も実行されて、2つの値がスタックに入る。FOR文はスタックから２つの値（1と10）を取り出して、インデックス変数Iに1を代入する。10は終了条件としてFOR文が保持する（スタックには返さない）。このとき、最初に入れた0がスタックの底辺に残ることになる。FOR文とNEXT文の間に 'I +' という実行される文がある。最初の I はインデックス変数であり、1から10の値をとる。Iはオブジェクトでもあるので、実行されるとスタックに入れられる。I=1のとき、スタックには0と1が入ることになる。次の + はコマンドである（多くの言語では + を演算子とするが、RPLではコマンド扱い）。+コマンドはスタックから2つのオブジェクトを取り出して加算して、その結果をスタックに入れる。I=1のとき、+コマンド実行前のスタックには0と1が入っているので、0 + 1 = 1となり、結果の1をスタックに入れる。I=2のとき、+コマンド実行前のスタックには1と2が入っているので、1 + 2 = 3となり、結果の3をスタックに入れる。この繰り返しで1から10までの数値を合計する。 START/NEXT構造は、開始インデックスから終了インデックスまでの単純なループをサポートする。FOR/NEXT構造と違って、インデックス変数（ループ変数）はプログラムから利用できない。しかし、インデックス変数は内部的に存在する。NEXTコマンドはインデックス変数を+1するだけである。START/NEXT構造の文法は以下のようになる。  index_from index_to START loop_statement NEXT FOR/NEXTとSTART/NEXTは1回のループでインデックス変数を+1することしかできない。しかし、NEXTを増分値とSTEPで置き換えると、インデックス変数は+1以外の値で増やしたり減らしたりできる。例えば、以下のループはインデックス変数を1回のループ毎に-2加算することによって、10から2へ逆行するようにループする。  « 10 2 START -2 STEP » WHILE/REPEAT/END構造は、ループの開始地点で条件テストをする回数未定のループをサポートする。WHILE/REPEAT/END構造の文法は以下のようになる。  WHILE condition REPEAT loop_statement END DO/UNTIL/END構造は、ループの最後で条件テストをする回数未定のループをサポートする。DO/UNTIL/END構造の文法は以下のようになる。  DO loop_statement UNTIL condition END ^ a b Patton, Charles M. (August 1987). “Computation for Handheld Calculators”. Hewlett-Packard Journal (Palo Alto, California, USA: Hewlett-Packard Company) 38 (8): 21–25. http://www.hpl.hp.com/hpjournal/pdfs/IssuePDFs/1987-08.pdf 2015年9月12日閲覧。.  ^ Wickes, William C. (1988). RPL: A Mathematical Control Language. Rochester, New York, USA: Institute for Applied Forth Research, Inc.. pp. 27–32. "Several existing operating systems and languages were considered, but none could meet all of the design objectives. A new system was therefore developed, which merges the threaded interpretation of Forth with the functional approach of Lisp. The resulting operating system, known unofficially as RPL (for Reverse-Polish Lisp), made its first public appearance in June of 1986 in the HP-18C Business Consultant calculator."  ^ Wickes, William C. (1991年3月11日). “RPL stands for Reverse Polish Lisp”. www.hpcalc.org. 2015年9月12日閲覧。 “RPL stands for Reverse Polish Lisp. In the early days of RPL development, we got tired of calling the unnamed system "the new system", and one of the development team came up with "RPL", both as a play on "RPN" which has been the loved/hated hallmark of HP calcs forever, and as an accurate indication of the derivation of the language from Forth and Lisp. RPL was never particularly intended to be a public term; at the time of the HP Journal article (August 1987) on the HP 28C there was an attempt to create a less whimsical name--hence "ROM-based procedural language," which preserved the initials but had a more dignified sound. The development team never calls it anything but (the initials) RPL. You can choose either of the two full-word versions that you prefer. Or how about "Rich People's Language?" Bill Wickes, HP Corvallis.” ^ Schoorl, André (2000年4月4日). “HP48 Frequently Asked Questions List”. HP Calculator Archive. pp. 69. 2015年9月12日閲覧。 ^ “I've heard the names RPL, Saturn, STAR, GL etc... What are they? - RPL”. FAQ: 2 of 4 - Hardware, Programs, and Programming. comp.sys.hp48 (2000年4月14日). 2015年9月12日閲覧。 ^ Nelson, Richard J. (2012-04-04). “HP RPN Evolves”. HP Solve (Hewlett-Packard) (27): 30–32. http://h20331.www2.hp.com/hpsub/downloads/HP_Calculator_eNL_04_April_2012%20(2).pdf 2015年9月12日閲覧。.  ^ a b Mier-Jedrzejowicz, Włodek A. C. (July 1991). A Guide to HP Handheld Calculators and Computers (5 ed.). HHC 2011. ISBN 978-1888840308. 1888840307. "RPL stands for Reverse Polish Lisp - it combined the RPN calculator language of earlier models with features of the Lisp and Forth programming languages. For a time HP explained the letters RPL as an acronym for "ROM-based Procedural Language"."  ^ “HP Celebrates 35 Years of Handheld Calculator Innovation”. Hewlett-Packard Development Company, L.P. (2007年). 2007年3月17日時点のオリジナルよりアーカイブ。2015年9月13日閲覧。 “1987: HP-28C: First full RPL calculator: In the late 1980s, HP developed a new programming language for its new series of extremely powerful calculators. By combing elements of RPN, Lisp and Forth, HP came up with a language called RPL (or ROM-based Procedural Language).” ^ LISPは本来前置記法を採用している ^ HP38G Aplet Template ^ HP-39/40G SysRPL Programming Tutorials ^ Horn, Joe K.. “RPL.DOC”. 2015年9月12日閲覧。 ^ Hewlett-Packard. “RPLMan from Goodies Disk 4” (RPLMAN.ZIP). 2015年9月12日閲覧。 ^ Kuperus, Klaas (2015年3月4日). “HP 50g: End of an era”. Moravia. 2015年4月2日時点のオリジナルよりアーカイブ。????-??-??閲覧。 ^ Kuperus, Klaas (2015年3月6日). “HP 50g not so good news?”. Moravia. 2016年1月1日閲覧。 ^ Wessman, Tim (2015年12月26日). “Windows 10 won't allow HP 50g USB drivers to be installed”. HP Museum. 2016年1月1日閲覧。 ^ 英語版記事では"The UserRPL command SYSEVAL tells the calculator to process designated parts of a UserRPL program as SysRPL code."と書かれていたが、これでは意味がよくわからない。一方で"HP 50g / 49g+ / 48gII graphing calculator advanced user’s reference manual"のSYSEVALの説明には "Evaluate System Object Command: Evaluates unnamed operating system objects specified by their memory addresses."と書かれていたので、このように書き換えた。 ^ a b http://hpgcc3.org/projects/newrpl ^ http://hpgcc3.org/projects/newrpl/8-newrpl-news/55-more-on-benchmarks ^ https://sourceforge.net/projects/newrpl/files/ ^ http://hpgcc3.org/projects/newrpl/project-status/8-newrpl-news/57-soft-menus ^ http://hpgcc3.org/projects/newrpl/downloads ^ https://sourceforge.net/projects/newrpl/files/TARGET%2050g-ROM/ ^ http://hpgcc3.org/projects/newrpl/8-newrpl-news/47-alpha-demo-5-is-getting-closer ^ http://hpgcc3.org/projects/newrpl/project-status/detailed-status ^ http://www.hpmuseum.org/forum/archive/index.php?thread-3288.html ^ Programming in System RPL (PDF) HP 48G Series – User's Guide (UG) (8th ed.). Hewlett-Packard. (December 1994). HP 00048-90126, (00048-90104). オリジナルの2016-08-06時点におけるアーカイブ。. https://web.archive.org/web/20160806145719/http://www.hpcalc.org/details.php?id=3937  [1] HP 48G Series – Advanced User's Reference Manual (AUR) (4th ed.). Hewlett-Packard. (December 1994). HP 00048-90136, 0-88698-01574-2. オリジナルの2016-08-06時点におけるアーカイブ。. https://web.archive.org/web/20160806145723/http://www.hpcalc.org/details.php?id=6036  [2] HP 50g graphing calculator user's guide (UG) (1 ed.). Hewlett-Packard. (April 2006). HP F2229AA-90006. http://www.hpcalc.org/details.php?id=6512  HP 50g / 49g+ / 48gII graphing calculator advanced user’s reference manual (AUR) (2 ed.). Hewlett-Packard. (2009-07-14). HP F2228-90010. http://www.hpcalc.org/details.php?id=7141  Programming in System RPL (2 ed.). (2002-04-24). オリジナルの2016-01-14時点におけるアーカイブ。. https://web.archive.org/web/20160114100225/http://isa.umh.es/calc/progsysrpl.pdf  (Older version: [3]) Rechlin, Eric, ed (2009-03-01). An Introduction to HP 48 System RPL and Assembly Language Programming. http://www.hpcalc.org/details.php?id=7114  Rechlin, Eric (2015年). “HP 49/50 Programming Documentation Files”. HP Calculator Archive. 2015年9月12日閲覧。 Rechlin, Eric (2015年). “HP 48 Programming Documentation Files”. HP Calculator Archive. 2015年9月12日閲覧。 Hicks, David G. (2013年). “RPL”. The Museum of HP Calculators (MoHPC). 2015年9月12日閲覧。 Bertrand, Joël (2015年). “RPL/2 - a new Reverse Polish Lisp”. 2015年9月12日閲覧。 (a GPL licensed RPL clone) Lapilli, Claudio Daniel (2014年1月3日). “newRPL”. 2015年9月12日閲覧。 (an open source RPL derivative for HP 50g etc.) “RPL言語（4 Level RPNが大幅に進化）”. 2017年4月3日閲覧。