DEV Community

Tomasz Wegrzanowski
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.
Enter fullscreen mode Exit fullscreen mode
$ fpc hello.pas
$ ./hello
Hello, World!
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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 writelns 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.
Enter fullscreen mode Exit fullscreen mode
$ fpc unicode.pas
$ ./unicode
5
7
4
呕贸艂W
呕贸艂w
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode
$ 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
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode
$ fpc point.pas
$ ./point
<420,69>
Enter fullscreen mode Exit fullscreen mode

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 enums 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

All code examples for the series will be in this repository.

Code for the Free Pascal episode is available here.

Discussion (2)

Collapse
bbrtj profile image
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.

Collapse
2colours profile image
2colours • Edited on
  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.