You are on page 1of 50

PROCEDURAL PARADIGM

ALGOL - 2ND GENERATION


LANGUAGE
History

- in the mid 1950s it became apparent to many


scientists that a universal, machine indepedent
programming language would be valuable.
- in 1958 a preliminary specification of the language
was published in Communications of ACM.
- several dialects of ALGOL-58 were implemented
(NELIAC, JOVIAL)
- in 1960 the final report on ALGOL -> ALGOL-60
- the ALGOL-60 was a very simple and clear language
(only 15 pages of BNF compared to other language
descriptions that stretched over hundreds and
sometimes thousands of pages)
- the language specification was done using the BNF
notation
Program Structure

- one of the major contributions of ALGOL-60 was that it


used a hierarchical structure throughout its design.
- unlike FORTRAN which allowed only the DO-loop to be
nested, ALGOL-60 allows nested control structures (such as
the FOR-loop) and nested environments - this significantly
reduces the need to use the GOTO statements in programs
- the statements are of two types:

declarative statements
imperative statements

- the declarative statements were used for variable


declarations, procedure declarations and switch
declarations
- the imperative statements were either computational or
control-flow
- major problem: there were no input-output statements!
- the only computational statement was the assignment of the
form variable := expression
- major contributions of ALGOL:
1) the assignment operation was different from the
one used in FORTRAN as it used := rather =
2) the use of the block structure which allows for
nested scopes - this allowed one to use a sequence of
statements whenever one was permitted by simply
enclosing the statements using BEGIN-END

- the fact that one statement can be replaced by a


sequence of statements is a good example of regularity
in the design of the languages:

a regular language is far easier to learn and there


are fewer exceptions that have to be memorised

- each block defines a nested scope


- the advantage of the nested scope is that the variables
are "visible" throughout the scope of the block
- FORTRAN had only disjoint scopes and the variables were
bound to the inner scopes of the subprograms - common
blocks were essentially defined at a global level but
they still had to be re-declared in each subprogram
- ALGOL through the implementation of the block structure
avoids variable re-declaration by allowing the programmer
to define any number of scopes to any depth
- the great advantage of the block structure is that allows
larger programs to be written faster with less errors -
though the common blocks allows data to be shared between
subprograms, they had to be declared in each subprogram
which lead to repetition of code (violates the abstraction
principle) and errors (from misspelling)
- allows for both dynamic and static scoping in the programs
- dynamic scoping:

the meanings of the statements and expressions


are determined by the dynamic structure of the
computations evolving in time

- static scoping:

the meaning of the statements and expressions


are determined by the static nature of the program
- the block allows efficient storage management on a stack

Syntax
- the syntax was greatly improved when compared with that of
the first generation languages

- ALGOL-60 still had the old control statements such as IF-


THEN and GOTO

- it also had a FOR-loop, a WHILE-loop and it introduced the


SWITCH statement to handle multiple cases

- the syntax was machine independent

- the variable names did not have restrictions on the number


of characters used

- ALGOL-60 introduced the concept of keywords which made the


syntax more readable and easier to understand while
eliminating errors resulting from the use of keywords as
variable names
Data Types and Structures

- three data types: integer, real and boolean


- lacked a double precision type (machine dependent) and a
complex data type (not primitive data type)
- regularity was a major goal of ALGOL-60
- regularity principle:

regular rules, without exceptions, are easier to


learn, use, describe and implement
- a special application of the regularity principle is the
zero-one-infinity principle:

the only reasonable numbers in a programming


languages design are zero, one and infinity

- arrays in ALGOL are generalized (more than 3 dimensions are


allowed and the bounds can be lower than 0 - [-100:200])
and dynamic (size of the required array is computed at
runtime and allocated as necessary)
- arrays in ALGOL can be indexed only by integers
- ALGOL-60 had strong typing and keywords
- unlike FORTRAN, ALGOL was designed to allow recursion
- communication is done by parameter passing
- two methods of passing parameters:

pass by value
pass by name

- pass by value has no side effects (the value of the


actual parameter cannot be modified) but it can be
very expensive when dealing arrays - all the values
in the array copied rather than just the reference to
the first element in the array

