Turbo Pascal
In the 80s, Borland released the Turbo Pascal system to a market plagued by long edit-compile-link times. The Turbo Pascal compiler was itself written in Assembly and took advantage of Pascal's single-pass program structure to achieve fast compilation times. Turbo Pascal also included an integrated text editor which made the entire process as simple as a modern day IDE. Programs were compiled to COM executables, which generally made them faster than the interpreted Pascals of its peers. Overall, Turbo Pascal quickly became known and is still remembered for being a pleasant system.
By the 90s, Borland had discontinued Turbo Pascal and moved onto Borland Delphi, which is in many ways its successor. In 2008, the division of Borland that produced Turbo Pascal was sold to Embarcadero, which still maintains Delphi.
Table of contents
Installation and usage
Bits and pieces of Turbo Pascal remain online. Although Embarcadero has various places on their site where the system is supposed to be preserved, most of these seem dead due to bitrot. In my experience, Turbo Pascal 5.5 seems to have been best preserved, and can be found here and there around the internet. The best place to get ahold of it is probably on archive.org. There you can find plenty of books and other material about Turbo Pascal too. The rest of this article describes Turbo Pascal 5.5.
The executables in these archives are generally not compatible with newer versions of Windows. DOSBox comes in handy here, and can run the Turbo Pascal system easily and without issue. To do this, download DOSBox, open it and mount the folder where Turbo Pascal is:
Z:\>rem mount <drive name> <path to the folder with TURBO.EXE> Z:\>mount c c:\users\me\downloads\tp55\disk1 Drive C is mounted as local directory c:\users\me\downloads\tp55\disk1
Navigate to the drive
Z:\>c:
And run Turbo Pascal!
C:\>turbo
At this point, you should be greeted with the blue Turbo Pascal editor and
its copyright notice. If not, type dir
and make sure
TURBO.EXE
is in the directory listing.
I'd recommend adding the folder where TURBO.EXE
is stored to
the PATH
environment variable such that it can be run in any
folder:
C:\>PATH=%PATH%;C:\
Note that the open source Free Pascal compiler also provides support for most Turbo Pascal code, which is an alternative if you wish to program with a slightly more modern setup. Free Pascal is just a compiler, however, and does not come with the integrated editor and debugger.
Using the editor
The editor is fairly conventional, with arrow keys to move around and tab
to indent. The menus at the top can be opened with Alt +
F for File
, Alt + R for
Run
, and so on. Additionally, once a menu has been opened,
the other menus can be navigated to with the arrow keys. The
Edit
menu just brings you back to the editor itself, and the
Escape key has the same effect.
Once a program has been written, it can be run directly from the
Run
menu. There is a default shortcut Ctrl +
F9 for that action, although DOSBox by default swallows it and
closes the emulator. On my machine, DOSBox will by default execute at
around 2000 cycles per second, which is way too fast to actually see any
output, since Turbo Pascal switches to the terminal while the program is
running and back to the editor once it is finished. This can be overcome
either by slowing down DOSBox with Ctrl + F11
(Ctrl + F12 to speed it back up), although that will
(naturally) make things annoyingly slow. Another option is to swap between
the program output and the editor with Alt + F5.
Finally, you can add a repeat until Keypressed
at the end of
your program to spin until a key is pressed like so:
program Wait; uses Crt; { Needed to use Keypressed } begin Writeln('Hello, world!'); repeat until Keypressed end.
Error messages are definitely not what we might have become used too with
languages like Rust and Elm, and generally the only information you'll get
is a message like Unknown identifier
,
";" expected
or Type mismatch
and your cursor
will be placed at the start of the offending token. The language is
(usually) simple enough though that this is (usually) enough to figure out
the error.
The language
Turbo Pascal is (perhaps unsurprisingly) a dialect of Pascal, and Standard Pascal programs are generally compatible with Turbo Pascal. See for instance the Free Pascal wiki for a comprehensive tutorial and introduction to the language.
Units
Perhaps the most notable features of Turbo Pascal since 5.5 is the unit system and the object oriented features. The unit system allows for modular programming by separating the code into different units. A unit might look something like
unit greeter; interface { uses and other declarations here } procedure Greet(msg : string}; implementation { Definitions here } procedure Greet(msg : string); begin Writeln(msg); end; { Unit initialization can be done with a begin block here. } end.
Note that in the implementation part above, the parameter part of the procedure declaration can be omitted (since it is already specified in the interface part). This is also true for functions.
A unit like greeter
should be stored in a file with the
unit name and the .PAS
extension (so
GREETER.PAS
) for the above unit. Otherwise, Turbo Pascal
won't automatically find and compile the unit for you.
To use a unit in some other unit or program, we can use the
uses
declaration. There can only be a single
uses
per unit or program, though multiple units can be used
in a single such declaration by separating them with a comma. Finally,
uses
declarations must come first in the program definitions
and the unit interface.
program main; uses greeter; begin Greet('Hello, world!') end.
Object-oriented programming
Version 5.5 introduced object oriented programming, and features most
things one might expect from such a language. Objects are defined by
creating object
types, which may specify some fields and some
methods.
program Main; type Animal = object constructor Init; procedure Greet; end; constructor Animal.Init; begin end; procedure Animal.Greet; begin Writeln('[Generic animal noise]') end; var A : Animal; begin A.Init; A.Greet; end.
Note that all objects must have an explicitly defined constructor. On my setup, Turbo Pascal crashes if it attempts to run a method on an object which hasn't been constructed (although no warning is emitted).
Objects may inherit from other objects. This ”brings along“ methods and fields from the parent object, which may be overriden by redeclaring and redefining them.
Cat = object(Animal) { Cat inherits from Animal } color : string; constructor Init(fur_color : string); end; { ... } constructor Cat.Init(fur_color : string); begin color := fur_color; end; { ... } var A : Animal; B : Cat; begin A.Init; B.Init('black'); A.Greet; B.Greet; { Calls Animal.Greet } end;
Methods (except constructors) may be virtual, which means the method call will be resolved at run-time through a vtable. This will only be done for references (aka pointer types in Turbo Pascal).
To demonstrate this, let's first change the Greet
procedure
to be virtual and override it for the Cat
type Animal = object { ... } procedure Greet; virtual; { note the semicolon } end; Cat = object(Animal) { ... } procedure Greet; virtual; end; { ... } procedure Cat.Greet; begin Write('"Meow," the '); Write(color); Writeln(' cat says.') end;
Next we'll create a pointer type to Animal
and a procedure
that uses it.
AnimalPtr = ^Animal; { ... } procedure SayHi(it : AnimalPtr); begin it^.Greet end;
At this point, we can give SayHi
pointers to any objects
which inherits from Animal
, and it will select the method at
runtime.
var A : Animal; B : Cat; begin A.Init; B.Init('black'); SayHi(@A); { => [Generic animal noise] } SayHi(@B) { => "Meow," says the black cat. } end.
Some programs
10 PRINT
Uses Random
from System
for random number
generation and Delay
from Crt
for timing. Note
that Random(x)
returns a number in the range
1 .. x
(inclusive in both ends).
program main; uses Crt; { Delay, Keypressed } begin Randomize; repeat if Random(2) = 1 then Write('/') else Write('\'); Delay(25) { milliseconds } until Keypressed end.
Fibonacci
Uses longint
instead of integer
because the
latter is only 16 bits while the former is 32 bits. Written to see how
slow things get. Note that because DOS is without multitasking, the only
way to stop the programs once things get slow is to press a key (setting
Keypressed
to true in the process) and wait for the current
fibonacci computation to complete. If things get unbearably slow, DOSBox
can be sped up to about 15 000 cycles per second without any configuration
(and even more with).
One fun thing to try is rewriting this program to use the imperative version of the fibonacci function instead and see the difference in speed. That version will overflow before the recursive version gets even a few numbers done.
program main; uses Crt; var i : longint; function Fibonacci(n : longint) : longint; begin if n = 0 then Fibonacci := 0 else if n = 1 then Fibonacci := 1 else Fibonacci := Fibonacci(n - 1) + Fibonacci(n - 2) end; begin i := 0; repeat Writeln(Fibonacci(i)); i := i + 1; until Keypressed end.
Resources
- Mastering Turbo Pascal 4.0 by Tom Swan has been the main resource behind this page, and is a wonderfully structured encyclopedia of most things Turbo Pascal, including its standard libraries and built-in functions.
- Stretching Turbo Pascal 5.5 by Kent Porter details object oriented programming as well as some other advanced features of the 5.5 version of Turbo Pascal