## DEV Community

Tomasz Wegrzanowski

Posted on

# 100 Languages Speedrun: Episode 73: Free Pascal

Turbo Pascal was my second language after QBasic.

Unfortunately there doesn't seem to be any easy way to run Turbo Pascal on modern hardware, so I'll do the next best thing and give Free Pascal a try.

### Hello, World!

Pascal code starts with `program Name`. Statements are separated by `;` and the whole thing with `.`. It's case insensitive, so you can do `writeln`, `WriteLn`, or even `WrItElN` if you wanted, but I'll stick to all lowercase.

``````program Hello;
begin
writeln('Hello, World!');
end.
``````
``````\$ fpc hello.pas
\$ ./hello
Hello, World!
``````

### Fibonacci

Let's try something a bit more ambitious - Fibonacci numbers.

``````program Fibonacci;

function fib(n:integer):integer;
begin
if n<=2 then
fib := 1
else
fib := fib(n-1) + fib(n-2);
end;

var
n:integer;

begin
for n := 1 to 20 do
begin
writeln('fib(', n, ')=', fib(n));
end;
end.
``````

Step by step:

• we declare full list of variables used by something before the `begin` part - in this case we declare `var n:integer;` - that's the list of all variables our program uses
• assignment uses `:=`
• `for n := 1 to 20 do` is a for loop
• we can pass any number of arguments to `writeln`, and mix strings and integers, it all works
• to define a function we use `function name(arguments):return_type;`, followed by `var` block with any additional local variables, then `begin...end` with the code
• to return from a function, we assign to variable with same name as the function, there's no `return` in Pascal
• `if condition then ... else ...;` is conditionals

### FizzBuzz

``````program FizzBuzz;

var
n:integer;

begin
for n := 1 to 100 do
begin
if n mod 15 = 0 then
writeln('FizzBuzz')
else if n mod 5 = 0 then
writeln('Buzz')
else if n mod 3 = 0 then
writeln('Fizz')
else
writeln(n);
end;
end.
``````

The only new thing here is slightly unusual syntax - `=` for equality check, and `mod` for modulo.

But you might have noticed something really weird - placement of semicolons. There's a lot of semicolon using languages and none of them would do this.

In every other language semicolons end statements. In Pascal semicolons separate statements.

Because those `writeln`s are still continuing with `else`, we cannot put semicolons after them - it will refuse to compile. Some semicolons like the one after the final `end` are optional, just because there's no more statements there. But if there were some, you'd need semicolons.

There's some logic to it, but it will likely just annoy you if you're used to the usual system every other language uses, and modern languages don't use semicolons anyway.

### Unicode

Obviously Turbo Pascal didn't support Unicode, as it predated is by very long time, but sadly neither than Free Pascal:

``````program Unicode;

begin
writeln(length('Hello'));
writeln(length('Ε»Γ³Εw'));

writeln(upcase('Ε»Γ³Εw'));
writeln(lowercase('Ε»Γ³Εw'));
end.
``````
``````\$ fpc unicode.pas
\$ ./unicode
5
7
4
Ε»Γ³ΕW
Ε»Γ³Εw
``````

### Unicode, attempt two

Apparently Free Pascal supports annotations like `{\$codepage UTF8}`, so let's see how that goes:

``````{\$codepage UTF8}
program Unicode;

begin
writeln(length('Hello'));
writeln(length('Ε»Γ³Εw'));

writeln(upcase('Ε»Γ³Εw'));
writeln(lowercase('Ε»Γ³Εw'));
end.
``````
``````\$ fpc unicode2.pas
\$ ./unicode2
5
4
2
This binary has no string conversion support compiled in.
Recompile the application with a unit that installs a unicodestring manager in the program uses clause.
Runtime error 234 at \$000000010E719BCD
\$000000010E719BCD
``````

Even more disastrously. Not only the length were incorrect in different way (5/7/4, then 5/4/2, correct is 5/4/1), the whole thing just crashed instead of even trying to convert strings to upper or lower case.

