Lecture 20

Programming Languages


First generation:


The first computers had to be programmed directly in machine code. Binary numbers were placed in the memory by setting switches.


Second Generation:

By 1950, computers were being programmed in assembly language. As we saw earlier, one line in Assembly Language is translated into one machine instruction by a program called an assembler. At this time, computers were so expensive and slow that this was the only feasible method of programming.

Programs were completely machine dependent and writing a program was a very time consuming task. In order to simplify the writing of programs, small sections of commonly used code were collected together into libraries.

There would be libraries for maths and input/output operations amongst other things. The program responsible for combining a program and the libraries is called linker.

To run the program, another program called the loader was used to put the program into memory and start it (something like the main function of assignment 2).

The original program is called the source code. The program before linking is called the object code. The program after linking is called the executable.


Third Generation:

This generation of languages is machine independent and has to be translated into machine language by a translator. The translator takes high level primitives and compiles a sequence of machine instructions to perform the required function. The translators are often called compilers.

These languages are called high level languages. A program written in a high level language will almost certainly need to be linked with libraries.

Source code --Translate--> Object code --Link--> Executable --Load--> Running Program.

C is an example of a third generation compiled language.

Another approach to executing a program is called interpretation. A program called an interpreter translates source directly by emulating a machine which has the source language as its machine code. In assignment 2 you wrote an interpreter for a RISC machine.

Interpretation is often considerably slower than compilation, this is because translation must be performed each time the program is run. It is possible to write a program that is a combination of interpreter and compiler. This is sometimes called a Just In Time (JIT) compiler because it compiles sections of the program as it is being executed, i.e. just in time.

Java is an example of an interpreted language.

Fourth Generation

There are many definitions of fourth generation languages. In general it is a language that requires no programming knowledge to use. A database package may allow the development of a complex application without the need to write any source code. This is done by choosing from various pre-designed options and specifying what is to happen for particular events (sometimes called triggers).

Fifth Generation

The fifth generation of languages is used to refer to declarative programming languages. These languages represent a problem by concentrating on specifying the problem rather than concentrating on how to solve the problem. From a good specification the machine should be able to find a method to solve the problem itself. This is a rapidly developing area and although declarative languages are rather inefficient at the moment, expect this to change.


Describing languages using the idea of generations works badly after the third generation because in practice there has been a split into a number of programming methodologies (called programming paradigms).

The Imperative Paradigm

Machine Languages
Imperative languages use sequence, selection and iteration to write programs that tell the machine how to perform a task. The following program solves the 8 queens problem - how can you arrange 8 queens on a chess board so that they don't attack one another. Don't worry about the algorithm, just notice that the program uses sequence, selection, iteration and recursion.

The Object-Oriented Paradigm

Object-oriented languages force the programmer to concentrate on abstract data types.This is done by having imperative code associated with variables (called objects) and having a hierarchy of variable types (called classes).
The following program is written in C++, it finds a single solution. Notice that 'queen' is a class that holds information about a single queen. The class also has functions (called member functions) to move a queen -'advance' , print a list of queens -'print' and check if it attacks another square. The solution is stored in a linked list. You will find out more about Object Oriented Languages in 59201 and 59234.

The Functional Paradigm

Functional languages have no variables and use recursion to perform computation. The advantage of functional languages is that it is easier to prove that a functional program is correct than an imperative program. The following solution to 8 queens is written in Haskell, notice that queens is a recursive definition, qu 0 is an empty list. qu m+1 is defined in terms of qu m, 'safe' checks for all attacks and 'check' checks for a single attack.
You will find out more about Haskell in 59202 and 59301
Source Code

The Declarative Paradigm

A declarative or logic programming language is one that is based on a subset of mathematical logic. The computer is programmed to infer relationships between values rather than compute output values from input values.
The following solution to 8 queens is written in Prolog. Understanding Prolog programs is difficult if you are used to looking at imperative languages, because the program does not say how the solution is to be found. A program is just a list of facts (rules), the prolog interpreter 'runs' the program by trying to find values that make the query true using the rules.
You will find out more about Prolog in 59202 and 59301