Modern Object Pascal guide

Link to Quick Modern Object Pascal for Programmers

Michalis Kamburelis and contributors: Maciej Izak

There are many books and resources about Pascal out there, but too many of them talk about the old Pascal, without classes, units or generics.

So I wrote this quick introduction to what I call modern Object Pascal. Most of the programmers using it don’t really call it “modern Object Pascal”, we just call it “our Pascal”. But when introducing the language, I feel it’s important to emphasize that it’s a modern, object-oriented language. It evolved a lot since the old (Turbo) Pascal that many people learned in schools long time ago. Feature-wise, it’s quite similar to C++ or Java or C#.

  • It has all the modern features you expect — classes, units, interfaces, generics…
  • It’s compiled to a fast, native code,
  • It’s very type safe,
  • High-level but can also be low-level if you need it to be.

It also has excellent, portable and open-source compiler called the Free Pascal Compiler, http://freepascal.org/ . And an accompanying IDE (editor, debugger, a library of visual components, form designer) called Lazarushttp://lazarus.freepascal.org/ . Myself, I’m the creator of Castle Game Engine, http://castle-engine.sourceforge.net/ , which is a cool portable 3D and 2D game engine using this language to create games on many platforms (Windows, Linux, MacOSX, Android, iOS, web plugin).

This introduction is mostly directed at programmers who already have experience in other languages. We will not cover here the meanings of some universal concepts, like “what is a class”, we’ll only show how to do them in Pascal.

See here!

Superpascal compiler

There is now a FPC version of SuperPascal at https://github.com/octonion/superpascal, archived here.

From Wikipedia:

SuperPascal is based on Niklaus Wirth’s sequential language Pascal, extending it with features for safe and efficient concurrency. Pascal itself was used heavily as a publication language in the 1970s; it was used to teach structured programming practices and featured in text books, for example, on compilers and programming languages. Brinch Hansen had earlier developed the language Concurrent Pascal, one of the earliest concurrent languages for the design of operating systems and real-time control systems.

The requirements of SuperPascal were based on the experience gained by Brinch Hansen over three years in developing a set of model parallel programs, which implemented methods for common problems in computational science.This experimentation allowed him to make the following conclusions about the future of parallel scientific computing:

Future parallel computers will be general-purpose, allowing programmers to think in terms of problem-orientated process configurations. This was based on his experience programming networks of transputers, which were general-purpose processors able to be connected in arrays, trees or hypercubes.
Regular problems in computational science require only deterministic parallelism, that is, expecting communication from a particular channel, rather than from several.
Parallel scientific algorithms can be developed in an elegant publication language and tested on a sequential computer. When it is established an algorithm works, it can easily be implemented in a parallel implementation language.

These then led to the following requirements for a parallel publication language:

-The language should extend a widely used standard language with deterministic parallelism and message communication. The extensions should be in the spirit of the standard language.
-The language should make it possible to program arbitrary configurations of parallel processes connected by communication channels. These configurations may be defined iteratively or recursively and created dynamically.
-The language should enable a single-pass compiler to check that parallel processes do not interfere in a time-dependent manner.

Features
The key ideas in the design of SuperPascal was to provide a secure programming, with abstract concepts for parallelism.

Security
SuperPascal is secure in that it should enable its compiler and run-time system to detect as many cases as possible in which the language concepts break down and produce meaningless results. SuperPascal imposes restrictions on the use of variables that enable a single-pass compiler to check that parallel processes are disjoint, even if the processes use procedures with global variables, eliminating time-dependent errors. Several features in Pascal were ambiguous or insecure and were omitted from SuperPascal, such as labels and goto statements, pointers and forward declarations.

Parallelism
The parallel features of SuperPascal are a subset of occam 2, with the added generality of dynamic process arrays and recursive parallel processes.

A parallel statement denotes that the fixed number of statements it contains must be executed in parallel. For example:

parallel
  source() |
  sink()
end

A forall statement denotes the parallel execution of a statement by a dynamic number of processes, for example:

