Bjarne Stroustrup and James Gosling both credit it as a major influence in the design of their languages. Built on top of Algol 60, it is the progenitor of the most popular, and reviled program paradigm, Object Oriented Programming. Designed by Ole-Johan Dahl, and Kristen Nygaard in 1962 at the Norwegian Computing Center in Oslo, it easily cracks the top 10 most influential computer programming languages ever invented. But in 2023 it is a distant memory. Having never reached the popularity of older languages still in use like Fortran, Lisp, and COBOL, I was curious to see what programming in this 60+ year old language would look like. But first I’d have to find a way to run it.
Finding an implementation 🕵️
It usually isn’t too hard to find working implementation of just about any programming language you want, even the old ones, but Simula’s was harder than I was used to. After extensive searching I stumbled upon Gnu Cim1. The landing page for Gnu Cim said…
See the software page for information on obtaining GNU Cim and other GNU software.
Great! Exactly what I was looking for. I clicked the link, scrolled down to the “All GNU Packages” section, and clinked on the Cim link (Lol). Annnd it sends me right back to the original Gnu Cim landing page. Not to be deterred, I did some more digging until I came across an FTP site with multiple versions of GNU Cim2. I saw a Win32 folder in the directory and clicked it.
I looked at the install.txt for the Windows folder, noticed the note for Windows 95/98 users, and immediately decide to just use WSL instead.
I download the tar.gz…
I run
tar -xzf
I
cd
into the unzipped folder and read the INSTALL fileI do the simple install with
./configure
,make
, andmake install
And I read the installed documentation using
info cim
At this point I’m feeling like a real graybeard. I only have one thing left to do. I fire up Nano, type the magic incantation…
begin
Outtext("Simula does it in C");
Outimage;
end
and…
I know nothing about C, and a segfault is pretty cryptic. I try it on my RPI 4 to make sure it isn't an WSL thing but that doesn't work either. So, it's back to looking for another implementation. After a few more failed attempts I find a browser based Simula compiler3. But unfortunately, when I try to type in some examples, I get a bunch of errors. After much searching, I do end up finding a version that works4. It's called Portable Simula, and it's based off the 1985 Simula standard. It requires openJDK 19 for some of its features but after downloading and running java -jar simula.jar
I’m finally greeted with a working Simula Environment.
The language 🗣️
Portable Simula conveniently gives us an editing environment along with the language. It provides basic functionality like saving, syntax highlighting, and even allows us to build and run the program from within the editor. It also provides us with a variety of sample programs written in Simula for us to study. The website comes with a document for the language standard5, complete with Backus-Naur notation, and a 200+ page text book6 to get us started.
Simula operates on blocks of code. Following in the footsteps of our programming ancestors we can invoke the sacred “Hello World” program by typing…
begin
OutText("Hello World!");
comment my first program;
end;
While later programming languages would use curly braces and whitespace, Simula uses keywords to denote logical blocks of code, which was common at the time. Furthermore, everything not enclosed in double quotes is interpreted as uppercase, so both beGIN
and BEGIN
are interpreted the same way. This was also characteristic of the time, as programmers programmed their computers by shouting. OutText
is a built-in function. It works like print
in other languages. Simula calls these functions System Procedures, or just procedures. Statements end with a semicolon and comments start with the keyword comment
.
Simula can work with numbers as well as text. Below we can see an example adding two numbers together.
begin
integer Int1,Int2;
integer Result;
Int1:=3;
Int2:=4;
Result := Int1 + Int2;
OutInt(Result, 1);
OutImage
end
Note that integers can be declared on 1 line as shown with integer Int1,Int2;
or by itself as shown with integer Result;
The variables can be assigned values with the :=
operator. OutInt
is used to “print” the integer, and OutImage is called to build the final Simula “Image”. From my digging it appears that OutImage is usually necessary at the end of a block, or a compiler error will be generated. I initially forgot OutImage
though so, I imagine that maybe Portable Simula is just implicitly adding this if it’s missing, or it was changed in a later standard. Regardless I’ll leave it in from now.
Working with text in Simula is a little different than with numbers. You can’t just do
begin
Text message;
message := "Howdy";
OutText(message);
OutImage;
end
As you will get a runtime error. Instead you need to swap “:=” with “:-” like this
begin
Text message;
message :- "Howdy";
OutText(message);
OutImage;
end
The reason we have to use “:-” instead of “:=” is because we can’t assign a string to a text variable that is longer than the text variables length. Referring to our Simula text book we see this note about text.
Strictly speaking the location reserved for the text variable holds a reference to a sequence of
characters. These characters are known as a text frame. A text reference contains a pointer to its text
frame plus related variables and procedures.
So a text frame needs to be large enough to hold the characters you want it to. In the first example
Text message;
message := "Howdy";
The message variable’s length
is 0. In the second example, message is given the value of “Howdy” and the text frame contains enough space for its 5 characters.
message :- "Howdy";
OutText(message);
Now that message has a value and a length > 0, you can mutate it.
begin
Text message;
message :- "Howdy";
message := "Hi";
OutText(message);
OutImage;
end
Mutating a text variable with :=
does not automatically update the “length” property of a text variable. If you were to call message.Length
you will see that it is still 5.
If in the above example you were to try to assign message to a string longer than 5 like for example “Hello There”, you will get a runtime error.
Text frames also have positions. Positions are the location of the next character that will be read with the GetChar
method.
Defining functions (or procedures in Simula parlance) is different then you may be used to.
begin
procedure SayHello;
comment Keyword Procedure;
OutText("Hi There");
procedure Square(T); Integer T;
begin
OutInt(T*T,4);
OutImage;
end--of--square--proc;
procedure Add(num1,num2,result);
! Adds to numbers together and stores in result;
name result; Integer num1,num2,result;
begin
result := num1 + num2;
end;
Integer result;
OutText("SayHello: ");
SayHello;
OutText(" Square: ");
Square(10);
OutText("Add: ");
Add(100, 200,result);
OutInt(result,4);
OutImage
end
SayHello
is the simplest procedure, returning nothing and requiring no arguments. Simula calls these procedures Keyword procedures. Since it requires no arguments, it is called without (). Trying to call it with () results in a runtime error.
Square
takes one argument and prints the square of the argument. We add the variable names in between the “()”. Everything after the (); is considered inside of the function body, and that is where we declare the types for are arguments. It’s common to keep this on the same line if the arguments are short enough. Large Simula programs can use a lot of begin
and end
blocks so it can be difficult to keep track of all of them. It is customary in larger programs to see end
blocks decorated with a comment as in end--of--square--proc
to keep track of them. “--
” is the 2nd of many ways to create comments in the language.
Finally Add
shows how we can get a result back from a function. There are three modes a variable can take when being passed into a function.
Simple Types are integer, real, character or Boolean. The mode they default to when used in a function is Value. This means that any changes to them are not permanent and go away once the program exits the function’s scope.
Reference
is actually the default mode for most types passed into functions in Simula. According to the documentation
When a parameter is passed by reference, the local parameter points at the location holding the object passed, rather as if the :- reference assignment operator had been used. No local copy is made of the contents of the object
This is true for all reference types except text, as the same text frame is referenced even when new pos and length properties are created.
Name
is Simula’s way of declaring that a variable is being passed by reference to a function. It’s useful when you want to get the result of the modification back from the function like we do in the Add
function. It works almost exactly like an out parameter in C#.
Now that we have a basic understanding of Simula, lets look at classes. Using the example below…
begin
class Address;
begin
text Nam, Street, Town, State, Code;
procedure initialize(fullName, road, city, yourState, zip);
text fullName, road, city, yourState, zip;
begin
Nam:- fullName;
Street:- road;
Town:- city;
State:- yourState;
Code:- zip;
end;
procedure printAddress;
begin
OutText(Nam);
OutText(" ");
OutText(Street);
OutText(" ");
OutText(Town);
OutText(", ");
OutText(State);
OutText(" ");
OutText(Code);
end;
end--of--class--Address;
! handling the class;
ref(Address) Addr;! Declare a pointer to Address;
Addr:- new Address;! Create an Address object and point Addr at it;
! " Remote" Access. AKA how Simula accesses methods;
Addr.initialize("Will Smith","805 St. Cloud Road","Bel Air","California","21014")
Addr.printAddress;
OutImage;
end
We see that classes can take procedures. The first procedure is initialization
. It not treated specially like constructors in modern languages, but it does allow us to initialize the variables of our class without having to assign each variable on a separate line. Variables defined in a class can be accessed directly without the need of prefixing themselves with “self.var
” or “this.var
”. Procedures are defined like normal, just inside of the class block. Before initializing the class, we have to create a pointer to the class using ref(Address)
. We instantiate the address class with new
and we initialize it by calling our initialize method. Finally, we call out printAddress
function without (), to see our Address.
Closing Thoughts📕
I’m really glad I was able to find a working implementation of Simula and experience this piece of programming history. I’ve only briefly touched on the language, but I hope I’ve kick started your interest in it. I would encourage everyone to download Portable Simula and give it a try themselves. Let me know what you think? It just might inspire you to write your own language 😉
As for why it wasn’t more popular, Bjarne Stroustrup mentioned that it was slow for the time, which is what ultimately led him to create C++ instead of continuing to use Simula. He would begin 11 years after the release of Simula 67. By 1983 his “C with classes” programming language would be renamed to C++. Then, in 1991 another language would enter the playing field, Java, and the rest is history. But while Simula would never reach the success of its peers, the techniques it pioneered, Objects, Classes, Inheritance, still live on today.
Call To Action 📣
If you made it this far thanks for reading! If you are new welcome! I’ve recently started a Twitter and would love for you to check it out. If you liked the article, consider liking and subscribing. And if you haven’t why not check out another article of mine! Thank you for your valuable time.