If you missed part 1 you can view it here📌
Continuing where we left off last week we will now write some Pascal code. We will be using Free Pascal, a modern implementation of Pascal with some additional features. Our examples will be from a partial implementation of a Brainfuck interpreter. But before we can get to that we need to talk about how Pascal programs are structured. Below we have the skeleton of a Pascal program
{
Multi line comment.
Can also use // for single line comments
}
// program name declaration
program myProgram;
const
{
Constants Here
}
type
{
Custom Types here
}
var
{
Variables go here
}
// program star
begin
{
// Your code here
}
end. // end of program uses keyword 'end' with a '.'
Things are defined in the file in a much more rigid way then in other programming languages. You have to specify all the constants, types, and variables at the top of the file before they are used in the program. This means if part way through the program you need another variable you have to jump back up to the top of the program and declare it. This even includes using variables like i, and j in loops. It takes some getting used to, but I suspect this is for a few reasons. One is Pascal’s roots as a teaching language. Enforcing structure into a program from the very beginning will make it easier for a novice programmer to construct programs, and read them. The other is that it probably aids both in file parsing, and compilation. I noticed through my time with Pascal that the compiler absolutely ripped through the code. I suspect the structure of the programs had a lot to do with this.
Free Pascal is unique in that is supports multiple dialects of Pascal. These dialects can be specified with mode directives. Here are some of the directives listed in the manual.
OBJFPC: This is the same mode as FPC mode, but it also includes classes, interfaces and exceptions.
TP: Turbo Pascal compatibility mode. In this mode, the compiler tries to mimic the Turbo Pascal compiler as closely as possible. Obviously, only 32-bit or 64-bit code can be compiled.
DELPHI: Delphi compatibility mode. In this mode, the compiler tries to resemble the Delphi compiler as best as it can: Most Delphi 7 and above features are implemented.
You might be wondering which mode directive we should select. For simple programs is doesn’t really matter, but for larger ones it’s worth using modern pascal unless you have compatibility reasons not to. The Castle Game Engine is a game engine written in Free Pascal. They have a whole article dedicate to modern pascal and they recommend using this directive for all new Pascal programs {$mode objfpc}{$H+}{$J-}
. Since I don’t have the any reason not to, I’ll follow their advice. From my research these are what the additional directives mean
{$H+}
: This directive controls the string handling in Pascal. In particular,{$H+}
enables the use of Ansistrings, which are dynamically sized strings. This is in contrast to{$H-}
, which would set strings to be Shortstrings (fixed-length, 255 characters maximum). All of this is to say if you turn this on, strings will behave like they do in most programs created in the last 30 years.{$J-}
: This switch tells the compiler whether or not assignments to typed constants are allowed. The default is to allow assignments to typed constants. In this case we are disallowing assignments to typed constants
Mode directives can be specified as compilations switches
fpc myPascalProgram.pas -MOBJFPC -Sh
Or in the source files themselves
{$mode objfpc}{$H+}{$J-}
//mode directive
program myProgram;
I personally like the source code approach, as it makes it clear what style and behavior the Pascal code will take when you open the file. Here how that would look in the first part of our BF interpreter.
{$mode objfpc}{$H+}{$J-} // Our directive
program BrainFuck;
// For imports
uses
SysUtils;
Besides our mode directive we include the SystUtils
library with ‘uses’, which works like import or #include in other languages. This allows us to use the function WriteLn
to write to standard out. Our program doesn’t have any constants, so we will move to the type section and forward declare our types.
// Type section of our program
type
TBrainFuck = class
// visibility of our member variables
private
FPC: integer;
FStack: integer;
FCode: ansistring;
FSP: integer;
FMem: array[0..29999] of byte;
public
// forward declaration of our constructor and procedure
constructor Create(code: ansistring);
procedure Interpret;
end;
Custom types are declared using a typeName = <type implementation>
syntax. Names is Pascal are case insensitive, similar to PowerShell, so charArray, CharArray, and CHARARRAY all resolve to the same name. Since we’ve used the objfpc
mode directive, we have access to classes, and they behave similar to classes in other languages. You can declare methods as public and private, and create constructors. All the methods must also be forward declared with their types much like a header file in C. Furthermore methods are separated into two categories and use two separate keywords, procedure, which is a method that doesn’t have a return value, and function which does. Since we only care about the side effects of the interpreter, we can just create an interpret function using a procedure.
We will be using an array of 0-29,999 bytes as the memory for our interpreter. In Pascal Arrays are fixed width, and are declared with an array[min..max] of <type>
syntax. They have an interesting property in that they don’t have to start as zero as seen in the example below.
program ArrayExample;
var
// You can also initialize the arrays with values
myArray: array[1..5] of Integer = (10, 20, 30, 40, 50);
i: Integer;
// start of our program
begin
// Access and print array elements
for i := 1 to 5 do
writeln('Element ', i, ': ', myArray[i]);
end.
One more thing about arrays. If you are are initializing the array with the values all at once it can go in the var section of the program.
You may have noticed in our BF example, that we have prefixed our variable names with T and F. Since Pascal plays fast and loose with variable names, it is common to do things like prefix variables that are within classes with F for field, and to prefix types with T, to differentiate them from other variables that would otherwise have the same name in the program.
Now that we’ve declared our class, it’s member variables variables and functions, we can work on the implementation details of the procedures
Since the body of a procedure is not declared when the procedure is initially created, in Pascal it is typical to write the implementation details of a procedure after all the types have been declared. This simply requires writing the procedure and putting the code between a begin and end block. For functions that are part of classes, using the dot syntax with the name of the associated class will be enough to get Pascal to associate the function to the proper procedure. The constructor function is differentiated from a regular function by having the keyword constructor before the function name. All variables in the function are assumed to either be arguments passed into the body from the function, properties from a class, or global variables declared in the var section. Let’s start with a simple example first
program functionExample;
var
square : Integer;
function squareAndAddTen(num : Integer): Integer;
var
finalResult : Integer ;
begin
square := num * num;
finalResult := square + 10;
squareAndAddTen := finalResult;
end;
begin
writeln(squareAndAddTen(10));
end.
In the above examples the square variable is declared in the var section making it global, so we can use it inside our function. If you need additional local variables inside a function in Pascal, you can create a var block within that function. It will be scoped to that function, and that is what is happening in our example with the finalResult variable. Finally a curiosity of Pascal, to return a value you assign the result to the name of the function. I’m told that newer Pascal’s like Free Pascal allow you to use the return keyword, but the quirk was intuitive enough that I never felt the need to.
Now that we know a little bit more about how Pascal functions work, we can apply that understanding to our BF program. After declaring our directives and classes above, we can work on the constructor and procedures.
// Our BF class constructor
constructor TBrainFuck.Create(code: ansistring);
// start of our constructor
begin
FCode := code;
FStack := 0;
FPC := 0;
end;
// Our BF Class procedure
procedure TBrainFuck.Interpret;
var
// local variable
CharCode: char;
// start of our procedure
begin
while FPC <= Length(FCode) do
begin
// assignment is done with := instead of =
CharCode := FCode[FPC];
case CharCode of
'+':
begin
if FMem[FSP] = 255 then
FMem[FSP] := 0
else
FMem[FSP] := FMem[FSP] + 1;
end;
'-':
begin
// = can be used as a comparison operator
if FMem[FSP] = 0 then
FMem[FSP] := 255
else
FMem[FSP] := FMem[FSP] - 1;
end;
'.':
begin
Write(Chr(FMem[FSP]));
end;
end;
Inc(FPC);
end;
end;
The constructor is straight forward and initializes the class fields. The Interpret function consists of a simple while loop and case statement that checks each character in a string. The characters in the string act as instructions for the interpreter. Since this is just a partial implementation we we will only create the implementations for “+, -, .” but see the article at the end for a more robust implementation of a BF interpreter.
Now that we’ve implemented our functions, we have to initialize the variables we will use in our program. Since we’ve already declared so much of our program up until this point this section will be very short.
var
bf: TBrainFuck;
stringCode: ansistring;
Then the only thing that is left is to write the code that executes our interpreter
begin
// Exclamation point
stringCode := '+++++++++++++++++++++++++++++++++.';
bf := TBrainFuck.Create(stringCode);
bf.Interpret();
end.
Now we compile our program...
And we print out an exclamation point. We get an ! because we increment the memory at the stack pointer 33 times (which corresponds to the ascii character !).
And that’s the basic of a Free Pascal program in a nut shell. I’d like to thank the people in the Unofficial Free Pascal Discord for the help with my questions as I was exploring the language. As you can see, while Pascal might be older than C it has a lot the features you are familiar with from other programming languages. If you want a language that has a few more features than C, and compiles very fast, Pascal might be a good choice for you, especially if you are thinking of getting into 8-bit retro computing.
Interesting Pascal Projects
I’ll end the article with a list of some interesting Pascal projects I came across while working on this article. Check them out!
Castle Game Engine - A cross platform 3D game engine
FPS4 - A PS4 Emulator written in Free Pascal
OpenSoldat - A 2D action game written in Pascal
Python4Delphi - A wrapper to interact between Python and Delphi code
Skia4Delphi - 2D Graphics API
Call To Action 📣
If you made it this far thanks for reading! If you are new welcome! I like to talk about technology, niche programming languages, AI, and low-level coding. I’ve recently started a Twitter and would love for you to check it out. I also have a Mastodon if that is more your jam. If you liked the article, consider liking and subscribing. And if you haven’t why not check out another article of mine! A.M.D.G and thank you for your valuable time.