I think "just straight crashes on Unicode" is pretty much the worst performance of any language so far.

### Classes

Let's close this episode by defining a class. Not really something Turbo Pascal had.

``````{\$mode objfpc}
program PointProgram;

type Point = class
public
x: integer;
y: integer;
constructor Create(_x, _y:integer);
function ToString: string;
end;

constructor Point.Create(_x, _y:integer);
begin
x := _x;
y := _y;
end;

function Point.ToString: string;
var
xs, ys: string;
begin
str(x, xs);
str(y, ys);
result := '<' + xs + ',' + ys + '>'
end;

operator + (p1, p2: Point): Point;
begin
result := Point.Create(p1.x + p2.x, p1.y + p2.y)
end;

var
a: Point;
b: Point;
c: Point;

begin
a := Point.Create(200, 30);
b := Point.Create(220, 39);
c := a + b;

writeln(c.ToString);
end.
``````
``````\$ fpc point.pas
\$ ./point
<420,69>
``````

Step by step:

• we need to turn on classes support with `{\$mode objfpc}` - there's a lot of switches like that, they change with dialect of Pascal you'll be using, and a lot of other things
• `type Point = class` - how we declare a class; there are other `type` declarations, like `enum`s etc.
• for simplicity I only specified `public` properties, `costructor Create`, and overridden `ToString`
• we specify implementations of the methods separately from their declarations
• `constructor Point.Create` just assigns the right fields
• `function Point.ToString: string;` returns default representation of a `Point` - we can first convert `x` and `y` to strings with classic Pascal `str(anything, aString)`, then concatenate them with `<` and `>` - there are many other solutions to this
• we can declare `operator +`, but it's not a method, and in fact it's completely separate from the class stuff
• in addition to assigning to name of the function to set return value, we can also assign to `result` - this is a pretty useful, as we can't exactly `+ := Point.Create(p1.x + p2.x, p1.y + p2.y)`
• we still need to call `writeln(c.ToString)` explicitly, it will not `.ToString` for us; it's just a convention, not language feature

### Should you use Free Pascal?

No.

Weirdly Free Pascal is occasionally used to build real programs, most notable Cheat Engine but it's basically boomers who learned programming with Turbo Pascal or Delphi, and never moved on.

There's no real reason to use Pascal of any kind.

I'm not saying it was all bad. For example even though it's been decades since I last coded Pascal, and I forgot most of the syntax, error messages for that were really top quality, with exact issue at exactly specified location.

But overall, no.

### Code

bbrtj

FP is cool. It compiles and runs very fast, doesn't need makefiles of any kind, is very portable and makes it super easy to build GUIs with Lazarus. It contains abstractions for many stuff you do by hand in C, and doesn't feel as bloated as C++. If anything, case insensivity and interfaces are the things that I don't like about it.

Also, there's much more built than just cheat engine. Delphi uses a dialect of Pascal that FPC has compatibility mode for. Lazarus can import delphi projects. And Delphi was used to build a bunch of stuff, including FLStudio. There's also Castle Game Engine written in FP, which in turn is used to build games for a bunch of platforms.

1. 'π©'.length == 2 in Javascript as well
2. "π§β".length == 2 in Python and (would you believe...) Ruby as well XDD Length of emojis is very much a heuristic thing in most languages, not something you should base any arguments upon (actually, Raku gets this right,"π§β".chars == 1). Actually useful related article: hsivonen.fi/string-length/
3. wiki.freepascal.org/Unicode_Suppor... If you use Lazarus (which you perhaps should for Free Pascal), it's dead simple to get that code working, I just needed to add "Uses LazUTF8;".

Should you read these language speedruns?
No. Despite my bias towards Polish people, I have to say the author is a superficial edgelord who couldn't get further than a couple of hot takes per language. Ironically enough, these short posts often contain grammar mistakes as well - the high standards apparently don't apply to everything.