Unit 3 - Principles of Programming Languages
Unit 3 - Principles of Programming Languages
int main()
{
printf("%d", g());
printf("\n");
return 0;
}
Output :
10
Dynamic Scoping: With dynamic scope, a global identifier refers to the identifier associated with the most
recent environment, and is uncommon in modern languages. In technical terms, this means that each
identifier has a global stack of bindings and the occurrence of a identifier is searched in the most recent
binding.
In simpler terms, in dynamic scoping the compiler first searches the current block and then successively all the
calling functions.
// Since dynamic scoping is very uncommon in
// the familiar languages, we consider the
// following pseudo code as our example. It
// prints 20 in a language that uses dynamic
// scoping.
int x = 10;
// Called by g()
int f()
{
return x;
}
// g() has its own variable
// named as x and calls f()
int g()
{
int x = 20;
return f();
}
main()
{
printf(g());
}
Output
20
iii. Pass-by-value-result
This passing method is actually a combination of pass-by-value and pass-by-result. The value of the actual
parameter is used to initialize the corresponding formal parameter, which then acts as a local variable. The
formal parameters must have local storage associated with the called subprogram. At termination, the
subprogram transmits the value of the formal parameter back to the actual parameter. As such, it uses in out-
mode semantics and copy passing conceptual model. Also, pass-by-value-result has the same advantages and
disadvantages as pass-by-value and pass-by-result with some more advantages. The largest extra advantage of
pass-by-value-result is that it solves pass-by-reference’s aliasing problems.
iv. Pass-by-reference
With pass-by-reference an address (reference to the memory location of the actual parameter) is passed to
the subprogram. It is another example of an inout-mode semantic.
Advantage- It is efficient in both time and space. This is no duplicate space required or copying.
Disadvantage – It increase the time to access formal parameters because of the additional level of indirect
addressing.
// Illustration of pass by reference
#include <iostream.h>
void square (int *x)
{
*x = (*x) * (*x);
}
int main ( )
{
int num = 10;
square(&num);
cout<<" Value of num is "<<num; // Value of num is 100
return 0;
}
As you can see the result will be that the value of a is 100. The idea is simple: the argument passed is the
address of the variable ‘num’. The parameter of ‘square’ function is a pointer pointing to type integer. The
address of ‘num’ is assigned to this pointer. You can analyze it as follows: &num is passed to int *x, therefore it
is the same as:
int *x = #
This means that ‘x’ is a pointer to an integer and has the address of the variable num.
Within the function we have: *x = (*x) * (*x);
* when used before a pointer will give the value stored at that particular address. Hence we find the product
of ‘num’ and store it in ‘num’ itself. i.e. the value of 100 is stored in the address of ‘num’ instead of 10 which
was originally present there. The diagram below illustrates the difference between pass by value and pass by
reference. Now when we dereference ‘x’ we are actually manipulating the value stored in ‘num’.
2. Type-Checking Parameters
It is now widely accepted that software reliability demands that the types of actual parameters be checked for
consistency with the types of the corresponding formal parameters.
Example
Result = sub1 (1)
The actual parameter is an integer constant. If the formal parameter of sub1 is a floating-point type, no
error will be detected without parameter type checking.
Early languages, such as Fortran 77 and the original version of C, did not require parameter type checking.
Pascal, FORTRAN 90, Java, and ADA: it is always required
Perl, PHP, and JavaScript do not have type checking.
5. Overloaded Subprograms
An overloaded operator is one that has multiple meanings. The types of its operands determine the
meaning of a particular instance of an overloaded operator.
For example, if the * operator has two floating-point operands in a Java program, it specifies floating-
point multiplication.
But if the same operator has two integer operands, it specifies integer multiplication.
An overloaded subprogram is a subprogram that has the same name as another subprogram in the
same referencing environment.
Every version of an overloaded subprogram must have a unique protocol; that is, it must be different
from the others in the number, order, or types of its parameters, or in its return if it is a function.
The meaning of a call to an overloaded subprogram is determined by the actual parameter list.
Users are also allowed to write multiple versions of subprograms with the same name in ADA, Java,
C++, and C#.
Overloaded subprograms that have default parameters can lead to ambiguous subprogram calls.
Function Overloading
If any class has multiple functions with same names but different parameters then they are said to be
overloaded. Function overloading allows you to use the same name for different functions, to perform, either
same or different functions in the same class.
Function overloading is usually used to enhance the readability of the program. If you have to perform one
single operation but with different number or types of arguments, then you can simply overload the function.
Example - int sum (int x, int y)
{
cout<<x+y;
}
Co-routines
A co-routine is a subprogram that has multiple entries and controls them itself
Also called symmetric control: caller and called co-routines are on a more equal basis
A co-routine call is named a resume
The first resume of a co-routine is to its beginning, but subsequent calls enter at the point just after the
last executed statement in the co-routine
Co-routines repeatedly resume each other, possibly forever
Co-routines provide quasi-concurrent execution of program units (the co-routines); their execution is
interleaved, but not overlapped
A B
Resume
Resume B Resume A
From master
Resume B Resume A
Resume B Resume A
First resume
Resume B
Resume A
subsquent resume