Delphi
Pascal

割と簡単に ’標準 Pascal' を試してみたい


はじめに

Delphi を使っていて、何が 標準 Pascal (Standard Pascal) に準拠していて何が準拠していないのかふと知りたくなることがあります。ISO/IEC 7185 の仕様を読めばいいのですが、実際にコードを実行して試したい事がよくあります。

そんな時は ideone で GPC を使ったり、同じく FPC で {$mode ISO} 指令を付けてみたりするのですが、これらは純粋な標準 Pascal ではないので、場合によっては検証にならなかったりします。


純粋な '標準 Pascal' を求めて

Windows 環境で最も簡単に実行できる標準 Pascal は Scott A. Moore 氏が書いた (改修した) Pascal-P5 だと思われます (P4 まではサブセット)。

Mac や Linux の場合には自前でソースコードをビルドする必要があります。

今回の話題からは外れますが X68000 (Human68K) だと Pure Pascal が標準 Pascal ですね。

image.png


環境設定

PASCAL-P5 のアーカイブを解凍したら、bin フォルダにある pcom.exe と pint.exe を適当な場所にコピーします。これが PASCAL-P5 の本体です。

PASCAL-P シリーズは P-CODE コンパイラです。簡単に言えば PCOM がソースコードを中間コード (P-CODE) 形式にコンパイルし、それを PINT が実行します。PCOM がコンパイラで PINT がインタプリタという訳です。なので、理屈的には PINT さえ移植できればどこでもプログラムを実行できます。

え? Java っぽい? え? .NET っぽい? え? VB っぽい?そうですか...

さて、PCOM は prd という名前のファイルをソースコードとみなし、コンパイルして prr という中間形式ファイルを出力します。そして PINT は prr という名前のファイルを中間形式ファイルとみなして実行します...名前決め打ちなんですよ、面倒ですね。

これを簡単にするバッチファイルもアーカイブの bin フォルダにあるのですが、何故かバッチファイルに cp や mv が使われていて Cygwin がないと動作しません。


バッチファイル

面倒なので Cygwin が不要なようにバッチファイルを書きました。以下の 4 つのファイルを pcom.exe / pint.exe と同じ場所に保存してください。


setpath.bat

カレントディレクトリを環境変数 PATH に設定するバッチファイルです。


setpath.bat

@echo off

cls
set PATH=%CD%;%PATH%
echo %PATH%


compile.bat

ソースファイルをコンパイルするバッチファイルです。


compile.bat

@echo off

cls

if not "%1"=="" goto paramok
echo *** Error: Missing parameter
goto exit

:paramok
if exist "%1.pas" goto fileexists
echo *** Error: Missing %1.pas file
goto exit

:fileexists
if "%2"=="" goto continue
if exist "%2" goto continue
echo *** Error: Missing %2 input file
goto stop

:continue
echo.
echo Compiling and running %1
echo.
copy %1.pas prd > nul
pcom
move prr %1.p5 > nul

:stop
del prd

:exit



run.bat

中間形式ファイルを実行するバッチファイルです。


run.bat

@echo off

cls

if not "%1"=="" goto paramok
echo *** Error: Missing parameter
goto exit

:paramok
if exist "%1.p5" goto fileexists
echo *** Error: Missing %1.p5 file
goto exit

:fileexists
if not "%2"=="" goto useinputfile
copy %1.p5 prd > nul
goto run

:useinputfile
rem The input file, if it exists, gets put on the end of the intermediate
type %1.p5 %2 > prd

:run
pint
if "%3"=="" goto stop
copy prr %3 > nul

:stop
del prd
del prr



p5.bat

ソースコードファイルをコンパイルして実行するバッチファイルです。


p5.bat

@echo off

cls

if not "%1"=="" goto paramok
echo *** Error: Missing parameter
goto stop

:paramok
if exist "%1.pas" goto fileexists
echo *** Error: Missing %1.pas file
goto stop

:fileexists
if "%2"=="" goto continue
if exist "%2" goto continue
echo *** Error: Missing %2 input file
goto stop