forall i := 0 to 10 do
  something()

Channels and communication
Parallel processes communicate by sending typed messages through channels created dynamically. Channels are not variables in themselves, but are identified by a unique value known as the channel reference, which are held by channel variables. A channel is declared, for example, by the declaration

type channel = *(boolean, integer);
  var c: channel;

which defines a new (mixed) type named channel and a variable of this type named c. A mixed type channel is restricted to transmitting only the specified types, in this case boolean and integer values. The channel c is initialised by the open statement:

open(c)

Message communication is then achieved with the send(channel, value) and receive(channel, variable) statements. The expression or variable providing the value for send, and the variable in receive, must both be of the same type as the first channel argument. The following example shows the use of these functions in a process that receives a value from the left channel and outputs it on the right one.

var left, right: channel; a: number;
  receive(left, a);
  send(right, a)

The functions send and receive can both take multiple input and output arguments respectively:

  send(channel, e1, e2,..., en);
  receive(channel, v1, v2,..., vn)

The following run-time communication errors can occur:
– Channel contention occurs when two parallel processes both attempt to send or receive on the same channel simultaneously.
A message type error occurs when two parallel processes attempt to communicate through the same channel and the output expression and input variable are of different types.
Deadlock occurs when a send or receive operation waits indefinitely for completion.

– Recursive procedures can be combined with parallel and forall statements to create parallel recursive processes. The following example shows how a pipeline of processes can be recursively defined using a parallel statement.

procedure pipeline(min, max: integer; left, right: channel);
var middle: channel;
begin
  if min < max then
    begin
      open(middle);
      parallel
        node(min, left, middle) |
        pipeline(min + 1, max, middle, right)
      end
    end
  else node(min, left, right)
end;
end;

Another example is the recursive definition of a process tree:

procedure tree(depth: integer, bottom: channel);
var left, right: channel;
begin
  if depth > 0 then
    begin
      open(left, right);
      parallel
        tree(depth - 1, left) |
        tree(depth - 1, right) |
        root(bottom, left, right)
      end
    end
  else leaf(bottom)

Interference control
The most difficult aspect of concurrent programming is unpredictable or non-reproducible behaviour caused by time-dependent errors. Time-dependent errors are caused by interference between parallel processes, due to variable updates or channel conflicts. If processes sharing a variable, update it at unpredictable times, the resulting behaviour of the program is time-dependent. Similarly, if two processes simultaneously try to send or receive on a shared channel, the resulting effect is time-dependent.

SuperPascal enforces certain restrictions on the use of variables and communication to minimise or eliminate time-dependent errors. With variables, a simple rule is required: parallel processes can only update disjoint sets of variables. For example, in a parallel statement a target variable cannot be updated by more than a single process, but an expression variable (which can’t be updated) may be used by multiple processes. In some circumstances, when a variable such as an array is the target of multiple parallel processes, and the programmer knows its element-wise usage is disjoint, then the disjointness restriction may be overridden with a preceding statement.

Structure and syntax
SuperPascal is a block structured language, with the same basic syntax as Pascal. A program consists of a header, global variable definitions, function or procedure definitions and a main procedure. Functions and procedures consists of blocks, where a block is a set of statements. Statements are separated by semicolons, as opposed to languages like C or Java, where they are terminated by semicolons.

The following is an example of a complete SuperPascal program, which constructs a pipeline communication structure with 100 nodes. A master node sends an integer token to the first node, this is then passed along the pipeline and incremented at each step, and finally received by the master node and printed out.

program pipeline;

const
    len = 100;

type
    channel = *(integer);

var
    left, right: channel;
    value: integer;

procedure node(i: integer; left, right: channel);
var value: integer;
begin
    receive(left, value);
    send(right, value+1)
end;

procedure create(left, right: channel);
type row = array [0..len] of channel;
var c: row; i: integer;
begin
    c[0] := left;
    c[len] := right;
    for i := 1 to len-1 do
        open(c[i]);
    forall i := 1 to len do
        node(i, c[i-1], c[i])