- pass by name uses substitution to prevent naming


conflicts between input-output parameters - it is
powerful but also dangerous and expensive
2nd Generation Languages

- were characterized by:


- use of the block structure
- structured control structures which eliminate much of
the need for confusing networks of GOTO statements by
hierarchically structuring the control flow
- the syntax structures were free format with machine
independent lexical conventions (reserved words)
Parameter Passing Techniques
- the two best known parameter passing methods are
call-by-value and call-by-reference
- the call-by-value has the advantage that the actual
parameter value is not modified
- the call-by-reference has the advantage that it is
very efficient when dealing scalar data structures
such as arrays
- still the two methods have some disadvantages which
lead to attempts to use other parameter passing
techniques
- ADA provides the best parameter passing methods as it
lets the programmer decide what access is allowed to
the parameter while still maintaining very good
efficiency
Call by Value

x = 5;

• The value of the actual


Sub(x + 6);
parameter is copied into
the formal parameter
Print X;
• Y is assigned the value of
X + 6 which is 11
• When the statement Print X Sub(val y : Y)
is executed, the value of y
X is still 5
y := y + 1;
Call by Reference
• Reference to the actual x x:=5;
parameter is copied into
the formal parameter Sub(x);
• Before the subroutine
Sub(x) is called, the Print x;
value of x is 5
• When Sub(x) is called, the
variable y gets the
address of x
• Hence when y:=y+1 is
computed, the resulting y
value (6) is put into x s
memory location
y := y + 1;
• When Print x is executed
the value of x is 6

Sub(ref y : Y)
CALL BY RESULT
- used in ADA to implement out mode parameters
- formal paramater acts as an un-initialised local variable
which is given a value during the execution of the procedure
- on leaving the procedure, the value of the formal parameter is
assigned to the actual parameter which must be a variable

Procedure Read_Negative_data(neg_number : out integer)


number : integer;
Begin
get(number);
while number >= 0 loop
put_line(“nuumber not negative, try again )
get(number);
end loop;
neg_number := number;
End Read_Negative;

Read_Negative(amount);

- thevalue of the integer variable amount is not updated to the


value of neg_number until procedure Read_Negative is left
CALL BY VALUE-RESULT
- amalgamation of call by value and call by result.
- the formal parameter acts as a local variable which is
initialised to the value of the actual parameter.
- within the procedure, changes to the formal parameter affect
only the local copy.
- when the procedure completes its execution, the actual
parameter is updated to the final value of the formal parameter.
Procedure Update(balance: in out integer)
transaction : integer;
Begin
for j in 1..10 loop
get(transaction);
balance := balance + transaction;
end loop;
End Update;

Update(currentaccount);

- the actual parameter currentaccount is only updated when the


procedure is Update completes its execution.
Static Scoping

• the scope of program variable is the range of statements


in which the variable is visible
• the scope rules of a language determine how a particular
occurrence of a name is associated with a variable
• a variable is considered to be local in a program if it
is declared there
• the non-local variables in a program are those variables
that are visible within the program but are not declared
there
• ALGOL-60 introduced a method of binding names to the non-
local variables called static scoping - this method has
been in used in some form by most of the languages
designed after ALGOL
• the visibility of the identifiers and the process of
binding of names to declarations is determined at compile
time - this is known as static scoping
Static Scoping

• the advantage of static scope is that it allows type


checking to be performed by the compiler
• static scoping also allows programmers to determine the
connection binding between the use of identifier and its
declaration

• consider the example of the ALGOL code shown below:

a:begin integer m;
procedure P;
m := 1;
b:begin integer m;
P; -> call 1;
end;
P; -> call 2;
end
Static Scoping Example

m (a)
P

SL DL (b)
m Call P - call one

SL DL (P)
m := 1

- m : = 1 refers to the variable declaration in the outer