:continue
echo.
echo Compiling and running %1
echo.
copy %1.pas prd > nul
pcom
move prr %1.p5 > nul
if not "%2"=="" goto useinputfile
copy %1.p5 prd > nul
goto run

:useinputfile
rem The input file, if it exists, gets put on the end of the intermediate
type %1.p5 %2 > prd

:run
pint
if "%3"=="" goto stop
copy prr %3 > nul

:stop
del prd
del prr



PASCAL-P5 の使い方

まず、サンプルプログラムを用意します。アーカイブの sample-programs フォルダにもサンプルがありますが、今回は FizzBuzz を用意してみました。


FizzBuzz.pas

program FizzBuzz(output);

var
i: Integer;
begin
for i:=1 to 100 do
begin
if ((i mod 3) + (i mod 5)) = 0 then
Writeln('Fizz Buzz')
else if (i mod 3) = 0 then
Writeln('Fizz')
else if (i mod 5) = 0 then
Writeln('Buzz')
else
Writeln(i);
end;
end.

まず、PASCAL-P5 (とバッチファイル) を格納したフォルダへ移動します。

image.png

アドレスバーに CMD と入力し〔Enter〕キーを押し、

image.png

カレントディレクトリでコマンドプロンプトを開きます。

image.png

先程の FizzBuzz.pas が違うフォルダにあるのであれば setpath を実行して PASCAL-P5 にパスを通しておきます。

image.png

compile fizzbuzz としてコンパイルします。ここでの拡張子の入力は不要ですが、ソースファイル名は *.pas である必要があります。

image.png

正しくコンパイルされると fizzbuzz.p5 ファイルが生成されます。これが中間形式ファイルです。

image.png

run fizzbuzz として実行します。拡張子は不要です。一旦中間形式ファイルができてしまえば、実行の都度コンパイルする必要はありません。

image.png

p5 fizzbuzz とすると、コンパイルと実行を連続して行います。

image.png


おわりに

目的は達成されました!めでたしめでたし...。


K&R の K の方へ

K&R の K の方「Why Pascal is Not My Favorite Programming Language (何故 Pascal はお気に入りのプログラミング言語ではないのか)」 なんてのを書いていましたが Turbo Pascal や Delphi...それ以前の Apple の Pascal ですらその問題の多くは解決しています (好みの問題は残りますが)。

先の論文が書かれたのは 1981 年ですが、


  • 1983: Pascal の最初の標準化 / Turbo Pascal 1.0

  • 1985: Apple による Object Pascal

  • 1990: Pascal 標準化改訂版 / Turbo Pascal 5.5 (Object Pascal)

  • 1995: Delphi 1.0

それ以降で (Object) Pascal が進化していないハズもなく。

例えば、論文に書かれていたループの問題についてですが、標準 Pascal だと


loop.pas

program loop(output);

begin
while True do
begin
break;
end;
end.

このような break を使ったループの脱出はできません。

image.png

Delphi とかだと普通にできます。

image.png


Linux の L の方へ

Linux の L の方の Pascal 嫌いという話についても古い Pascal に基づくものなので的外れな指摘もあるかと思います。

例えば


Of course, in stupid languages like Pascal,

where labels cannot be descriptive, goto's can be bad.



labeltest.pas

program labeltest(output);

label
jump;
begin
goto jump;
writeln('Hello');
jump:
writeln('World');
end.

確かに標準 Pascal だとラベルに任意の名前を付ける事はできず、符号なしの 4 桁以下の整数を指定する必要がありますが、

image.png

Delphi ならラベルに識別子が使えます (符号なしの整数も使えます)。

image.png

古い Pascal しか知らないと「Pascal...面倒くさいよね!」という意見が出てしまうのもわからなくはないですが、Delphi 等のモダンな (Object) Pascal が面倒くさい訳ではありません。


そして最新版の Delphi

image.png

魔改造 Pascal である Delphi には無償版 (Community Edition) もあるので、K の方や L の方が言ってた事が今でも正しい指摘なのかどうかをぜひ試してみてください。

... Delphi 使いは逆に標準 Pascal を触ってみて Delphi の有難みを知ってください (w