100 Languages Speedrun: Episode 73: Free Pascal
Tags: pascal
Published: 2022-01-29 01:19:50

Turbo Pascal was my second language after [QBasic](https://dev.to/taw/100-languages-speedrun-episode-53-qbasic-2nd4).

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(length('💩'));

  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(length('💩'));

  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](https://en.wikipedia.org/wiki/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

[All code examples for the series will be in this repository](https://github.com/taw/100-languages-speedrun).

[Code for the Free Pascal episode is available here](https://github.com/taw/100-languages-speedrun/tree/master/episode-73-free-pascal).