block a (for both calls)
- the contour of P is nested in inside block a even though
it is called from block b
Dynamic Scoping
• in dynamic scoping, the binding between the use of an
identifier and its declaration depends on the execution of
the program and therefore it is delayed until run-time
• the correct attributes of a non-local variable visible to a
program statement cannot be determined statically
• a statement in a subroutine that contains a reference to
non-local variable can potentially refer to a differ
variable entry every time the statement is executed by the
program
• there are two major problems with dynamic scoping:
• there is no way to statically type-check references to
non-locals

dynamic scoping makes programs a lot more difficult to


read
- during the time the subprogram is executed the local
variables of the subprogram are visible to any other
executing subprogram there is no way to protect local
variables from such accessibility
Dynamic Scoping - Example 1

m (a)
P Call P - call two

SL DL (P)

m := 1

m := 1 refers to the m declared in block a


Dynamic Scoping - Example 2

m (a)
P

m (b)
Call P - call one
SL DL
P
m := 1

m := 1 refers to the variable declared in block b


Pointers
- a pointer type is one in which the variables consists of a
memory address and a special value: NIL - the value NIL is
not a valid address and is used to indicate that the
pointer cannot be currently be used to reference another
object
- the pointer types have been designed for two uses:
to provide some of the power of indirect addressing used
in assembly language

to provide a method of dynamic storage management


- an occurrence of a pointer can be interpreted in two ways:
as a reference to the contents of memory cell to which
the variable is bound (which is an address) - normal
pointer

as a reference to the value in the memory cell whose


address is in the memory to which the variable is bound
- dereferencing pointer
Pointers
• pointers point to objects
• they are most often used to implement dynamic structures
such linked lists and binary trees
• pointers are variables
• pointers hold:
addresses or
hold addresses of variables or
hold addresses of subprograms
- a pointer is usually given it s value by taking the
address of a variable or subprogram

pointer-variable =

Address-of(variable-name)

pointer-variable =

Address-of(function-name)
Pointers

• Dereferencing a pointer is the process of following the


pointer to the variable or subprogram whose address it
holds

<Dereference(pointer-variable)>

- a pointer variable may have the null value which indicates


that the pointer is not pointing to a variable or
subprogram - this is known as a dangling pointer
- it is illegal to attempt to dereference a pointer when it
contains the null value
- incorrect use of pointers can also lead situations where
memory areas are allocated but become inaccessible - such
programs are to have “memory leaks”
- to deal with problem of dangling pointers one can use
tombstones
- to deal with the problem of memory leaks one can use
reference counters or garbage collection
Example of a Memory Leak

memory allocated
A := B
but not accessible

B
Example of a Dangling Pointer
memory allocated
but not accessible

B
memory allocated
delete A
but not accessible

B
memory
deallocated
Pointers vs References

- C++ includes a special kind of pointer type that is used


primarily for the parameters in function definitions:
references
• pointers:
the value of the pointer variable (ie where it points to) can
be changed

the value of the variable the pointer points to can also be


changed

- references are constant pointers:


reference pointed at something and cannot be moved

the value of the variable the reference points to can be


changed
Pointers vs References

6
Pointer Pointer Variable

Variable 12
Variable

function2
Reference
Reference Variable

Constant M

Variable
Pointers vs References

10
Pointer
Pointer Variable

Variable 20
Variable

Reference function1

Reference Variable

Constant H

Variable
Strong and Weak Typing

• strong typing is very important when considering


language design as it helps eliminate errors before run-
time
• there is no actual definition for a strongly defined
language: essentially a strongly defined language is a
language in which each name in a program has only a
single type associated with it and that type is known at
compile time
• the advantage of strong typing is that the type of
variables known at compile time and the compiler can
catch errors
such assigning character values to an integer array
- weak typing means the type of variable may not be known
until run-time and as a result errors may go
undetected
e.g. equivalence statements in FORTRAN (integer sharing
the same memory space with real)
Activation Record - Concepts
• ALGOL allows procedures to be recursive and it is possible that
there may be several instances of the same procedure active at
one time
• what is needed is a method for the dynamic creation of
activation records to hold these instances
• to know the state of the procedure activation it is necessary
to know:
the code that makes up the body of the procedure
the place in the code where the activation of the procedure is
now executing
the value of the variables visible to this activation
- the code does not vary between different instances of
the execution of the procedure so it is not necessary to
include it in the activation record
- hence the activation record contains the variable parts which
define a particular execution of a subprogram
Instruction Part (IP)
Environment Part (EP)
Activation Record - Concepts

