Subprograms & Blocks
Unit – 3
Subprograms: Fundamentals of subprograms, design
issues for subprograms, local referencing environments,
parameter passing methods, parameters that are
subprograms, calling subprograms indirectly,
overloaded subprograms, generic subprograms, design
issues for functions, user defined overloaded operators,
closures, co routines.
Implementing subprograms: General semantics of
calls and returns, implementing simple subprograms,
implementing subprograms with stack-dynamic local
variables, nested subprograms, blocks, implementing
dynamic scoping
Abstract Data types: The concept of abstraction,
introductions to data abstraction, design issues,
language examples, parameterized ADT, encapsulation
constructs, naming encapsulations
Fundamentals of subprograms
All subprograms discussed have the following 3
Important Characteristics
Each subprogram has a single entry point.
The calling function or subprogram or method is
suspended during the execution of the
subprogram.
After subprogram execution terminates the
control returns to the caller.
Note : Fortran subprograms can have multiple
entries
Basic Definitions
A subprogram definition describes the interface to and
the actions of the subprogram abstraction.
A subprogram call is the explicit request that a specific
subprogram be executed.
A subprogram is said to be active if, after having been
called, it has begun execution but has not yet
completed that execution.
Subprograms are of 2 types 1. Procedures 2. Functions
A subprogram header specifies the return type, name
and parameter list.
Examples: def adder (parameters):
This is the header of a Python subprogram named adder
and ruby subprogram headers also begin with def.
The header of a JavaScript subprogram begins with
function.
In C, the header of a function named adder might be as
follows: void adder (parameters)
The reserved word void in this header indicates that the
subprogram does not return a value.
•One characteristic of Python functions that sets them apart from the
functions of other common programming languages is that function
def statements are executable.
•When a def statement is executed, it assigns the given name to the
given function body.
•Until a function’s def has been executed, the function cannot be
called.
example:
if . . .
def fun(. . .):
...
else
def fun(. . .):
...
•If the then clause of this selection construct is executed, that version
of the function fun can be called, but not the version in the else
clause.
• Likewise, if the else clause is chosen, its version of the function can
be called but the one in the then clause cannot.
Ruby methods differ from the subprograms of
other programming languages.
Ruby methods can be defined inside and
outside the class, the methods defined outside
are considered as root object methods.
Such methods can be called without an object
receiver, as if they were functions in C or C++.
If a Ruby method is called without a receiver,
self is assumed.
If there is no method by that name in the class,
enclosing classes are searched, up to Object, if
necessary.
The protocol of a subprogram is its parameter
profile plus its return type.
Parameters
Parameter profile of a subprogram contains the number,
order and types of its formal parameters.
The protocol of a subprogram is parameter profile +
return type.
The parameters in the subprogram header are called
formal parameters.
The parameters which are passed in call statement are
called actual parameters.
In most of the languages binding between formal and
actual parameters is done based on the position, Such
parameters are called positional parameters.
But Ada, python & Fortran 95 uses keyword parameters in
which parameters can appear in any order.
The advantage of keyword parameters is that they can
appear in any order in the actual parameter list.
Python functions can be called using this technique:
sumer(length = my_length, list = my_array, sum =
my_sum) where the definition of sumer has the formal
parameters length, list, and sum.
The disadvantage to keyword parameters is
that the user of the subprogram must know the
names of formal parameters.
Default value parameters
In python, ruby, C++, Fortran 95, Ada, and PHP supports
the default values to the formal parameters.
If the actual parameters in the function call are missing
then default values are substituted to formal
parameters.
Example :Python : def cal_pay(income, exemptions
=1, tax_rate)
pay = cal_pay(20000.0, tax_rate = 0.5)
C++ : float cal_pay(float income, int exemptions=1,
float tax_rate)
pay = cal_pay(20000.0,0.15);
Design issues for subprograms
Design of the subprograms are complex and several design issues
are involved.
1.Are local variables statically or dynamically allocated?
2.Can subprogram definitions appear in other subprogram definitions?
3. What parameter-passing method or methods are used?
4.Are the types of the actual parameters checked against the types of
the
formal parameters?
5.If subprograms can be passed as parameters and subprograms can
be nested.
6.what is the referencing environment of a passed subprogram?
7.Can subprograms be overloaded?
8.Can subprograms be generic?
Local Referencing Environments
The variables which are defined in a subprogram are called
local variables, thereby defining local referencing
environment.
Scope of the local variables is limited to the body of the
subprogram.
Local variables can be static or stack-dynamic.
If local variables are stack-dynamic, they are bound to
storage when the subprogram begins execution and
unbound from storage when the subprogram terminates.`
The main advantage of stack-dynamic local variables, the
the flexibility they provide to the subprogram and it is
essential that recursive subprograms have stack-dynamic
local variables.
Another advantage of stack-dynamic locals is that the
storage for local variables in an active subprogram can be
shared with the local variables in all inactive subprograms.
The disadvantages of stack-dynamic local
variables is
1. Cost of the time required to allocate, initialize and
de-allocate.
2. Access to stack-dynamic variables can only done in
indirect way (using pointers).
3. If a subprogram uses a stack-dynamic local
variables it cannot be history sensitive:it cannot
retain the values of local variables between
switching
The advantages of static local variables over stack-
dynamic local variables is
1. Static local variables are more efficient – they
require no runtime overhead for allocation and de-
allocation.
2. Static local variables can be accessed directly
3. History-sensitive
Disadvantage of static variables
1. Static variable doesn’t support recursion
2. Storage cannot be shared
Note – In C and C++ functions, by default local
variables are stack-dynamic unless explicitly
declared static.
Parameter-Passing Methods
Parameters-passing are the ways in which parameters are
transmitted to and/or from called programs.
First is on the different semantics models of parameter-passing
methods.
Later we discuss the various implementation models invented by
language designers for these semantics models.
Semantics Models of Parameter Passing
They are 3 distinct semantic models of parameter passing.
1. in mode 2. out mode 3. in out mode
In mode : actual parameter values are copied to formal
parameters.
Out mode : formal parameter values are passed to calling function
using “return” statement.
In out mode : is bidirectional mode in which actual parameter
values are copied to formal parameters and value of formal
parameters is passed to calling function.
In mode
Fun(int a, int b)
Fun(a,b);
call {…}
out mode
Fun(int a, int b)
Fun(a,b);
Return {…}
In out
call mode
Fun(int a, int b)
Fun(a,b);
Return {…}
Implementation Models of Parameter
passing
They are 5 basic parameter transmission
modes in that 3 are very commonly used
mechanisms.
1. Pass-by-value 2.Pass-by-result 3.Pass-by-value-result
4.Pass-by-name 5.Pass-by-reference
Pass-by-value
When a parameter is passed by value, the value of the actual
parameter used to initialize the corresponding formal
parameters.
Pass by value is implemented in 2 ways
1. Copy method.
2. Transmitting access path.
Second method needs a write protection for the actual
parameters (read only).
Enforcing the write protection is additional overhead and
difficult. This is one reason to use copy transfer instead of
access path transfer.
C++ provides a convenient and effective method for
enforcing write protection on pass-by-value parameters that
are transmitted by access path.
Advantage : - pass by value is fast in both linkage and access
time
Disadvantage : - Requires additional storage. Copy
operations are costly when parameter size is large.
Pass by result
Pass by result Is a implementation model for out mode
parameters.
When a parameter is passed by result, no value is
transmitted to the subprogram.
The corresponding formal parameter acts as a local
var, but just before control is transferred back to the
caller, its value is transmitted back to the caller’s
actual parameter, which must be a var.
One problem with the pass-by-result model is that
there can be an actual parameter collision, such as the
one created with the call. sub(p1, p1)
In sub, assuming that the two formal parameters have
different names, the two can obviously be assigned
different values.
Then whichever of the two is copied to their
corresponding actual parameter last becomes the
value of p1.
Pass by value result
It is a implementation model for in out mode
parameters.
At first the actual parameter values are copied to
formal parameters like pass by value and later just
before control transfer to the callee the values of
formal parameters are copied into actual parameters
like pass by result.
Some times pass by value result is known as pass by
copy.
Pass by reference
Pass-by-reference is a second implementation model
for inout-mode parameters.
Rather than copying data values back and forth, this
method transmits an access path, usually just an
address, to the called subprogram. This provides the
access path to the cell storing the actual parameter.
The actual parameter is shared with the called
subprogram. Advantages :-
Passing of parameters is efficient in terms of both
time and space.
Duplicate space is not required, nor is any copying.
Disadvantages :-
Access to the formal parameters will be slower
than pass-by-value, because of additional level
of indirect addressing that is required.
Second, if only one-way communication to the
called subprogram is required, Inadvertent and
erroneous changes may be made to the actual
parameter.
There are several ways pass-by-reference
parameters can create aliases.
First, collisions can occur between actual
parameters. void fun(int &first,
int &second)
If the call to fun happens to pass the same
variable twice: fun(total, total)
Then first and second in fun will be aliases.
Pass by name
It is also another in out mode parameter implementation
model.
Here the parameters are passed by name. when a
subprogram call is made all the formal parameter
occurrences are substituted with name of actual
parameters.
A pass by name formal parameter is bound to an access
method at the time of the subprogram call, but the
actual binding to a value or an address is delayed until
the formal parameter is assigned or referenced.
Pass by name mainly used by macros and generic
parameters.
Parameters That Are Subprograms
•In programming, a number of situations occur that are most
conveniently handled if subprogram names can be sent as
parameters to other subprograms.
•In C and C++, functions cannot be passed as parameters, but
pointers to functions can.
•The second complication with parameters that are
subprograms appears only with languages that allow nested
subprograms.
•The issue is what referencing environment for executing the
passed subprogram should be used.
•There are three choices:
1. The environment of the call statement that enacts the passed
subprogram (shallow binding)
2.The environment of the definition of the passed subprogram
(deep binding)
3.The environment of the call statement that passed the
subprogram as an actual parameter (ad hoc binding)
function sub1() { Consider the execution of sub2
var x; when it is called in sub4.
function sub2() { shallow binding, the referencing
alert(x); // Creates a environment of that execution is
dialog box with the that of sub4, so the reference to x
in sub2 is bound to the local x in
value of x
sub4 and the output of the
}; program is 4.
function sub3() { Deep binding, the referencing
var x; environment of sub2’s execution is
x = 3; that of sub1, so the reference to x
sub4(sub2); in sub2 is bound to the local x in
}; sub1and the output is 1.
function sub4(subx) { For ad hoc binding, the binding is
var x; to the local x in sub3 and the
x = 4; output is 3.
subx();
};
x = 1;
sub3();
};
Overloaded subprograms
An overloaded operator is one that has multiple
meanings.
The meaning of a particular instance of an overloaded
operator is determined by the types of its operands.
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.
C++, Java, Ada, and C# include predefined
overloaded subprograms.
For example, many classes in C++, Java, and
C# have overloaded constructors.
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, and possibly in its
return type if it is a function.
Example: C++ functions
void fun(int a, int b){……}
void fun(float a, float b){…..}
Call to the right subprogram or function is
determined by the actual parameters in some
languages and return type in some languages.
C++, java and C# uses parameter profile to
determine the call to the subprogram.
Ada uses return type to determine the call to
the right subprogram.
Coercion and default parameters can cause
problems in determining the right
void fun(float a) Causes
subprogram. compiler
{
….. error
}
void fun(double
a){ Fun with
….. double type
} is called
void main( ){
fun(10);
Generic subprograms
A programmer should not need to write four
different sort subprograms to sort four arrays
that differ only in element type.
A generic or polymorphic subprogram takes
parameters of different types on different
activations.
Overloaded subprograms provide a particular kind of
polymorphism called ad hoc polymorphism.
Languages that support object-oriented
programming usually support subtype
polymorphism.
Parametric polymorphism is provided by a subprogram
that takes a generic parameter that is used in a type
expression that describes the types of the parameters of
the subprogram.
Parametrically polymorphic subprograms are
often called generic subprograms. Ada, C++, Java
5.0+, C# , and F# provide a kind of compile-time
parametric polymorphism.
Generic subprogram in C++
C++ uses template keyword to define generic
functions.
Example:
template <typename Type>
Type max(Type a, Type b) {
return a > b ? a : b;
}
………
max(3, 7); /* integer type*/
max(3.0, 7.0); /* float type*/
Generic subprogram in java
Java started supporting generic sub programming
from java 5.0;
Java’s generic methods differ from the generic
subprograms of Ada and C++ in several ways.
1. Generic parameters must be classes, they
cannot be primitive types.
2. Java creates only one copy of the generic
method unlike C++ and Ada.
3. User can specify the range of classes that can
be passed as generic parameters. Such restrictions
are called bounds which can done by using
extends keyword.
Generic subprogram in java
Java uses angular brackets to specify the generic type, here
in the below example G is the generic parameter type.
Example:
class GenericDemo <G> {
public G x;
public method(G a){
x=a;
}
}
Note : java supports wildcard types which can specified with
<?>.
The generic methods of C# similar to the java 5.0 generic
method expect C# doesn’t support wild card entry.
Design Issues for functions
They are 2 design issues specific to the functions
1. Are side effects are allowed?
2. What types of values can be returned?
3. How many values can be returned?
Functional side effects
Some times functions can cause side effects when
they are used in expressions. Example :
c=x+fun(&x);
Here in the above example the value of x can be
modified in function causing side effect.
Most of the languages allows side effects and
aliasing except Ada, Ada allows only in-mode
Types of Returned values
Most of the imperative programming languages
limits the types that they can return.
C allows any type to be returned by its functions
except arrays and functions, but can be handled by
pointers.
C++ allows to return user-defined types or classes.
JavaScript, python and Rubby can return functions
or methods like parameters. (methods are like
objects)
Neither java nor C# can return methods as a
parameters ( methods are not types or objects).
User-Defined Overloaded Operators
Operators can be overloaded by the user in Ada, C++,
Python, and Ruby.
In some languages operators can be overloaded like
functions.
Example: In C++
…….
int operator ++(int a){
return a+2;
}
Some times operator overloading can effect the
readability of the program, so the degree of usage of
operator overloading is up to the user.
Co-routines
Co routines is a special kind of subprograms in
which there is no master-slave relationship like
conventional subprograms.
Here caller and called co routines are treated
on equal basis, so the control mechanism is
often called symmetric unit control model.
co routines can have multiple entry points and
they are history sensitive.
Co routines starts the execution from where
they left, so the invocation of a co routine is
called resume rather than a call
Co routine Execution
Model
master
Resume B Resume A
Resume B Resume A
Resume B
A B
Implementing subprograms
The General Semantics of Calls and Returns
•The subprogram call and return operations are together called
subprogram linkage.
•General semantics of subprogram calls
– Parameter passing methods
– Stack-dynamic allocation of local variables
– Save the execution status of calling program
– Transfer of control and arrange for the return
– If subprogram nesting is supported, access to nonlocal variables
must be arranged.
•The required actions of a subprogram return are less complicated
than those of a call.
• General semantics of subprogram returns:
– In mode and inout mode parameters must have their values
returned
– Deallocation of stack-dynamic locals
– Restore the execution status
– Return control to the caller
Implementing “Simple” Subprograms
•By “simple” we mean that subprograms cannot be nested
and all local variables are static.
• The semantics of a call to a “simple” subprogram
requires the following actions:
-Save the execution status of the current program unit.
-Compute and pass the parameters.
- Pass the return address to the called.
- Transfer control to the called.
• The semantics of a return from a simple subprogram
requires the following actions:
- If there are pass-by-value-result or out-mode
parameters, the current values of those parameters are
moved to or made available to the corresponding
actual parameters.
-If the subprogram is a function, the functional value is
moved to a place accessible to the caller.
-The execution status of the caller is restored.
- Control is transferred back to the caller.
•The call and return actions require storage for the
following:
-Status information about the caller
-Parameters
-Return address
- Return value for functions
-Temporaries used by the code of the subprograms
•The format, or layout, of the non-code part of a
subprogram is called an activation record, because the
data it describes are relevant only during the activation, or
execution of the subprogram.
• An activation record instance is a concrete example of an
activation record, a collection of data in the form of an
activation record.
Figure.1 : An Activation Record for Simple Subprograms
• Figure :2 shows a program consisting of a main program and three
subprograms: A, B, and C.
Figure:The code and activation records of a program with simple subprograms
Implementing Subprograms with Stack-Dynamic Local Variables
•Now examine the implementation of the subprogram linkage in languages in
which locals are stack dynamic.
More complex activation record
•The compiler must generate code to cause implicit allocation and
deallocation of local variables
•Recursion must be supported (adds the possibility of multiple
simultaneous activations of a subprogram).
• The activation record format is static, but its size may be dynamic.
• In languages with stack-dynamic local variables, activation record
instances must be created dynamically.
•The typical activation record for such a language is shown in Figure.
•Because the return address, dynamic link, and parameters are
placed in the activation record instance by the caller, these entries
must appear first.
Fig:A typical activation record for a language with stack-dynamic local
variables
•The return address usually consists of a pointer to the instruction
following the call in the code segment of the calling program unit.
•The dynamic link is a pointer to the base of the activation record
instance of the caller.
• An activation record instance is dynamically created when a
subprogram is called .
• Activation record instances reside on the run-time stack.
• The Environment Pointer (EP) must be maintained by the run-time
system. It always points at the base of the activation record instance
of the currently executing program unit.
•Example: C Function
void sub(float total, int part)
{
int list[5];
float sum;
...
}
Figure: The activation record for function sub
•The caller actions are as follows:
1. Create an activation record instance.
2. Save the execution status of the current program unit.
3. Compute and pass the parameters.
4. Pass the return address to the called.
5. Transfer control to the called.
•The prologue actions of the called are as follows:
1. Save the old EP in the stack as the dynamic link and create the
new value.
2. Allocate local variables.
•The epilogue actions of the called are as follows:
1. If there are pass-by-value-result or out-mode parameters, the
current values of those parameters are moved to the corresponding
actual parameters.
2. If the subprogram is a function, the functional value is moved to a
place accessible to the caller.
3. Restore the stack pointer by setting it to the value of the current
EP minus one and set the EP to the old dynamic link.
4. Restore the execution status of the caller.
5. Transfer control back to the caller.
Nested Subprograms
• The languages that allow subprograms to be nested are
Fortran 95+ Ada, Python, JavaScript, Ruby, and Lua, as
well as the functional languages.
• In this section, we examine the most commonly used
approach to implementing subprograms that may be
nested.
The Basics
•A reference to a nonlocal variable in a static-scoped
language with nested subprograms requires a two-step
access process.
•All nonstatic variables that can be non-locally accessed
are in existing activation record instances and therefore
are somewhere in the stack.
•The first step of the access process is to find the instance
of the activation record in the stack in which the variable
was allocated.
•The second part is to use the local_offset of the variable
(within the activation record instance) to access it.
Blocks
•C-based languages, provide for user-specified local scopes for
variables called blocks.
Example of a block:
{ int temp;
temp = list[upper];
list[upper] = list[lower];
list[lower] = temp;
}
• The lifetime of temp in the above example begins when control
enters the block.
• An advantage of using a local variable like temp is that it cannot
interfere with any other variable with the same name.
• Blocks are treated as parameter less subprograms that are always
called from the same place in the program.
• Therefore, every block has an activation record.
•An instance of its activation record is created every time the block is
executed.
•Blocks can also be implemented in a different and somewhat simpler
and more efficient way.
•The maximum amount of storage required for block variables at any
time during the execution of a program can be statically determined,
because blocks are entered and exited in strictly textual order.
• For example:
void main() {
int x, y, z;
while ( . . . ) {
int a, b, c;
...
while ( . . . ) {
int d, e;
...
}
}
while ( . . . ) {
int f, g;
...
}
...
}
Fig: Block variable storage when blocks are not treated as parameter
less procedures
Implementing Dynamic Scoping
•
The Concept of Abstraction
•An abstraction is a view or representation of an entity that
includes only the most significant attributes.
•In a general sense, abstraction allows one to collect
instances of entities into groups in which their common
attributes need not be considered.
• For example, suppose we define birds to be creatures
with the following attributes: two wings, two legs, a tail,
and feathers.
•Then, if we say a crow is a bird, a description of a crow
need not include those attributes.
•The same is true for robins, and sparrows.
•These common attributes in the descriptions of specific
species of birds can be abstracted away, because all
species have them.
•Within a particular species, only the attributes that
distinguish that species need be considered.
•For example, crows have the attributes of being black,
being of a particular size, and being noisy.
•A description of a crow needs to provide those attributes,
but not the others that are common to all birds.
•This results in significant simplification of the descriptions
of members of the species.
•In the world of programming languages, abstraction is a
weapon against the complexity of programming; its
purpose is to simplify the programming process.
• It is an effective weapon because it allows programmers
to focus on essential attributes, while ignoring subordinate
attributes.
•The two fundamental kinds of abstraction in
contemporary programming languages are process
abstraction and data abstraction.
•All subprograms are process abstractions because they
provide a way for a program to specify a process, without
providing the details of how it performs its task.
•For example, when a program needs to sort an array of
numeric data of some type: sortInt(list, listLen)
•The only essential attributes are the name of the array to
be sorted, the type of its elements, the array’s length.
•The particular algorithm that sortInt implements is an
attribute that is not essential to the user.
•The user needs to see only the name and protocol of the
•sorting subprogram to be able to use it.
Introduction to Data Abstraction
•The evolution of data abstraction began in 1960 with the first
version of COBOL, which included the record data structure.
• The C-based languages have structs, which are also records.
•An abstract data type is a data structure, in the form of a
record, but which includes subprograms that manipulate its
data.
•Syntactically, an abstract data type is an enclosure that
includes only the data representation of one specific data type
and the subprograms that provide the operations for that type.
•Through access controls, unnecessary details of the type can
be hidden from units outside the enclosure that use the type.
•Program units that use an abstract data type can declare
variables of that type, even though the actual representation is
hidden from them.
• An instance of an abstract data type is called an object.
Floating-Point as an Abstract Data Type
•The concept of an abstract data type, at least in terms of
built-in types, a floating-point data type.
•Most programming languages include at least one of
these. A floating-point type provides the means to create
variables to store floating-point data and also provides a
set of arithmetic operations for manipulating objects of the
type.
•Floating-point types in high-level languages employ a key
concept in data abstraction: information hiding.
• The actual format of the floating-point data value in a
memory cell is hidden from the user, and the only
operations available are those provided by the language.
•The user is not allowed to create new operations on data
of the type, except those that can be constructed using
the built-in operations.
•The user cannot directly manipulate the parts of the
actual representation of values because that
representation is hidden.
User-Defined Abstract Data Types
•A user-defined abstract data type should provide the
same characteristics as those of language-defined types,
such as a floating-point type:
1. a type definition that allows program units to declare
variables of the type but hides the representation of
objects of the type;
2. a set of operations for manipulating objects of the type.
•An Abstract data type is a data type that satisfies the
following conditions:
1. Declarations and protocols of the operations should be
in a one single syntactic unit. But implementation or
definition may be in the same / different syntactic units
2. Representation of objects of the ADT is hidden from the
program, only operations and types are known.
•Program units that use a specific abstract data type are
called clients of that type.
An Example
Suppose an abstract data type is to be constructed for a stack that has
the following abstract operations:
create(stack) :Creates and possibly initializes a stack object
destroy(stack) : Deallocates the storage for the stack
empty(stack) :A predicate (or Boolean) function that returns
true if the specified stack is empty and false
otherwise
push(stack, element) : Pushes the specified element on the specified
stack
pop(stack) :Removes the top element from the specified
stack
top(stack) :Returns a copy of the top element from the
specified stack
Design Issues for Abstract Data Types
1. Is it possible to make Abstract type name and
subprograms or functions headers visible to the
users, so that they can declare the variables of that
abstract type and manipulate using the subprograms.
2. Is it possible to define operations other than the
provided built in operations of ADT.
3. All the ADTs should provide common operations like
checking equality, inequality and assignment…etc.
4. Whether ADTs can be parameterized so it can be
independent of the type of the data.
5. Is what access controls are provided and how such
controls are specified.
Language Examples
•The concept of data abstraction had its origins in SIMULA 67,
although that language did not provide complete support for abstract
data types.
• In this section, we describe the support for data abstraction provided
by Ada, C++, Java, C#, and Ruby.
Abstract Data Types in Ada
•Ada provides an encapsulation construct that can be used to define a
single abstract data type, including the ability to hide its
representation
Encapsulation
The encapsulating constructs in Ada are called packages.
In Ada packages contains two parts 1. specification package 2.
Body package
Specification package provides interface of the encapsulation( in
simple it contains the declarations).
Body package provides the implementation of the declarations
which are provided in the specification package.
Both specification package and body package is associated by the
same name.
Example: Stack ADT in Ada
--specification package --body package
package stack is
type stack is limited
package body stack is
private; procedure empty(stk : in
Max_size : 100; stack) return boolean is
procedure empty(stk : in begin
stack) return boolean ; return
procedure push(stk : in out stk.top :=0;
stack; element : in integer); end empty;
prodecure pop(stk: in out procedure push(stk : in
stack);
--private part which is hidden
out stack; element : in
from user Integer)
type list is array begin
(1..Max_Size) of Integer; …..
type stack is end push
record procedure pop(stk: in
x : list; out stack)
top : Integer range begin
0..MaxSize :=0;
……..
end record;
end stack end pop
Information Hiding
•if the representation is not hidden, then the defined type
is not an abstract data type.
•There are two approaches to hiding the representation
from clients in the package specification.
•The representation of the type appears in a part of the
specification called the private part, which is introduced
by the reserved word private.
•The private clause is visible to the compiler but not to
client program units.
• The second way to hide the representation is to define
the abstract data type as a pointer and provide the
pointed-to structure’s definition in the body package,
whose entire contents are hidden from clients.
Abstract Data Types in C++
C++ provide two constructs to define ADTs
1. class
2. structure (struct)
class is some what more cleaner and more direct way to
provide ADTs.
Encapsulation
Data defined in the C++ class are called data members
and function are called member functions
Instances of the classes can be stack dynamic or heap
dynamic, heap dynamic class objects are created using
new operator and destroyed using delete operator.
Member functions can be defined in two ways
1. Both the protocol and function definition is
provided in the class it self, this type of functions are
implicitly in lined.
2. or Defining the function outside the class using
the operator :: (scope resolution operator).
Parameterized Abstract Data Types
•For example, we should be able to design a stack
abstract data type that can store any scalar type elements
rather than be required to write a separate stack
abstraction for every different scalar type.
• The following package specification describes the interface of a
generic stack abstract data type with these features.
• The body package for Generic_Stack is the type of the Element
formal parameter in Push and Top is Element_Type .
•The following statement instantiates Generic_Stack for a stack of 100
Integer type elements:
package Integer_Stack is new Generic_Stack(100, Integer);
•One could also build an abstract data type for a stack of length 500
for Float Elements
package Float_Stack is new Generic_Stack(500, Float);
•These instantiations build two different source code versions of the
Generic_Stack package at compile time.
Generic
Max_Size : Positive; -- A generic parameter for stack
-- size
type Element_Type is private; -- A generic parameter
-- for element type
package Generic_Stack is
-- The visible entities, or public interface
type Stack_Type is limited private;
function Empty(Stk : in Stack_Type) return Boolean;
procedure Push(Stk : in out Stack_Type;
Element : in Element_Type);
procedure Pop(Stk : in out Stack_Type);
function Top(Stk : in Stack_Type) return Element_Type;
-- The hidden part
private
type List_Type is array (1..Max_Size) of Element_Type;
type Stack_Type is
record
List : List_Type;
Topsub : Integer range 0..Max_Size := 0;
end record;
end Generic_Stack;
C++
~Stack() {delete stackPtr;}; // A
#include <iostream.h> destructor
template <typename Type> //
void push(Type number) {
Type is the template
parameter if (topSub == maxLen)
class Stack { cout << "Error in push—stack is full\n";
private:
Type *stackPtr; else stackPtr[++ topSub] = number
int maxLen; }
int topSub; void pop() {
public: if (empty())
// A constructor for 100 element cout << "Error in pop—stack is empty\n
stacks else topSub --;
Stack() { }
stackPtr = new Type [100]; Type top() {
maxLen = 99; if (empty())
topSub = -1; cerr << "Error in top--stack is empty\n"
} else
// A constructor for a given return (stackPtr[topSub]);
number of elements }
Stack(int size) { int empty() {return (topSub == -1)
stackPtr = new Type [size]; }
maxLen = size - 1;
topSub = -1;
}
•Stack<int> myIntStack;
Java 5.0
import java.util.*;
public class Stack2<T> {
private ArrayList<T> stackRef;
private int maxLen;
public Stack2() { // A constructor
stackRef = new ArrayList<T> (); maxLen = 99; }
public void push(T newValue) { if (stackRef.size() == maxLen)
System.out.println("Error in push—stack is full");
else
stackRef.add(newValue);
}
public void pop() { if (empty())
System.out.println("Error in pop—stack is empty");
else
stackRef.remove(stackRef.size() - 1);
}
public T top() { if (empty()) {
System.out.println("Error in top—stack is empty");
return null;
}
Else return (stackRef.get(stackRef.size() - 1)); }
public boolean empty() {return (stackRef.isEmpty());}
•Thisclass could be instantiated for the String type with the following:
Stack2<String> myStack = new Stack2<String>();
Previous Questions
1. Explain the generic functions in C++ with examples.
2. Explain the design issues of subprograms and operations.
3. Compare the merits and demerits of call by name and call
by reference
4. Define scope and lifetime of variables. Write suitable
example for each.
5. What are the different models of parameter passing
methods? How are they implemented? Give example for
each.
6. What are various parameter passing techniques
supported in Ada and C programming Languages
7. Explain about generic sub programs
8. What are the three semantic models of parameter
passing?
9. Define shallow and deep binding for referencing
environments of subprograms that they been passed as a
parameters
What are the two fundamental design considerations for parameter-passing
methods? [2] [2017]
What is an overloaded subprogram? Give an example. [3][2017]
Give the two kind of abstractions in programming languages. [2][2017]
What are the characteristics of subprograms? [2][2019]
Explain about coroutines. [3][2019]
Give a detailed note on pass-by-name and pass-by-reference parameter
passing methods.[5][2017]
b) Explain about generic sub-programs with examples. [5][2017]
a) Describe the shallow-access method of implementing dynamic scoping.[5]
[2017]
b) What is the need of an activation record in implementing a subprogram?
Explain with an example.[5][2017]
Define sub program. What are the distinct categories of subprograms. [5]
[2019]
Explain about the generic subprograms in Ada with an example.[5][2019]
b) Explain about the semantic models of parameter passing. [5][2019]