But Why?
Ask those of you who know.
What‽
Ask the most of you.
(It's funny, because you can't divide one person)
So what is this 'Pascal'?
Well, it's a programming language created in 1970 by Niklaus Wirth. It was one of the main programming language promoting the, at the time controversial, structured programming. While Wirth moved on and developed Modula and Oberon, Pascal still stayed in development.
It was very popular in it's time. Eventually tho, UNIX came and took C with it. C became the prominent language used by the cool programmers, and Pascal, while still competing, was more seen as the language you learn at school before you move to more serious language.
The final nail in Pascal's coffin was Delphi. A dialect of Pascal, that made few sad decisions and became replaced by Java and later C#.
While neither Pascal, nor Delphi ever truly died, you don't hear about them outside the history lesson anymore.
Well, multiple reasons.
First is my curse, which makes me very interested in some other language every time I decide to do something bigger in Lisp.
Second, less spiritual reason, is that I like computer history. I like learning about old computers, operating systems, programming languages and tech in general. I wanted to try some language popular back in the days to see how how much things evolved since then and how it evolved into current languages.
I don't count C, as I'm already familiar with it and most languages are based on it, so not that much to learn here as far as history goes.
When I think about old languages, few main come to mind. FORTRAN, COBOL, BASIC and pascal. Now also FORTH I guess, but I already played enough with this one for now.
COBOL is generally considered a good example of what not to do when writing a language. It tried to be very newbie friendly by being very verbose. I don't mind a bit of verbosity, but COBOL seems like a bit too much even for my taste. I will not do COBOL for now.
FORTRAN was originally developed to help mathematicians write code without knowing assembly. I looked a bit into FORTRAN before, and while it seems quite usable for math, I'm not sure I would want to use it for anything else. I don't have any complex math problems to solve, so I will not do FORTRAN for now.
BASIC was a very popular interpreted language for early home computers. It was basically used as a shell. It was designed to be user friendly, but not to the extend of COBOL. It does not look that bad, but I feel more like doing some lower-level compiled language now. BASIC would be more interesting on bare metal, or even in a emulator, but that is not what I want to do now. It certainly is on the list, but I will not do BASIC for now.
Pascal was popular at it's time, even with common people. This was the compiled language that you would use at home. It has many similarities with modern languages, that would be interesting to compare and modern languages seem to be starting to take inspiration from Pascal again. I will do Pascal now!
Well, I'm writing a little project with Raylib that will get it's own b-log later. Here, I will only talk about the language.
Here is a example hello world program:
program HelloWorld; {$mode objfpc}{$H+} { This code was written by De-Alchmst Feel free to steal as much as you'd like } const NUMBER = 5; var Hello: string = 'Hello'; World: string = 'World'; // procedures do not return values, functions do procedure SayHello(); var I, Count: integer; Greeting: string; begin Greeting := Hello + ', ' + World + '!'; for I := 0 to NUMBER do begin Count := I + 1; writeLn(Count, ' ', Greeting); end; end; begin SayHello; end. Outocme: 1 Hello, World! 2 Hello, World! 3 Hello, World! 4 Hello, World! 5 Hello, World! 6 Hello, World!
Ok, there are a few things to unpack here. First thing I would like to note is that Pascal is, just like a lot of languages at the time, case insensitive. This is how I do cases, feel free do disagree.
Second, Pascal is designed in such a way, that the compiler only needs to read the file once. This makes compilation faster, but it means that you can only refer to things defined before in the code.
Also, the compiler stops at the 'end.', so yes, it will compile even with the outcome after that.
As you can see, the code is structured into blocks.
First, you define 'program'. This is used by the compiler. It should be the same as your file name. Note, that it takes space in the namespace, so you can't name a variable 'HelloWorld' now.
You then define constants in the 'const' block and variables in the 'var' block.
Then the program code is written in the 'begin' block. Functions are separated into functions if they return a value or procedures, if they don't.
They can be anywhere, but again, can only call functions/procedures if they are defined before them. They can have their own private 'const' and 'var' blocks. In both definitions and calls, empty parenthesis can be omitted.
There are multiple ways to write comments. One is with the C style double '/' and the second ones use curly braces.
This also implies that you don't use curly braces for blocks, but instead, you use 'begin' - 'end;'. They are usually written on their own lines, so I will try doing that at least for now. I don't like doing that in C, but we'll see.
One more thing to mention is the '{$mode objfpc}{$H+}' Pascal has it's own preprocessor. It can also be used to define compiler behavior. I should probably mention that I use the free pascal compiler. You can read what these options do here.
One of the things I like about modern Pascal is the build system, or rather the lack of.
You could specify the compiler options described above by compiler flags, but you don't have to. Unlike C, Pascal uses quite nice unit system, which automatically finds, recompiles (if needed) and links all parts of your code, without having to specify if all.
This is a example usage of a unit:
----- Main.pas ----- program Main; {$mode objfpc}{$H+} // additional units seperated by ',' uses Hello; var Name: string; I: integer; begin Name := 'World'; for I := 0 to NUM do Greet(Name); end. ----- Hello.pas ----- unit Hello; interface const NUM = 5; procedure Greet(Name: string); implementation procedure Greet(Name: string); begin writeLn('Hello, ' + name + '!'); end; initialization writeLn('PROGRAM STARTS NOW'); end. to compile this program, simply run $ fpc Main.pas
Units are separated into two sections: 'interface' and 'implementation'.
In 'interface' you only define headers of all functions/procedures that you want to export. You then define them properly in 'implementation'.
Both sections can have their own 'var' and 'const' blocks, which are either private, or public. You don't have to repeat these.
Finally, units can ave two bonus sections: 'initialization' and 'finalization', that are called at the start and the end of the program respectively.
It reminds me a bit of hardcore C# style OOP, but it does not get in the way.
Pascal also has a 'type' block. Here you can define records (structs):
type TPoint = record X,Y,Z : integer; end;
You can also define other types of types. You can either define just a synonym for a existing type to better controll function arguments, or even a range:
type TScore = integer; THealthPoints = 0..100;
Also note the I prefix type names with 'T'. If I didn't, I could not have a variable named 'Point', so I name it 'TPoint' to avoid that.
You can also do enums like this:
type TDirections = (UP, RIGHT, DOWN, LEFT);
C bindings are actually quite easy. First, you say the name of the library, for example:
{$linklib libraylib}
and load the C types:
uses ctypes;
Then you can declare a functions in the 'interface' section like so:
procedure SetTargetFPS(fps: integer); external;
Note that in this specific situation, the case matters. The name must match the C name. If you don't want the names to be same, you can do it like so:
procedure SetFps(fps: integer); external; name = 'SetTargetFPS'
You actually don't need to use the C types for arguments here, but I reccommend to use them in record definitions.
TRectangle = record X, Y, Width, Height : cfloat; end;
Some other things I would like to mention:
You have two types of arrays: dynamic, indexed from 0 and static, defined from starting and ending index. Yes, you can make a array indexed from -47 to 40.
You don't have '+=' and '-='. You do have 'ind' and 'dec'. They only work on ints tho.
Records are treated as a value, not a link. You can pass them by value by prefixing the arguments with 'var'.
You have a 'with' statement that works like in python.
You also have 'for..in' loop. You can not create anonymou record instances to give as arguments. You have to define a variable, or a constant.
'case' statement can also take ranges.
Strings can only be defined with single quotes. Double quotes are not used for anything.
'/' is used for division of floats and 'div' for division of integers.
I have only written vary few Pascal by now. That is why it's called "First impressions". I do have opinions tho.
It's minimalistic. It does not support functional programming and what not. It does have OOP, tho a bit glued in, but it does not support a lot of things. That is not a bad thing tho. I like simple.
It's not too low-level. You get resizable arrays, string concatenation, fancy type system... It does not feel too bare-bones.
It does not get in your way. Well, at least not into mine. My coding style consists of a lot of procedures, lot of globals they operate on and minimal amount of OOP.
Some languages, like crystal, really don't like this. Pascal seems quite aligned with this approach. It might get a bit too annoying to write all variables in the 'var' block if you write long functions, but I prefer a lot of short ones, so that is not a problem for me.
Sure, it's a bit aged, but I enjoyed it so far.