• the instruction part (or instruction pointer) designates


the current instruction being (or to be) executed in
this activation of the subprogram
• the environment part defines both the local and non-
local context to be used for this activation of the
subprogram - it determines how the instructions are
interpreted
• the context of the statements contained in a procedure
is simple: it is the names declared in that procedure
together with the names declared in the surrounding
procedures
• in case a name is declared more than once, then its
innermost binding is the one that is seen
• if one wishes to look up a name, the one has to see if
it is in the local environment - if it is, then that
binding is used, otherwise one has to look in the
surrounding environment (this is done until a binding is
found or an error is flagged)
Activation Records - Concepts

• the local context contains: local variables, actual parameters


and register
• when a subprogram is called, it must provide some
reference to the calling program so that it will know
which caller to resume when it completed its execution
• a very simple way to do this is to provide a pointer to
the calling program activation record - the pointer is
stored in the activation record of the subprogram
invoked and it is known as dynamic link
• a sequence of dynamic links that reach from the callee
to the caller is known as a dynamic chain
• the dynamic link is a pointer to the top of the
activation record of the caller - in statically scoped
languages, this link is used in the destruction of the
current activation record when the procedure finishes
its processing
Activation Records - Concepts

• a static link (static scope pointer), points to the bottom of


the activation record instance of an activation of the static
parent
• the non-local context contains: the dynamic call sequence (or
dynamic chain) and the static scope
• there are two ways to access non-local variables in statically
scoped languages: using static chains or using displays
• the static chains technique
• the actual address of a variable may change with each execution
• however, all variables that can be accessed non-locally are in
an existing activation record somewhere in the stack
• step 1 - find the instance of the activation record in which
the variable was allocated
in a given subprogram only variables that are declared
static ancestor scopes can be non-locally accessed – the search
is guided by enclosing scope, starting with the most closely
nested first
- step 2 - use the local offset of the variable within the
activation record to access it
Activation Records - Concepts
• finding the correct activation record instance of a non-local
variable is simple - it involves searching the static chain
until a static ancestor activation record instance that
contains the variable is found
• still, it is easier than that:
because the nesting level is known at compile time, the
compiler can determine if a variable is non-local but also
the length of the chain needed to reach the activation
record instance containing the non-local variable
- let static-depth be an integer associated with a static
scope that indicates how deeply it is nested in the
outermost scope
- the length of the static chain needed to reach the
correct activation record instance for a non-local
variable X is the difference between the static depth of
the procedure containing the reference to the variable X
and the static depth of the procedure containing the
declaration of X
- the difference is called the nesting depth, or chain-
offset
Activation Records - Concepts

• the static chain technique has the disadvantage that the


access to a non-local variable in scopes beyond the static
parent is costly
• furthermore, it is difficult for a programmer working on a
time critical program to estimate the costs of non-local
references, as the cost of each reference depends on the
depth of the nesting between the reference and the scope of
declaration
• the display technique
• the static links are collected in a single array called a
display rather than being stored in the activation records
• the contents of the display at any specific time is a list
of addresses of the accessible activation record instances
in the stack, one for each scope, in the order in which
they are nested
• access to non-local variables using a display requires only
two steps regardless of the number of scope levels between
the reference and the declaration of the variable
Activation Records - Concepts
• the static chain technique has the disadvantage that the access
to a non-local variable in scopes beyond the static parent is
costly
• step 1: the link to the correct activation record which resides
in the display is found using a statically computed value
called the display-offset which is closely related to the
chain-offset
• the local-offset within the activation record instance is
computed and used in the same way as in the static chain
implementation
• a non-local reference is represented by an ordered pair of
integers - [display-offset|local-offset]
• all subroutine invoked/ended requires the display be modified
to indicate the new scope situation
• a subroutine termination also requires the saved pointer in the
activation record instance of the terminating subroutine to be
placed back in the display
• a pointer at position N in the display points to an activation
record instance for a procedure with a static depth of N
• the disadvantage of the display method is that it requires
extra memory for the array implementing the display
Activation Record

