Principles of Programming Language: B.Tech
Principles of Programming Language: B.Tech
Principles of Programming Language: B.Tech
language
B.Tech (CSE)
Notes
Prepared By:
https://topperworld.in/
Topperworld.in
CONTENTS
UNIT-I
1. Reasons for studying
2. Concepts of programming languages
3. Programming domains
6. Language categories
9. Programming environments.
UNIT-II
1. Introduction
2. primitive
3. character
4. user defined, array
5. Associative, record, union, pointer and reference types, design and implementation uses
related to these types.
6. Names, Variable, concept of binding, type checking.
7. Strong typing
8. Type compatibility
9. Named constants
10. Variable initialization
https://topperworld.in/
Topperworld.in
UNIT-III
1. Fundamentals of sub-programs
2. Scope and lifetime of variable
3. Static and dynamic scope
4. Design issues of subprograms and operations, local referencing environments
5. Parameter passing methods
6. Overloaded sub-programs
7. Generic sub-programs
8. Parameters that are sub-program names
9. Design issues for functions user defined overloaded operators, co routines.
UNIT-IV
1. Abstract Data types
2. Concurrency
3. Exception handling
4. Logic Programming Language
UNIT-V
1. Functional Programming Languages
2. Introduction
3. LISP, ML, Haskell
4. Scripting Language: Pragmatics
5. Python
6. Procedural abstraction, data abstraction, separate compilation, module library
https://topperworld.in/
Topperworld.in
UNIT - I
PRELIMINARY CONCEPTS
Programming Domains
• Scientific applications
– In the early 40s computers were invented for scientific applications.
– The applications require large number of floating point computations.
– Fortran was the first language developed scientific applications.
– ALGOL 60 was intended for the same use.
• Business applications
– The first successful language for business was COBOL.
– Produce reports, use decimal arithmetic numbers and characters.
– The arrival of PCs started new ways for businesses to use computers.
https://topperworld.in/
Topperworld.in
• Artificial intelligence
– Symbolic rather than numeric computations are manipulated.
– Symbolic computation is more suitably done with linked lists than arrays.
– LISP was the first widely used AI programming language.
• Systems programming
– The O/S and all of the programming supports tools are collectively known as its system
software.
– Need efficiency because of continuous use.
• Scripting languages
– Put a list of commands, called a script, in a file to be executed.
– PHP is a scripting language used on Web server systems. Its code is embedded in HTML
documents. The code is interpreted on the server before the document is sent to a
requesting browser.
• Special-purpose languages
Readability
• Software development was largely thought of in term of writing code “LOC”.
• Language constructs were designed more from the point of view of the computer than the users.
• Because ease of maintenance is determined in large part by the readability of programs,
readability became an important measure of the quality of programs and programming languages.
The result is a crossover from focus on machine orientation to focus on human orientation.
• The most important criterion “ease of use”
• Overall simplicity “Strongly affects readability”
– Too many features make the language difficult to learn. Programmers tend to learn a
subset of the language and ignore its other features. “ALGOL 60”
– Multiplicity of features is also a complicating characteristic “having more than one way
to accomplish a particular operation.”
– Ex “Java”:
count = count + 1
https://topperworld.in/
Topperworld.in
count += 1
count ++
++count
– Although the last two statements have slightly different meaning from each other and
from the others, all four have the same meaning when used as stand-alone expressions.
– Operator overloading where a single operator symbol has more than one meaning.
– Although this is a useful feature, it can lead to reduced readability if users are allowed to
create their own overloading and do not do it sensibly.
• Orthogonality
– Makes the language easy to learn and read.
– Meaning is context independent. Pointers should be able to point to any type of variable
or data structure. The lack of orthogonality leads to exceptions to the rules of the
language.
– A relatively small set of primitive constructs can be combined in a relatively small
number of ways to build the control and data structures of the language.
– Every possible combination is legal and meaningful.
– Ex: page 11 in book.
– The more orthogonal the design of a language, the fewer exceptions the language rules
require.
– The most orthogonal programming language is ALGOL 68. Every language construct
has a type, and there are no restrictions on those types.
– This form of orthogonality leads to unnecessary complexity.
• Control Statements
– It became widely recognized that indiscriminate use of goto statements severely reduced
program readability.
– Ex: Consider the following nested loops written in C
while (incr < 20)
{
https://topperworld.in/
Topperworld.in
sum += incr;
incr++;
loop1:
loop2:
sum += incr;
go to loop2;
next:
incr++;
go to loop1:
out:
– Basic and Fortran in the early 70s lacked the control statements that allow strong
restrictions on the use of gotos, so writing highly readable programs in those languages
was difficult.
– Since then, languages have included sufficient control structures.
– The control statement design of a language is now a less important factor in readability
than it was in the past.
https://topperworld.in/
Topperworld.in
▪ Syntax Considerations
– The syntax of the elements of a language has a significant effect on readability.
– The following are examples of syntactic design choices that affect readability:
• Identifier forms: Restricting identifiers to very short lengths detracts from
readability. ANSI BASIC (1978) an identifier could consist only of a single letter
of a single letter followed by a single digit.
• Special Words: Program appearance and thus program readability are strongly
influenced by the forms of a language’s special words. Ex: while, class, for. C
uses braces for pairing control structures. It is difficult to determine which group
is being ended. Fortran 95 allows programmers to use special names as legal
variable names.
• Form and Meaning: Designing statements so that their appearance at least
partially indicates their purpose is an obvious aid to readability.
• Semantic should follow directly from syntax, or form.
• Ex: In C the use of static depends on the context of its appearance.
If used as a variable inside a function, it means the variable is created at compile
time.
If used on the definition of a variable that is outside all functions, it means the
variable is visible only in the file in which its definition appears.
Writability
▪ It is a measure of how easily a language can be used to create programs for a chosen problem
domain.
▪ Most of the language characteristics that affect readability also affect writability.
• Simplicity and orthogonality
https://topperworld.in/
Topperworld.in
– A smaller number of primitive constructs and a consistent set of rules for combining them
is much better than simply having a large number of primitives.
• Support for abstraction
– Abstraction means the ability to define and then use complicated structures or operations
in ways that allow many of the details to be ignored.
– A process abstraction is the use of a subprogram to implement a sort algorithm that is
required several times in a program instead of replicating it in all places where it is
needed.
• Expressivity
– It means that a language has relatively convenient, rather than cumbersome, ways of
specifying computations.
Reliability
▪ A program is said to be reliable if it performs to its specifications under all conditions.
• Type checking: is simply testing for type errors in a given program, either by the compiler or
during program execution.
– The earlier errors are detected, the less expensive it is to make the required repairs. Java
requires type checking of nearly all variables and expressions at compile time.
• Exception handling: the ability to intercept run-time errors, take corrective measures, and then
continue is a great aid to reliability.
• Aliasing: it is having two or more distinct referencing methods, or names, for the same memory
cell.
– It is now widely accepted that aliasing is a dangerous feature in a language.
• Readability and writability: Both readability and writability influence reliability.
Cost
– Categories
– Training programmers to use language
– Writing programs “Writability”
– Compiling programs
– Executing programs
https://topperworld.in/
Topperworld.in
Programming methodologies
• 1950s and early 1960s: Simple applications; worry about machine efficiency
https://topperworld.in/
Topperworld.in
• Late 1960s: People efficiency became important; readability, better control structures
– Structured programming
– Top-down design and step-wise refinement
• Late 1970s: Process-oriented to data-oriented
– data abstraction
• Middle 1980s: Object-oriented programming
Language Categories
• Imperative
– Central features are variables, assignment statements, and iteration
– C, Pascal
• Functional
– Main means of making computations is by applying functions to given parameters
– LISP, Scheme
• Logic
– Rule-based
– Rules are specified in no special order
– Prolog
• Object-oriented
– Encapsulate data objects with processing
– Inheritance and dynamic type binding
– Grew out of imperative languages
– C++, Java
Programming Environments
• The collection of tools used in software development
• UNIX
– An older operating system and tool collection
• Borland JBuilder
– An integrated development environment for Java
• Microsoft Visual Studio.NET
– A large, complex visual environment
– Used to program in C#, Visual BASIC.NET, Jscript, J#, or C++
https://topperworld.in/
Topperworld.in
2. Implementors
Context-Free Grammars
- Developed by Noam Chomsky in the mid-1950s
- Language generators, meant to describe the syntax of natural languages
A rule has a left-hand side (LHS) and a right-hand side (RHS), and consists of terminal and
nonterminal symbols
BNF:
A grammar is a finite nonempty set of rules. An abstraction (or nonterminal symbol) can have more
than one RHS
| ident, <ident_list>
A derivation is a repeated application of rules, starting with the start symbol and ending with a
sentence (all terminal symbols)
An example grammar:
<var> -> a | b | c | d
An example derivation:
=> a = b + <term>
=> a = b + const
https://topperworld.in/
Topperworld.in
Every string of symbols in the derivation is a sentential form A sentence is a sentential form that has only
terminal symbols A leftmost derivation is one in which the leftmost non terminal in each sentential form
is the one that is expanded A derivation may be neither leftmost nor rightmost
An example grammar:
<program> -> <stmts>
<stmts> -> <stmt> | <stmt> ; <stmts>
<stmt> -> <var> = <expr>
<var> -> a | b | c | d
<expr> -> <term> + <term> | <term> - <term>
<term> -> <var> | const
An example derivation:
<program> => <stmts> => <stmt>
=> <var> = <expr> => a = <expr>
=> a = <term> + <term>
=> a = <var> + <term>
=> a = b + <term>
=> a = b + const
Every string of symbols in the derivation is a sentential form A sentence is a sentential form that has only
terminal symbols A leftmost derivation is one in which the leftmost nonterminal in each sentential form is
the one that is expanded A derivation may be neither leftmost nor rightmost A parse tree is a hierarchical
representation of a derivation
https://topperworld.in/
Topperworld.in
EBNF:
<expr> -> <term> {(+ | -) <term>}
Syntax Graphs - put the terminals in circles or ellipses and put the nonterminals in rectangles; connect
with lines with arrowheads
Categories:
- Additions to cfgs to carry some semantic info along through parse tree Primary value of AGs:
2. Each rule has a set of functions that define certain attributes of the nonterminals in the rule
3. Each rule has a (possibly empty) set of predicates to check for attribute consistency
Let X0 -> X1 ... Xn be a rule Functions of the form S(X0) = f(A(X1), ... A(Xn)) define
synthesized attributes Functions of the form I(Xj) = f(A(X0), ... , A(Xn)), for i <= j <= n, define
inherited attributes Initially, there are intrinsic attributes on the leaves
Example: expressions of the form id + id - id's can be either int_type or real_type
types of the two id's must be the same type of the expression must match it's expected type
BNF:
<expr> -> <var> + <var>
<var> -> id
PARSE TREE:
A hierarchical representation of a derivation. Every internal node of a parse tree is labeled with
a non terminal symbol; every leaf is labeled with a terminal symbol. Every subtree of a parse tree describes
one instance of an abstraction in the sentence
https://topperworld.in/
Topperworld.in
Ambiguous grammar
A grammar is ambiguous if it generates a sentential form that has two or more distinct parse trees An
ambiguous expression grammar:
<op> -> / | -
If we use the parse tree to indicate precedence levels of the operators, we cannot have ambiguity An
unambiguous expression grammar:
grammar
2. Put alternative parts of RHSs in parentheses and separate them with vertical bars
3. Put repetitions (0 or more) in braces ({}) <ident> -> letter {letter | digit}
BNF:
<expr> -> <expr> + <term>
| <expr> - <term>
| <term>
| <term> / <factor>
https://topperworld.in/
Topperworld.in
| <factor>
Attribute Grammar
Attributes:
actual_type - synthesized for <var> and <expr>
Attribute Grammar:
Semantic rules:
<var>[1].env <expr>.env
<var>[2].env <expr>.env
<expr>.actual_type <var>[1].actual_type
Predicate:
<var>[1].actual_type = <var>[2].actual_type
<expr>.expected_type = <expr>.actual_type
Semantic rule:
3. In many cases, both kinds of attributes are used, and it is some combination of top-down and
<var>[1].env <expr>.env
<var>[2].env <expr>.env
<var>[1].actual_type =? <var>[2].actual_type
4. <expr>.actual_type <var>[1].actual_type
<expr>.actual_type =? <expr>.expected_type
Dynamic Semantics
- No single widely acceptable notation or formalism for describing semantics
I. Operational Semantics
- Describe the meaning of a program by executing its statements on a machine, either simulated or actual.
The change in the state of the machine (memory, registers, etc.) defines the meaning of the statement
1. The detailed characteristics of the particular computer would make actions difficult to understand
- The process:
1. Build a translator (translates source code to the machine code of an idealized computer)
Axiomatic Semantics
- Based on formal logic (first order predicate calculus)
- Approach: Define axioms or inference rules for each statement type in the language
- An assertion before a statement (a precondition) states the relationships and constraints among variables
that are true at that point in execution
- A weakest precondition is the least restrictive precondition that will guarantee the postcondition
- An example: a := b + 1 {a > 1}
Program proof process: The postcondition for the whole program is the desired results. Work back through
the program to the first statement. If the precondition on the first statement is the same as the program spec,
the program is correct.
2. {I} B {I} (evaluation of the Boolean must not change the validity of I)
- The loop invariant I is a weakened version of the loop postcondition, and it is also a precondition.
- I must be weak enough to be satisfied prior to the beginning of the loop, but when combined with the
loop exit condition, it must be strong enough to force the truth of the postcondition
2. It is a good tool for correctness proofs, and excellent framework for reasoning about
programs, but it is not as useful for language users and compiler writers
Denotational Semantics
- Based on recursive function theory
- The most abstract semantics description method
2. Define a function that maps instances of the language entities onto instances of the corresponding
mathematical objects
- The meaning of language constructs are defined by only the values of the program's variables
- The difference between denotational and operational semantics: In operational semantics, the state
changes are defined by coded algorithms; in denotational semantics, they are defined by rigorous
mathematical functions
- Let VARMAP be a function that, when given a variable name and a state, returns the current value of
the variable
VARMAP (ij, s) = vj
1. Decimal Numbers
<dec_num> → 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
| <dec_num> (0 | 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9)
2. Expressions
Me(<expr>, s) =
case <expr> of
<var> =>
if VARMAP(<var>, s) = undef
then error
else VARMAP(<var>, s)
<binary_expr> =>
if (Me(<binary_expr>.<left_expr>, s) = undef
OR Me(<binary_expr>.<right_expr>, s) =
undef)
then error
else
Me(<binary_expr>.<left_expr>, s) +
Me(<binary_expr>.<right_expr>, s)
https://topperworld.in/
Topperworld.in
else Me(<binary_expr>.<left_expr>, s) *
Me(<binary_expr>.<right_expr>, s)
3 Assignment Statements
Ma(x := E, s) =
if Me(E, s) = error
then error
else s’ = {<i1’,v1’>,<i2’,v2’>,...,<in’,vn’>},
= Me (E, s) if ij = x
Ml(while B do L, s) =
if Mb(B, s) = undef
then error
then s
then error
The meaning of the loop is the value of the program variables after the statements in the loop have been
executed the prescribed number of times, assuming there have been no errors
• In essence, the loop has been converted from iteration to recursion, where the recursive control
is mathematically defined by other recursive state mapping functions
• Recursion, when compared to iteration, is easier to describe with mathematical rigor
UNIT-II
DATA TYPES
Data Types:
• Primitive
• Structured
Integer Types:
– Python has an integer type and a long integer which can get as big as it needs to.
1. Representing Integers:
– Sign bit
– Ones complement
• Sign bit
• Ones complement
Twos Complement:
• For scientific use support at least two floating-point types (e.g., float and double; sometimes
more)
• The float type is the standard size, usually being stored in four bytes of memory.
• The double type is provided for situations where larger fractional parts and/or a larger range of
exponents is needed
• Floating-point values are represented as fractions and exponents, a form that is borrowed from
scientific notation
https://topperworld.in/
Topperworld.in
• The collection of values that can be represented by a floating-point type is defined in terms of
precision and range
• Precision is the accuracy of the fractional part of a value, measured as the number of bits
• Range is a combination of the range of fractions and, more important, the range of exponents.
• We can convert the decimal number to base 2 just as we did for integers
– fixed number of bits for the whole and fractional parts severely limits the range of values
we can represent
• Use a fixed number of bits for the exponent which is offset to allow for negative exponents
– float
– double
• Some scripting languages only have one kind of number which is a floating point type
– Essential to COBOL
• Advantage: accuracy
C# decimal Type:
• 128-bit representation
– no roundoff error
• Boolean
– Range of values: two elements, one for “true” and one for “false”
– A Boolean value could be represented by a single bit, but because a single bit of memory
cannot be accessed efficiently on many machines, they are often stored in the smallest
efficiently addressable cell of memory, typically a byte.
• Character
• Rational (Scheme)
Character Strings :
• Character string constants are used to label output, and the input and output of all kinds of data
are often done in terms of strings.
• Operations:
– Catenation
– Substring reference
– Pattern matching
https://topperworld.in/
Topperworld.in
• Design issues:
• C and C++
– Not primitive
– Primitive
• Java
– String class
String Implementation
– integer
– char
– boolean
– enumeration types
– subrange types
Enumeration Types:
• All possible values, which are named constants, are provided in the definition
C example:
• Design issues
– duplication of names
– coercion rules
Ex:
typedef enum weekday {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}
weekday;
– toString and valueOf are overridden to make input and output easier
System.out.println (season);
// prints WINTER
Example:
• Ada’s design:
Day1: Days;
Day2: Weekday;
Day2:= Day1;
Evaluation
Subrange types enhance readability by making it clear to readers that variables of subtypes can store only
certain ranges of values. Reliability is increased with subrange types, because assigning a value to a
subrange variable that is outside the specified range is detected as an error, either by the compiler (in the
case of the assigned value being a literal value) or by the run-time system (in the case of a variable or
expression). It is odd that no contemporary language except Ada has subrange types.
• Specific elements of an array are referenced by means of a two-level syntactic mechanism, where
the first part is the aggregate name, and the second part is a possibly dynamic selector consisting
of one or more items known as subscripts or indices.
• If all of the subscripts in a reference are constants, the selector is static; otherwise, it is dynamic.
The selection operation can be thought of as a mapping from the array name and the set of
https://topperworld.in/
Topperworld.in
subscript values to an element in the aggregate. Indeed, arrays are sometimes called finite
mappings. Symbolically, this mapping can be shown as
▪ array_name(subscript_value_list) → element
Subscript Bindings and Array Categories
• The binding of the subscript type to an array variable is usually static, but the subscript value ranges
are sometimes dynamically bound.
• There are five categories of arrays, based on the binding to subscript ranges, the binding to storage,
and from where the storage is allocated.
• A static array is one in which the subscript ranges are statically bound and storage allocation is
static (done before run time).
• The advantage of static arrays is efficiency: No dynamic allocation or deallocation is
required.
• The disadvantage is that the storage for the array is fixed for the entire execution time of
the program.
• A fixed stack-dynamic array is one in which the subscript ranges are statically bound, but the
allocation is done at declaration elaboration time during execution.
• The advantage of fixed stack-dynamic arrays over static arrays is space efficiency
• The disadvantage is the required allocation and deallocation time
• A stack-dynamic array is one in which both the subscript ranges and the storage allocation are
dynamically bound at elaboration time. Once the subscript ranges are bound and the storage is
allocated, however, they remain fixed during the lifetime of the variable.
• The advantage of stack-dynamic arrays over static and fixed stack-dynamic arrays is
flexibility
• A fixed heap-dynamic array is similar to a fixed stack-dynamic array, in that the subscript ranges
and the storage binding are both fixed after storage is allocated
• The advantage of fixed heap-dynamic arrays is flexibility—the array’s size always fits
the problem.
• The disadvantage is allocation time from the heap, which is longer than allocation time
from the stack.
• A heap-dynamic array is one in which the binding of subscript ranges and storage allocation is
dynamic and can change any number of times during the array’s lifetime.
• The advantage of heap-dynamic arrays over the others is flexibility:
• The disadvantage is that allocation and deallocation take longer and may happen many
times during execution of the program.
https://topperworld.in/
Topperworld.in
Array Initialization
Some languages provide the means to initialize arrays at the time their storage is allocated.
An array aggregate for a single-dimensioned array is a list of literals delimited by parentheses and slashes.
For example, we could have
Integer, Dimension (3) :: List = (/0, 5, 5/)
In the C declaration
int list [] = {4, 5, 7, 83};
These arrays can be initialized to string constants, as in
char name [] = "freddie";
Arrays of strings in C and C++ can also be initialized with string literals. In this case, the array is one of
pointers to characters.
For example,
char *names [] = {"Bob", "Jake" ,"Darcie"};
In Java, similar syntax is used to define and initialize an array of references to String objects.
For example,
String[] names = ["Bob", "Jake", "Darcie"];
Ada provides two mechanisms for initializing arrays in the declaration statement: by listing them in the
order in which they are to be stored, or by directly assigning them to an index position using the =>
operator, which in Ada is called an arrow.
For example, consider the following:
List : array (1.5) of Integer := (1, 3, 5, 7, 9);
Bunch : array (1.5) of Integer := (1 => 17, 3 => 34,
others => 0);
when multi dimensioned arrays are actually arrays of arrays. For example, a matrix would appear as an
array of single-dimensioned arrays.
For example,
myArray[3][7]
Slices
A slice of an array is some substructure of that array.
For example, if A is a matrix, then the first row of A is one possible slice, as are the last row and the first
column. It is important to realize that a slice is not a new data type. Rather ,it is a mechanism for
referencing part of an array as a unit.
Evaluation
Arrays have been included in virtually all programming languages
Implementation of Array Types
Implementing arrays requires considerably more compile-time effort than does implementing primitive
types. The code to allow accessing of array elements must be generated at compile time. At run time, this
code must be executed to produce element addresses. There is no way to pre compute the address to be
accessed by a reference such as
list [k]
A single-dimensioned array is implemented as a list of adjacent memory cells. Suppose the array list is
defined to have a subscript range lower bound of 0. The access function for list is often of the form
address
( list [k] ) = address (list [0] ) + k * element_size where the first operand of the addition is the
constant part of the access function, and the second is the variable part .
If the element type is statically bound and the array is statically bound to storage, then the value of the
constant part can be computed before run time. However, the addition and multiplication operations must
be done at run time.
The generalization of this access function for an arbitrary lower bound is address (list[k]) = address
( list [lower_bound]) + ( (k - lower_bound) * element_size)
Associative Arrays
An associative array is an unordered collection of data elements that are indexed by an equal number of
values called keys. In the case of non-associative arrays, the indices never need to be stored (because of
their regularity). In an associative array, however, the user-defined keys must be stored in the structure.
So each element of an associative array is in fact a pair of entities, a key and a value. We use Perl’s design
of associative arrays to illustrate this data structure. Associative arrays are also supported directly by
https://topperworld.in/
Topperworld.in
Python, Ruby, and Lua and by the standard class libraries of Java, C++, C#, and F#. The only design issue
that is specific for associative arrays is the form of references to their elements.
Structure and Operations
In Perl, associative arrays are called hashes, because in the implementation their elements are stored and
retrieved with hash functions. The namespace for Perl hashes is distinct: Every hash variable name must
begin with a percent sign (%). Each hash element consists of two parts: a key, which is a string, and a
value, which is a scalar (number, string, or reference). Hashes can be set to literal values with the
assignment statement, as in
%salaries = ("Gary" => 75000, "Perry" => 57000,
"Mary" => 55750, "Cedric" => 47850);
Recall that scalar variable names begin with dollar signs ($).
For example,
$salaries {"Perry"} = 58850;
A new element is added using the same assignment statement form. An element can be removed from the
hash with the delete operator, as in
Delete $salaries{"Gary"};
Record Types
A record is an aggregate of data elements in which the individual elements are identified by names and
accessed through offsets from the beginning of the structure. There is frequently a need in programs to
model a collection of data in which the individual elements are not of the same type or size. For example,
information about a college student might include name, student number, grade point average, and so
forth. A data type for such a collection might use a character string for the name, an integer for the student
number, a floating point for the grade point average, and so forth. Records are designed for this kind of
need.
The following design issues are specific to records:
• What is the syntactic form of references to fields?
• Are elliptical references allowed?
Definitions of Records
The fundamental difference between a record and an array is that record elements, or fields, are not
referenced by indices. Instead, the fields are named with identifiers, and references to the fields are made
using these identifiers The COBOL form of a record declaration, which is part of the data division of a
COBOL program, is illustrated in the following example:
01 EMPLOYEE-RECORD.
02 EMPLOYEE-NAME.
https://topperworld.in/
Topperworld.in
The fields of records are stored in adjacent memory locations. But because the sizes of the fields are not
necessarily the same, the access method used for arrays is not used for records. Instead, the offset address,
relative to the beginning of the record, is associated with each field. Field accesses are all handled using
these offsets. The compile-time descriptor for a record has the general
form shown in Figure 6.7. Run-time descriptors for records are unnecessary
Record
Name
Type
Field 1
Offset
…...
Name
Type
field n Offset
Address
https://topperworld.in/
Topperworld.in
Union Types
A union is a type whose variables may store different type values at different times during program
execution. As an example of the need for a union type, consider a table of constants for a compiler, which
is used to store the constants found in a program being compiled. One field of each table entry is for the
value of the constant. Suppose that for a particular language being compiled, the types of constants were
integer, floating point, and Boolean. In terms of table management, it would be convenient if the same
location, a table field, could store a value of any of these three types. Then all constant values could be
addressed in the same way. The type of such a location is, in a sense, the union of the three value types it
can store.
Design Issues
The problem of type checking union types, leads to one major design issue. The other fundamental
question is how to syntactically represent a union. In some designs, unions are confined to be parts
of record structures, but in others they are not. So, the primary design issues that are particular to union
types are the following:
• Should type checking be required? Note that any such type checking must be dynamic.
• Should unions be embedded in records?
Unions are implemented by simply using the same address for every possible variant. Sufficient storage
for the largest variant is allocated. The tag of a discriminated union is stored with the variant in a record
like structure. At compile time, the complete description of each variant must be stored. This can be done
by associating a case table with the tag entry in the descriptor. The case table has an entry for each
variant, which points to a descriptor for that particular variant. To illustrate this arrangement, consider the
following Ada example:
type Node (Tag : Boolean) is
record
https://topperworld.in/
Topperworld.in
case Tag is
when True => Count : Integer;
when False => Sum : Float;
end case;
end record;
The descriptor for this type could have the form shown in Figure
Discriminated union
BOOLEAN
Offset count
integer
• True •
Address False •
Sum
Float
– range of values that consists of memory addresses plus a special value, nil
• A pointer can be used to access a location in the area where storage is dynamically
created (usually called a heap)
Pointer Operations:
• Dereferencing yields the value stored at the location represented by the pointer’s value
j = *ptr
Pointer Operations
IllustraDtee d
referencing a pointer
assignment
ptr = &j j = *ptr
allocation
ptr = (int*)malloc(
sizeof(
int))
Addison-Wesley.
Pointer Problems:
https://topperworld.in/
Topperworld.in
Pointer
Problems
• Dangling
pointers
(dangerous)
– A pointer points
to a heap-
dynamic variable
that has been
de-allocated
• Garbage
– An allocated
heap-dynamic
variable that is
no longer
Addison-Wesley
• void * can point to any type and can be type checked (cannot be de-referenced)
https://topperworld.in/
Topperworld.in
Float stuff[100];
Float *p;
p = stuff;
Reference Types:
• C++ includes a special kind of pointer type called a reference type that is used primarily for
formal parameters
• Java extends C++’s reference variables and allows them to replace pointers entirely
Evaluation of Pointers:
• Pointers are like goto's--they widen the range of cells that can be accessed by a variable
• Pointers or references are necessary for dynamic data structures--so we can't design a language
without them
• A machine consists of
–
https://topperworld.in/
Topperworld.in
Names:
– Maximum length?
Length of Names:
• Language examples:
– FORTRAN I: maximum 6
– COBOL: maximum 30
• Real VarName (Real is a data type followed with a name, therefore Real is a
keyword)
Variables:
– Name
– Address
– Value
– Type
– Lifetime
– Scope
Variable Attributes:
• Type - allowed range of values of variables and the set of defined operations
Value - the contents of the location with which the variable is associated (r-value
• Load time -- bind a FORTRAN 77 variable to a memory cell (or a C static variable)
https://topperworld.in/
Topperworld.in
• A binding is static if it first occurs before run time and remains unchanged throughout program
execution.
• A binding is dynamic if it first occurs during execution or can change during execution of the
program
Type Binding:
– An explicit declaration is a program statement used for declaring the types of variables
– An implicit declaration is a default mechanism for specifying types of variables (the first
appearance of the variable in the program)
Type Checking
• Generalize the concept of operands and operators to include subprograms and assignments
• Type checking is the activity of ensuring that the operands of an operator are of compatible types
Compatible type :
It is one that is either legal for the operator, or is allowed under language rules to be
implicitly converted, by compiler- generated code, to a legal type
• If all type bindings are static, nearly all type checking can be static (done at compile time)
• If type bindings are dynamic, type checking must be dynamic (done at run time)
– Advantage: allows the detection of misuse of variables that result in type errors
https://topperworld.in/
Topperworld.in
– C and C++
– Ada is almost
– Java is similar
Strong Typing:
• Advantage of strong typing: allows the detection of the misuses of variables that result in type
errors
• Language examples:
• FORTRAN 77 is not: parameters, EQUIVALENCE
• Pascal is not: variant records
• C and C++ are not: parameter type checking can be avoided; unions are not
type checked
• Ada is, almost (UNCHECKED CONVERSION is loophole)
(Java is similar)
• Coercion rules strongly affect strong typing--they can weaken it considerably (C+ versus Ada)
• Although Java has just half the assignment coercions of C++, its strong typing is
still far less effective than that of Ada
Type Compatibility
• Our concern is primarily for structured types
• Def: Name type compatibility means the two variables have compatible types if
they are in either the same declaration or in declarations that use the same type name
https://topperworld.in/
Topperworld.in
Named Constants
⚫ Def: A named constant is a variable that is bound to a value only when it is bound
to storage
⚫ Advantages: readability and modifiability
⚫ Used to parameterize programs
• The binding of values to named constants can be either static (called manifest
constants) or dynamic
• Languages:
• Pascal: literals only
• FORTRAN 90: constant-valued expressions
• Ada, C++, and Java: expressions of any kind
Variable Initialization
• Def: The binding of a variable to a value at the time it is bound to storage is called
initialization
• Initialization is often done on the declaration statement
https://topperworld.in/
Topperworld.in
e.g., Java
int sum = 0;
Coercion:
• Java's strong typing is still far less effective than that of Ada
List = 17.3;
• But …
• The lifetime of a variable is the time during which it is bound to a particular memory cell
• Depending on the language, allocation can be either controlled by the programmer or done
automatically
Variable Scope:
• The nonlocal variables of a program unit are those that are visible but not declared there
• The scope rules of a language determine how references to names are associated with variables
• Scope and lifetime are sometimes closely related, but are different concepts
Static Scope:
• To connect a name reference to a variable, you (or the compiler) must find the declaration
• Search process: search declarations, first locally, then in increasingly larger enclosing scopes,
until one is found for the given name Enclosing static scopes (to a specific scope) are called its
static ancestors; the nearest static ancestor is called a static parent
• Variables can be hidden from a unit by having a "closer" variable with the same name
• C++, Java and Ada allow access to some of these "hidden" variables
– In Ada: unit.name
A calls C and D
B calls A and E
https://topperworld.in/
Topperworld.in
• Suppose the spec is changed so that D must now access some data in B
• Solutions:
– Put D in B (but then C can no longer call it and D cannot access A's variables)
– Move the data from B that D needs to MAIN (but then all procedures can access them)
Dynamic Scope:
• Based on calling sequences of program units, not their textual layout (temporal versus spatial)
• References to variables are connected to declarations by searching back through the chain of
subprogram calls that forced execution to this point
• Static scoping
– Reference to x is to MAIN's x
• Dynamic scoping
– Reference to x is to SUB1's x
– Advantage: convenience
Referencing Environments:
• The referencing environment of a statement is the collection of all names that are visible in the
statement
https://topperworld.in/
Topperworld.in
• In a static-scoped language, it is the local variables plus all of the visible variables in all of the
enclosing scopes
Arithmetic Expressions:
• An operator can be unary, meaning it has a single operand, binary, meaning it has two operands,
or ternary, meaning it has three operands.
• In most programming languages, binary operators are infix, which means they appear between
their operands.
• One exception is Perl, which has some operators that are prefix, which means they precede their
operands.
• An implementation of such a computation must cause two actions: fetching the operands, usually
from memory, and executing arithmetic operations on those operands.
– operators
– operands
– parentheses
– function calls
–
https://topperworld.in/
Topperworld.in
• operator overloading
Operators:
– unary -, !
– +, -, *, /, %
Conditional Expressions:
• An example:
if (count == 0) average = 0
• Precedence rules define the order in which “adjacent” operators of different precedence levels are
evaluated
– parentheses
– unary operators
– *, /
+, -
• Associativity rules define the order in which adjacent operators with the same precedence level
are evaluated
• APL is different; all operators have equal precedence and all operators associate right to left
2. Constants: sometimes a fetch from memory; sometimes the constant is in the machine language
instruction
• Functional side effects: when a function changes a two-way parameter or a non-local variable
a = 10;
https://topperworld.in/
Topperworld.in
b = a + fun(a);
• Advantage: it works!
2. Write the language definition to demand that operand evaluation order be fixed
Overloaded Operators:
• Use of an operator for more than one purpose is called operator overloading
– Can be avoided by introduction of new symbols (e.g., Pascal’s div for integer division)
Type Conversions
• A narrowing conversion converts an object to a type that does not include all of the values of the
original type
• A widening conversion converts an object to a type that can include at least approximations to all
of the values of the original type
Coercion:
• Disadvantage of coercions:
Casting:
• Examples
– C: (int) angle
Errors in Expressions:
• Causes
Relational Operators:
• Operator symbols used vary somewhat among languages (!=, /=, .NE., <>, #)
Boolean Operators:
• Example operators
FORTRAN 77 FORTRAN 90 C Ada
.OR .or || or
No Boolean Type in C:
– it uses int type with 0 for false and nonzero for true
• Consequence
postfix ++, --
*,/,%
binary +, -
=, !=
&&
||
Index++;
– When index=length, LIST [index] will cause an indexing problem (assuming LIST has
length -1 elements)
Mixed-Mode Assignment:
int a, b;
float c;
c = a / b;
Assignment Statements:
• = can be bad when it is overloaded for the relational operator for equality
https://topperworld.in/
Topperworld.in
Compound Assignment:
• Example
a=a+b
is written as
a += b
• Unary assignment operators in C-based languages combine increment and decrement operations
with assignment
• Examples
Assignment as an Expression:
• In C, C++, and Java, the assignment statement produces a result and can be used as operands
• An example:
ch = get char() is carried out; the result (assigned to ch) is used in the condition for the while
statement
One important result: It was proven that all algorithms represented by flowcharts can be coded
with only two-way selection and pretest logical loops
Control Structure
Selection Statements
• A selection statement provides the means of choosing between two or more paths of execution
• Two general categories:
–Two-way selectors
–Multiple-way selectors
• General form:
If control_expression
then clause
else clause
• Design Issues:
–What is the form and type of the control expression?
–How are the then and else clauses specified?
–How should the meaning of nested selectors be specified?
• If the then reserved word or some other syntactic marker is not used to introduce the then clause, the
control expression is placed in parentheses
• In C89, C99, Python, and C++, the control expression can be arithmetic
• In languages such as Ada, Java, Ruby, and C#, the control expression must be Boolean
https://topperworld.in/
Topperworld.in
Clause Form
• In many contemporary languages, the then and else clauses can be single statements or
compound statements
• In Perl, all clauses must be delimited by braces (they must be compound)
Nesting Selectors
• Java example
if ( sum == 0)
if ( count == 0)
result = 0;
else result = 1;
• Which if gets the else?
• Java's static semantics rule: else matches with the nearest if
Nesting Selectors (continued)
• To force an alternative semantics, compound statements may be used:
if (sum == 0) {
if (count == 0)
result = 0;
}
else result = 1;
• The above solution is used in C, C++, and C#
• Perl requires that all then and else clauses to be compound
• Statement sequences as clauses: Ruby
if sum == 0 then
if count == 0 then
result = 0
else
https://topperworld.in/
Topperworld.in
result = 1
end
end
•Python
if sum == 0 :
if count == 0 :
result = 0
else :
result = 1
…
when choice list => stmt_sequence;
when others => stmt_sequence;]
end case;
• More reliable than C‘s switch (once a stmt_sequence execution is completed, control is passed to the
first statement after the case statement
• Ada design choices:
1. Expression can be any ordinal type
2. Segments can be single or compound
3. Only one segment can be executed per execution of the construct
4. Unrepresented values are not allowed
• Constant List Forms:
1. A list of constants
2. Can include:
- Subranges
- Boolean OR operators (|)
• Multiple Selectors can appear as direct extensions to two-way selectors, using else-if clauses, for
example in Python:
if count < 10 :
bag1 = True
elsif count < 100 :
bag2 = True
elif count < 1000 :
https://topperworld.in/
Topperworld.in
bag3 = True
Iterative Statements
Counter-Controlled Loops
• A counting iterative statement has a loop variable, and a means of specifying the initial and
terminal, and stepsize values
• Design Issues:
• Should it be legal for the loop variable or loop parameters to be changed in the loop body, and if so,
does the change affect loop control?
• Should the loop parameters be evaluated only once, or once for every iteration?
- The expressions can be whole statements, or even statement sequences, with the statements separated by
commas
–The value of a multiple-statement expression is the value of the last statement in the expression
–If the second expression is absent, it is an infinite loop
• Design choices:
- There is no explicit loop variable
- Everything can be changed in the loop
- The first expression is evaluated once, but the other two are evaluated with each iteration
•C++ differs from C in two ways:
•The control expression can also be Boolean
•The initial expression can include variable definitions (scope is from the definition to the end of the loop
body)
•Java and C#
–Differs from C++ in that the control expression must be Boolean
Iterative Statements: Logically-Controlled Loops
•Repetition control is based on a Boolean expression
https://topperworld.in/
Topperworld.in
•Design issues:
–Pretest or posttest?
–Should the logically controlled loop be a special case of the counting loop statement or a separate
statement?
• Sometimes it is convenient for the programmers to decide a location for loop control (other than top or
bottom of the loop)
•Simple design for single loops (e.g., break)
•Design issues for nested loops
•Should the conditional be part of the exit?
•Should control be transferable out of more than one loop?
Iterative Statements: User-Located Loop Control Mechanisms break and continue
•C , C++, Python, Ruby, and C# have unconditional unlabeled exits (break)
•Java and Perl have unconditional labeled exits (break in Java, last in Perl)
•C, C++, and Python have an unlabeled control statement, continue, that skips the remainder of the
current iteration, but does not exit the loop
•Java and Perl have labeled versions of continue
Iterative Statements: Iteration Based on Data Structures
•Number of elements of in a data structure control loop iteration
https://topperworld.in/
Topperworld.in
•Control mechanism is a call to an iterator function that returns the next element in some chosen order, if
there is one; else loop is terminate
•C's for can be used to build a user-defined iterator:
for (p=root; p==NULL; traverse(p)){
}
•C#‘s foreach statement iterates on the elements of arrays and other
collections:
Strings[] = strList = {"Bob", "Carol", "Ted"};
foreach (Strings name in strList)
Console.WriteLine ("Name: {0}", name);
- The notation {0} indicates the position in the string to be displayed
•Perl has a built-in iterator for arrays and hashes, foreach
Unconditional Branching
• Basic Idea: if the order of evaluation is not important, the program should
not specify one
• Form
do <Boolean> -> <statement>
[] <Boolean> -> <statement>
...
[] <Boolean> -> <statement>
od
•Semantics: for each iteration
–Evaluate all Boolean expressions
–If more than one are true, choose one non-deterministically; then start loop again
–If none are true, exit loop
Guarded Commands: Rationale
UNIT-III
Basic Definitions:
• Positional
• Keyword
• Sort (List => A, Length => N);
• For named association:
Advantage: order is irrelevant
• parameter’s names
Sort (List => A, Length => N);
https://topperworld.in/
Topperworld.in
Example, in Ada:
• Allocation/deallocation time
• Indirect addressing
• Subprograms cannot be history sensitive
• Static locals are the opposite
Parameters and Parameter Passing:
• Pass-by-value
• Pass-by-result
• Pass-by-value-result
• Pass-by-reference
• Pass-by-name
https://topperworld.in/
Topperworld.in
Pass-By-Value
• in mode
• Either by physical move or access path
Disadvantages of access path method: Must write-protect in the called subprogram, Accesses cost
more (indirect addressing)
Pass-By-Result
• out mode
Local’s value is passed back to the caller
...
sub1(x, x);
Pass-By-Value-Result
inout mode
Disadvantages:
Those of pass-by-result
Those of pass-by-value
Pass-By-Reference
inout mode
Disadvantages:
Slower accesses can allow aliasing: Actual parameter collisions: sub1(x, x); Array element
collisions: sub1(a[i], a[j]); /* if i = j */ Collision between formals and globals Root cause of all of
these is: The called subprogram is provided wider access to non locals than is necessary
Pass-by-value-result does not allow these aliases (but has other problems!)
Pass-By-Name multiple modes By textual substitution ,Formals are bound to an access method at
the time of the call, but actual binding to a value or address takes place at the time of a reference or
assignment
https://topperworld.in/
Topperworld.in
Resulting semantics:
If actual is an expression with a reference to a variable that is also accessible in the program, it is also
like nothing else
Pass-By-Name Example 1
begin
x := 1;
y := 2;
x := 2;
y := 3;
end;
sub1(i, a[i]);
Pass-By-Name Example 2
begin
k := 1;
y := x;
https://topperworld.in/
Topperworld.in
k := 5;
z := x;
end;
sub1(k+1, j, i);
Disadvantages of Pass-By-Name
FORTRAN, Before 77, pass-by-reference 77—scalar variables are often passed by value result
C++: Like C, but also allows reference type parameters, which provide the efficiency of pass-by-
reference with in-mode semantics
Ada
All three semantic modes are available If out, it cannot be referenced If in, it cannot be assigned
Java Like C++, except only references
ALGOL 60 and most of its descendants use the runtime stack Value—copy it to the stack; references are
indirect to the stack Result—sum, Reference—regardless of form, put the address in the stack
Name:
Run-time resident code segments or subprograms evaluate the address of the parameter Called for each
reference to the formal, these are called thunks Very expensive, compared to reference or value-result
Simple variables are passed by copy (valueresult) Structured types can be either by copy or reference
This can be a problem, because Aliasing differences (reference allows aliases, but value-result does not)
Procedure termination by error can produce different actual parameter results Programs with such errors
are “erroneous”
If a multidimensional array is passed to a subprogram and the subprogram is separately compiled, the
compiler needs to know the declared size of that array to build the storage mapping function
C and C++
Programmer is required to include the declared sizes of all but the first subscript in the actual parameter ,
This disallows writing flexible subprograms Solution: pass a pointer to the array and the sizes of the
dimensions as other parameters; the user must include the storage mapping function, which is in terms of
the size
Ada
Unconstrained arrays—declared size is part of the object declaration Pre-90 FORTRAN , Formal
parameter declarations for arrays can include passed parameters
...
END
• Efficiency
• One-way or two-way
• These two are in conflict with one another!
• Good programming => limited access to
• variables, which means one-way whenever possible
• Efficiency => pass by reference is fastest way to pass structures of significant size Also, functions
should not allow reference Parameters
Subprograms As Parameters: Issues
Early Pascal and FORTRAN 77 do not Later versions of Pascal, Modula-2, and FORTRAN 90 do Ada
does not allow subprogram parameters C and C++ - pass pointers to functions; parameters can be type
checked
Possibilities:
It is that of the subprogram that passed it (ad hocbinding, never been used)
https://topperworld.in/
Topperworld.in
Overloading
An overloaded subprogram is one that has the same name as another subprogram in the same referencing
environment C++ and Ada have overloaded subprograms built-in, and users can write their own
overloaded subprograms
Generic Subprograms
1. A generic or polymorphic subprogram is one that takes parameters of different types on different
activations Overloaded subprograms provide ad hoc polymorphism
2. A subprogram that takes a generic parameter that is used in a type expression that describes the type
of the parameters of the subprogram provides parametric polymorphism
3. See Ada generic and C++ template examples in text
4. Independent compilation is compilation of some of the units of a program separately from the rest of
the program, without the benefit of interface information
5. Separate compilation is compilation of some of the units of a program separately from the rest of the
program, using interface information to check the correctness of the interface between the two parts
Language Examples:
Functions
Design Issues:
The nonlocal variables of a subprogram are those that are visible but not declared in the subprogram
Global variables are those that may be visible in all of the subprograms of a program
FORTRAN COMMON
Static scoping
External declarations: C
Users can further overload operators in C++ and Ada not carried over into Java)
sum : Integer := 0;
begin
end loop;
return sum;
end "*";
Coroutines:
Coroutine is a subprogram that has multiple entries and controls them itself Also called symmetric
control A coroutine call is named a resume. The first resume of a coroutine is to its beginning, but
subsequent calls enter at the point just after the last executed statement in the coroutine. Typically,
coroutines repeatedly resume each other, possibly forever. Coroutines provide quasiconcurrent
execution of program units (the coroutines) Their execution is interleaved, but not overlapped
https://topperworld.in/
Topperworld.in
UNIT-IV
Abstraction:
- Nearly all programming languages designed since 1980 have supported data abstraction with some
kind of module
Encapsulation:
- Original motivation:
2. Some means of partial compilation (compilation units that are smaller than the whole program)
- Obvious solution: a grouping of subprograms that are logically related into a unit that can be
separately compiled
2. FORTRAN 77 and C - Files containing one or more subprograms can be independently compiled
3. FORTRAN 90, C++, Ada (and other contemporary languages) - separately compliable modules
Definitions: An abstract data type is a user-defined datatype that satisfies the following two conditions:
Definition 1: The representation of and operations of objects of the type are defined in a single
syntactic unit; also, other units can create objects of the type.
Definition 2: The representation of objects of the type is hidden from the program units that use
these objects, so the only operations possible are those provided in the type's definition.
https://topperworld.in/
Topperworld.in
Advantage of Restriction 1:
Advantage of Restriction 2:
- Reliability--by hiding the data representations, user code cannot directly access objects
of the type. User code cannot depend on the representation, allowing the representation to be
changed without affecting user code.
- User-defined abstract data types must have the same characteristics as built-in abstract data
types
2. A method of making type names and subprogram headers visible to clients, while hiding actual
definitions.
3. Some primitive operations must be built into the language processor (usually just assignment
and comparisons for equality and inequality)
- Some operations are commonly needed, but must be defined by the type designer
Language Examples:
1. Simula 67
2. Ada
- Information Hiding
- Hidden types are named in the spec package in, as in:
- Representation of an exported hidden type is specified in a special invisible (to clients) part of
the spec package (the private clause), as in:
package … is
type NODE_TYPE is
record
end record;
…
https://topperworld.in/
Topperworld.in
- A spec package can also define unhidden type simply by providing the representation outside a
private clause
1. The compiler must be able to see the representation after seeing only the spec package (the
compiler can see the private clause)
2. Clients must see the type name, but not the representation (clients cannot see the private clause)
• C++, Ada, Java 5.0, and C# 2005 provide support for parameterized ADTs
Parameterized ADTs in Ada
• Ada Generic Packages
–Make the stack type more flexible by making the element type and the size of the stack generic
generic
Max_Size: Positive;
type Elem_Type is private;
package Generic_Stack is
Type Stack_Type is limited private;
function Top(Stk: in out StackType) return Elem_type;
…
end Generic_Stack;
Package Integer_Stack is new Generic_Stack(100,Integer);
Package Float_Stack is new Generic_Stack(100,Float);
Parameterized ADTs in C++
• Classes can be somewhat generic by writing parameterized constructor
functions
class stack {
…
stack (int size) {
stk_ptr = new int [size];
max_len = size - 1;
top = -1;
https://topperworld.in/
Topperworld.in
};
…
}
stack stk(100);
• The stack element type can be parameterized by making the class a template class
template <class Type>
class stack {
private:
Type *stackPtr;
const int maxLen;
int topPtr;
public:
stack() {
stackPtr = new Type[100];
maxLen = 99;
topPtr = -1;
}
…
}
Parameterized Classes in Java 5.0
• Generic parameters must be classes
• Most common generic types are the collection types, such as Linked List and Array List
• Eliminate the need to cast objects that are removed
• Eliminate the problem of having multiple types in a structure
Parameterized Classes in C# 2005
• Similar to those of Java 5.0
• Elements of parameterized structures can be accessed through indexing
• The concept of ADTs and their use in program design was a milestone in the development of
languages
• Two primary features of ADTs are the packaging of data with their associated operations and
information hiding
• Ada provides packages that simulate ADTs
• C++ data abstraction is provided by classes
• java‘s data abstraction is similar to C++
https://topperworld.in/
Topperworld.in
Object-Oriented Programming
• Abstract data types
• Inheritance
–Inheritance is the central theme in OOP and languages that support it
• Polymorphism
Inheritance
• Productivity increases can come from reuse
–ADTs are difficult to reuse—always need changes
–All ADTs are independent and at the same level
• Inheritance allows new classes defined in terms of existing ones, i.e., by allowing them to inherit
common parts
• Inheritance addresses both of the above concerns--reuse ADTs after minor changes and define classes
in a hierarchy
Object-Oriented Concepts
• ADTs are usually called classes
• Class instances are called objects
• A class that inherits is a derived class or a subclass
• The class from which another class inherits is a parent class or super class
• Subprograms that define operations on objects are called methods
• Calls to methods are called messages
• The entire collection of methods of an object is called its message protocol or message interface
• Messages have two parts--a method name and the destination object
• In the simplest case, a class inherits all of the entities of its parent
• An abstract method is one that does not include a definition (it only defines a protocol)
Categories of Concurrency:
1. Physical concurrency - Multiple independent processors ( multiple threads of control)
2. Logical concurrency - The appearance of physical concurrency is presented by time sharing
one processor (software can be designed as if there were multiple threads of control)
- Coroutines provide only quasiconcurrency
Reasons to Study Concurrency:
1. It involves a new way of designing software that can be very useful--many real-world
situation involve concurrency
2. Computers capable of physical concurrency are now widely used
Fundamentals (for stmt-level concurrency) :
Def: A task is a program unit that can be in concurrent execution with other program units
- Tasks differ from ordinary subprograms in that:
1. A task may be implicitly started
2. When a program unit starts the execution of a task, it is not necessarily suspended
3. When a task’s execution is completed, control may not return to the caller
Def: A task is disjoint if it does not communicate with or affect the execution of any other task in the
program in any way Task communication is necessary for synchronization
- Task communication can be through:
1. Shared nonlocal variables
2. Parameters
3. Message passing
- Kinds of synchronization:
1. Cooperation
https://topperworld.in/
Topperworld.in
- Task A must wait for task B to complete some specific activity before task A can continue its
execution
e.g., the producer-consumer problem
2. Competition
- When two or more tasks must use some resource that cannot be simultaneously used
e.g., a shared counter
- A problem because operations are not atomic
- Competition is usually provided by mutually exclusive access (methods are discussed later
- Providing synchronization requires a mechanism for delaying task execution
- Task execution control is maintained by a program called the scheduler, which maps task
execution onto available processors
- Tasks can be in one of several different execution states:
1. New - created but not yet started
2. Runnable or ready - ready to run but not currently running (no available processor)
3. Running
4. Blocked - has been running, but cannot not continue (usually waiting for some event to
occur)
5. Dead - no longer active in any sense
Liveness is a characteristic that a program unit may or may not have
- In sequential code, it means the unit will eventually complete its execution
- In a concurrent environment, a task can easily lose its liveness
- If all tasks in a concurrent environment lose their liveness, it is called deadlock
- Design Issues for Concurrency:
1. How is cooperation synchronization provided?
2. How is competition synchronization provided?
3. How and when do tasks begin and end execution?
4. Are tasks statically or dynamically created?
Example: A buffer and some producers and some consumers
Technique: Attach two SIGNAL objects to the buffer, one for full spots and one for empty spots
Methods of Providing Synchronization:
1. Semaphores
2. Monitors
3. Message Passing
https://topperworld.in/
Topperworld.in
end
- Competition Synchronization with Semaphores:
- A third semaphore, named access, is used to control access (competition synchronization)
- The counter of access will only have the values 0 and 1
- Such a semaphore is called a binary semaphore
SHOW the complete shared buffer example
- Note that wait and release must be atomic!
Evaluation of Semaphores:
1. Misuse of semaphores can cause failures in cooperation synchronization
e.g., the buffer will overflow if the wait of full spots is left out
2. Misuse of semaphores can cause failures in competition synchronization
e.g., The program will deadlock if the release of access is left out
:
2. Monitors ( Concurrent Pascal, Modula, Mesa)
The idea: encapsulate the shared data and it operations to restrict access
A monitor is an abstract data type for shared data show the diagram of monitor buffer operation,
- Example language: Concurrent Pascal
- Concurrent Pascal is Pascal + classes, processes (tasks), monitors, and the queue data type (for
semaphores)
Example language: Concurrent Pascal (continued) processes are types
Instances are statically created by declarations
- An instance is “started” by init, which allocate its local data and begins its execution
- Monitors are also types Form:
type some_name = monitor (formal parameters)
shared variables , local procedures
exported procedures (have entry in definition) initialization code
- delay takes a queue type parameter; it puts the process that calls it in the specified queue and
removes its exclusive access rights to the monitor’s data structure
- Differs from send because delay always blocks the caller
- continue takes a queue type parameter; it disconnects the caller from the monitor, thus freeing the
monitor for use by another process.
-It also takes a process from the parameter queue (if the queue isn’t empty) and starts it, Differs from
release because it always has some effect (release does nothing if the queue is empty)
Java Threads
• The concurrent units in Java are methods named run
– A run method code can be in concurrent execution with other such methods
– The process in which the run methods execute is called a thread
Class myThread extends Thread
public void run () {…}
}
…
Thread myTh = new MyThread ();
myTh.start();
Controlling Thread Execution
• The Thread class has several methods to control the execution of threads
The yield is a request from the running thread to voluntarily surrender the processor
– The sleep method can be used by the caller of the method to block the thread
– The join method is used to force a method to delay its execution until the run method of another thread
has completed its execution
Thread Priorities
• A thread‘s default priority is the same as the thread that create it
– If main creates a thread, its default priority is NORM_PRIORITY
• Threads defined two other priority constants, MAX_PRIORITY and MIN_PRIORITY
• The priority of a thread can be changed with the methods setPriority
Cooperation Synchronization with Java Threads
• Cooperation synchronization in Java is achieved via wait, notify, and notifyAll methods
– All methods are defined in Object, which is the root class in Java, so all objects inherit them
• The wait method must be called in a loop
• The notify method is called to tell one waiting thread that the event it was waiting has happened
• The notifyAll method awakens all of the threads on the object‘s wait list
https://topperworld.in/
Topperworld.in
Synchronizing Threads
EXCEPTION HANDLING
In a language without exception handling:
When an exception occurs, control goes to the operating system, where a message is displayed
and the program is terminated
In a language with exception handling:
Programs are allowed to trap some exceptions, thereby providing the possibility of fixing the
problem and continuing. Many languages allow programs to trap input/ output errors (including EOF)
Definition 1:
An exception is any unusual event, either erroneous or not, detectable by either hardware or
software, that may require special processing
Definition 2: The special processing that may be required after the detection of an exception is called
exception handling
Definition 3: The exception handling code unit is called an exception handler
Definition 4: An exception is raised when its associated event occurs
A language that does not have exception handling capabilities can still define, detect, raise, and handle
exceptions
- Alternatives:
1. Send an auxiliary parameter or use the return value to indicate the return status of a
Subprogram
- e.g., C standard library functions
2. Pass a label parameter to all subprograms (error return is to the passed label)
- e.g., FORTRAN
3. Pass an exception handling subprogram to all subprograms
5. Should there be default exception handlers for programs that do not provide their own?
6. Can built-in exceptions be explicitly raised?
7. Are hardware-detectable errors treated as exceptions that can be handled?
8. Are there any built-in exceptions?
7. How can exceptions be disabled, if at all?
PL/I Exception Handling
- Exception handler form:
EX:
ON condition [SNAP]
BEGIN;
...
END;
- condition is the name of the associated exception
- SNAP causes the production of a dynamic trace to the point of the exception
- Binding exceptions to handlers
- It is dynamic--binding is to the most recently executed ON statement
- Continuation
- Some built-in exceptions return control to the statement where the exception was raised
- Others cause program termination
- User-defined exceptions can be designed to go to any place in the program that is labeled
- Other design choices:
- User-defined exceptions are defined with:
CONDITION exception_name
- Exceptions can be explicitly raised with:
SIGNAL CONDITION (exception_name)
- Built-in exceptions were designed into three categories:
a. Those that are enabled by default but could be disabled by user code
b. Those that are disabled by default but could be enabled by user code
c. Those that are always enabled
- Evaluation
- The design is powerful and flexible, but has the following problems:
a. Dynamic binding of exceptions to handler makes programs difficult to write and to read
b. The continuation rules are difficult to implement and they make programs hard
to read
https://topperworld.in/
Topperworld.in
- Continuation
- The block or unit that raises an exception but does not handle it is always terminated (also any block
or unit to which it is propagated that does not handle it)
- User-defined Exceptions:
exception_name_list : exception;
raise [exception_name]
(the exception name is not required if it is in a handler--in this case, it propagates the same exception)
- Exception conditions can be disabled with:
pragma SUPPRESS(exception_list)
https://topperworld.in/
Topperworld.in
- Predefined Exceptions:
CONSTRAINT_ERROR - index constraints, range constraints, etc.
NUMERIC_ERROR - numeric operation cannot return a correct value, etc.
PROGRAM_ERROR - call to a subprogram whose body has not been elaborated
STORAGE_ERROR - system runs out of heap
TASKING_ERROR - an error associated with tasks
- Evaluation
- The Ada design for exception handling embodies the state-of-the-art in language design in 1980
- A significant advance over PL/I
- Ada was the only widely used language with exception handling until it was added to C++
C++ Exception Handling :
- Added to C++ in 1990
- Design is based on that of CLU, Ada, and ML
• Like those of C++, except every catch requires a named parameter and all parameters must be
descendants of Throwable
•Syntax of try clause is exactly that of C++
•Exceptions are thrown with throw, as in C++, but often the throw includes the new operator to create the
object, as in: throw new MyException ();
Binding Exceptions to Handlers
•Binding an exception to a handler is simpler in Java than it is in C++
–An exception is bound to the first handler with a parameter is the same class as the thrown object or an
ancestor of it
•An exception can be handled and rethrown by including a throw in the handler (a handler could also
throw a different exception)
Continuation
• If no handler is found in the method, the exception is propagated to the method‘s caller
• If no handler is found (all the way to main), the program is terminated
•To ensure that all exceptions are caught, a handler can be included in any try construct that catches all
exceptions
–Simply use an Exception class parameter
https://topperworld.in/
Topperworld.in
• The Java throws clause is quite different from the throw clause of C++
•Exceptions of class Error and RunTimeException and all of their descendants are called unchecked
exceptions; all other exceptions are called checked exceptions
•Checked exceptions that may be thrown by a method must be either:
–Listed in the throws clause, or Handled in the method
Other Design Choices
•A method cannot declare more exceptions in its throws clause than the method it overrides
•A method that calls a method that lists a particular checked exception in its throws clause has three
alternatives for dealing with that exception:
–Catch and handle the exception
–Catch the exception and throw an exception that is listed in its own throws clause
–Declare it in its throws clause and do not handle it
The finally Clause
•Can appear at the end of a try construct
•Form:
finally {
...
}
•Purpose: To specify code that is to be executed, regardless of what happens in the try construct
Example
•A try construct with a finally clause can be used outside exception handling
try {
for (index = 0; index < 100; index++) {
…
if (…) {
return;
} //** end of if
} //** end of try clause
finally {
…
} //** end of try construct
https://topperworld.in/
Topperworld.in
• Based on logic and declarative programming 60’s and early 70’s, Prolog (Programming in
logic, 1972) is the most well known representative of the paradigm.
• Prolog is based on Horn clauses and SLD resolution
• Mostly developed in fifth generation computer systems project
• Specially designed for theorem proof and artificial intelligence but allows general purpose
computation.
• Some other languages in paradigm: ALF, Frill, G¨odel,, Mercury, Oz, Ciao, _Prolog, datalog, and
CLP languages
Proof: by refutation, try to un satisfy the clauses with a goal clause G. Find 9(G).
Linear resolution for definite programs with constraints and selected atom.
Unification. Bidirectional.
Prolog terms:
Atoms:
https://topperworld.in/
Topperworld.in
Variables:
Starts with an atom head have one or more arguments (any term) enclosed in parenthesis, separated
by comma structure head cannot be a variable or anything other than atom.
Is(X,+(Y,1)) _ X is X + 1
Static sugars:
Prolog interpreter automatically maps some easy to read syntax into its actual structure.
String: "ABC" _ [65,66,67] (ascii integer values) use display (Term). to see actual structure of the term
https://topperworld.in/
Topperworld.in
Unification:
S=T
head of S = head of T
S _ T;P =
Unification Example:
X = a ! pwith X = a
a(X,3) = a(X,3,2) ! ×
a(X,3) = b(X,3) ! ×
https://topperworld.in/
Topperworld.in
Declarations:
p1(arg1, arg2, ...) :- p2(args,...) , p3(args,...) .means if p2 and p3 true, then p1 is true. There can be
arbitrary number of (conjunction of) predicates at right hand side.
p(args) :- q(args).
p(args) :- s(args).
Lists Example:
% list membership
memb(X, [X| Re s t ]) .
memb(X, [ | Re s t ]) :- memb(X, Re s t ).
% concatenation
Procedural Interpretation:
For goal clause all matching head clauses (LHS of clauses) are kept as backtracking points (like a
junction in maze search) Starts from first match. To prove head predicate, RHS predicates need to be
proved recursively. If all RHS predicates are proven, head predicate is proven. When fails, prolog goes
back to last backtracking point and tries next choice. When no backtracking point is left, goal clause fails.
All predicate matches go through unification so goal clause variables can be instantiated.
operators (is) force arithmetic expressions to be evaluated all variables of the operations needs to be
instantiated.
is operator forces RHS to be evaluated: X is Y+3*Y Y needs to have a numerical value when search hits
this expression. Note that X is X+1 is never successful in Prolog. Variables are instantiated once.
gcd (X,X,X) .
Deficiencies of Prolog
• Intrinsic limitations
•Expert systems
UNIT-V
2. Construction:
A functional form that takes a list of functions as parameters and yields a list of the results of applying
each of its parameter functions to a given parameter
Form: [f, g]
For f (x) = x * x * x and g (x) = x + 3,
[f, g] (4) yields (64, 7)
3. Apply-to-all:
A functional form that takes a single function as a parameter and yields a list of values obtained by
applying the given function to each element of a list of parameters
https://topperworld.in/
Topperworld.in
Form:
For h (x) =x * x * x
f( h, (3, 2, 4)) yields (27, 8, 64)
LISP –
LISP is the first functional programming language, it contains two forms those are
1. Data object types: originally only atoms and lists
2. List form: parenthesized collections of sub lists and/or atoms
e.g., (A B (C D) E)
Fundamentals of Functional Programming Languages:
- The objective of the design of a FPL is to mimic mathematical functions to the greatest extent possible
- The basic process of computation is fundamentally different in a FPL than in an imperative language
- In an imperative language, operations are done and the results are stored in variables for later use
- Management of variables is a constant concern and source of complexity for imperative programming
- In an FPL, variables are not necessary, as is the case in mathematics
- In an FPL, the evaluation of a function always produces the same result given the same parameters
- This is called referential transparency
A Bit of LISP:
- Originally, LISP was a type less language. There were only two data types, atom and list
- LISP lists are stored internally as single-linked lists
- Lambda notation is used to specify functions and function definitions, function applications, and data
all have the same form
E .g :,
If the list (A B C) is interpreted as data it is a simple list of three atoms, A, B, and C If it is
interpreted as a function application, it means that the function named A is applied to the two
parameters, B and C
- The first LISP interpreter appeared only as a demonstration of the universality of the
computational capabilities of the notation
Scheme:
- A mid-1970s dialect of LISP, designed to be cleaner, more modern, and simpler version than the
contemporary dialects of LISP, Uses only static scoping
https://topperworld.in/
Topperworld.in
- Functions are first-class entities, They can be the values of expressions and elements of lists, They can
be assigned to variables and passed as parameters
- Primitive Functions:
1. Arithmetic: +, -, *, /, ABS, SQRT
Ex: (+ 5 2) yields 7
2. QUOTE: -takes one parameter; returns the parameter without evaluation
- QUOTE is required because the Scheme interpreter, named EVAL, always evaluates
parameters to function applications before applying the function. QUOTE is used to avoid parameter
evaluation when it is not appropriate
- QUOTE can be abbreviated with the apostrophe prefix operator
e.g., '(A B) is equivalent to (QUOTE (A B))
3. CAR takes a list parameter; returns the first element of that list
e.g., (CAR '(A B C)) yields A
(CAR '((A B) C D)) yields (A B)
4. CDR takes a list parameter; returns the list after removing its first element
e.g., (CDR '(A B C)) yields (B C)
(CDR '((A B) C D)) yields (C D)
5. CONS takes two parameters, the first of which can be either an atom or a list and the second of
which is a list; returns a new list that includes the first parameter as its first element and the second
parameter as the remainder of its result
e.g., (CONS 'A '(B C)) returns (A B C)
6. LIST - takes any number of parameters; returns a list with the parameters as elements
- Predicate Functions: (#T and () are true and false)
1. EQ? takes two symbolic parameters; it returns #T if both parameters are atoms and the two are the
same
e.g.,(EQ? 'A 'A) yields #T
(EQ? 'A '(A B)) yields ()
Note that if EQ? is called with list parameters, the result is not reliable Also, EQ? does not work for
numeric atoms
2. LIST? takes one parameter; it returns #T if the parameter is an list; otherwise ()
3. NULL? takes one parameter; it returns #T if the parameter is the empty list; otherwise ()
Note that NULL? returns #T if the parameter is ()
4. Numeric Predicate Functions
=, <>, >, <, >=, <=, EVEN?, ODD?, ZERO?
https://topperworld.in/
Topperworld.in
e.g.,
((LAMBDA (L) (CAR (CAR L))) '((A B) C D))
- A Function for Constructing Functions
DEFINE - Two forms:
1. To bind a symbol to an expression
EX:
(DEFINE pi 3.141593)
(DEFINE two_pi (* 2 pi))
2. To bind names to lambda expressions
EX:
(DEFINE (cube x) (* x x x))
- Example use:
(cube 4)
- Evaluation process (for normal functions):
1. Parameters are evaluated, in no particular order
2. The values of the parameters are substituted into the function body
3. The function body is evaluated
4. The value of the last expression in the body is the value of the function
(Special forms use a different evaluation process)
Control Flow:
- 1. Selection- the special form, IF
(IF predicate then_exp else_exp)
e.g.,
(IF (<> count 0)
https://topperworld.in/
Topperworld.in
(/ sum count)
0 )
ML :
- A static-scoped functional language with syntax, that is closer to Pascal than to LISP
- Uses type declarations, but also does type inferencing to determine the types of undeclared variables
(See Chapter 4)
- It is strongly typed (whereas Scheme is essentially type less) and has no type coercions
- Includes exception handling and a module facility for implementing abstract data types
Haskell:
- Different from ML (and most other functional languages) in that it is PURELY functional
Examples
fib 0 = 1
fib 1 = 1
fact n
| n == 0 = 1
| n > 0 = n * fact (n - 1)
a guard
3. List operations
- Length: #
e.g., #directions is 4
- Catenation is with +
[1, 3, 5, 7]
- Examples:
product [ ] = 1
e.g.,
https://topperworld.in/
Topperworld.in
[n * n | n ¬ [1..20]]
positive integers
n mod i == 0]
Quicksort:
sort [ ] = [ ]
++ [a] ++
sort [b | b ¬ x; b > a]
5. Lazy evaluation
- Infinite lists
e.g.,
positives = [0..]
squares = [n * n | n ¬ [0..]]
e.g.,
member squares 16 would return True ,The member function could be written as: member
[] b = False member (a:x) b = (a == b) || member x
However, this would only work if the parameter to squares was a perfect square; if not, it will keep
generating them forever. The following version will always work:
member2 (m:x) n
|m<n = member2 x n
| m == n = True
| otherwise = False
https://topperworld.in/
Topperworld.in
Imperative Languages:
o Efficient execution
o Complex semantics
o Complex syntax
- Functional Languages:
o Simple semantics
o Simple syntax
o Inefficient execution
Scripting languages
Pragmatics
In such a system, the script is said to glue the sub systems together
PYTHON
Python is extensible: if we invoke how to program in C, it is easy to add new built in function or module
to the interpreter, either to perform critical operations at maximum speed of to link python programs to
libraries that may only be available in binary form
• PYTHON has a limited repertoire of primitive types: integer, real, and complex
Numbers.
• It has no specific character type; single-character strings are used instead.
• Its boolean values (named False and True) are just small integers.
• PYTHON has a rich repertoire of composite types: tuples, strings, lists, dictionaries, and
objects.
Primitive values and strings are immutable; lists, dictionaries, and objects are mutable; tuples are mutable
if any of their components are mutable
Python is a dynamically typed language. Based on the value, type of the variable is during the execution
of the program.
Python (dynamic)
C=1
C = [1,2,3]
C(static)
Double c; c = 5.2;
C = “a string….”
Weakly vs. strongly typed python language differs in their automatic conversions.
Perl (weak)
$b = `1.2`
$c = 5 * $b;
Python (strong)
b =`1.2`
c= 5* b;
• A PYTHON program consists of a number of modules, which may be grouped into packages.
• Within a module we may initialize variables, define procedures, and declare classes
• Within a procedure we may initialize local variables and define local procedures.
• Within a class we may initialize variable components and define procedures (methods).
• PYTHON was originally a dynamically-scoped language, but it is now statically scoped
In python, variables defined inside the function are local to that function. In order to change them as
global variables, they must be declared as global inside the function as given below.
S=1
Def myfunc(x,y);
https://topperworld.in/
Topperworld.in
Z=0
Global s;
S=2
Procedural abstraction
Since PYTHON is dynamically typed, a procedure definition states the name but not the type of each
formal parameter
Python procedure
p,q=m,n
while p%q!=0:
p,q=q,p%q
return q
min = val
max = val
Data Abstraction
• PYTHON has three different constructs relevant to data abstraction: packages ,modules , and
classes
https://topperworld.in/
Topperworld.in
• Modules and classes support encapsulation, using a naming convention to distinguish between
public and private components.
• A Class is a group of components that may be class variables, class methods, and instance
methods.
• A procedure defined in a class declaration acts as an instance method if its first formal parameter
is named self and refers to an object of the class being declared. Otherwise the procedure acts as a
class method.
Separate Compilation
• Each module must explicitly import every other module on which it depends
• When that module is first imported, it is compiled and its object code is stored in a file named
program.pyc
• The PYTHON compiler does not reject code that refers to undeclared identifiers. Such code
simply fails if and when it is executed
• The compiler will not reject code that might fail with a type error, nor even code that will
certainly fail, such as:
Module Library
• PYTHON is equipped with a very rich module library, which supports string handling, markup,
mathematics, and cryptography, multimedia, GUIs, operating system services, internet services,
compilation, and so on.
• Unlike older scripting languages, PYTHON does not have built-in high-level string processing or
GUI support, so module library provides it.