end;

begin
    open(left, right);

    parallel
        send(left, 0) |
        create(left, right) |
        receive(right, value)
    end;

    writeln('The resulting value is ', value)
end.

Implementation
The SuperPascal software can be accessed freely from the Brinch Hansen Archive. It consists of a compiler and interpreter, which are both written in normal, sequential Pascal (ISO Level 1 standard Pascal). This is supported by the GNU Pascal compiler and newer versions of the Free Pascal compiler (2.7.1+) with the -Miso switch, with the following respective small modifications to the code.

For GPC, the file interpret.p uses the non-standard clock function (line 1786), which is used to obtain the system time. Instead, the Extended Pascal getTimeStamp function can be used (which is supported by the GNU Pascal compiler), by declaring a variable of type TimeStamp, setting that with the current time using getTimeStamp and assigning the Second field of the TimeStamp to the variable t.

Free Pascal also needs a solution to the above “clock” problem (On windows, just declare gettickcount as external with “clock” as name). In addition, the reset/rewrites that are marked as non-standard in the source need to be changed to assign/reset (or rewrite) pairs. (GPC probably only errors on this if you enable strict flags), and the C preprocessor commands #include ‘xx’ must be changed to {$include ‘xx’}.

There is now a FPC version of SuperPascal at https://github.com/octonion/superpascal, archived here.

 

DriverLynx DLPORTIO and Windows 7 and 8 and 64 bit

DriverLynx PortIO (DLLPORT.SYS) is needed on Windows NT and higher to access the I/O ports in a PC from a program, for example in Delphi.

Download here the driver installation and the Pascal unit.

Working examples, including the driverlynx driver and with Delphi example sources are on my Programs and PC ports pages

Alas, Windows 7 (and Vista) make it a bit more difficult to install this driver. It seems everything is allright running the installer (port95nt.exe), but running the program gives the error DLPORTIO.SYS is not loaded.

But it can be done as follows:

  • Right Click Port95nt.exe
    – Properties
    Compatibility
    – Run this program in compatibility mode for: Windows XP Service Pack 2
    – Run this program as an administrator

And now it does install and the program runs.

There is now a version of the inpout library DLPORTIO, usable form Delphi 7 as I have shown before, also for 64 bit (Windows 7 and 8.1):

http://www.highrez.co.uk/downloads/inpout32/

From Version 1.0.0.7, InpOut provides basic DLPortIO compatibility.

To use it, take the 32bit DLL (in \Windows x86) and rename it to DLPortIO.dll

Freepascal and Lazarus on Raspberry Pi

A page describing how to get the latest Freepascal and Lazarus development systems on all versions of the Raspberry Pi and Raspbian wheezy and jessie in optimal format, targeted at ARMV6 and ARMV7.

Pascal has been a comfortable programming language since I started programming in the 70ties. Coming from the Portable P2 and P4 compilers on Digital computers, made by the team of Niklaus Wirth, HP1000 Pascal, VAX/VMS Pascal via Turbo Pascal on MS-DOS and Delphi on Windows to Freepascal and Lazarus on the Raspberry. Now getting freepascal and Lazarus on the Pi is easy but you get quite old versions:

sudo su
apt-get install fp-compiler
apt-get install lazarus

On Raspbian wheezy you get Freepascal 2.6.0 and Lazarus 0.9.30.4. version dating from 2012. Working but not quite bleeding edge. Perfect for a first session! On Raspbian jessie you get more recent versions: Freepascal 2.6.4 and Lazarus 1.2.4. Much better! Note that for me Lazarus did not show up in the Programming menu on the desktop on jessie, but easy to add yourself with the menu editor (lazarus is located somewhere in /usr/local/). Freepascal is missing the character based fp IDE alas. And the programs compiled on the Raspberry Pi 2 B crashed on the older Raspberry Pi for me. So far so good for most of us. But not what I wanted. I have both Raspberry Pi’s Version 1 and the newer Version 2 systems. All systems run Lazarus on the desktop, but the older version 1 systems are running Lazarus quite slow due to the ARM V6 CPU and lack of memory. But the resulting programs are running fast enough, we have a real compiler here! What I want is:

compile and test on the Raspberry Pi 2 MB and enjoy the speed.
Run on all Raspberry Pi models, so limited to ARMV6.
Run on older wheezy and modern jessie Raspbian.
The RPi 2 has four ARM V7 cores, Freepascal and Lazarus will benefit in speed from this architecture if compiled for ARMV7.
So I set out to build images of Raspbian with more current versions of Freepascal and Lazarus on both latest Raspbian jessie and wheezy

Recipe for ARM V6 RPi versions 1 and 2 Model A, A+, B, B+, 2B
Recipe ARM V7 version 2 Model B
Building the latest version of Feepascal requires a seed compiler, version 2.6.4. This is available as binary for ARM, a generic version. The trick in building Lazarus is making sure the Freepascal compiler is targeted for the same architecture, so we have to build a Freepascal compiler for the same architecture,.

Setup a fresh system

First a fresh system, get the latest jessie and/or wheezy from raspberrypi.org. These are the steps I perform for a new system. My main system is a Windows system, I do most work from there, including remote access.

Image SD card (Win32DiskImager), 16GB minimal. 8 GB may work, but I often get problems with installing Lazarus due to out of disk space.

Boot and login (user pi, password raspberry) locally

With raspi-config at least change

Expand file system
Boot into commandline (desktop is in the way during the build!)
Change password – Overclock (medium for older, RPI2 voor RPi2 B)
Advanced options:
enable ssh
memory split to 16 MB, you can chage that back later for graphics work – change hostname and reboot
Get the IP address assigned to the Pi Type

 ifconfig 

and note the IP address assigned to the RPi. Now you can use PuTTY from Windows to access the command line of your Pi or continue on the RPi itself.

Get rights as root for the whole session

sudo su

Increase swapfile to prevent ‘out of memory’ during compilation

nano /etc/dphys-swapfile
/etc/init.d/dphys-swapfile stop
/etc/init.d/dphys-swapfile start
ls -lh /var

change from 100 to 1000 and check its 1000M now. Remember to cut that back to the default after the builds!

Get a current system

apt-get update
apt-get upgrade

Make some room,

Software I do not intend to use at all and take up a lot of disk space

apt-get -y purge wolfram-engine scratch minecraft-pi sonic-pi dillo gpicview penguinspuzzle
apt-get remove --purge oracle-java8-jdk openjdk-7-jre oracle-java7-jdk openjdk-8-jre
apt-get purge libreoffice*
sudo apt-get clean
sudo apt-get autoremove
apt-get remove fp-compiler
apt-het remove lazarus
apt-get -y autoremove 
apt-get -y clean 
df -h 

Get subversion and unzip

apt-get update
apt-get install subversion unzip

Get seed compiler fpc 2.6.4 installed

 
mkdir /usr/local/fpc 
cd /usr/local/fpc 
wget -O fpc-2.6.4.arm-linux.tar http://sourceforge.net/projects/freepascal/files/Linux/2.6.4/fpc-2.6.4.arm-linux.tar/download 
tar xvf fpc-2.6.4.arm-linux.tar 
cd fpc-2.6.4.arm-linux 
./install.sh 

answer location question from script with /usr/local, other questions with Y

ls /usr/local/lib/fpc y

to check it has 2.6.4

Cleanup

 
rm /usr/local/fpc/fpc-2.6.4.arm-linux.tar 

After installing FPC, type fp and use the IDE to enter and compile the first program:

program test ;

begin
  writeln('Hello world!');
end.

Save,as helloworld, build and run it with

./helloworld

Hello world!

screenshotARMv7

Raspberry Pi 2 Model B only! Resulting programs only run on RPi 2B!

Install fpc trunk (version 3.1.1 at the moment)