Address Instruction Pointer

x | y | z[0] z[1] ... Local Variables

m | n | p | functptr Formal Parameters

R1 | R2 | R3 | X | Y | Z Register Store

Pointer Dynamic Link

Pointer Static Link


Dynamic Chain - Example

Sub 1

Sub 2

Sub 3
Sub 4

Sub 5 Sub 1
AR #1
Dynamic Chain - Example

Sub 1

Sub 2

Sub 3
Sub 4
Sub 2
AR #2
Sub 5 Sub 1
AR #1
Dynamic Chain - Example

Sub 1

Sub 2

Sub 3 Sub 3
AR #3
Sub 4
Sub 2
AR #2
Sub 5 Sub 1
AR #1
Dynamic Chain - Example

Sub 1

Sub 2
Sub 4
AR #4
Sub 3 Sub 3
AR #3
Sub 4
Sub 2
AR #2
Sub 5 Sub 1
AR #1
Dynamic Chain - Example

Sub 1
Sub 4
Sub 2 AR #5
Sub 4
AR #4
Sub 3 Sub 3
AR #3
Sub 4
Sub 2
AR #2
Sub 5 Sub 1
AR #1
Dynamic Chain - Example

Sub 2
Sub 1 AR #6
Sub 4
Sub 2 AR #5
Sub 4
AR #4
Sub 3 Sub 3
AR #3
Sub 4
Sub 2
AR #2
Sub 5 Sub 1
AR #1
Static Chain - Example

Sub 1 [0]

Sub 2 [1]

Sub 3 [1]
Sub 4 [2]

Sub 5 [2] Sub 1 [0]


AR #1
Static Chain - Example

Sub 1 [0]

Sub 2 [1]

Sub 3 [1] Sub 2 @ 1

Sub 4 [2] Sub 1 @ 0


Sub 2 [1]
Therefore AR #2
Sub 5 [2] assign this Sub 1 [0]
AR to the AR #1
static link
Static Chain - Example

Sub 1 [0]

Sub 2 [1]

Sub 3 [1] Sub 3 @ 1 Sub 3 [1]


AR #3
Sub 4 [2] Sub 2 @ 1
Sub 2 [1]
Therefore AR #2
Sub 5 [2] assign same Sub 1 [0]
AR to the AR #1
static link
Static Chain - Example

Sub 1 [0]

Sub 2 [1]
Sub 4 @ 2 Sub 4 [2]
AR #4
Sub 3 [1] Sub 3 @ 1 Sub 3 [1]
AR #3
Sub 4 [2] Therefore
assign this Sub 2 [1]
AR to the AR #2
Sub 5 [2] static link Sub 1 [0]
AR #1
Static Chain - Example

Sub 1 [0]
Sub 4 @ 2 Sub 4 [2]
Sub 2 [1] AR #5
Sub 4 @ 2
Sub 4 [2]
Therefore AR #4
Sub 3 [1] assign same Sub 3 [1]
AR to this AR #3
Sub 4 [2] static link
Sub 2 [1]
AR #2
Sub 5 [2] Sub 1 [0]
AR #1
Static Chain - Example

Sub 2 @ 1 Sub 2 [1]


Sub 1 [0] AR #6
Sub 4 @ 2 Sub 4 [2]
Sub 2 [1] AR #5
Therefore
assign next Sub 4 [2]
AR up the AR #4
Sub 3 [1] static chain Sub 3 [1]
AR #3
Sub 4 [2]
Sub 2 [1]
AR #2
Sub 5 [2] Sub 1 [0]
AR #1
Steps to Calling a Procedure

Save caller’s state


Transmit parameters to callee
Establish callee’s dynamic link
Establish callee’s static link
Enter the callee

Steps to Exiting a Procedure

Delete callee’s state


Restore the state of caller
Continue execution of the caller at the saved
Instruction Pointer address