cd /usr/local/fpc
svn co http://svn.freepascal.org/svn/fpc/trunk source
cd source
make all OPT=-dFPC_ARMHF
make install OPT=-dFPC_ARMHF PREFIX=/usr/local
make install sourceinstall OPT=-dFPC_ARMHF PREFIX=/usr/local
ls /usr/local/lib/fpc

shows 2.6.4 and 3.1.1 present.

Now make fpc 3.1.1 available

rm -f "/usr/local/bin/ppcarm"
ln -sf "/usr/local/lib/fpc/3.1.1/ppcarm" "/usr/local/bin/ppcarm"

Install some packages

apt-get update
apt-get install -y libx11-dev libgdk-pixbuf2.0-dev libcairo2-dev gir1.2-coglpango-1.0 libpangox-1.0-dev xorg-dev libgtk2.0-dev libpango1.0-dev

Get the source

This time I show to get not the bleeding edge trunk Lazarus 1.5, but the fix 1.4.5 version.

mkdir /usr/local/lazarus
cd /usr/local/lazarus
svn co http://svn.freepascal.org/svn/lazarus/branches/fixes_1_4 source

cd source
make all OPT=-dFPC_ARMHF
make install OPT=-dFPC_ARMHF PREFIX=/usr/local

Now continue with the Post build steps!

ARMv6

Resulting programs run on all RPi’s! Install fpc trunk (version 3.1.1 at the moment)

cd /usr/local/fpc
svn co http://svn.freepascal.org/svn/fpc/trunk source
cd source
make all OPT="-dFPC_ARMHF -CpARMV6 -OpARMV6"
make install OPT="-dFPC_ARMHF -CpARMV6 -OpARMV6" PREFIX=/usr/local
make install sourceinstall OPT="-dFPC_ARMHF -CpARMV6 -OpARMV6" PREFIX=/usr/local
ls /usr/local/lib/fpc

shows 2.6.4 and 3.1.1 present Now make fpc 3.1.1 available

rm -f "/usr/local/bin/ppcarm"
ln -sf "/usr/local/lib/fpc/3.1.1/ppcarm" "/usr/local/bin/ppcarm"

Install some packages

apt-get update
apt-get install -y libx11-dev libgdk-pixbuf2.0-dev libcairo2-dev gir1.2-coglpango-1.0 libpangox-1.0-dev xorg-dev libgtk2.0-dev libpango1.0-dev

Get the source

mkdir /usr/local/lazarus
cd /usr/local/lazarus
svn co http://svn.freepascal.org/svn/lazarus/trunk source
cd source 
make all OPT="-dFPC_ARMHF -CpARMV6 -OpARMV6"
make install OPT="-dFPC_ARMHF -CpARMV6 -OpARMV6" PREFIX=/usr/local

Post build steps

Cleanup the source code

rm -rf /usr/local/lazarus

Set swapfile to default

nano /etc/dphys-swapfile
/etc/init.d/dphys-swapfile stop
/etc/init.d/dphys-swapfile start
ls -lh /var

change from 1000 to 100 and check its 100M now.

Fixing the GCC Library path

nano /etc/fpc.cfg

Change the line

# path to the gcclib

to

# path to the gcclib
-Fl/usr/lib/gcc/arm-linux-gnueabihf/4.6

Start Lazarus

You can start Lazarus from the desktop

startx

With jessie the Lazarus entry did not appear in the menu programming. Add this yourself with the Menu editor, browse the computer to find the lazarus executable in /usr/local/share/lazarus, the desktop icon is there also. Lazarus asks the first time run where the fpc sources are

/usr/local/fpc/source

Now you are ready to run! Resources from which I learned how to write the steps above! Thank you!

How to install Lazarus Pascal on Raspberry Pi 2 (Raspbian), Tweaking4All
Compiling the Latest Lazarus/Free Pascal for Raspberry Pi, Big Dan the Blogging Man
Raspberry Pi 2, FreePascal, Lazarus and Delphi, Simon J Stuart
http://forum.lazarus.freepascal.org/index.php?topic=30647.0