0% found this document useful (0 votes)
98 views144 pages

PPL 2

Ppl notes

Uploaded by

smgreat1212
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
98 views144 pages

PPL 2

Ppl notes

Uploaded by

smgreat1212
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 144

UNIT I

Preliminary Concepts:
Reasons for studying concepts of programming languages,
programming domains,
language evaluation criteria,
influences on language design,
language categories,
language design trade-offs,
implementation methods,
programming environments,
Evolution of Major Programming Languages.
Syntax and Semantics:
General problem of describing syntax,
formal methods of describing syntax,
attribute grammars,
describing the meanings of programs

Preliminary Concepts

Reasons for studying concepts of programming languages

Increased ability to express ideas.


• It is believed that the depth at which we think is influenced by the
expressive power of the language in which we communicate our thoughts.
It is difficult for people to conceptualize structures they can‘t describe,
verbally or in writing.

• Language in which they develop S/W places limits on the kinds of control
structures, data structures, and abstractions they can use.

• Awareness of a wider variety of P/L features can reduce such limitations


in S/W development.

• Can language constructs be simulated in other languages that do not


support those constructs directly?

Improved background for choosing appropriate languages


• Many programmers, when given a choice of languages for a new project,
continue to use the language with which they are most familiar, even if it
is poorly suited to new projects.

https://jntuhbtechadda.blogspot.com/
• If these programmers were familiar with other languages available, they
would be in a better position to make informed language choices.

Greater ability to learn new languages


• Programming languages are still in a state of continuous evolution, which
means continuous learning is essential.

• Programmers who understand the concept of OO programming will have


easier time learning Java.

• Once a thorough understanding of the fundamental concepts of languages


is acquired, it becomes easier to see how concepts are incorporated into
the design of the language being learned.

Understand significance of implementation


• Understanding of implementation issues leads to an understanding of why
languages are designed the way they are.

• This in turn leads to the ability to use a language more intelligently, as it


was designed to be used.

Ability to design new languages


• The more languages you gain knowledge of, the better understanding of
programming languages concepts you understand.

Overall advancement of computing


• In some cases, a language became widely used, at least in part, b/c those
in positions to choose languages were not sufficiently familiar with P/L
concepts.

• Many believe that ALGOL 60 was a better language than Fortran; however,
Fortran was most widely used. It is attributed to the fact that the
programmers and managers didn‘t understand the conceptual design of
ALGOL 60.

• Do you think IBM has something to do with it?

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.

https://jntuhbtechadda.blogspot.com/
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.
• Spreadsheets and database systems were developed for business.

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.

Language Evaluation Criteria

Readability
• Software development was largely thought of in term of writing code
o LOC.
• Language constructs were designed more from the point of view 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.
o ALGOL 60

https://jntuhbtechadda.blogspot.com/
• Multiplicity of features is also a complicating characteristic
o having more than one way to accomplish a particular operation.

• Ex ―Java:
count = count + 1
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.

• 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://jntuhbtechadda.blogspot.com/
{
while (sum <= 100)
{
sum += incr;
}
incr++;
}
if C didn‘t have a loop construct, this would be written as follows:
loop1:
if (incr >= 20) go to out;
loop2:
if (sum > 100) go to next;
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.

Data Types and Structures


• The presence of adequate facilities for defining data types and data
structures in a language is another significant aid to reliability.

• Ex: Boolean type.


timeout = 1 or timeout = true

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 detract from

https://jntuhbtechadda.blogspot.com/
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.

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


• 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.
• Ex:
++count ⇔ count = count + 1 // more convenient and shorter

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.

https://jntuhbtechadda.blogspot.com/
• 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
o Training programmers to use language
o Writing programs ―Writability‖
o Compiling programs
o Executing programs
o Language implementation system ―Free compilers is the key,
success of Java
o Reliability, does the software fail?
o Maintaining programs: Maintenance costs can be as high as two to
four times as much as development costs.
o Portability ―standardization of the language, Generality (the
applicability to a wide range of applications)

Influences on language design

We use imperative languages, at least in part, because we use von


Neumann machines
• Data and programs stored in same memory
• Memory is separate from CPU
• Instructions and data are piped from memory to CPU
• Results of operations in the CPU must be moved back to memory
• Basis for imperative languages
o Variables model memory cells
o Assignment statements model piping
o Iteration is efficient

Programming methodologies

https://jntuhbtechadda.blogspot.com/
• 1950s and early 1960s: Simple applications; worry about machine
efficiency

• Late 1960s: People efficiency became important; readability, better


control structures
o Structured programming
o Top-down design and step-wise refinement

• Late 1970s: Process-oriented to data-oriented


o 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

Language design trade-offs

• Reliability vs. cost of execution

• Example: C programs execute faster than semantically equivalent Java


programs, although Java programs are more reliable.
o Java demands all references to array elements be checked for proper
indexing but that leads to increased execution costs.
o C does not require index range checking

https://jntuhbtechadda.blogspot.com/
Implementation methods
• The major methods of implementing programming languages are
compilation, pure interpretation, and hybrid implementation

o Compilation: Programs are translated into machine language


o Pure Interpretation: Programs are interpreted by another program
known as an interpreter
o Hybrid Implementation Systems: A compromise between compilers
and pure interpreters.

• The operating system and language implementation are layered over


machine interface of a computer.

• These layers can be thought of as virtual computers, providing interfaces


to the user at higher levels.

Compilation
• Translate high-level program (source language) into machine code
(machine language)

• Slow translation, fast execution


• C, COBOL, and Ada are by compilers.

https://jntuhbtechadda.blogspot.com/
• Compilation process has several phases:

o lexical analysis: converts characters in the source program into


lexical units
• The lexical units of a program are identifiers, special words
operators, and punctuation symbols.

o Syntax analysis: transforms lexical units into parse trees


• These parse trees represent the syntactic structure of program

o Semantics analysis: generate intermediate code


• Intermediate languages sometimes look very much like assembly
languages and in fact sometimes are actual assembly language.

o Symbol table: the type and attribute information of each user-


defined name in the program

o Optimization: improve programs by making them smaller or faster


or both

o Code generation: machine code is generated

https://jntuhbtechadda.blogspot.com/
• Fetch-execute-cycle (on a von Neumann architecture)
initialize the program counter
repeat forever
fetch the instruction pointed by the counter
increment the counter
decode the instruction
execute the instruction
end repeat

• Von Neumann Bottleneck


o The speed of the connection between a computer’s memory and its
processor determines the speed of a computer.

o Instructions often can be executed a lot faster than they can be


moved to the processor for execution.

o This connection speed is called the von Neumann bottleneck; it is


the primary limiting factor in the speed of computers

Pure Interpretation

• Programs are interpreted by another program called an interpreter, with


no translation.

• Advantage: easy implementation of many source-level debugging


operations, because all run-time error messages can refer to source-level
units.

• Disadvantage: slower execution (10 to 100 times slower than compiled


programs)

https://jntuhbtechadda.blogspot.com/
• Bottleneck: Statement decoding, rather than the connection between the
processor and memory, is the bottleneck of a pure interpreter.

• Significant comeback with some Web scripting languages (e.g., JavaScript


and PHP).

Hybrid Implementation Systems

• A compromise between compilers and pure interpreters

• A high-level language program is translated to an intermediate language


that allows easy interpretation

• Faster than pure interpretation

https://jntuhbtechadda.blogspot.com/
• Examples:
o Perl programs are partially compiled to detect errors before
interpretation

o Java were hybrid: the intermediate form, byte code, provides


portability to any machine that has a byte code interpreter and a
run-time system (together, these are called Java Virtual Machine)

Programming environments
• The collection of tools used in software development
• UNIX
o An older operating system and tool collection
• Borland JBuilder
o An integrated development environment for Java
• Microsoft Visual Studio.NET
o A large, complex visual environment
o Used to program in C#, Visual BASIC.NET, Jscript, J#, or C++

Evolution of Major Programming Languages


• Programming has its origin in the 19th century, when the first
“programmable” looms and player piano scrolls were developed.

• This followed the punch cards encoded data in 20th century that used to
direct the mechanical processing. In the 1930s and early 1940s lambda
calculus remained the influential in language design.

• The decade of 1940s has many landmarks to its credit in the initial
development of modern computers and programming languages.

• In the beginning of this decade, first electrically powered digital computers


were created. The first high-level programming language to be designed
for a computer was Plankalkül, developed for the German Z3 by Konrad
Zuse between 1943 and 1945.

• Programmers of early 1950s computers, notably UNIVAC I and IBM 701,


used machine language programs, that is, the first-generation language
(1GL).

• Grace Ho copper is credited with implementing the first commercially


oriented computer language. After programming an experimental
computer at Harvard University, she worked on the UNIVAC I and II
computers and developed a commercially usable high-level programming
language called FLOW-MATIC.

https://jntuhbtechadda.blogspot.com/
• The 1GL programming was quickly superseded by similarly machine-
specific, but mnemonic, second generation languages (2GL) known as
assembly languages or “assembler”.

• Later in the 1950s, assembly language programming, which had evolved


to include the use of macro instructions, was followed by the development
of “third generation” programming languages (3GL), such as FORTRAN,
LISP, and COBOL.

• IBM in 1957 developed a language that would simplify work involving


complicated mathematical formulas known as FORTRAN (FORmula
TRANslator).

• FORTRAN was the first comprehensive high-level programming language


that was widely used. In 1957, the Association for Computing Machinery
in the United States started development of a universal language that
would correct some of FORTRAN’s shortcomings.

• Next year they released ALGOL (ALGOrithmic Language), another


scientifically oriented language. This was followed by LISP. Originally
specified in 1958, lisp is the second-oldest high-level programming
language in widespread use today; only FORTRAN is older.

• Lisp is a family of computer programming languages with a long history


and a distinctive fully-parenthesized syntax. OBOL (Common Business-
Oriented Language), a commercial and business programming language,
concentrated on data organization and file-handling and is widely used
today in business.

• 3GLs are more abstract and are “portable”, or at least implemented


similarly on computers that do not support the same native machine code.
Updated versions of all of these 3GLs are still in general use, and each has
strongly influenced the development of later languages.

• At the end of the 1950s, the language formalized as ALGOL 60 was


introduced, and most later programming languages are, in many respects,
descendants of ALGOL. The format and use of the early programming
languages was heavily influenced by the constraints of the interface.

• CBASIC (Beginner’s All-purpose Symbolic Instruction Code) was


developed in the early 1960s for use by non-professional computer users.

• LOGO was developed to introduce children to computers. C, a language


Bell Laboratories designed in the 1970s, is widely used in developing
systems programs, as is its successor, C++.

https://jntuhbtechadda.blogspot.com/
• Other languages have been developed to permit programming in Internet
applications. The most popular is Java, an Object-Oriented programming
language introduced in 1995 by Sun Microsystems. Java enables the
distribution of both the data and small applications called applets.

Syntax and Semantics


Introduction
• Syntax – the form of the expressions, statements, and program units

• Semantics - the meaning of the expressions, statements, and program


units.
Ex: while (<Boolean_expr>) <statement>

• The semantics of this statement form is that when the current value
of the Boolean expression is true, the embedded statement is
executed.

• The form of a statement should strongly suggest what the statement


is meant to accomplish.

General problem of describing syntax


• A sentence or “statement” is a string of characters over some alphabet.
The syntax rules of a language specify which strings of characters from
the language’s alphabet are in the language.

• A language is a set of sentences.

• A lexeme is the lowest level syntactic unit of a language. It includes


identifiers, literals, operators, and special word. (e.g. *, sum, begin) A
program is strings of lexemes.

• A token is a category of lexemes (e.g., identifier.) An identifier is a token


that have lexemes, or instances, such as sum and total.

• Ex: index = 2 * count + 17;

Lexemes Tokens
index identifier
= equal_sign
2 int_literal
* mult_op
count identifier
+ plus_op
17 int_literal
; semicolon

https://jntuhbtechadda.blogspot.com/
Language Recognizers and Generators
• In general, language can be formally defined in two distinct ways: by
recognition and by generation.

• Language Recognizers:
o A recognition device reads input strings of the language and decides
whether the input strings belong to the language.
o It only determines whether given programs are in the language.
o Example: syntax analyzer part of a compiler. The syntax analyzer,
also known as parsers, determines whether the given programs are
syntactically correct.

• Language Generators:
o A device that generates sentences of a language
o One can determine if the syntax of a particular sentence is correct
by comparing it to the structure of the generator

Formal methods of describing syntax

• The formal language generation mechanisms are usually called grammars


• Grammars are commonly used to describe the syntax of programming
languages.

Backus-Naur Form and Context-Free Grammars


• It is a syntax description formalism that became the most widely used
method for programming language syntax.

Context-free Grammars
o Developed by Noam Chomsky in the mid-1950s who described four
classes of generative devices or grammars that define four classes
of languages.

o Context-free and regular grammars are useful for describing the


syntax of programming languages.

o Tokens of programming languages can be described by regular


grammars.

o Whole programming languages can be described by context-free


grammars.

Backus-Naur Form (1959)


o Invented by John Backus to describe ALGOL 58 syntax.
o BNF (Backus-Naur Form) is equivalent to context-free grammars
used for describing syntax.

https://jntuhbtechadda.blogspot.com/
Fundamentals
o A metalanguage is a language used to describe another language
“Ex: BNF.”

o In BNF, abstractions are used to represent classes of syntactic


structures--they act like syntactic variables (also called nonterminal
symbols)
<assign> → <var> = <expression>

o This is a rule; it describes the structure of an assignment statement

o A rule has a left-hand side (LHS) “The abstraction being defined”


and a right-hand side (RHS) “consists of some mixture of tokens,
lexemes and references to other abstractions”, and consists of
terminal and nonterminal symbols.

o Example: total = sub1 + sub2

o A grammar is a finite nonempty set of rules and the abstractions are


called nonterminal symbols, or simply nonterminals.

o The lexemes and tokens of the rules are called terminal symbols or
terminals.

o A BNF description, or grammar, is simply a collection of rules.

o An abstraction (or nonterminal symbol) can have more than one


RHS
<smt> → <single_smt>
| begin end<smt_list> end

o Multiple definitions can be written as a single rule, with the different


definitions separated by the symbol |, meaning logical OR.

Describing Lists
o Syntactic lists are described using recursion.
<ident_list> → ident
| ident, <ident_list>

o A rule is recursive if its LHS appears in its RHS.

Grammars and derivations


o The sentences of the language are generated through a sequence of
applications of the rules, beginning with a special nonterminal of
the grammar called the start symbol.

https://jntuhbtechadda.blogspot.com/
o A derivation is a repeated application of rules, starting with the start
symbol and ending with a sentence (all terminal symbols)

o 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

o An example derivation for a simple statement a = b + const


<program> => <stmts> => <stmt>
=> <var> = <expr>
=> a = <expr>
=> a = <term> + <term>
=> a = <var> + <term>
=> a = b + <term>
=> a = b + const

o Every string of symbols in the derivation, including <program>, is a


sentential form.

o A sentence is a sentential form that has only terminal symbols.

o A leftmost derivation is one in which the leftmost nonterminal in


each sentential form is the one that is expanded. The derivation
continues until the sentential form contains no nonterminals.

o A derivation may be neither leftmost nor rightmost.

Parse Trees
o Hierarchical structures of the language are called parse trees.
o A parse tree for the simple statement A = B + const
<program>
|
<smts>
|
<smt>
/|\
<var> = <exp>
| /|\
a <term> + <term>
| |
<var> const
|
b

https://jntuhbtechadda.blogspot.com/
Ambiguity
o A grammar is ambiguous if it generates a sentential form that has
two or more distinct parse trees.

o Ex: Two distinct parse trees for the same sentence, const – const /
const
<expr> → <expr> <op> <expr> | const
<op> → / | -

o Ex: Two distinct parse trees for the same sentence, A = B + A *

Operator Precedence
• The fact that an operator in an arithmetic expression is generated lower
in the parse tree can be used to indicate that it has higher precedence over
an operator produced higher up in the tree.

https://jntuhbtechadda.blogspot.com/
• In the left parsed tree above, one can conclude that the * operator has
precedence over the + operator. How about the tree on the right-hand side?

• An unambiguous Grammar for Expressions

• Leftmost derivation of the sentence A = B + C * A

• A parse tree for the simple statement, A = B + C * A

https://jntuhbtechadda.blogspot.com/
• Rightmost derivation of the sentence A = B + C * A

• Both of these derivations, however, are represented by the same parse


tree.

Associativity of Operators
• Do parse trees for expressions with two or more adjacent occurrences of
operators with equal precedence have those occurrences in proper
hierarchical order?

• An example of an assignment using the previous grammar is: A = B + C +


A

• Figure above shows the left + operator lower than the right + operator.
This is the correct order if + operator meant to be left associative, which is

https://jntuhbtechadda.blogspot.com/
typical.

• When a grammar rule has LHS also appearing at beginning of its RHS, the
rule is said to be left recursive. The left recursion specifies left
associativity.

• In most languages that provide it, the exponentiation operator is right


associative. To indicate right associativity, right recursion can be used. A
grammar rule is right recursive if the LHS appears at the right end of the
RHS. Rules such as
<factor> → <exp> ** <factor>
| <exp>
<exp> → (<exp>)
| id

Extended BNF
• Because of minor inconveniences in BNF, it has been extended in several
ways. EBNF extensions do not enhance the descriptive powers of BNF;
they only increase its readability and writability.

• Three extension are commonly included in various versions of EBNF


o Optional parts are placed in brackets ([ ])
<if_stmt> → if (expression>) <statement> [else <statement> ]

• Without the use the brackets, the syntactic description of this


statement would require the following two rules:

<if_stmt> → if (expression>) <statement>


| if (expression>) <statement> else <statement>

o Put repetitions (0 or more) in braces ({ }) → {, }


<ident_list> → <term> { , <identifier> }

o Put multiple-choice options of RHSs in parentheses and separate them


with vertical bars (|, OR operator)
<term> → <term> (* | / | %) <factor>

• In BNF, a description of this would require the following three


rules:
<term> → <term> * <factor>
| <term> / <factor>
| <term> % <factor>

https://jntuhbtechadda.blogspot.com/
Attribute grammars
An attribute grammar is a device used to describe more of the structure
of a programming language than can be described with a context-free grammar.

Static Semantics
• Context-free grammars (CFGs) cannot describe all of the syntax of
programming languages.

• In Java, for example, a floating-point value cannot be assigned to an integer


type variable, although the opposite is legal.

• The static semantics of a language is only indirectly related to the meaning


of programs during execution; rather, it has to do with the legal forms of
programs (syntax rather than semantics).

• Many static semantic rules of a language state its type constraints. Static
semantics is so named because the analysis required to these specifications
can be done at compile time.

• Attribute grammars was designed by Knuth (1968) to describe both the


syntax and the static semantics of programs.

Basic Concepts
• Attribute grammars have additions to are context-free grammars to carry
some semantic information on parse tree nodes.

• Attribute grammars are context-free grammars to which have been added


attributes, attribute computation functions, and predicate function.

Attribute Grammars Defined


• Associated with each grammar symbol X is a set of attributes A(X).
o The set A(X) consists of two disjoint set S(X) and I(X), call
synthesized and inherited attributes.
o Synthesized attributes are used to pass semantic information up a
parse tree, while inherited attributes pass semantic information
down and across tree.

• Let X0 → X1 ... Xn be a rule


o Functions of the form S(X0) = f(A(X1), . , A(Xn)) define synthesized
attributes
o Functions of the form I(Xj) = f(A(X0), ... , A(Xn)), for i <= j <= n, define
inherited attributes
o Initially, there are intrinsic attributes on the leaves.

https://jntuhbtechadda.blogspot.com/
Intrinsic Attributes
• Intrinsic attributes are synthesized attributes of leaf nodes whose values
are determined outside the parse tree.

• For example, the type of an instance of a variable in a program could come


form the symbol table, which is used to store variable names and their
types.

Examples Attribute Grammars

The look-up function looks up a given variable name in the symbol table
and returns the variable’s type.

• The syntax portion of our example attribute grammar is


<assign> → <var> = <var>
<expr> → <var>[2] + <var>[3]
| <var>
<var> → A|B|C

• actual_type - A synthesized attribute associated with nonterminal and .


o It is used to store the actual type, int or real, or a variable or
expression.
o In the case of a variable, the actual type is intrinsic.
o In the of an expression, it is determined from the actual types of
child node or children nodes of the nonterminal.

• expected_type - A inherited attribute associated with nonterminal .


o It is used to store the type, either int or real, that is expected for the
expression, as determined by the type of the variable on the left side
of the assignment statement.

https://jntuhbtechadda.blogspot.com/
Computing Attribute Values
• Now, consider the process of computing the attribute values of a parse
tree, which is sometimes called decorating the parse tree.

• The tree in Figure 3.7 show the flow of attribute values in the example of
Figure 3.6.

• The following is an evaluation of the attributes, in an order in which it is


possible to computer them:

• The tree in Figure 3.8 shows the final attribute values on the nodes. In
this example, A is defined as a real and B is defined as an int.

https://jntuhbtechadda.blogspot.com/
Describing the meanings of programs

• Three methods of semantic description:


o Operational semantics: It is a method of describing the meaning of
language constructs in terms of their effects on an ideal machine.

o Denotation semantics: Mathematical objects are used to


represents the meanings of languages constructs. Language entities
are converted to these mathematical objects with recursive
functions.

o Axiomatic semantics: It is based on formal logic and devised as a


tool for proving the correctness of programs.

Operational Semantics
• The idea behind operational semantics is to describe the meaning of a
statement or program, by specifying the effects of running it on a machine.
The effects on the machine are viewed as the sequence of changes in its
states, where the machine’s state is the collection of the collection of the
values in its storage.

• Most programmers have written a small test program to determine the


meaning of some programming language construct.

• The basic process of operational semantics is not unusual. In fact, the


concept is frequently used in programming textbooks and programming
in reference manuals.

• For example, the semantics of the C for construct can described in terms
of simpler statements, as in

https://jntuhbtechadda.blogspot.com/
• Operational semantics depends on programming languages of lower
level, not mathematics and logic.

Denotational Semantics
• Denotational semantics is the most rigorous and most widely known
formal method for describing the meaning of programs.

• It is solidly based on recursive function theory.

Two Simple Examples


Example 1: –
o We use a very simple language construct, character string representations
of binary numbers, to introduce the denotational method.

o The syntax of such binary numbers can be described by the following


grammar rules:
<bin_num> → '0'
| '1'
| <bin_num> '0'
| <bin_num> '1'

• A parse tree for the example binary number, 110, is show in Figure 3.9.

• The semantic function, named Mbin, maps the syntactic objects, as


described in the previous grammar rules, to the objects in N, the set of

https://jntuhbtechadda.blogspot.com/
non-negative decimal numbers. The function Mbin is defined as follows:
Mbin ('0') = 0
Mbin ('1') = 1
Mbin (<bin_num> '0') = 2 * Mbin (<bin_num>)
Mbin (<bin_num> '1') = 2 * Mbin (<bin_num>) + 1

• The meanings, or denoted objects (which in this case are decimal


numbers), can be attached to the nodes of the parse tree, yielding the tree
in Figure 3.10)

Axiomatic Semantics
• Axiomatic Semantics is based on mathematical logic.

• It is defined in conjunction with the development of a method to prove the


correctness of programs.
o Such correction proofs, when they can be constructed, show that a
program performs the computation described by its specification.
o In a proof, each statement of a program is both preceded and
followed by a logical expression that specified constraints on
program variables.

• Approach: Define axioms or inference rules for each statement type in the
language (to allow transformations of expressions to other expressions.)
o The expressions are called assertions.

Assertions
• The logical expressions are called predicates, or assertions.
• An assertion before a statement (a precondition) states the relationships
and constraints among variables that are true at that point in execution.
• An assertion following a statement is a postcondition.

https://jntuhbtechadda.blogspot.com/
Weakest Preconditions
• A weakest precondition is the least restrictive precondition that will
guarantee the validity of the associated postcondition.

• The usual notation for specify the axiomatic semantic of a given statement
form is
{P} statement {Q}
where P is the precondition, Q is the postcondition, and S is the
statement form

o An example: a = b + 1 {a > 1}
One possible precondition: {b > 10}
Weakest precondition: {b > 0}

• If the weakest precondition can be computed from the given postcondition


for each statement of a language, then correctness proofs can be
constructed from programs in that language.

• Program proof process: The postcondition for the whole program is the
desired result. 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.

• An Axiom is a logical statement that is assumed to be true.

• An Inference Rule is a method of inferring the truth of one assertion on


the basis of the values of other assertions.
S1, S2, …, Sn
S
o The rule states that if S1, S2, …, and Sn are true, then the truth of S
can be inferred. The top part of an inference rule is call its antecedent;
the bottom part is called it consequent.

Assignment Statements
• Ex: a = b / 2 – 1 {a < 10}
The weakest precondition is computed by substituting b / 2 -1 in the
assertion {a < 10} as follows:
b / 2 – 1 < 10
b / 2 < 11
b < 22
∴ the weakest precondition for the given assignment and the postcondition is
{b < 22}

https://jntuhbtechadda.blogspot.com/
• An assignment statement has a side effect if it changes some variable other
than its left side.

• Ex: x = 2 * y – 3 {x > 25}


The weakest precondition is computed as follows:
2 * y – 3 > 25
2 * y > 28
y > 14
∴ the weakest precondition for the given assignment and the postcondition
is {y > 14}

• Ex: x = x + y – 3 {x > 10}


The weakest precondition is computed as follows:
x + y – 3 > 10
y > 13 – x
∴ the weakest precondition for the given assignment and the postcondition
is {y > 13 -x}

Sequences
• The weakest precondition for a sequence of statements cannot be
described by an axiom, because the precondition depends on the
particular kinds of statements in the sequence.

• In this case, the precondition can only be described with an inference rule.

• Let S1 and S2 be adjacent program statements. If S1 and S2 have the


following preconditions and postconditions.
{P1} S1 {P2}
{P2} S2 {P3}
The inference rule for such a two-statement sequence is
{P1} S1 {P2}, {P2} S2 {P3}
{P1} S1, S2 {P3}

• Ex:
y = 3 * x + 1;
x = y + 3; {x < 10}
The weakest precondition is computed as follows:
y + 3 < 10
y<7
3*x+1<7
3*x<6

https://jntuhbtechadda.blogspot.com/
x<2
∴ the weakest precondition for the first assignment statement is {x < 2}

Selection
• We next consider the inference rule for selection statements, the general
form of which is if B then S1 else S2
We consider only selections that include else clause. The inference rule is
{B and P} S1 {Q}, {not B and P} S2 {Q}
{P} if B then S1 else S2 {Q}

• Example of selection statement is


If (x > 0) then
y = y - 1;
else
y = y + 1;
{y > 0}
We can use the axiom for assignment on the then clause
y = y - 1 {y > 0}
This produce precondition {y – 1 > 0} or {y > 1}
Now we apply the same axiom to the else clause
y = y + 1 {y > 0}
This produce precondition {y + 1 > 0} or {y > -1}
y > 1 AND y > -1
{y > 1}
Because {y > 1} => {y > -1}, the rule of consequence allows us to use {y > 1}
for the precondition of selection statement.

https://jntuhbtechadda.blogspot.com/
UNIT-II
Names, Bindings, and Scopes:
Introduction,
names,
variables,
concept of binding,
scope,
scope and lifetime,
referencing environments,
named constants

Data types:
Introduction,
primitive,
character,
string types,
user defined ordinal types,
array,
associative arrays,
record,
tuple types,
list types,
union types,
pointer and reference types,
type checking,
strong typing,
type equivalence

Expressions and Statements:


Arithmetic expressions,
overloaded operators,
type conversions,
relational and boolean expressions,
short- circuit evaluation,
assignment statements,
mixed-mode assignment

Control Structures:
introduction,
selection statements,
iterative statements,
unconditional branching,
guarded commands.

https://jntuhbtechadda.blogspot.com/
Names, Bindings, and Scopes
Definitions

• Name: Identifiers that allow us to refer to variables, constants, functions,


types, operations, and so on
• Binding: An association of a name with an object
• Scope: The lifetime of a binding of a name to an object
• Referencing environment: The complete set of bindings in effect at a certain
point in a program

Variables

In programming, a variable is a container (storage area) to hold data.

To indicate the storage area, each variable should be given a unique name
(identifier). Variable names are just the symbolic representation of a memory
location. For example:

int playerScore = 95;

Here, playerScore is a variable of int type. Here, the variable is assigned


an integer value 95.

The value of a variable can be changed, hence the name variable.

char ch = 'a';
// some code
ch = 'l';

Rules for naming a variable

• A variable name can only have letters (both uppercase and lowercase
letters), digits and underscore.
• The first letter of a variable should be either a letter or an underscore.
• There is no rule on how long a variable name (identifier) can be. However,
you may run into problems in some compilers if the variable name is
longer than 31 characters.

Note: You should always try to give meaningful names to variables. For example:
firstName is a better variable name than fn.

Binding Times

• Language design time: The syntax and semantics of a language are


typically set at language design time. Examples would be the control
constructs, how variable declarations are written, whether static or dynamic
scoping is used.

https://jntuhbtechadda.blogspot.com/
• Language implementation time: Most language manuals leave a variety of
issues to the discretion of the language implementor. Typical examples might
be the precision (number of bits) of the fundamental types, the organization
and maximum sizes of the stack and the heap, and the handling of run-time
exceptions, such as arithmetic overflow.

• Compile time: Compiler associates names with objects, for example, a type
with a variable or the layout of a stack allocated object with a variable.

• Link time: References to functions may not be resolved until separate .o files
are compiled together. Then a placeholder reference can be replaced with an
"address" (actually an offset from a relocation register)

• Load time: A program is actually assigned physical memory when it


executes

• Run time: Binding is delayed until run-time, such as dynamic typing in


interpreted languages (the type of a variable cannot be determined until it is
assigned a value in dynamic typing), the assignment of a heap-allocated
object to a pointer variable, or the binding of a virtual method to a function
call.

• Static vs dynamic binding


• Static binding is any binding that occurs prior to run-time (either
compiler or link time).
• Dynamic binding is any binding that occurs at run-time (either load
or run time).

• Earlier binding decisions are associated with faster code (static typing),
whereas later binding decisions are associated with more flexible code
(dynamic typing, pointers point to different objects)

Scope

Scope Rules: Determine the value of a variable when it is not in the current
scope

Types of Scope

• Static Scope: Scope can be determined at compile-time, typically by finding


a matching declaration in the most closely enclosing block.

• C/C++ only have the global level and the function level.

https://jntuhbtechadda.blogspot.com/
• Some languages, like Python, Ada, or Pascal, allow functions to be nested
within other functions.

• Implemented by maintaining a static link in each frame that points to the


"parent" frame, which is the frame of the most recent invocation of the
lexically surrounding subroutine. The number of links can be statically
determined, so a fixed set of instructions can be emitted to follow the
links.

• Many languages, including Java, allow nested inner classes, which are a
form of static scoping. Each instance of an inner class can access the
environment of its enclosing classes. Each inner class maintains a static
class link to its "enclosing" object, so that at runtime the class chain can
be followed to find a reference to an enclosing instance variable. As with
static links, a fixed set of instructions can be emitted to follow the links.

• Inheritance is another form of nesting, but in this case scope resolution


is done at compile time by following class pointers up the inheritance
hierarchy. Since an object's record is simply a collection of all of its
ancestor variables, plus its own variables, the compiler can insert a direct
reference to the appropriate variable in the object's record, rather than
requiring a run-time search of the class hierarchy.

• Some functional languages and many scripting languages do not require


variable declarations in functions, and object-oriented languages do not
require variable declarations a long as the reference is to an instance
variable. Scripting languages handle undeclared variables in different
ways.
o Python treats any variable that gets assigned a value as a local
variable. A programmer can import a global variable using the global
keyword.

o Perl treats any variable that gets assigned a value as a global


variable. A programmer can declare a variable as local using either
the my keyword for static scoping (newer and preferred), or the local
keyword for dynamic scoping (older and generally not wanted).

• Dynamic Scope: Scope cannot be determined until run-time, typically by


following stack frames until a matching declaration is found.
• The number of links is unknown, so a loop must be used to follow the
chain.

https://jntuhbtechadda.blogspot.com/
• Used in older languages, like Lisp, and initially in Perl. Perl now has a
way of specifying static scope as well.

• Provides a convenient way to allow access to variables without passing


parameters, but it can make code difficult to follow when reading it
statically and code can break if a new subroutine with the same
declaration gets inserted during maintenance.

Aliasing

Definition: More than one name refers to the same object (aliasing usually is
caused by references or pointers)

• Problem for compilers: Interferes with optimization. Here's an example:


int a, b;
int *p, *q;
a = *p
*q = 3
b = *p;

• The compiler would like to store the value of *p into a register and then
assign this register value to b, without having to reload *p. However, if q
refers to the same object as p, then the register value is no longer valid.
Unless the compiler can prove that q and p can never point to the same
object, the compiler must reload the value of *p.

• Languages without aliasing, like Fortran, require pointer-based data


structures to be implemented using arrays, which is much more efficient,
but less flexible. Arrays have contiguous storage and pre-allocate large
blocks of memory, which is what makes them more efficient, plus they do
not introduce an aliasing problem.

• In C99, you may add the restrict qualifier to a pointer declaration. This
qualifier asserts that the object to which the pointer refers has no alias in
the current scope.

• Overloading Built-in Operators: Some languages, such as C++, provide


ways to overload built-in operators, such as + or (). Other languages, such
as Java, do not allow operator overloading, on the premise that it makes
code difficult to statically read, since the reader cannot know which
version of the operator will get called.

https://jntuhbtechadda.blogspot.com/
Forms of operator overloading

• Prefix overloading: The operator is treated as though it belongs to a class


and takes a single argument (the first argument is the class). For example,
in C++, you might have the following definition for an operator that adds two
complex numbers:

class complex
{
double real, imaginary;
...
public:
complex operator+(complex &other)
{
return complex(real + other.real, imaginary + other.imaginary);
};
...
complex A, B, C;
C = A + B; // treated by C++ as C = A.operator+(B)

• Infix overloading: The operator is declared outside a class and its


arguments are all provided in an argument list. This handles situations
where a class object might not be the left operand. For example, how would
one handle the following case with prefix overloading:

string lname = "vander zanden";


string name = "brad" + lname;
An example of infix overloading in C++ that handles the above case might be:
string operator+(char *operand1, string operand2)
{
return string(operand1) + operand2;
}
int main()
{
string lname = "vander zanden";
string name = "brad " + lname;
}

Binding of Referencing Environments

When a subroutine can be passed as a parameter to a function, an issue


arises as to whether the referencing environment it uses when it is called is the
referencing environment in effect when the subroutine is passed as a parameter,
or when the subroutine is actually called. It is called deep binding if the
referencing environment is the one in effect when the subroutine is passed as a
parameter and shallow binding if it is the one in effect when the subroutine is

https://jntuhbtechadda.blogspot.com/
called. Notice that deep binding corresponds to an early binding of the
referencing environment and shallow binding corresponds to a late binding of
the referencing environment.

Example: Look at the following C++ pseudo-code and assume that it is


dynamically scoped

class person
{
int age;
}
int threshold;
database people;
boolean older_than_threshold(person p)
{
return p.age >= threshold;
}
void print_person(person p)
{
// call appropriate I/O routines to print person on standard output
// make use of nonlocal variable line_length to format data in columns
}
void print_selected_records(database db, procedure predicate,
print_routine)
{
int line_length;
if (device_type(stdout) == terminal)
line_length = 80
else // standard line length on older printers or files
line_length = 132
foreach person p in db do
if predicate(p)
print_routine(p)
}
main
{
threshold = 35;
print_selected_records(people, older_than_threshold, print_person);
}

shallow binding: you would probably want shallow binding for the print routine,
since you would want it to pick up the value of line_length set in
print_selected_records.

https://jntuhbtechadda.blogspot.com/
deep binding: you would probably want deep binding for threshold, since it
appears that you are trying to alter the value of threshold in main and hoping
that that value is used for older_than_threshold.

Passing Functions as Parameters

Design Considerations

• Statically scoped languages typically use deep binding, since you are
usually looking to pick up the static scope, not the dynamic scope of a
variable (note that shallow binding is essentially saying that you care
about what's on the stack when the function is called, which is what
dynamic scoping is all about)

• Dynamically scoped languages typically use shallow binding, since you


typically do care about what's on the stack when the function is called

Implementation

• Shallow binding: Trivial--same as dynamic scoping

• Deep binding: Need to save the current referencing environment as well


as a pointer to the function. The bundle as a whole is referred to as a
closure
o Statically scoped language: Save a pointer to the function and the
static link that S would use right now if it were called in the current
context. When S is finally called, we temporarily restore the saved
static link, rather than creating a new one. When S follows its static
chain to access a nonlocal object, it will find the object instance that
was current at the time the closure was created. The instance may
not have the value it had at the time the closure was created, but
its identity, at least, will reflect the intent of the closure's creator.
Note that you are passing a nested function to a more deeply nested
function, so when S is called, the less deeply nested context is
further down the stack.

o Dynamically scope language: Beyond the scope of this course,


although our examples will assume that the closure contains
references to variables, rather than copies of the variables' values.
Hence changes made by a function will be to the current value of
the variable, not the value in effect when the function was passed
as a parameter.

https://jntuhbtechadda.blogspot.com/
Returning Functions as Return Values

• Definitions
• First class value: can be returned from a function, passed as a
parameter, and assigned to variables (e.g., functions in scripting
languages, C, C++, functional languages)

• Second class: can be passed as a parameter but not returned from a


function or assigned to a variable (e.g., functions in some languages)

• Third class: cannot be passed even as a parameter (e.g., a label)

• Implementation of closures when nested functions may be returned as a


return value (note that this is not a problem for non-nested languages
such as C)

Example Problem:

def plus_x(x):
return def lambda(y):
return x+y

plus_x returns an unnamed function (lambda functions denote unnamed


functions in functional languages and have been adopted by scripting languages
such as Python). This unnamed function takes y as a parameter, adds it to x,
and returns the sum. The problem is that in a normal imperative language, x is
reclaimed once plus_x exits, and hence would be undefined when our unnamed
function is called. This problem is referred to as unlimited extent. Local variables
with unlimited extent cannot be reclaimed. This in turn means they cannot be
allocated on the stack but instead must be allocated on the heap.

• Functional languages: Functional languages simply allocate local objects


on the heap and use garbage collection to reclaim them when they are no
longer needed

• Imperative languages: Imperative languages like to maintain stack-based


allocation and reclamation of local objects, so they may place restrictions
on returning nested functions
o Languages like C and C++ that do not permit nested functions do
not have this problem.
o Most other imperative languages, like Module-2 an Module-3, only
allow outermost functions to be returned as return values and make
nested functions either second or third class values

https://jntuhbtechadda.blogspot.com/
• Mimicing the context of nested functions with object closures: In object-
oriented languages, we can encapsulate our function as a method and let
the object's fields hold context for the method. Here's a Java example for
the plus_x problem:

interface IntFunc
{
int call(int i);
}
class PlusX implements IntFunc
{
int x;
public PlusX(int n) { x = n; }
public int call(int i) { return i + x; }
}
...
IntFunc f = new PlusX(2);
System.out.println(f.call(3)); // prints 5

The interface defines an abstract type for objects enclosing a function from
integers to integers. Whereas Python would capture the value of x in a function
closure, Java captures it in an object-closure (also called a function object or
functor).

DATA TYPES
As its name indicates, a data type represents a type of the data which
you can process using your computer program. It can be numeric,
alphanumeric, decimal, etc.

• Example dealt with whole numbers


10 + 20

• Example added two decimal numbers


10.50 + 20.50

• Example is dealing with a mix of different data


Name: Zara Ali
Class: 6th
Section: J
Age: 13
Sex: F
o Student name "Zara Ali" is a sequence of characters which is also
called a string.

https://jntuhbtechadda.blogspot.com/
o Student class "6th" has been represented by a mix of whole number
and a string of two characters. Such a mix is called alphanumeric.
o Student section has been represented by a single character which is
'J'.
o Student age has been represented by a whole number which is 13.

o Student sex has been represented by a single character which is 'F'.

In computer science and computer programming, a data type or simply


type is an attribute of data which tells the compiler or interpreter how the
programmer intends to use the data. Most programming languages support
basic data types of integer numbers (of varying sizes), Floating-point numbers
(which approximate real numbers), characters and Booleans. A data type
constrains the values that an expression, such as a variable or a function, might
take. This data type defines the operations that can be done on the data, the
meaning of the data, and the way values of that type can be stored. A data type
provides a set of values from which an expression (i.e. variable, function, etc.)
may take its values.

Classes of Data Type


There are three types of data types −
• Fundamental data types − These are the predefined data types which
are used by the programmer directly to store only one value as per
requirement, i.e., integer type, character type, or floating type. For
example − int, char, float, etc.
• Derived data types − These data types are derived using built-in data
type which are designed by the programmer to store multiple values of
same type as per their requirement. For example − Array, Pointer,
function, list, etc.
• User-defined data types − These data types are derived using built-in
data types which are wrapped into a single a data type to store multiple
values of either same type or different type or both as per the requirement.
For example − Class, Structure, etc.

• Primitive data types


There are eight types of data types

1) Primitive Numeric Data Types:


a) Integer:
An integer number can hold a whole number, but no fraction. For the
value to be negative, you must place a hyphen symbol (-) before the value.
Examples of integer numbers: 42 ,-100

https://jntuhbtechadda.blogspot.com/
b) Floating - Point
A real number can hold a whole number or a fractional number that uses
a decimal point. For the value to be negative, you must place a hyphen symbol
(-) before the value. Examples of real numbers: 20.0005

2) Boolean Types
Boolean types are the simplest of all types. Their range of values has only
two elements, one for true and one for false. These data types are often used to
represent switches or flags in programs.

3) Character String Types


A character string type is one in which the objects consists of sequence of
characters. The string data can include numbers and other numerical symbols
but will be treated as text. Examples of strings are: "I am 6000 years old"

4) Arrays Types
An array is an aggregated of homogeneous data elements in which the
individual elements are identified by their position in the aggregate, relative to
its first element. Examples of arrays are: Character strings in C are implemented
as arrays of char. char name[ ] = "satya".

5) Pointer Types
A pointer type is one in which the variables have a range of values that
consists of memory addresses and a specific value, nil. Pointers have been
designed for two distinct kinds of uses. Pointers provide some of the addressing
flexibility of the indirect addressing that is highly used in assembly language.
And pointers provide a method of dynamic storage management . Examples of
pointers are: In C language pointers are implemented as *. int *ptr;

6) Set Types
A set type is one whose variables can store unordered collections of
distinct values from some ordinal type called its base type. The maximum
number of elements in a set is called its cardinality. Set types are often used to
model mathematical sets. Examples of set types in pascal. type colors = (red,
blue, green, yellow)

7) Union Types
A union is a type that is allowed to store different type values at different
times during program execution. Pascal introduced the concepts of integrated
discriminated unions with a record structure. Discriminated union is called a
record variant.
Characters and strings
A character type (typically called "char") may contain a single letter, digit,
punctuation mark, symbol, formatting code, control code, or some other
specialized code (e.g., a byte order mark). In C, char is defined as the smallest

https://jntuhbtechadda.blogspot.com/
addressable unit of memory. On most systems, this is 8 bits; Several standards,
such as POSIX, require it to be this size. Some languages have two or more
character types, for example a single-byte type for ASCII characters and a multi-
byte type for Unicode characters. The term "character type" is normally used
even for types whose values more precisely represent code units, for example
a UTF-16 code unit as in Java (support limited to 16-bit characters only)
and JavaScript.
Characters may be combined into strings. The string data can include
numbers and other numerical symbols but will be treated as text.
Strings are implemented in various ways, depending on the programming
language. The simplest way to implement strings is to create them as an array
of characters, followed by a delimiting character used to signal the end of the
string, usually NUL. These are referred to as null-terminated strings, and are
usually found in languages with a low amount of hardware abstraction, such
as C and Assembly. While easy to implement, null terminated strings have been
criticized for causing buffer overflows. Most high-level scripting languages, such
as Python, Ruby, and many dialects of BASIC, have no separate character type;
strings with a length of one are normally used to represent single characters.
Some languages, such as C++ and Java, have the capability to use null-
terminated strings (usually for backwards-compatibility measures), but
additionally provide their own class for string handling ( std::string and
java.lang.String , respectively) in the standard library.

There is also a difference on whether or not strings are mutable


or immutable in a language. Mutable strings may be altered after their creation,
whereas immutable strings maintain a constant size and content. In the latter,
the only way to alter strings are to create new ones. There are both advantages
and disadvantages to each approach: although immutable strings are much less
flexible, they are simpler and completely thread-safe. Some examples of
languages that use mutable strings include C++, Perl and Ruby, whereas
languages that do not include JavaScript, Lua, Python and Go. A few languages,
such as Objective-C, provide different types for mutable and immutable strings.
Literals for characters and strings are usually surrounded by quotation
marks: sometimes, single quotes (') are used for characters and double quotes
(") are used for strings. Python accepts either variant for its string notation.
Examples of character literals in C syntax are:
• 'A'
• '4'
• '$'
• '\t' (tab character)

https://jntuhbtechadda.blogspot.com/
Examples of string literals in C syntax are:
• "A"
• "Hello World"

User-Defined Ordinal Types


An ordinal type is one in which the range of possible values can be easily
associated with a set of positive integers. In pascal the built-in ordinal types are
integers, char, Boolean. User can define two types of ordinal types: enumeration
and subrange.

a) Enumeration types
An enumeration type is one in which the user enumerates all of the
possible values, which are symbolic constants. In Ada a typical enumeration
type is shown as: type DAYS is ( M, T, W, R, F, Sa, S);
b) Subrange types
A subrange type is an ordered contiguous subsequence of an ordinal type.
These types were introduced by Pascal. For example: 12 . . . 16 is a subrange of
the integer type.

Arrays

When there is a need to use many variables then There is a big problem
because we will Conflict with name of variables So that in this Situation where
we wants to Operate on many numbers then we can use array . The Number of
Variables also increases the complexity of the Program. So that we uses Arrays.

Arrays are Set of Elements having same data type or we can Say that
Arrays are Collection of Elements having same name and same data type But
Always Remember Arrays are Always Start From its index value and the index
of array is start From 0 to n-1.

Suppose we wants to Access 5th Element of array then we will use 4th
Element Because Arrays are Start From 0 and arrays are always stored in
Continuous Memory Locations The Number of Elements and Types of array are
Identified by Subscript of array Elements. The Various types of Array those are
provided by c as follows:-

1. Single Dimensional Array

2. Two Dimensional Array

3. Three Dimensional array

4. Character Array or Strings

https://jntuhbtechadda.blogspot.com/
1. Single Dimensional Array
A dimensional is used representing the elements of the array for example

int a[5]

The [] is used for dimensional or the sub-script of the array that is


generally used for declaring the elements of the array For Accessing the Element
from the array we can use the Subscript of the Array like this

a[3]=100

This will set the value of 4th element of array. So there is only the single
bracket then it called the Single Dimensional Array.

2) Two Dimensional Array or the Matrix


The Two Dimensional array is used for representing the elements of the
array in the form of the rows and columns and these are used for representing
the Matrix A Two Dimensional Array uses the two subscripts for declaring the
elements of the Array

Like this int a[3][3]

So this is the Example of the Two Dimensional Array In this first 3


represents the total number of Rows and the Second Elements Represents the
Total number of Columns The Total Number of elements are judge by Multiplying
the Numbers of Rows * Number of Columns in The Array in the above array the
Total Number of elements are 9.

When we talk about the Two Dimensional of the Character array The first
Subscript of the array if used for representing the Total Numbers of Strings and
the second Subscript is used for defining the length of the array Characters in
the String like This

char name[5][10]

It declares the 5 names and each having the characters up to 10 So the


First Subscript is used for defining the total number of the Strings and the
Second is used for Length of the Characters

3) Multidimensional or the Three Dimensional Array :


The Multidimensional Array are used for Representing the Total Number
of Tables of Matrix A Three dimensional Array is used when we wants to make
the two or more tables of the Matrix Elements for Declaring the Array Elements
we can use the way like this

int a[3][3][3]

https://jntuhbtechadda.blogspot.com/
In this first 3 represents the total number of Tables and the second 3
represents the total number of rows in the each table and the third 3 represents
the total number of Columns in the Tables.

So this makes the 3 Tables having the three rows and the three columns

The Main and very important thing about the array that the elements are
stored always in the Contiguous in the memory of the Computer.

4) Character Array of String:


Like an integer characters are also be in the Array The Array of Characters
are called as the Strings They are Generally used for representing the Strings
Always Remember that a String is Terminated with the \0 or Null Character

There are the built in string Operation those are provided by the C
Language in the String.h Header file Like

1) strLen: For Getting the Length or Total Numbers of Characters in String

2) strconcat: This is Used for Joining the two Strings or This function is
used for Concatenating the two Strings.

3) strRev: This Function is used for obtaining the Reverse of the String

4) strcmp: This Function is used for Comparing the Two Strings and it
gives us the Result as follows after comparing the Two Strings

it Returns us + value

if String1 is Greater than String2

it Returns us the - Value

if String1 is Less than String2

it Returns us the 0

if string1 is Equals to String2

Like The array elements of Integer Types The Character array also are the
Single Dimensional or The Two Dimensional Array.

Single Dimensional Array The Single Dimensional array are used for
creating the Number of characters like

char name[10]

in this we can use the 10 characters on the name variable Means we can give
the name as 10 characters long

https://jntuhbtechadda.blogspot.com/
Associative Array

In computer science, an associative array, map, symbol table, or


dictionary is an abstract data type composed of a collection of (key, value)
pairs, such that each possible key appears at most once in the collection.

Implementing associative arrays poses the dictionary problem, a classic


computer science problem: the task of designing a data structure that maintains
a set of data during 'search', 'delete', and 'insert' operations. The two major
solutions to the dictionary problem are a hash table or a search tree. In some
cases it is also possible to solve the problem using directly addressed arrays,
binary search trees, or other more specialized structures.
Many programming languages include associative arrays as primitive data
types, and they are available in software libraries for many others. Content-
addressable memory is a form of direct hardware-level support for associative
arrays.
Associative arrays have many applications including such fundamental
programming patterns as memorization and the decorator pattern.
Record
A record is a data structure for storing a fixed number of elements. It is
similar to a structure in C language. At the time of compilation, its expressions
are translated to tuple expressions.
How to create a record?
The keyword ‘record’ is used to create records specified with record name
and its fields. Its syntax is as follows −
record(recodname, {field1, field2, . . fieldn})
The syntax to insert values into the record is −
#recordname
{
fieldName1 = value1, fieldName2 = value2 .. fieldNamen = valuen
}

Tuple
A tuple is a compound data type having a fixed number of terms. Each
term in a tuple is known as an element. The number of elements is the size of
the tuple.
A tuple type is a comma-separated list of types, enclosed in parentheses.

You can use a tuple type as the return type of a function to enable the
function to return a single tuple containing multiple values. You can also name
the elements of a tuple type and use those names to refer to the values of the

https://jntuhbtechadda.blogspot.com/
individual elements. An element name consists of an identifier followed
immediately by a colon (:). For an example that demonstrates both of these
features, see Functions with Multiple Return Values.

Program to define a tuple in C#


The following program shows how to define a tuple of four terms and print
them using C#, which is an object-oriented programming language.

using System;
public class Test
{
public static void Main()
{
var t1 = Tuple.Create(1, 2, 3, new Tuple<int, int>(4, 5));
Console.WriteLine("Tuple:" + t1);
}
}

It will produce the following output –


Tuple :(1, 2, 3, (4, 5))

Advantages of Tuple
Tuples offer the following advantages −
• Tuples are fined size in nature i.e. we can’t add/delete elements to/from
a tuple.
• We can search any element in a tuple.
• Tuples are faster than lists, because they have a constant set of values.
• Tuples can be used as dictionary keys, because they contain immutable
values like strings, numbers, etc.
List types
List is the most versatile data type available in functional programming
languages used to store a collection of similar data items. The concept is similar
to arrays in object-oriented programming. List items can be written in a square
bracket separated by commas. The way to writing data into a list varies from
language to language.
Union Type
A union is a special data type available in C that allows to store different
data types in the same memory location. You can define a union with many
members, but only one member can contain a value at any given time. Unions

https://jntuhbtechadda.blogspot.com/
provide an efficient way of using the same memory location for multiple-
purpose.
Defining a Union
To define a union, you must use the union statement in the same way as
you did while defining a structure. The union statement defines a new data type
with more than one member for your program. The format of the union
statement is as follows −

union [union tag]


{
member definition;
member definition;
...
member definition;
}
[one or more union variables];

The union tag is optional and each member definition is a normal


variable definition, such as int i; or float f; or any other valid variable definition.
At the end of the union's definition, before the final semicolon, you can specify
one or more union variables but it is optional. Here is the way you would define
a union type named Data having three members i, f, and str −

union Data
{
int i;
float f;
char str[20];
}
data;

Now, a variable of Data type can store an integer, a floating-point number,


or a string of characters. It means a single variable, i.e., same memory location,
can be used to store multiple types of data. You can use any built-in or user
defined data types inside a union based on your requirement.
The memory occupied by a union will be large enough to hold the largest
member of the union. For example, in the above example, Data type will occupy
20 bytes of memory space because this is the maximum space which can be
occupied by a character string.
Accessing Union Members
To access any member of a union, we use the member access operator
(.). The member access operator is coded as a period between the union variable

https://jntuhbtechadda.blogspot.com/
name and the union member that we wish to access. You would use the
keyword union to define variables of union type.

Pointer and Reference types

The “pointer” and “reference” both are used to point or refer an another
variable. But, the basic difference among both of them is that a pointer variable
points to a variable whose memory location is stored in it. The reference variable
is an alias for a variable which is assigned to it.

BASIS FOR
POINTER REFERENCE
COMPARISON

Basic The pointer is the memory The reference is an alias for


address of a variable. a variable.

Returns The pointer variable returns The reference variable


the value located at the returns the address of the
address stored in pointer variable preceded by the
variable which is preceded by reference sign '&'.
the pointer sign '*'.

Operators *, -> &

Null Reference The pointer variable can refer The reference variable can
to NULL. never refer to NULL.

Initialization An uninitialized pointer can An uninitialized reference


be created. can never be created.

Time of The pointer variable can be The reference variable can


Initialization initialized at any point of time only be initialized at the
in the program. time of its creation.

https://jntuhbtechadda.blogspot.com/
BASIS FOR
POINTER REFERENCE
COMPARISON

Reinitialization The pointer variable can be The reference variable can


reinitialized as many times as never be reinitialized again
required. in the program.

Definition of Pointer
A “pointer” is a variable that holds the memory location of another variable.
The operators used by the pointer variable is * and ->. The declaration of pointer
variable contains the base data type followed by the ‘*’ sign and the variable
name.
type *var_name;

Example
Let us understand pointer with the help of an example.
1. int a=4;
2. int * ptr= &a;
3. cout<<a; //4
4. cout<<ptr; //2007 address of varaible a
5. cout<<*ptr; //4
Here, we have an integer variable a and, a pointer variable ptr which stores
the address of variable a.

Pointer Arithmetic
The pointer variable can be operated with two arithmetic operators that
are “addition” and “subtraction”. The addition referred as “increment”, and the
subtraction is referred as “decrement”. As a pointer variable is incremented, it
points to the memory location of the next variable of its base type. As a pointer
variable is decremented, it points to the memory location of the previous variable
of its base type. Hence, an array can be efficiently accessed by a pointer variable.

Multiple Indirection
A pointer points to the other pointer variable which is pointing to the target
value. This kind of pointer is always initialized with the address of another
pointer variable. The declaration of a pointer to a pointer is as follow.
1. type **var_name;

Let’s study it with an example.


1. int a=4;

https://jntuhbtechadda.blogspot.com/
2. int * ptr1= &a;
3. int ** ptr2= &ptr1;
4. cout<<a; //4
5. cout<<ptr1; //2007 address of varaible a
6. cout<<*ptr1; //4
7. cout<<ptr2; //1007 address of pointer variable ptr1.
8. cout<<**ptr2; //4

Function pointer
As we know that a function is not a variable, still it has a memory location,
that can be assigned to a pointer variable. Once a pointer points to a function,
then the function can be called with that function pointer.

The important points to remember about the pointer.

• The pointer variable can be created without its initialization, and it can be
initialized anywhere in the program.
• The pointer variable can be reinitialized to an another variable.
• The pointer variable can refer to NULL.

Definition of Reference
The reference variable is used to refers to the variable which is assigned to
that reference variable. The operator used by the reference variable is ‘&’. The
declaration of a reference variable contains base type followed by ‘&’ sign and
then variable name.
1. type & refer_var_name = var_ name;

Here, the type is the datatype, the & operator confirms that it is a reference
variable. The refer_var_name is the name of the reference variable. The var_name
is the name of the variable, which we want the reference variable to refer.

Example
Let us understand the reference variable with the help of an example.
1. int a = 4;
2. int &b = a; // b refers to a
3. b = 6; // now a = 6
Here, the variable of type int is assigned a value 4. The reference variable
is assigned the variable a, i.e. b is alias of a. Now, when we assign another value
to b, we modify the value of a. Hence, it can be said that the changes done to a
reference variable will also occur in variable referred by that reference variable.

https://jntuhbtechadda.blogspot.com/
The most important point is that the reference variable must be initialized
at the time of its creation. Once the reference variable is initialized with a
variable, it can not be reinitialized to refer an another variable. The moment you
assign a value to a reference variable, you assign that value to a variable that a
reference variable points to. The reference variable can never refer to NULL.
Arithmetic can not be performed on a reference variable.

The reference variable can be used in three ways:

• As a function return value.


• As a function parameter.
• As a stand alone reference.

Key Differences Between Pointer and Reference

1. Reference is like creating another name to refer a variable so that it can be


referred with different names. On the other hand, a pointer is simply a
memory address of a variable.
2. A pointer variable if proceeded by ‘*’ returns the value of a variable whose
address is stored in the pointer variable. A reference variable when
proceeded by ‘&’ returns the address of that variable.
3. Pointer operators are * and -> whereas, reference operator is &.
4. A pointer variable if does not carry any variable’s address it points to null.
On the other hand, a reference variable can never refer to Null.
5. You can always create an initialized pointer variable, but we create a
reference when we need an alias of some variable so you can never create
an initialize reference.
6. You can reinitialize a pointer but once you initialize a reference you cannot
reinitialize it again.
7. You can create an empty pointer and initialize it at any time but you have
to initialize reference only when you create a reference.

Note
Java does not support pointers.

Conclusion
The pointer and reference both are used to point or refer another variable. But
both differ in their usage and implementation.

https://jntuhbtechadda.blogspot.com/
Type checking
If type checking is performed at compile-time, one may speak about static
type checking; otherwise, that is, type checking is performed at run-time, a term
dynamic type checking is applied. In principle, type checking can always be
performed at run-time if the information about types of values in program is
accessible in executing code. Obviously, dynamic type checking, compared to
static one, leads to the increase of size and execution time of the object program
and lowers the reliability of the compiled code. A programming language is called
a language with static type checking or strongly typed language, if the type of
each expression can be determined at compile-time, thereby guaranteeing that
the type-related errors cannot occur in object program. Pascal is an example of
a strongly typed language. However, even for Pascal some checks can be
performed only dynamically. For instance, consider the following definitions:
table: array [0..255] of char;
i: integer;

A compiler cannot guarantee that the argument i in the expression table[i]


is actually in the specified boundaries, that is, not less than zero and not greater
than 255. In some cases, such checking can be performed by techniques like
data flow analysis, but it is far from being always possible. It is clear that this
sample demonstrates a common situation, namely, the control of slice
arguments, occurring in the greater part of programming languages. Of course,
this checking is usually performed dynamically.

Two types of Type checking:


• Static type checking means that the correctness of using types is
performed at compile-time
• Dynamic type checking means that the correctness of using types is
performed at run-time

Type checking means checking that each operation should receive proper
number of arguments and of proper data type.

Like
A=B*j+d;

* and - are basically int and float data types-based operations and if
any variable in this A=B*j+d; Is of other than int and float then compiler will
generate type error.

https://jntuhbtechadda.blogspot.com/
Two ways of Type Checking:
1) Dynamic Type Checking:
• It is done at runtime.
• It uses concept of type tag which is stored in each data objects that
indicates the data type of the object.

Example:
An integer data object contains its 'type' and 'values' attribute so Operation only
be performed after type checking sequence in which type tag of each argument
is checked. If the types are not correct then error will be generated.

• Perl and Prolog follow basically dynamically type checking because data
type of variables A+B in this case may be changed during program
execution.

• so that type checking must be done at runtime.

Advantages of Dynamic Type:


• It is much flexible in designing programs or we ca say that the flexibility
in program design.
• In this no declarations are required.
• In this type may be changed during execution.
• In this programmer are free from most concern about data type.

Disadvantage of Dynamic Type:


1. difficult to debug: We need to check program execution paths for testing
and in dynamic type checking, program execution path for an operation
is never checked.
2. extra storage: Dynamic type checking need extra storage to keep type
information during execution.
3. Seldom hardware support: As hardware seldom support the dynamic
type checking so we have to implement in software which reduces
execution speed.

2. Static Type Checking:


• Static Type Checking is done at complete time.
• Information needed at compile time is provided- by declaration- by
language structures.
• The information required includes:
1) for each operation: The number, order, and data type, of its
arguments.

https://jntuhbtechadda.blogspot.com/
2) For each variables: Name and data type of data object.
Example-
A+B
in this type of A and B variables must not be changed.

3) for each constant: Name and data type and value


const int x=28;
const float x=2.087;
In this data type, the value and name is specified and in further if checked
value assigned should match its data type.

Advantages of Static Type Checking:


1) compiler saves information:- if that type of data is according to the operation
then compiler saves that information for checking later operations which
further no need of compilation.

2) checked execution paths: As static type checking includes all operations that
appear in any program statement, all possible execution paths are checked,
and further testing for type error is not needed. So no type tag on data objects
at run-time are not required, and no dynamic checking is needed.

Disadvantages of Static Type Checking


It affects many aspects of languages
1) declarations
2) data control structures
3) provision of compiling separately some subprograms.

Strong Typing
If we change detect all types of errors statically in a program, we can say
that language is' strongly typed'.

It provides a level of security to our program.

Example
f:s-> R

In this function f mail signature s generate output R and R is not outside


the range of R data type.

IF every operation is type safe then automatically language is strongly typed.

Example of strongly typed languages are:


C,Java, C++, RubyRail, smalltalk, python.

https://jntuhbtechadda.blogspot.com/
Type infer:- In this, like in ML, the language implementation will infer any
missing type information from other declared type.

Example:
funarea(length:int, width:int):int= length *width;

This is the standard declaration which tells length and width of int data
type and its return type is int and function name area. But leaving any two of
these declarations still leaves the function will only one interpretation. Knowing
that * can multiply together either two reals or two integers. ML interprets the
following as equivalent to the previous example.

Funarea(length,width)int= length*weight;

Funarea(length:int,width)= length*weight;

Funarea(length,width:int)= length*weight;

However:
Funarea(length,width)= length*weight;

Is invalid as it is now ambiguous as to that type of arguments. They could


all be int or they could be real.

Equivalence of types
The essential part of type checking is controlling equivalence of types. It
is extremely important for a compiler to check the equivalence of types quickly.
Structural equivalence of types. Two types are called structurally equivalent, if
both are either the same primitive type, or constructed by applying the same
constructor to a structurally equivalent types. In other words, two types are
structurally equivalent if and only if they are identical. We can check whether
two types are structurally equivalent by using the following function:
bool sequiv (s, t)
{
if (s and t – two identical primitive types)
{
return true;
}
else if (s == array (s1, s2) && t == array (t1, t2))
{
return sequiv (s1, t1) && sequiv (s2, t2);
}
else if (s == s1*s2 && t == t1*t2)
{

https://jntuhbtechadda.blogspot.com/
return sequiv (s1, t1) && sequiv (s2, t2);
}
else if (s==pointer (s1) && t == pointer (t1))
{
return sequiv (s1, t1);
}
else if (s==proc (s1, s2) && t == proc (t1, t2))
{
return sequiv (s1, t1) && sequiv (s2, t2);
}
else
{
return false;
}
}

Expressions
Expressions perform the work of a program. Among other things,
expressions are used to compute and to assign values to variables and to help
control the execution flow of a program. The job of an expression is twofold: to
perform the computation indicated by the elements of the expression and to
return a value that is the result of the computation.

Definition: An expression is a series of variables, operators, and method calls


(constructed according to the syntax of the language) that evaluates to a single
value.

This partial listing of the MaxVariablesDemo program shows some of the


program's expressions in boldface:

...
//other primitive types
char aChar = 'S';
boolean aBoolean = true;

//display them all


System.out.println("The largest byte value is " + largestByte);
...

if (Character.isUpperCase(aChar))
{
...
}

https://jntuhbtechadda.blogspot.com/
Each expression performs an operation and returns a value, as shown in
the following table.

Some Expressions from MaxVariablesDemo

Expression Action Value Returned

aChar = 'S' Assign the character 'S' The value of aChar


to the character after the assignment
variable aChar ('S')

"The largest byte value is " + Concatenate the string The resulting string:
largestByte "The largest byte value The largest byte value
is " and the value of is 127
largest Byte converted
to a string

Character.isUpperCase(aChar) Call the method is The return value of


UpperCase the method: true

The data type of the value returned by an expression depends on the


elements used in the expression. The expression aChar = 'S' returns a character
because the assignment operator returns a value of the same data type as its
operands and aChar and 'S' are characters. As you see from the other
expressions, an expression can return a boolean value, a string, and so on.

The Java programming language allows you to construct compound


expressions and statements from various smaller expressions as long as the data
type required by one part of the expression matches the data type of the other.
Here's an example of a compound expression:

x*y*z

In this particular example, the order in which the expression is evaluated


is unimportant because the results of multiplication is independent of order; the
outcome is always the same, no matter what order you apply the multiplications.
However, this is not true of all expressions. For example, the following expression
gives different results, depending on whether you perform the addition or the
division operation first:

x + y / 100 //ambiguous

You can specify exactly how you want an expression to be evaluated, using
balanced parentheses — ( and ). For example, to make the previous expression
unambiguous, you could write:

https://jntuhbtechadda.blogspot.com/
(x + y)/ 100 //unambiguous, recommended

If you don't explicitly indicate the order in which you want the operations
in a compound expression to be performed, the order is determined by
the precedence assigned to the operators in use within the expression. Operators
with a higher precedence get evaluated first. For example, the division operator
has a higher precedence than does the addition operator. Thus, the two following
statements are equivalent:

x + y / 100
x + (y / 100) //unambiguous, recommended

When writing compound expressions, you should be explicit and indicate


with parentheses which operators should be evaluated first. This practice will
make your code easier to read and to maintain.

The following table shows the precedence assigned to the operators in the
Java platform. The operators in this table are listed in precedence order: The
higher in the table an operator appears, the higher its precedence. Operators
with higher precedence are evaluated before operators with a relatively lower
precedence. Operators on the same line have equal precedence. When operators
of equal precedence appear in the same expression, a rule must govern which is
evaluated first. All binary operators except for the assignment operators are
evaluated from left to right. Assignment operators are evaluated right to left.

Operator Precedence

postfix operators expr++ expr--

unary operators ++expr --expr +expr -expr ~ !

Multiplicative */%

Additive +-

Shift << >> >>>

Relational < > <= >= instanceof

Equality == !=

bitwise AND &

https://jntuhbtechadda.blogspot.com/
bitwise exclusive OR ^

bitwise inclusive OR |

logical AND &&

logical OR ||

Conditional ?:

Assignment = += -= *= /= %= &= ^= |= <<= >>= >>>=

An expression is a combination of one or more operands, zero or more


operators, and zero or more pairs of parentheses.

There are three kinds of expressions:

• An arithmetic expression evaluates to a single arithmetic value.


• A character expression evaluates to a single value of type character.
• A logical or relational expression evaluates to a single logical value.

The operators indicate what action or operation to perform.

The operands indicate what items to apply the action to. An operand can be any of the
following kinds of data items:

• Constant
• Variable
• Array element
• Function
• Substring
• Structured record field (if it evaluates to a scalar data item)
• An expression

Arithmetic Expressions
An arithmetic expression evaluates to a single arithmetic value, and its
operands have the following types. @ indicates a nonstandard feature.

• BYTE @
• COMPLEX
• COMPLEX*32 (SPARC only) @

https://jntuhbtechadda.blogspot.com/
• DOUBLE COMPLEX @
• DOUBLE PRECISION
• INTEGER
• LOGICAL
• REAL
• REAL*16 (SPARC only) @

Overloaded operators
Operator overloading is a technique by which operators used in a
programming language are implemented in user-defined types with customized
logic that is based on the types of arguments passed.

Operator overloading facilitates the specification of user-defined


implementation for operations wherein one or both operands are of user-defined
class or structure type. This helps user-defined types to behave much like the
fundamental primitive data types. Operator overloading is helpful in cases where
the operators used for certain types provide semantics related to the domain
context and syntactic support as found in the programming language. It is used
for syntactical convenience, readability and maintainability.

Java does not support operator overloading, except for string


concatenation for which it overloads the + operator internally.

Operators are referenced using operator notation in expressions and


functional notation in declarations. The syntax, precedence and associativity of
an operator cannot be changed by using user-defined operator declarations.

For example, operators in C# are categorized based on the type of


operation they perform. Some of them are overloaded in user-defined types by
defining them in static member functions and using the operator keyword. The
parameters of the operator function represent the operands, while the return
type of an operator function represents the result of the operation. Overloading
is implemented in pairs for operators, such as comparison operators like "=="
and "!=". The Equals() method for these operators should be overridden to avoid
a compiler warning. Overloading is not to be used for operators such as
conditional, logical ( and !!), assignment (+=, -=, etc.), casting and array indexing
([]).
It is highly recommended that operator overloading be implemented such
that the results produced are what are intuitively expected out of the default
implementation of the operator. Certain mathematical rules such as
commutative law, applicable to expressions with two operands, cannot be
applicable when used in overloading for types as they are only defined for
numerical operands.

https://jntuhbtechadda.blogspot.com/
Type conversions
In computer science, type conversion or typecasting refers to changing
an entity of one datatype into another. There are two types of conversion: implicit
and explicit. The term for implicit type conversion is coercion. Explicit type
conversion in some specific way is known as casting. Explicit type conversion
can also be achieved with separately defined conversion routines such as an
overloaded object constructor.

1.Implicit type conversion

Implicit type conversion, also known as coercion, is an automatic type


conversion by the compiler. Some languages allow, or even require compilers to
provide coercion.
In a mixed type expression, a subtype s will be converted into
a supertype t or some subtypes s1, s2, ... will be converted to a
supertype t (maybe none of the si is of type t) at runtime so that the program will
run correctly. For example:

double d;
long l;
int i;
if (d > i) d = i;
if (i > l) l = i;
if (d == l) d *= 2;

is legal in a C language program. Although d, l and i belong to the


different datatypes, they will be automatically converted into the same datatype
each time a comparison or assignment is executed.

2.Explicit type conversion


There are several kinds of explicit conversion.
checked
before the conversion is performed a runtime check is done to see if the
destination type can actually hold the source value. If not an error
condition is raised.
unchecked
no check is performed and when the destination type cannot hold the
source value the result is undefined.
bit pattern
The data is not interpreted at all and just the raw bit pattern is copied.

https://jntuhbtechadda.blogspot.com/
Each programming language has its own rules on how types can be
converted. In general, both objects and fundamental data types can
be converted.

Relational and boolean expressions


A boolean expression is an expression that has relational and/or logical
operators operating on boolean variables. A boolean expression evaluates to
either true or false.

1. Relational operators are:

== is identical to
!= is not identical to
< is less than
<= is less than or equal to
> is greater than
>= is greater than or equal to

Relational operators can operate on integers, floats, doubles and even


strings (in a lexicographical fashion).

2. Logical operators are:

! logical negation
&& logical AND
|| logical OR
Logical operators operate on boolean variables or boolean expressions
only.

3. Examples of Boolean expression:

long int winning_lottery_number = 947423945645, your_ticket_number;


bool is_a_winner;
cout << "Enter your lottery ticket number: ";
cin >> your_ticket_number;
is_a_winner = (your_ticket_number == winning_ticket_number); // can
omit the parentheses
cout << "Please tell me if I won! ";
cout << "Output a 1 if I won, otherwise output a 0: ";
cout << is_a_winner << endl;

https://jntuhbtechadda.blogspot.com/
Another example:

bool isMarried, hasChildren, shouldShootMyself;


cout << "Are you married?\n";
cout << "Enter 1 if you are, otherwise enter 0: ";
cin >> isMarried;
cout << "Do you have any children?\n";
cout << "Enter 1 if you do, otherwise enter 0: ";
cin >> hasChildren;
shouldShootMyself = (isMarried && hasChildren); // can omit the
parentheses
cout << "Output a 1 if I should shoot myself, otherwise output a 0: ";
cout << shouldShootMyself;

This example assumes that examScore and numberOfMissingHW are integers:

bool isFailing;
isFailing = (examScore < 55) || (numberOfMissingHW >= 3);
// both pairs of parentheses are inserted for readability reasons only

Most C++ compilers will treat any nonzero number as true and will treat
zero as false.

Careless use of Boolean expressions can lead to unexpected results. For


example, a student fails a course if his score is less than the class average,
otherwise the student passes the course. Someone may write the following code:

if ( ! score > average )


cout < < "You failed the course.\n";
else
cout < < "You passed the course.\n";

The person read the code as saying: if it is not true that the score is higher
than the average, then you failed the course, otherwise you passed the course.
The above code will not cause problem during compilation, and it will also run
without run-time error. However the code actually has a mistake.

Suppose the score is 34 and the average is 63. The compiler applies the
precedence rule and interprets the Boolean expression as the following

( ! score ) > average

https://jntuhbtechadda.blogspot.com/
This turns out to evaluates to false for the following reasons. First because
! is a unary logical negation operator and the value of score is nonzero and so
score is converted to true. Thus !score evaluates to false. The next operator >
compares 2 numbers and so !score is converted to 0, and then this value is
compared with 63. Since 0 is not greater than 63, the entire expression evaluates
to false, and the output will be: You passed the course.

Of course the correct way is to use parentheses and write the above
Boolean expression as follows:

if ( ! (score > average) )


cout < < "You failed the course.\n";
else
cout < < "You passed the course.\n";

C++ uses short-circuit evaluation of compound Boolean expressions for the sake
of efficiency.

• An expression such as (a && b) is false if either a or b is false. The


program first evaluates a to see if it is true or false. If a is found to be false,
the program will set (a && b) as false without evaluate b at all.
• Similarly an expression such as (a || b) is true if either a or b is true. The
program first evaluates a to see if it is true or false. If a is found to be true,
the program will set (a || b) as true without evaluate b at all.

The following example shows how this C++ feature can be exploited to
avoid run-time error that will occur if count happens to be zero:

if (count != 0) && ((sumOfScores/static_cast(count)) < 35)


cout < < "What a low class average. Fire the professor!\n";

Make sure you revisit this example after we cover the if statement. The NOT
operator is a unary operator. It negates a boolean variable or expression, turning
them from true to false and vice versa.

https://jntuhbtechadda.blogspot.com/
Note that if a, b, c and d are integers, for example, then

Expression Equivalent Expression


!(a > b) a <= b
!(a == b) a != b
!(a == b || c == d) a != b && c != d
!(a == b && c > d) a != b || c <= d

Short- circuit evaluation


Short-circuit evaluation, minimal evaluation, or McCarthy evaluation
(after John McCarthy) is the semantics of some Boolean operators in
some programming languages in which the second argument is executed or
evaluated only if the first argument does not suffice to determine the value of
the expression: when the first argument of the AND function evaluates to false ,
the overall value must be false ; and when the first argument of the OR function
evaluates to true , the overall value must be true .

In programming languages with lazy evaluation (Lisp, Perl, Haskell), the


usual Boolean operators are short-circuit. In others (Ada, Java, Delphi), both
short-circuit and standard Boolean operators are available. For some Boolean
operations, like exclusive or (XOR), it is not possible to short-circuit, because
both operands are always required to determine the result.
Short-circuit operators are, in effect, control structures rather than
simple arithmetic operators, as they are not strict. In imperative language terms
(notably C and C++), where side effects are important, short-circuit operators
introduce a sequence point – they completely evaluate the first argument,
including any side effects, before (optionally) processing the second
argument. ALGOL 68 used proceduring to achieve user-defined short-circuit
operators and procedures.
The use of short-circuit operators has been criticized as problematic:
The conditional connectives — "cand" and "cor" for short — are ... less
innocent than they might seem at first sight. For instance, cor does not
distribute over cand: compare
(A cand B) cor C with (A cor C) cand (B cor C);
in the case ¬A ∧ C , the second expression requires B to be defined, the first
one does not. Because the conditional connectives thus complicate the formal
reasoning about programs, they are better avoided.

https://jntuhbtechadda.blogspot.com/
In C, when a logical operation is being evaluated, if the result is known
before all sub expressions have been evaluated, then the evaluation stops, or
short circuits. The two situations where this can occur is when the first
expression of a logical AND operation is FALSE (zero) or the first expression of a
logical OR operation is TRUE (non-zero). In both of these cases, the result is
already known. For AND, if either of the two expressions is FALSE, the result
will be FALSE. For OR, if either of the two expressions is TRUE, then the result
will be TRUE.
In most situations, this won't be a problem, but you need to be careful not
to use the results of the second expression somewhere else in your code because
there is no guarantee that it will ever be evaluated.

Assignment statements
Statements are roughly equivalent to sentences in natural languages.
A statement forms a complete unit of execution. The following types of
expressions can be made into a statement by terminating the expression with a
semicolon (;):

• Assignment expressions
• Any use of ++ or --
• Method calls
• Object creation expressions

These kinds of statements are called expression statements. Here are some
examples of expression statements:
aValue = 8933.234; //assignment statement
aValue++; //increment "
System.out.println(aValue); //method call "
Integer integerObject = new Integer(4); //object creation "

In addition to these kinds of expression statements, there are two other


kinds of statements. A declaration statement declares a variable. You've seen
many examples of declaration statements.
double aValue = 8933.234; //declaration statement
A control flow statement regulates the order in which statements get
executed. The for loop and the if statement are both examples of control flow
statements.

An assignment statement gives a value to a variable. For example,


x = 5; gives x the value 5.

https://jntuhbtechadda.blogspot.com/
The value of a variable may be changed. For example, if x has the value
5, then the assignment statement

x = x + 1; will give x the value 6.

The general syntax of an assignment statement is

variable = expression;

where:
• the variable must be declared;
• the variable may be a simple name, or an indexed location in an array,
or a field (instance variable) of an object, or a static field of a class; and
• the expression must result in a value that is compatible with the type of
the variable. In other words, it must be possible to cast the expression
to the type of the variable.

Examples:
int i = 0;
price[itemNumber] = 0.80 * price[itemNumber];
myDog.name = "Fido";

Mixed-mode assignment

• In FORTRAN, C, and C++, any numeric value can be assigned to any


numeric scalar variable; whatever conversion is necessary is done.

• In Pascal, integers can be assigned to reals, but reals cannot be assigned


to integers (the programmer must specify whether the conversion from real
to integer is truncated or rounded).

• In Java, only widening assignment coercions are done.

• In Ada, there is no assignment coercion.

https://jntuhbtechadda.blogspot.com/
Control Structures
Introduction
Control Structures are just a way to specify flow of control in programs.
Any algorithm or program can be more clear and understood if they use self-
contained modules called as logic or control structures. It basically analyses and
chooses in which direction a program flows based on certain parameters or
conditions.

There are three basic types of logic, or flow of control, known as:
1. Sequence logic, or sequential flow
2. Selection logic, or conditional flow
3. Iteration logic, or repetitive flow

1. Sequential Logic (Sequential Flow)


Sequential logic as the name suggests
follows a serial or sequential flow in which the flow
depends on the series of instructions given to the
computer. Unless new instructions are given, the
modules are executed in the obvious sequence.
The sequences may be given, by means of
numbered steps explicitly. Also, implicitly follows
the order in which modules are written. Most of
the processing, even some complex problems, will
generally follow this elementary flow pattern. Sequential Control flow

2. Selection Logic (Conditional Flow)


Selection Logic simply involves a number of conditions or parameters
which decides one out of several written modules. The structures which use
these type of logic are known as Conditional Structures.

These structures can be of three types:


• Single Alternative
This structure has the form:
If (condition) then:
[Module A]
[End of If structure]

• Double Alternative
This structure has the form:
If (Condition), then:
[Module A]
Else:
[Module B]
[End if structure]

https://jntuhbtechadda.blogspot.com/
• Multiple Alternatives
This structure has the form:
If (condition A), then:
[Module A]
Else if (condition B), then:
[Module B]
..
..
Else if (condition N), then:
[Module N]
[End If structure]
In this way, the flow of the program depends on the set of conditions
that are written. This can be more understood by the following flow charts:

Double Alternative Control Flow


3.Iteration Logic (Repetitive Flow)
The Iteration logic employs a loop which involves a repeat statement
followed by a module known as the body of a loop.

The two types of these structures are:


• Repeat-For Structure
This structure has the form:

Repeat for i = A to N by I:
[Module]
[End of loop]

https://jntuhbtechadda.blogspot.com/
Here, A is the initial value, N is the end value and I is the increment.
The loop ends when A>B. K increases or decreases according to the
positive and negative value of I respectively.

Repeat-For Flow
• Repeat-While Structure
It also uses a condition to control the loop. This structure has the form:
Repeat while condition:
[Module]
[End of Loop]

Repeat While Flow

https://jntuhbtechadda.blogspot.com/
In this, there requires a statement that initializes the condition
controlling the loop, and there must also be a statement inside the module
that will change this condition leading to the end of the loop.
Unconditional branching
Unconditional branching is when the programmer forces the execution of
a program to jump to another part of the program. Theoretically, this can be
done using a good combination of loops and if statements. In fact, as a
programmer, you should always try to avoid such unconditional branching and
use this technique only when it is very difficult to use a loop.

We can use “goto” statements (unconditional branch statements) to jump


to a label in a program.
The goto statement is used for unconditional branching or transfer of
the program execution to the labeled statement.

UNCONDITIONAL CONTROL STATEMENT:


▪ C supports an unconditional control statement that is goto.
▪ goto is used to transfer control from one point to other in a C program.
▪ goto is a branching statement.
▪ It requires a label.
▪ goto is a keyword.

A goto statement in C programming provides an unconditional jump from


the 'goto' to a labeled statement in the same function.

NOTE − Use of goto statement is highly discouraged in any programming


language because it makes difficult to trace the control flow of a program,
making the program hard to understand and hard to modify. Any program that
uses a goto can be rewritten to avoid them.

Syntax
The syntax for a goto statement in C is as follows −

goto label;
..
.
label: statement;
Here label can be any plain text except C keyword and it can be set anywhere
in the C program above or below to goto statement.

https://jntuhbtechadda.blogspot.com/
Flow Diagram

Example
#include <stdio.h>
int main () {
/* local variable definition */
int a = 10;
/* do loop execution */
LOOP:do {
if( a == 15) {
/* skip the iteration */
a = a + 1;
goto LOOP;
}
printf("value of a: %d\n", a);
a++;
}
while( a < 20 );
return 0;
}

https://jntuhbtechadda.blogspot.com/
When the above code is compiled and executed, it produces the following result−

value of a: 10
value of a: 11
value of a: 12
value of a: 13
value of a: 14
value of a: 16
value of a: 17
value of a: 18
value of a: 19

Guarded commands

The guarded command is the most important element of the guarded


command language. In a guarded command, just as the name says, the
command is "guarded". The guard is a proposition, which must be true before
the statement is executed. At the start of that statement's execution, one may
assume the guard to be true. Also, if the guard is false, the statement will not be
executed. The use of guarded commands makes it easier to prove
the program meets the specification. The statement is often another guarded
command.
Syntax
A guarded command is a statement of the form G → S, where
• G is a proposition, called the guard
• S is a statement
If G is true, the guarded command may be written simply S.
Semantics
At the moment G is encountered in a calculation, it is evaluated.
• If G is true, execute S
• If G is false, look at the context to decide what to do (in any case, do not
execute S)

https://jntuhbtechadda.blogspot.com/
UNIT-III
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

Subprograms
A Subprogram is a program inside any larger program that can be reused
any number of times.

Characteristics of a Subprogram:
• A Subprogram is implemented using the Call & Return instructions in
Assembly Language.

• The Call Instruction is present in the Main Program and the Return(Ret)
Instruction is present in the subprogram itself.

https://jntuhbtechadda.blogspot.com/
• It is important to note that the Main Program is suspended during the
execution of any subprogram. Moreover, after the completion of the
subprogram the main program executes from the next sequential address
present in the Program Counter.

• For the implementation of any subprogram, a “Stack” is used to store


the “Return Address” to the Main Program. Here, Return Address means
the immediately next instruction address after the Call Instruction in the
Main program. This Return Address is present inside the Program
Counter. Thus, during the execution of the Call Instruction, the Program
Counter value is first pushed to the Stack as the Return Address and then
the Program Counter value is updated to the given address in the Call
Instruction. Similarly, during the execution of Return (Ret) Instruction,
the value present in the stack is popped and the Program Counter value
is restored for further execution of the Main Program.

• The Main advantage of Subprogram is that it avoids repetition of Code and


allows us to reuse the same code again and again.

https://jntuhbtechadda.blogspot.com/
A subprogram is a sequence of instructions whose execution is invoked
from one or more remote locations in a program, with the expectation that when
the subprogram execution is complete, execution resumes at the instruction
after the one that invoked the subprogram. In high-level languages,
subprograms are also called subroutines, procedures, and functions. In object-
oriented languages, they are usually called methods or constructors. In most
modern high-level languages, subprograms can have parameters, local
variables, and returned values.

At the assembly language level, use of subprograms requires subprogram


linkage protocols. These protocols involve designating registers for special
purposes and the use of special instructions for subprogram calls and returns.

Basic Definitions
• A subprogram definition is a description of the actions of the subprogram
abstraction.
• A subprogram call is an explicit request that the called subprogram be
executed.

https://jntuhbtechadda.blogspot.com/
• A subprogram is said to be active if, after having been called, it has begun
execution but has not yet completed that execution.

The two fundamental types of the subprograms are:


o Procedures
o Functions

• A subprogram header is the first line of the definition, serves several


definitions:
o It specifies that the following syntactic unit is a subprogram
definition of some particular kind.
o The header provides a name for the subprogram.
o May optionally specify a list of parameters.
• Consider the following header examples:
o Fortran
Subroutine Adder(parameters)
o Ada
procedure Adder(parameters)
o C
void Adder(parameters)

• No special word appears in the header of a C subprogram to specify its


kind.
• The parameter profile (sometimes called the signature) of a subprogram is
the number, order, and types of its formal parameters.
• The protocol of a subprogram is its parameter profile plus, if it is a
function, its return type.
• A subprogram declaration provides the protocol, but not the body, of the
subprogram.
• A formal parameter is a dummy variable listed in the subprogram header
and used in the subprogram.
• An actual parameter represents a value or address used in the
subprogram call statement.
• Function declarations are common in C and C++ programs, where they
are called prototypes.
• Java and C# do not need declarations of their methods, because there is
no requirement that methods be defined before they are called in those
languages.

Parameters
• Subprograms typically describe computations. There are two ways that a
non-local method program can gain access to the data that it is to process:
1. Through direct access to non-local variables.

https://jntuhbtechadda.blogspot.com/
• The only way the computation can proceed on different data is to
assign new values to those non-local variables between calls to the
subprograms.
• Extensive access to non-locals can reduce reliability.
2. Through parameter passing “more flexible”.
• Data passed through parameters are accessed through names that are
local to the subprogram.
• A subprogram with parameter access to the data it is to process is a
parameterized computation.
• It can perform its computation on whatever data it receives through its
parameters.
• A formal parameter is a dummy variable listed in the subprogram header
and used in the subprogram.
• Subprograms call statements must include the name of the subprogram and
a list of parameters to be bound to the formal parameters of the subprogram.
• An actual parameter represents a value or address used in the subprogram
call statement.
• Actual/Formal Parameter Correspondence:
1. Positional: The first actual parameter is bound to the first formal
parameter and so forth. “Practical if list is short.”
2. Keyword: the name of the formal parameter is to be bound with the
actual parameter. “Can appear in any order in the actual parameter list.”
SORT(LIST => A, LENGTH => N);
• Advantage: order is irrelevant
• Disadvantage: user must know the formal parameter’s names.
• Default Values:
procedure SORT(LIST : LIST_TYPE;
LENGTH : INTEGER := 100);
...
SORT(LIST => A);

• In C++, which has no keyword parameters, the rules for default parameters
are necessarily different.
• The default parameters must appear last, for parameters are positionally
associated.
• Once a default parameter is omitted in a call, all remaining formal
parameters must have default values.
float compute_pay(float income, float tax_rate,
int exemptions = 1)

• An example call to the C++ compute_pay function is:


pay = compute_pay(20000.0, 0.15);

https://jntuhbtechadda.blogspot.com/
Procedures and Functions
• There are two distinct categories of subprograms, procedures and
functions.
• Procedures: provide user-defined parameterized computation statements.
• The computations are enacted by single call statements.
• Procedures can produce results in the calling program unit by two
methods:
o If there are variables that are not formal parameters but are still
visible in both the procedure and the calling program unit, the
procedure can change them.
o If the subprogram has formal parameters that allow the transfer of
data to the caller, those parameters can be changed.
• Functions: provide user-defined operators which are semantically
modelled on mathematical functions.
o If a function is a faithful model, it produces no side effects.
o It modifies neither its parameters nor any variables defined outside
the function.
• The methods of Java, C++, and C# are syntactically similar to the
functions of C.

Design Issues for Subprograms


The nature of the local environment of a subprogram dictates the nature
of the subprogram. Are local variables statically or dynamically allocated?

Can subprogram definitions be nested. Can subprogram names be passed


as parameters. If a language allows nested subprograms and the passing of
subprogram names, what is the referencing environment of the subprogram that
was passed?

Can subprograms be overloaded. An overloaded subprogram is one that


has the same name as another subprogram in the same referencing
environment.

A closure is a nested subprogram and its referencing environment, which


together allow the subprogram to be called from anywhere in a program.
• Are local variables static or dynamic?
• Can subprogram definitions appear in other subprogram definitions?
• What parameter passing methods are provided?
• Are parameter types checked?
• If subprograms can be passed as parameters and subprograms can be
nested, what is the referencing environment of a passed subprogram?
• Can subprograms be overloaded?
• Can subprogram be generic?
• If the language allows nested subprograms, are closures supported?

https://jntuhbtechadda.blogspot.com/
Local Referencing Environments
• Vars that are defined inside subprograms are called local vars.
• Local vars can be either static or stack dynamic “bound to storage when
the program begins execution and are unbound when execution
terminates.”
• Advantages of using stack dynamic:
a. Support for recursion.
b. Storage for locals is shared among some subprograms.
• Disadvantages:
a. Allocation/deallocation time.
b. Indirect addressing “only determined during execution.”
c. Subprograms cannot be history sensitive “can’t retain data values of
local vars between calls.”
• Advantages of using static vars:
a. Static local vars can be accessed faster because there is no indirection.
b. No run-time overhead for allocation and deallocation.
c. Allow subprograms to be history sensitive.
• Disadvantages:
a. Inability to support recursion.
b. Their storage can’t be shared with the local vars of other inactive
subprograms.
• In C functions, locals are stack-dynamic unless specifically declared to be
static.
• Ex:
int adder(int list[ ], int listlen)
{
static int sum = 0; //sum is static variable
int count; //count is stack-dynamic
for (count = 0; count < listlen; count++)
sum += list[count];
return sum;
}
• Ada subprograms and the methods of C++, Java, and C# have only stack
dynamic local variables.

Parameter Passing Methods


Semantic Models of Parameter Passing
• Formal parameters are characterized by one of three distinct semantic
models:
o in mode: They can receive data from corresponding actual
parameters.
o out mode: They can transmit data to the actual parameter.
o inout mode: They can do both.

https://jntuhbtechadda.blogspot.com/
• There are two conceptual models of how data transfers take places in
parameter transmission:
o Either an actual value is copied (to the caller, to the callee, or both
ways), or
o An access path is transmitted.
• Most commonly, the access path is a simple pointer or reference.
• Figure below illustrates the three semantics of parameter passing when
values are copied.

Implementation Models of Parameter Passing


1. Pass-by-Value
• When a parameter is passed by value, the value of the actual parameter
is used to initialize the corresponding formal parameter, which then acts
as a local var in the subprogram, thus implementing in-mode semantics.
• Disadvantages: Additional storage is required for the formal parameter,
either in the called subprogram or in some area outside both the caller
and the called subprogram.
The actual parameter must be copied to the storage area for the
corresponding formal parameter. “If the parameter is large such as an
array, it would be costly.

2. Pass-by-Result
• Pass-by-Result is an 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.

https://jntuhbtechadda.blogspot.com/
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.

3. Pass-by-Value-Result
• It is an implementation model for inout-mode parameters in which actual
values are copied.
• It is a combination of pass-by-value and pass-by-result.
• The value of the actual parameter is used to initialize the corresponding
formal parameter, which then acts as a local var.
At subprogram termination, the value of the formal parameter is
transmitted back to the actual parameter.
• It is sometimes called pass-by-copy because the actual parameter is
copied to the formal parameter at subprogram entry and then copied back
at subprogram termination.

4. 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, sometimes 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:
The passing process is efficient in terms of 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.
• Inadvertent and erroneous changes may be made to the actual parameter.
• Aliases can be created as in C++.
void fun(int &first, int &second)
If the call to fun happens to pass the same var twice, as in
fun(total, total)
Then first and second in fun will be aliases.

5. Pass-by-Name
• The method is an inout-mode parameter transmission that doesn’t
correspond to a single implementation model.
• When parameters are passed by name, the actual parameter is, in effect,
textually substituted for the corresponding formal parameter in all its
occurrences in the subprogram.

https://jntuhbtechadda.blogspot.com/
• A 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.
• Because pass-by-name is not used in any widely used language, it is not
discussed further here.

Parameter-Passing Methods of Major Languages


• Fortran
o Always used the inout semantics model
o Before Fortran 77: pass-by-reference
o Fortran 77 and later: scalar variables are often passed by value-
result
• C
o Pass-by-value
o Pass-by-reference is achieved by using pointers as parameters
• C++
o A special pointer type called reference type for pass-by-reference
void fun(const int &p1, int p2, int &p3) { … }
• Java
o All parameters are passed are passed by value
o Object parameters are passed by reference
Although an object reference passed as a parameter cannot
itself be changed in the called subprogram, the referenced object
can be changed if a method is available to cause the change.
• Ada
o Three semantics modes of parameter transmission: in, out, in out;
in is the default mode
o Formal parameters declared out can be assigned but not referenced;
those declared in can be referenced but not assigned; in out
parameters can be referenced and assigned
• C#
o Default method: pass-by-value
o Pass-by-reference is specified by preceding both a formal parameter
and its actual parameter with ref
• PHP:
o very similar to C#
• Perl:
o all actual parameters are implicitly placed in a predefined array
named @_

https://jntuhbtechadda.blogspot.com/
Type-Checking Parameters
• It is now widely accepted that software reliability demands that the types
of actual parameters be checked for consistency with the types of the
corresponding formal parameters.
• Ex:
result = sub1(1)
• The actual parameter is an integer constant. If the formal parameter of
sub1 is a floating-point type, no error will be detected without parameter
type checking.
• Early languages, such as Fortran 77 and the original version of C, did not
require parameter type checking.
• Pascal, FORTRAN 90, Java, and Ada: it is always required
• Perl, PHP, and JavaScript do not have type checking.

Implementing Parameter-Passing Methods


• In most contemporary languages, parameter communication takes place
through the run-time stack.
• The run-time stack is initialized and maintained by the run-time system,
which is a system program that manages the execution of programs.
• The run-time stack is used extensively for subprogram control linkage and
parameter passing.
• Pass-by-value parameters have their values copied into stack locations.
• The stack location then serves as storage for the corresponding formal
parameters.
• Pass-by-result parameters are implemented as the opposite of pass-by-
value.
• The values assigned to the pass-by-result actual parameters are placed in
the stack, where they can be retrieved by the calling program unit upon
termination of the called subprogram.
• Pass-by-value-result parameters can be implemented directly from their
semantics as a combination pf pass-by-value and pass-by-result.
• The stack location for the parameters is initialized by the call and it then
used like a local var in the called subprogram.
• Pass-by-reference parameters are the simplest to implement.
• Only its address must be placed in the stack.
• Access to the formal parameters in the called subprogram is by indirect
addressing from the stack location of the address.

https://jntuhbtechadda.blogspot.com/
• Figure below illustrates the previous parameters’ passing methods.

• The subprogram sub is called from main with the call sub(w, x ,y, z), where
w is passed by value, x is passed by result, y is passed by value-result,
and z is passed by reference.
• A subtle but fatal error can occur with pass-by-reference and pass-by-
value-result parameters if care is not take in their implementation.
• Suppose a program contains two references to the constant 10, the first
as an actual parameter in a call to a subprogram.
• Further suppose that the subprogram mistakenly changes the formal
parameter that corresponds to the 10 to the value 5.
• The compiler may have built a single location for the value 10 during
compilation, as compilers often do, and use that location for all references
to the constant 10 in the program.
• But after the return from the subprogram, all subsequent occurrences of
10 will actually be references to the value 5.
• If this is allowed to happen, it creates a programming problem that is very
difficult to diagnose.
• This happened in many implementations of Fortran IV.

Parameters that are Subprogram Names


• In languages that allow nested subprograms, such as JavaScript, there is
another issue related to subprogram names that are passed as
parameters.

https://jntuhbtechadda.blogspot.com/
• The question is what referencing environment for executing the passed
subprogram should be used.
• The three choices are:
1. It is the environment of the call statement that enacts the passed
subprogram “Shallow binding.”
2. It is the environment of the definition of the passed subprogram “Deep
binding.”
3. It is the environment of the call statement that passed the subprogram
as an actual parameter ”Ad hoc binding; has never been used”
• Ex: “written in the syntax of Java”
function sub1( )
{
var x;
function sub2( )
{
alert(x); // Creates a dialog box with the value of x
};
function sub3( )
{
var x;
x = 3;
sub4(sub2);
};
function sub4(subx )
{
var x;
x = 4;
subx( );
};
x = 1;
sub3( );
};
• Consider the execution of sub2 when it is called in sub4.
• Shallow Binding: the referencing environment of that execution is that of
sub4, so the reference to x in sub2 is bound to the local x in sub4, and
the output of the program is 4.
• Deep Binding: the referencing environment of sub2’s execution is that of
sub1, so the reference so the reference to x in sub2 is bound to the local
x in sub1 and the output is 1.
• Ad hoc: the binding is to the local x in sub3, and the output is 3.
• Shallow binding is not appropriate for static-scoped languages with nested
subprograms.

https://jntuhbtechadda.blogspot.com/
Overloaded Subprograms
• An overloaded operator is one that has multiple meanings. The types of its
operands determine the meaning of a particular instance of an overloaded
operator.
• For example, if the * operator has two floating-point operands in a Java
program, it specifies floating-point multiplication.
• But if the same operator has two integer operands, it specifies integer
multiplication.
• An overloaded subprogram is a subprogram that has the same name as
another subprogram in the same referencing environment.
• Every version of an overloaded subprogram must have a unique protocol;
that is, it must be different from the others in the number, order, or types
of its parameters, or in its return if it is a function.
• The meaning of a call to an overloaded subprogram is determined by the
actual parameter list.
• Users are also allowed to write multiple versions of subprograms with the
same name in Ada, Java, C++, and C#.
• Overloaded subprograms that have default parameters can lead to
ambiguous subprogram calls.
void fun(float b = 0.0);
void fun( );

fun( ); // The call is ambiguous and will cause a compilation error.

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.
• 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.

Generic Functions in C++


• Generic functions in C++ have the descriptive name of template functions.
• The following is the C++ version of the generic sort subprogram.
template <class Type>
void generic_sort (Type list [ ], int len)
{
int top, bottom;
Type temp;

https://jntuhbtechadda.blogspot.com/
for (top = 0, top < len –2; top ++)
for (bottom = top + 1; bottom < len – 1; bottom++)
if (list [top] > list [bottom])
{
temp = list [top];
list[top] = list[bottom];
}
} // end for bottom
} // end for generic
}
• The instantiation of this template function is:
float flt_list [100];

generic_sort (flt_list, 100);

Design Issues for Functions


• Are side effects allowed?
• What types of values can be returned?

Functional Side Effects


• Because of the problems of side effects of functions that are called in
expressions, parameters to functions should always be in-mode
parameters.
• Ada functions can have only in-mode formal parameters.
• This effectively prevents a function from causing side effects through its
parameters or through aliasing of parameters and globals.
• In most languages, however, functions can have either pass-by-value or
pass-by-reference parameters, thus allowing functions that cause side
effects and aliasing.

Types of Returned Values


• C allows any type to be returned by its functions except arrays and
functions.
• C++ is like C but also allows user-defined types, or classes, to be returned
from its functions.
• JavaScript functions can be passed as parameters and returned from
functions.

User-Defined Overloaded Operators


• Nearly all programming languages have overloaded operators.
• Users can further overload operators in C++ and Ada (Not carried over into
Java)
• How much operator overloading is good, or can you have too much?
Function “*”(A,B: in Vec_Type): return Integer is

https://jntuhbtechadda.blogspot.com/
Sum: Integer := 0;
begin
for Index in A’range loop
Sum := Sum + A(Index) * B(Index)
end loop
return sum;
end “*”;

c = a * b; -- a, b, and c are of type Vec_Type

Coroutines
• A coroutine is a subprogram that has multiple entries and controls them
itself.
• It is also called symmetric control.
• It also has the means to maintain their status between activation.
• This means that coroutines must be history sensitive and thus have static
local vars.
• Secondary executions of a coroutine often begin at points other than its
beginning.
• 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.

https://jntuhbtechadda.blogspot.com/
Implementing subprograms

The General Semantics of Calls and Returns


The subprogram call and return operations of a language are together
called subprogram "linkage".

General semantics of calls to a subprogram responsible for


• Parameter passing methods for in and inout arguments.
• Stack vs dynamic allocation of local variables.
• Saving the execution status of calling program.
• Transfer of control and set up for the return back to the call point.
• If subprogram nesting is supported (Pascal, Ada), access to nonlocal
variables must be arranged.

General semantics of subprogram returns responsible for


• Out mode and inout mode parameters must have their values returned.
• Deallocation of stack or dynamic locals (clean up stack or garbage
collection).
• Restore the execution status as prior to the call.
• Return control to the caller.

Implementing “Simple” Subprograms


• Call Semantics:
- Save the execution status of the caller
- Pass the parameters
- Pass the return address to the callee
- Transfer control to the callee

https://jntuhbtechadda.blogspot.com/
• Return Semantics:
- If pass-by-value-result or out mode parameters are used, move the
current values of those parameters to their corresponding actual
parameters (arguments).
- If it is a function, move the functional value to a place the caller can
get it.
- Restore the execution status of the caller.
- Transfer control back to the caller.
• Required storage:
- Status information, parameters, return address, return value for
functions.
• Two separate parts:
- the actual code (that cannot change).
- and the non-code part (local variables and data that can change).
• The format, or layout, of the non-code part of an executing subprogram is
called an activation Record.
• An activation record instance is a concrete example of an activation record
(the collection of data for a particular subprogram activation).

https://jntuhbtechadda.blogspot.com/
Implementing Subprograms with Stack-Dynamic Local Variables
• 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).

https://jntuhbtechadda.blogspot.com/
More Complex Activation Records

• The activation record format is static, but its size may be dynamic.
• The dynamic link points to the top of an instance of the activation record
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.
• An Example: C Function
void sub(float total, int part)
{
int list[5];
float sum;
...
}

https://jntuhbtechadda.blogspot.com/
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 arguments.
4. Record the return address for the callee.
5. Transfer control to the callee.

The prologue actions of the callee 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 callee 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
arguments.
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 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
• Some non-C-based static-scoped languages (e.g., Fortran 95, Ada,
Python, JavaScript, Ruby, and Lua) use stack-dynamic local variables
and allow subprograms to be nested.
• All variables that can be non-locally accessed reside in some activation
record instance in the stack.
• The process of locating a non-local reference:
1. Find the correct activation record instance
2. Determine the correct offset within that activation record instance
• Locating a Non-local Reference
– Finding the offset is easy
– Finding the correct activation record instance
• Static semantic rules guarantee that all non-local variables that can be
referenced have been allocated in some activation record instance that is
on the stack when the reference is made.
• Static Scoping
– A static chain is a chain of static links that connects certain activation
record instances.
– The static link in an activation record instance for subprogram A points
to one of the activation record instances of A's static parent.

https://jntuhbtechadda.blogspot.com/
– The static chain from an activation record instance connects it to all of
its static ancestors.
– Static_depth is an integer associated with a static scope whose value is
the depth of nesting of that scope.
– The chain_offset or nesting_depth of a nonlocal reference is the difference
between the static_depth of the reference and that of the scope when it is
declared.
– A reference to a variable can be represented by the pair:
(chain_offset, local_offset),
where local_offset is the offset in the activation record of the
variable being referenced.

Static Chain Maintenance


• At the call,
- The activation record instance must be built.
- The dynamic link is just the old stack top pointer.
- The static link must point to the most recent ARI of the static parent.
- Two methods:
1. Search the dynamic chain.
2. Treat subprogram calls and definitions like variable references
and definitions.

• Evaluation of Static Chains


- Problems:
1. A nonlocal reference is slow if the nesting depth is large.
2. Time-critical code is difficult:
a. Costs of nonlocal references are difficult to determine.
b. Code changes can change the nesting depth, and therefore the
cost.

• Displays
- An alternative to static chains that solves the problems with that
approach.
- Static links are stored in a single array called a display.
- The contents of the display at any given time is a list of addresses
of the accessible activation record instances.

Blocks
• Blocks are user-specified local scopes for variables
• An example in C
{
int temp;
temp = list [upper];
list [upper] = list [lower];
list [lower] = temp;

https://jntuhbtechadda.blogspot.com/
}
• 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.
• Implementing Blocks
- Two Methods:
1. Treat blocks as parameter-less subprograms that are always
called from the same location.
- Every block has an activation record; an instance is created
every time the block is executed.
2. Since the maximum storage required for a block can be statically
determined, this amount of space can be allocated after the local
variables in the activation record.

Implementing dynamic scoping


Dynamic scoping is a programming language paradigm that you don’t
typically see. The scoping that most programmers are used to is called lexical
scoping. It’s found in Lua and many other languages. Lexical scoping is the
dominant choice for a reason: it’s easy to reason about and understand just by
looking at the code. We can see what variables are in scope just by looking at
the structure of the text in our editor. Scoping controls how a variable’s value is
resolved.

Dynamic scoping does not care how the code is written, but instead how
it executes. Each time a new function is executed, a new scope is pushed onto
the stack. This scope is typically stored with the function’s call stack. When a
variable is referenced in the function, the scope in each call stack is checked to
see if it provides the value

We can implement dynamic scoping fairly easily in Lua through the debug
library. We'll mimic the example above with a function called dynamic that takes
the name of a variable, as a string, to look up dynamically.

In implementing setfenv we could use debug.getupvalue to implement


setfenv. For dynamic scoping we'll rely on the debug.getlocal function.

The signature of getlocal is debug.getlocal ([thread,] level, local). In this


example we're not concerned with the thread so we'll focus on level and local.
• level is an integer that represents how many levels up the call stack we
want to look for the variable we're searching for.
• local is the index of that local variable we want to resolve, starting at 1.

https://jntuhbtechadda.blogspot.com/
The return value of this function is either nil if nothing was found, or the
name and value of the variable.

To find a local variable in an higher up scope, we just need to keep


incrementing level and querying each local variable by its numeric index until
we find the matching name.

Abstract Data types

What Abstraction Means


Abstract data types are an instance of a general principle in software
engineering, which goes by many names with slightly different shades of
meaning. Here are some of the names that are used for this idea:

• Abstraction. Omitting or hiding low-level details with a simpler, higher-


level idea.
• Modularity. Dividing a system into components or modules, each of
which can be designed, implemented, tested, reasoned about, and reused
separately from the rest of the system.
• Encapsulation. Building walls around a module (a hard shell or capsule)
so that the module is responsible for its own internal behaviour, and bugs
in other parts of the system can’t damage its integrity.
• Information hiding. Hiding details of a module’s implementation from the
rest of the system, so that those details can be changed later without
changing the rest of the system.
• Separation of concerns. Making a feature (or “concern”) the
responsibility of a single module, rather than spreading it across multiple
modules.

As a software engineer, you should know these terms, because you will
run into them frequently. The fundamental purpose of all of these ideas is to
help achieve the three important properties that we care about in 6.005: safety
from bugs, ease of understanding, and readiness for change.

Abstract Data Type Examples


Here are some examples of abstract data types, along with some of their
operations, grouped by kind.
int is Java’s primitive integer type. int is immutable, so it has no mutators.
• creators: the numeric literals 0, 1, 2, …
• producers: arithmetic operators +, -, ×, ÷
• observers: comparison operators ==, !=, <, >

https://jntuhbtechadda.blogspot.com/
• mutators: none (it’s immutable)

List is Java’s list interface. List is mutable. List is also an interface, which means
that other classes provide the actual implementation of the data type. These
classes include ArrayList and LinkedList.
• creators: ArrayList and LinkedList constructors, Collections.singletonList
• producers: Collections.unmodifiableList
• observers: size, get
• mutators: add, remove, addAll, Collections.sort

String is Java’s string type. String is immutable.


• creators: String constructors
• producers: concat, substring, toUpperCase
• observers: length, charAt
• mutators: none (it’s immutable)

This classification gives some useful terminology, but it’s not perfect. In
complicated data types, there may be an operation that is both a producer and
a mutator, for example. Some people reserve the term producer only for
operations that do no mutation.

Designing an Abstract Type


Designing an abstract type involves choosing good operations and
determining how they should behave. Here are a few rules of thumb.
It’s better to have a few, simple operations that can be combined in
powerful ways, rather than lots of complex operations.
Each operation should have a well-defined purpose, and should have
a coherent behaviour rather than a panoply of special cases. We probably
shouldn’t add a sum operation to List, for example. It might help clients who
work with lists of Integers, but what about lists of Strings? Or nested lists? All
these special cases would make sum a hard operation to understand and use.
The set of operations should be adequate in the sense that there must be
enough to do the kinds of computations clients are likely to want to do. A good
test is to check that every property of an object of the type can be extracted. For
example, if there were no get operation, we would not be able to find out what
the elements of a list are. Basic information should not be inordinately difficult
to obtain. For example, the size method is not strictly necessary for List, because
we could apply get on increasing indices until we get a failure, but this is
inefficient and inconvenient.
The type may be generic: a list or a set, or a graph, for example. Or it may
be domain-specific: a street map, an employee database, a phone book, etc.

https://jntuhbtechadda.blogspot.com/
But it should not mix generic and domain-specific features. A Deck type
intended to represent a sequence of playing cards shouldn’t have a generic add
method that accepts arbitrary objects like ints or Strings. Conversely, it wouldn’t
make sense to put a domain-specific method like dealCards into the generic type
List.

Design Issues

• What is the form of the container for the interface to the type?
• Can abstract types be parameterized?
• What access controls are provided?

Language Examples

1. Abstract Data Types in Ada

• The encapsulation construct is called a package


o Specification package (the interface)
o Body package (implementation of the entities named in the
specification)
• Information Hiding
o The specification package has two parts, public and private
o The name of the abstract type appears in the public part of the
specification package. This part may also include representations of
unhidden types
o The representation of the abstract type appears in a part of the
specification called the private part
• More restricted form with limited private types
• Private types have built-in operations for assignment and comparison
• Limited private types have NO built-in operations
• Reasons for the public/private spec package:
o The compiler must be able to see the representation after seeing only
the spec package (it cannot see the private part)
o Clients must see the type name, but not the representation (they
also cannot see the private part)

• Having part of the implementation details (the representation) in the spec


package and part (the method bodies) in the body package is not good
• One solution: make all ADTs pointers
• Problems with this:
o Difficulties with pointers
o Object comparisons
o Control of object allocation is lost

https://jntuhbtechadda.blogspot.com/
2. Abstract Data Types in C++

• Based on C struct type and Simula 67 classes


• The class is the encapsulation device
• All of the class instances of a class share a single copy of the member
functions
• Each instance of a class has its own copy of the class data members
• Instances can be static, stack dynamic, or heap dynamic
• Information Hiding
o Private clause for hidden entities
o Public clause for interface entities
o Protected clause for inheritance

• Constructors:
o Functions to initialize the data members of instances (they do not
create the objects)
o May also allocate storage if part of the object is heap-dynamic
o Can include parameters to provide parameterization of the objects
o Implicitly called when an instance is created
o Can be explicitly called
o Name is the same as the class name
• Destructors
o Functions to cleanup after an instance is destroyed; usually just to
reclaim heap storage
o Implicitly called when the object’s lifetime ends
o Can be explicitly called
o Name is the class name, preceded by a tilde (~)

3. Abstract Data Types in Java

• Similar to C++, except:


o All user-defined types are classes
o All objects are allocated from the heap and accessed through
reference variables
o Individual entities in classes have access control modifiers (private
or public), rather than clauses
o Java has a second scoping mechanism, package scope, which can
be used in place of friends
• All entities in all classes in a package that do not have access control
modifiers are visible throughout the package

https://jntuhbtechadda.blogspot.com/
4. Abstract Data Types in C#

• Based on C++ and Java


• Adds two access modifiers, internal and protected internal
• All class instances are heap dynamic
• Default constructors are available for all classes
• Garbage collection is used for most heap objects, so destructors are rarely
used
• structs are lightweight classes that do not support inheritance
• Common solution to need for access to data members: accessor methods
(getter and setter)
• C# provides properties as a way of implementing getters and setters
without requiring explicit method calls

5. Abstract Data Types in Ruby

• Encapsulation construct is the class


• Local variables have “normal” names
• Instance variable names begin with “at” signs (@)
• Class variable names begin with two “at” signs (@@)
• Instance methods have the syntax of Ruby functions (def … end)
• Constructors are named initialize (only one per class)—implicitly called
when new is called
o If more constructors are needed, they must have different names
and they must explicitly call new

• Class members can be marked private or public, with public being the
default
• Classes are dynamic

Parameterized Abstract Data Types

• Parameterized ADTs allow designing an ADT that can store any type
elements (among other things) – only an issue for static typed languages
• Also known as generic classes
• C++, Ada, Java 5.0, and C# 2005 provide support for parameterized ADTs

1. Ada

• Ada Generic Packages

https://jntuhbtechadda.blogspot.com/
o 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);

2. 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;
};

}
Stack stk(100);

3. Java 5.0

• Generic parameters must be classes


• Most common generic types are the collection types, such as LinkedList
and ArrayList
• Eliminate the need to cast objects that are removed
• Eliminate the problem of having multiple types in a structure
• Parameterized Classes in Java 5.0
o Prior to Java 5.0

ArrayList myArray=new ArrayList();


myArray.add(0,new Integer(47));

https://jntuhbtechadda.blogspot.com/
Integer myInt=(Integer)myArray.get(0);
– Java 5.0
ArrayList <Integer> myArray =new ArrayList <Integer>();

4. C# 2005

• Similar to those of Java 5.0


• Elements of parameterized structures can be accessed through indexing

Encapsulation Constructs

1. Introduction

• Large programs have two special needs:


o Some means of organization, other than simply division into
subprograms
o 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 (compilation units)
• Such collections are called encapsulation

2. Nested Subprograms

• Organizing programs by nesting subprogram definitions inside the


logically larger subprograms that use them
• Nested subprograms are supported in Ada, Fortran 95, Python, and Ruby

3. Encapsulation in C

• Files containing one or more subprograms can be independently compiled


• The interface is placed in a header file
• Problem: the linker does not check types between a header and associated
implementation
• #include preprocessor specification – used to include header files in
applications

4. Encapsulation in C++

• Can define header and code files, similar to those of C


• Or, classes can be used for encapsulation
o The class is used as the interface (prototypes)

https://jntuhbtechadda.blogspot.com/
o The member definitions are defined in a separate file
• Friends provide a way to grant access to private members of a class

5. Ada Packages

• Ada specification packages can include any number of data and


subprogram declarations
• Ada packages can be compiled separately
• A package’s specification and body parts can be compiled separately

Naming Encapsulations

• Large programs define many global names need a way to divide into logical
groupings
• A naming encapsulation is used to create a new scope for names

1. C++ Namespaces

• Can place each library in its own namespace and qualify names used
outside with the namespace
• C# also includes namespaces

2. Java Packages

• Packages can contain more than one class definition; classes in a package
are partial friends
• Clients of a package can use fully qualified name or use the import
declaration

3. Ada Packages

• Packages are defined in hierarchies which correspond to file hierarchies


• Visibility from a program unit is gained with the with clause

4. Ruby Modules

• Ruby classes are name encapsulations, but Ruby also has modules
• Typically encapsulate collections of constants and methods
• Modules cannot be instantiated or subclassed, and they cannot define
variables
• Methods defined in a module must include the module’s name
• Access to the contents of a module is requested with the require method

https://jntuhbtechadda.blogspot.com/
UNIT-IV Concurrency: introduction, introduction to subprogram level
concurrency, semaphores, monitors, message passing, Ada support for
concurrency, Java threads, concurrency in functional languages, statement level
concurrency. Exception Handling and Event Handling: Introduction, exception
handling in Ada, C++, Java, introduction to event handling, event handling with
Java and C#.

Languages that support object-oriented programming now are firmly entrenched in


the mainstream. From COBOL to LISP, including virtually every language in
between, dialects that support object-oriented programming have appeared. C++,
Objective-C, and Ada 95 support procedural and data-oriented programming, in
addition to object-oriented programming.
Smalltalk was the first language to offer complete support for object- oriented
programming.
The concept of object-oriented programming had its roots in SIMULA 67 but was not
fully developed until the evolution of Smalltalk resulted in Smalltalk 80.
A language that is object oriented must provide support for three key language
features: abstract data types, inheritance, and dynamic binding of method calls to
methods.
An abstraction is a view or representation of an entity that includes only the most
significant attributes.
The two fundamental kinds of abstraction in contemporary programming languages
are process abstraction and data abstraction.

Concurrency:

Concurrency in software execution can occur at four different levels: instruction level
(executing two or more machine instructions simultaneously), statement level
(executing two or more high-level language statements simultaneously), unit level
(executing two or more subprogram units simultaneously), and program level
(executing two or more programs simultaneously).

Concurrent control mechanisms increase programming flexibility. One of the most


commonly used programs is now Web browsers, whose design is based heavily on
concurrency. Browsers must perform many different functions at the same time,
among them sending and receiving data from Web servers, rendering text and images
on the screen, and reacting to user actions with the mouse and the keyboard.

Statement-level concurrency is quite different from concurrency at the unit level.

Multiprocessor Architectures:

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


1
https://jntuhbtechadda.blogspot.com/
A large number of different computer architectures have more than one processor and
can support some form of concurrent execution.


Late 1950s - one general-purpose processor and one or more special-purpose
processors for input and output operations
• Early 1960s - multiple complete processors, used for program-level
concurrency
• Mid-1960s - multiple partial processors, used for instruction-level concurrency
• Single-Instruction Multiple-Data (SIMD) machines
• Multiple-Instruction Multiple-Data (MIMD) machines
– Independent processors that can be synchronized (unit-level
concurrency)
Categories of Concurrency:

There are two distinct categories of concurrent unit control. The most natural category
of concurrency is that in which, assuming that more than one processor is available,
several program units from the same program literally execute simultaneously. This is
physical concurrency. A slight relaxation of this concept of concurrency allows the
programmer and the application software to assume that there are multiple processors
providing actual concurrency, when in fact the actual execution of programs is taking
place in interleaved fashion on a single processor. This is logical concurrency.

One useful technique for visualizing the flow of execution through a program is to
imagine a thread laid on the statements of the source text of the program.
Every statement reached on a particular execution is covered by the thread
representing that execution.
Formally, a thread of control in a program is the sequence of program points reached
as control flows through the program.
Programs that have coroutines but no concurrent subprograms, though they are
sometimes called quasi-concurrent, have a single thread of control. Programs
executed with physical concurrency can have multiple threads of control.
program designed to have more than one thread of control is said to be multithreaded.

Motivations for the Use of Concurrency


There are at least four different reasons to design concurrent software systems.

• Speed of execution of programs on machines with multiple processors.


• When a machine has just one processor, a program written to use concurrent
execution can be faster than the same program written for sequential (non-
concurrent) execution.
• Concurrency provides a different method of conceptualizing program
solutions to problems.
• Concurrency is to program applications that are distributed over several
machines, either locally or through the Internet.

Introduction to Subprogram-Level Concurrency

Task is a unit of a program, similar to a subprogram, that can be in concurrent


execution with other units of the same program. Each task in a program can support

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


2
https://jntuhbtechadda.blogspot.com/
one thread of control. Tasks are sometimes called processes. In some languages, for
example Java and C#, certain methods serve as tasks. Such methods are executed in
objects called threads.
Tasks fall into two general categories: heavyweight and lightweight. Simply stated,
a heavyweight task executes in its own address space. Lightweight tasks all run in the
same address space.
A task can communicate with other tasks through shared nonlocal variables, through
message passing, or through parameters. If a task does not communicate with or affect
the execution of any other task in the program in any way, it is said to be disjoint.

Synchronization is a mechanism that controls the order in which tasks execute. Two
kinds of synchronization are required when tasks share data: cooperation and
competition. Cooperation synchronization is required between task A and task B
when task A must wait for task B to complete some specific activity before task A can
begin or continue its execution. Competition synchronization is required between two
tasks when both require the use of some resource that cannot be simultaneously used..
A simple form of cooperation synchronization can be illustrated by a common
problem called the producer-consumer problem.

• Cooperation: 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
• Competition: Two or more tasks must use some resource that cannot be
simultaneously used, e.g., a shared counter
– Competition is usually provided by mutually exclusive access

Scheduler


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
Task Execution States

• New - created but not yet started


Ready - ready to run but not currently running (no available processor)
• Running
• Blocked - has been running, but cannot now continue (usually waiting for
some event to occur)
• Dead - no longer active in any sense

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


3
https://jntuhbtechadda.blogspot.com/
Liveness and Deadlock
• 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


• Competition and cooperation synchronization
• Controlling task scheduling
• How and when tasks start and end execution
• How and when are tasks created

Methods of Providing Synchronization


• Semaphores
• Monitors
• Message Passing

Semaphores

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


4
https://jntuhbtechadda.blogspot.com/
A semaphore is a simple mechanism that can be used to provide synchronization of
tasks. Although semaphores are an early approach to providing synchronization, they
are still used, both in contemporary languages and in library-based concurrency
support systems.

In an effort to provide competition synchronization through mutually exclusive access


to shared data structures, Edsger Dijkstra devised semaphores in 1965 (Dijkstra,
1968b). Semaphores can also be used to provide cooperation synchronization.

A semaphore is an implementation of a guard. Specifically, a semaphore is a data


structure that consists of an integer and a queue that stores task descriptors. A task
descriptor is a data structure that stores all of the relevant information about the
execution state of a task.

• A semaphore is a data structure consisting of a counter and a queue for storing


task descriptors
• Semaphores can be used to implement guards on the code that accesses shared
data structures
• Semaphores have only two operations, wait and release (originally called P
and V by Dijkstra)
• Semaphores can be used to provide both competition and cooperation
synchronization

Cooperation Synchronization

• Example: A shared buffer


• The buffer is implemented as an ADT with the operations DEPOSIT and
FETCH as the only ways to access the buffer
• Use two semaphores for cooperation: empty spots and full spots
• The semaphore counters are used to store the numbers of empty spots and full
spots in the buffer
• DEPOSIT must first check emptyspots to see if there is room in the buffer
• If there is room, the counter of emptyspots is decremented and the value is
inserted
• If there is no room, the caller is stored in the queue of emptyspots
• When DEPOSIT is finished, it must increment the counter of fullspots
• FETCH must first check fullspots to see if there is a value
• If there is a full spot, the counter of fullspots is decremented and the
value is removed
• If there are no values in the buffer, the caller must be placed in the
queue of fullspots
• When FETCH is finished, it increments the counter of emptyspots
• The operations of FETCH and DEPOSIT on the semaphores are accomplished
through two semaphore operations named wait and release

Competition Synchronization

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


5
https://jntuhbtechadda.blogspot.com/
One of the most important features of monitors is that shared data is resident in the
monitor rather than in any of the client units. The programmer does not synchronize
mutually exclusive access to shared data through the use of semaphores or other
mechanisms.
• Shared data is resident in the monitor (rather than in the client units)
• All access resident in the monitor
– Monitor implementation guarantee synchronized access by allowing
only one access at a time
– Calls to monitor procedures are implicitly queued if the monitor is
busy at the time of the call

Monitors
One solution to some of the problems of semaphores in a concurrent environment is to
encapsulate shared data structures with their operations and hide their
representations—that is, to make shared data structures abstract data types with some
special restrictions.

Cooperation Synchronization
Mutually exclusive access to shared data is intrinsic with a monitor, cooperation
between processes is still the task of the programmer.
Different languages provide different ways of programming cooperation
synchronization, all of which are related to semaphores.

• Cooperation between processes is still a programming task


– Programmer must guarantee that a shared buffer does not experience
underflow or overflow

EVALUATION OF MONITORS:

• A better way to provide competition synchronization than are semaphores

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


6
https://jntuhbtechadda.blogspot.com/
• Semaphores can be used to implement monitors
• Monitors can be used to implement semaphores
• Support for cooperation synchronization is very similar as with semaphores,
so it has the same problems

MESSAGE PASSING

• Message passing is a general model for concurrency


– It can model both semaphores and monitors
– It is not just for competition synchronization
• Central idea: task communication is like seeing a doctor--most of the time she
waits for you or you wait for her, but when you are both ready, you get
together, or rendezvous

Message Passing Rendezvous


• To support concurrent tasks with message passing, a language needs:

- A mechanism to allow a task to indicate when it is willing to accept messages

- A way to remember who is waiting to have its message accepted and some “fair”
way of choosing the next message
• When a sender task’s message is accepted by a receiver task, the actual
message transmission is called a rendezvous

Ada Support for Concurrency


Ada tasks can be more active than monitors. Monitors are passive entities that provide
management services for the shared data they store. They provide their services,
though only when those services are requested. When used to manage shared data,
Ada tasks can be thought of as managers that can reside with the resource they
manage. They have several mechanisms, some deterministic and some
nondeterministic, that allow them to choose among competing requests for access to
their resources.

• The Ada 83 Message-Passing Model


– Ada tasks have specification and body parts, like packages; the spec
has the interface, which is the collection of entry points:

task Task_Example is
entry ENTRY_1 (Item : in Integer);
end Task_Example;

Task Body

• The body task describes the action that takes place when a rendezvous occurs
• A task that sends a message is suspended while waiting for the message to be
accepted and during the rendezvous
• Entry points in the spec are described with accept clauses in the body

accept entry_name (formal parameters) do

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


7
https://jntuhbtechadda.blogspot.com/

end entry_name

Example:

task body Task_Example is


begin
loop
accept Entry_1 (Item: in Float) do
...
end Entry_1;
end loop;
end Task_Example;

Multiple Entry Points

• Tasks can have more than one entry point


– The specification task has an entry clause for each
– The task body has an accept clause for each entry clause, placed in a
select clause, which is in a loop

A Task With Multiple Entries


task body Teller is
loop
select
accept Drive_Up(formal params) do
...
end Drive_Up;
...
or
accept Walk_Up(formal params) do
...
end Walk_Up;
...
end select;
end loop;
end Teller;

Semantics of Tasks with Multiple accept Clauses

• If exactly one entry queue is nonempty, choose a message from it

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


8
https://jntuhbtechadda.blogspot.com/
• If more than one entry queue is nonempty, choose one, non-deterministically,
from which to accept a message
• If all are empty, wait
• The construct is often called a selective wait
• Extended accept clause - code following the clause, but before the next clause
– Executed concurrently with the caller

Cooperation Synchronization with Message Passing

• Provided by Guarded accept clauses


when not Full(Buffer) =>
accept Deposit (New_Value) do
...
end
• An accept clause with a with a when clause is either open or closed
– A clause whose guard is true is called open
– A clause whose guard is false is called closed
– A clause without a guard is always open

Semantics of select with Guarded accept Clauses:

• select first checks the guards on all clauses


• If exactly one is open, its queue is checked for messages
• If more than one are open, non-deterministically choose a queue among them
to check for messages
• If all are closed, it is a runtime error
• A select clause can include an else clause to avoid the error
– When the else clause completes, the loop repeats

Competition Synchronization with Message Passing


• Modeling mutually exclusive access to shared data
• Example--a shared buffer
• Encapsulate the buffer and its operations in a task
• Competition synchronization is implicit in the semantics of accept clauses
– Only one accept clause in a task can be active at any given time
Task Termination

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


9
https://jntuhbtechadda.blogspot.com/
• The execution of a task is completed if control has reached the end of its code
body
• If a task has created no dependent tasks and is completed, it is terminated
• If a task has created dependent tasks and is completed, it is not terminated
until all its dependent tasks are terminated
• A terminate clause in a select is just a terminate statement
• A terminate clause is selected when no accept clause is open
• When a terminate is selected in a task, the task is terminated only when its
master and all of the dependents of its master are either completed or are
waiting at a terminate

Concurrency in Ada 95

• A block or subprogram is not left until all of its dependent tasks are terminated
• Ada 95 includes Ada 83 features for concurrency, plus two new features
• Protected objects: A more efficient way of implementing shared data to
allow access to a shared data structure to be done without rendezvous
• Asynchronous communication

Ada 95: Protected Objects


A protected object is similar to an abstract data type

Access to a protected object is either through messages passed to entries, as
with a task, or through protected subprograms
• A protected procedure provides mutually exclusive read-write access to
protected objects
• A protected function provides concurrent read-only access to protected objects
Asynchronous Communication

• Provided through asynchronous select structures


• An asynchronous select has two triggering alternatives, an entry clause or a
delay
– The entry clause is triggered when sent a message
– The delay clause is triggered when its time limit is reached

JAVA THREADS

The concurrent units in Java are methods named run, whose code can be in concurrent
execution with other such methods (of other objects) and with the main method.
The process in which the run methods execute is called a thread.
Java’s threads are lightweight tasks, which means that they all run in the same address
space.

Class myThread extends Thread


public void run () {…}
}

Thread myTh = new MyThread ();
myTh.start();

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


10
https://jntuhbtechadda.blogspot.com/
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
Competition Synchronization with Java Threads

• A method that includes the synchronized modifier disallows any other method
from running on the object while it is in execution

public synchronized void deposit( int i) {…}
public synchronized int fetch() {…}

• The above two methods are synchronized which prevents them from
interfering with each other
• If only a part of a method must be run without interference, it can be
synchronized thru synchronized statement
synchronized (expression)
statement

• 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

C# THREADS

• Loosely based on Java but there are significant differences


• Basic thread operations
– Any method can run in its own thread
– A thread is created by creating a Thread object

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


11
https://jntuhbtechadda.blogspot.com/
– Creating a thread does not start its concurrent execution; it must be
requested through the Start method
– A thread can be made to wait for another thread to finish with Join
– A thread can be suspended with Sleep
– A thread can be terminated with Abort

Synchronizing Threads

• Three ways to synchronize C# threads


– The Interlocked class
• Used when the only operations that need to be synchronized are
incrementing or decrementing of an integer
– The lock statement
• Used to mark a critical section of code in a thread
lock (expression) {… }
– The Monitor class
• Provides four methods that can be used to provide more
sophisticated synchronization

EXCEPTION AND EVENT HANDLING


Most computer hardware systems are capable of detecting certain run-time error
conditions, such as floating-point overflow. Early programming languages were
designed and implemented in such a way that the user program could neither detect
nor attempt to deal with such errors. In these languages, the occurrence of such an
error simply causes the program to be terminated and control to be transferred to the
operating system.

Exception to be any unusual event, erroneous or not, that is detectable by either


hardware or software and that may require special processing. The special processing
that may be required when an exception is detected is called exception handling. This
processing is done by a code unit or segment called an exception handler.

An exception is raised when its associated event occurs. In some C-based languages,
exceptions are said to be thrown, rather than raised.
Different kinds of exceptions require different exception handlers. Detection of end-
of-file nearly always requires some specific program action.

Advantages of Built-in Exception Handling

• Error detection code is tedious to write and it clutters the program


• Exception handling encourages programmers to consider many different
possible errors
• Exception propagation allows a high level of reuse of exception handling code

Design Issues

• How and where are exception handlers specified and what is their scope?
• How is an exception occurrence bound to an exception handler?

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


12
https://jntuhbtechadda.blogspot.com/
• Can information about the exception be passed to the handler?
• Where does execution continue, if at all, after an exception handler completes
its execution? (continuation vs. resumption)
• Is some form of finalization provided?
• How are user-defined exceptions specified?
• Should there be default exception handlers for programs that do not provide
their own?
• Can built-in exceptions be explicitly raised?
• Are hardware-detectable errors treated as exceptions that can be handled?
• Are there any built-in exceptions?
• How can exceptions be disabled, if at all?

Exception Handling Control Flow

EXCEPTION HANDLING IN ADA


Ada exception handlers are often local to the code in which the exception can be
raised (although they can be propagated to other program units). Because this
provides them with the same referencing environment, parameters for handlers are not
necessary and are not allowed. Therefore, if an exception is handled in a unit different
from the unit that raised the exception, no information about the exception can be
passed to the handler

• Handler form:
when exception_choice{|exception_choice} => statement_sequence
...
[when others =>
statement_sequence]

exception_choice form:

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


13
https://jntuhbtechadda.blogspot.com/
exception_name | others
• Handlers are placed at the end of the block or unit in which they occur

Binding Exceptions to Handlers

• If the block or unit in which an exception is raised does not have a handler for
that exception, the exception is propagated elsewhere to be handled
– Procedures - propagate it to the caller
– Blocks - propagate it to the scope in which it appears
– Package body - propagate it to the declaration part of the unit that
declared the package (if it is a library unit, the program is terminated)
– Task - no propagation; if it has a handler, execute it; in either case,
mark it "completed"

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)

Other Design Choices


User-defined Exceptions form:
exception_name_list : exception;
• Raising Exceptions form:
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)
PREDEFINED EXCEPTIONS:

• CONSTRAINT_ERROR - index constraints, range constraints, etc.


• NUMERIC_ERROR - numeric operation cannot return a correct value
(overflow, division by zero, 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

EXCEPTION HANDLING IN C++

The exception handling of C++ was accepted by the ANSI C++ standardization
committee in 1990 and subsequently found its way into C++ implementations. The
design is based in part on the exception handling of CLU, Ada, and ML. One major

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


14
https://jntuhbtechadda.blogspot.com/
difference between the exception handling of C++ and that of Ada is the absence of
predefined exceptions in C++.
C++ uses a special construct that is introduced with the reserved word try for this
purpose. A try construct includes a compound statement called the try clause and a list
of exception handlers.

• Exception Handlers Form:


try {
-- code that is expected to raise an exception
}
catch (formal parameter) {
-- handler code
}
...
catch (formal parameter) {
-- handler code
}

The Catch Function

• catch is the name of all handlers--it is an overloaded name, so the formal


parameter of each must be unique
• The formal parameter need not have a variable
– It can be simply a type name to distinguish the handler it is in from
others
• The formal parameter can be used to transfer information to the handler
• The formal parameter can be an ellipsis, in which case it handles all
exceptions not yet handled

Throwing Exceptions

• Exceptions are all raised explicitly by the statement:


throw [expression];
• The brackets are metasymbols
• A throw without an operand can only appear in a handler; when it appears, it
simply re-raises the exception, which is then handled elsewhere
• The type of the expression disambiguates the intended handler

Unhandled Exceptions

• An unhandled exception is propagated to the caller of the function in which it


is raised
• This propagation continues to the main function

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


15
https://jntuhbtechadda.blogspot.com/
• If no handler is found, the default handler is called

Continuation


After a handler completes its execution, control flows to the first statement
after the last handler in the sequence of handlers of which it is an element
• Other design choices
– All exceptions are user-defined
– Exceptions are neither specified nor declared
– The default handler, unexpected, simply terminates the program;
unexpected can be redefined by the user
– Functions can list the exceptions they may raise
– Without a specification, a function can raise any exception (the throw
clause)
Evaluation

• It is odd that exceptions are not named and that hardware- and system
software-detectable exceptions cannot be handled
• Binding exceptions to handlers through the type of the parameter certainly
does not promote readability

EXCEPTION HANDLING IN JAVA

• Based on that of C++, but more in line with OOP philosophy


• All exceptions are objects of classes that are descendants of the Throwable
class

Classes of Exceptions

• The Java library includes two subclasses of Throwable :


– Error
• Thrown by the Java interpreter for events such as heap
overflow
• Never handled by user programs
– Exception
• User-defined exceptions are usually subclasses of this
• Has two predefined subclasses, IOException and
RuntimeException (e.g., ArrayIndexOutOfBoundsException
and NullPointerException

Java Exception Handlers

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


16
https://jntuhbtechadda.blogspot.com/
• 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 try construct, the search is continued in the


nearest enclosing try construct, etc.
• 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 insure that all exceptions are caught, a handler can be included in any try
construct that catches all exceptions
– Simply use an Exception class parameter
– Of course, it must be the last in the try construct

Checked and Unchecked Exceptions

• 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

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
Assertions

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


17
https://jntuhbtechadda.blogspot.com/
• Statements in the program declaring a boolean expression regarding the
current state of the computation
• When evaluated to true nothing happens
• When evaluated to false an Assertion Error exception is thrown
• Can be disabled during runtime without program modification or
recompilation
• Two forms
– assert condition;
– assert condition: expression;

INTRODUCTION TO EVENT HANDLING

Event handling is similar to exception handling. In both cases, the handlers are
implicitly called by the occurrence of something, either an exception or an event.
While exceptions can be created either explicitly by user code or implicitly by
hardware or a software interpreter, events are created by external actions, such as user
interactions through a graphical user interface (GUI).

• An event is a notification that something specific has occurred, such as a


mouse click on a graphical button..
• An event is created by an external action such as a user interaction through a
GUI
• An event handler is a segment of code that is executed in response to the
appearance of an event. Event handlers enable a program to be responsive to
user actions

Another common use of event handlers is to check for simple errors and omissions in
the elements of a form, either when they are changed or when the form is submitted to
the Web server for processing.
Using event handling on the browser to check the validity of form data saves the time
of sending that data to the server, where their correctness then must be checked by a
server-resident program or script before they can be processed. This kind of event-
driven programming is often done using a client-side scripting language, such as
JavaScript.

Event Handling with Java

The Java Event Model

• User interactions with GUI components create events that can be caught by
event handlers, called event listeners
• An event generator tells a listener of an event by sending a message
• An interface is used to make event-handling methods conform to a standard
protocol
• A class that implements a listener must implement an interface for the listener
• One class of events is ItemEvent, which is associated with the event of
clicking a checkbox, a radio button, or a list item
• The ItemListener interface prescribes a method, itemStateChanged, which is a
handler for ItemEvent events

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


18
https://jntuhbtechadda.blogspot.com/
• The listener is created with addItemListener

Event Handling in C#

Event handling in C# (and in the other .NET languages) is similar to that of Java.
.NET provides two approaches to creating GUIs in applications, the original Windows
Forms and the more recent Windows Presentation Foundation.

All C# event handlers have the same protocol: the return type is void and the two
parameters are of types object and EventArgs.

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


19
https://jntuhbtechadda.blogspot.com/
UNIT-V Functional Programming Languages: Introduction, mathematical
functions, fundamentals of functional programming language, LISP, support for
functional programming in primarily imperative languages, comparison of
functional and imperative languages Logic Programming Language:
Introduction, an overview of logic programming, basic elements of prolog,
deficiencies of prolog, applications of logic programming. Scripting Language:
Pragmatics, Key Concepts,
Case Study : Python – Values and Types, Variables , Storage and Control,
Bindings and Scope, Procedural Abstraction, Data Abstraction, Separate
Compilation, Module Library.

Functional programming languages are modeled on mathematical functions i.e all the
computations can be done by applying mathematical functions to the specified
parameters.

MATHEMATICAL FUNCTIONS

A mathematical function is a mapping of members of one set, called the domain set,
to another set, called the range set. A function definition specifies the domain and
range sets, either explicitly or implicitly, along with the mapping. The mapping is
described by an expression or, in some cases, by a table.

FEATURES OF FUNCTIONAL PROGRAMMING LANGUAGES:


1. The primary means of performing language can be obtained by applying
mathematical functions to the specified parameters
2. Pure functional programming languages does not use any variables,
assignment statements and iterations
3. Computation can be performed based on the functions rather than the state
changes that occurred in program
4. During the process of program development , previously developed functions
can be used to build more complex functions which produces the final result
from the initial data.
5. In FPLs successive functional transformations can be performed on the initial
data in order to obtain the final result .The general form of successive
transformations is given as
function_n(… function_3(function_2(function_1(data)))…)

ADVANTAGES OF FUNCTIONAL PROGRAMMING LANGUAGES:

1. In FPLs the programmers are not concerned with the variables because the
memory cells are not conceptualized into the language.
2. Less labour is required for constructing the programs
3. They have simple syntactic and semantic structures.
4. Concurrent program execution is easy to understand , design and use.
5. Programmer is not concerned with the cooperation synchronization and
dynamic division of the programs.
DISADVANTAGES:

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


1
https://jntuhbtechadda.blogspot.com/
1. Less efficient than the imperative programming languages
2. Because of the use of Interpreters the process of writing programs in FPLs is
slower than that of imperative Programming Languages.

Simple Functions
Function definitions are often written as a function name, followed by a list of
parameters in parentheses, followed by the mapping expression. For example,
cube(x) ≡ x * x * x, where x is a real number In this definition, the domain and range
sets are the real numbers. The symbol ≡ is used to mean “is defined as.” The
parameter x can represent any member of the domain set, but it is fixed to represent
one specific element during evaluation of the function expression.
A method called as the Lambda notation is used for nameless functions. A
Lambda expression is a function that represents the parameter and function
mapping.
λ(x) x * x
A lambda Calculus is defined as a formal computation model using lambda
expressions. Lambda calculus can be either typed or un-typed.

Function Forms:

A higher-order function, or functional form, is one that either takes one or more
functions as parameters or yields a function as its result, or both. One common kind of
functional form is function composition, which has two functional parameters and
yields a function whose value is the first actual parameter function applied to the
result of the second.

For example f(x) ≡ x+2


g(x) ≡ 3*x

then h is defined as h(x) ≡ f(g(x)) i.e h(x) ≡(3*x)+2

Apply to all function


• 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
Form: α
For h (x) ≡ x * x
α( h, (2, 3, 4)) yields (4, 9, 16)

FUNDAMENTAL OF FPL
The objective of the design of a functional programming language is to imitate
mathematical functions to the greatest extent possible. This results in an approach to
problem solving that is fundamentally different from approaches used with imperative
languages. In an imperative language, an expression is evaluated and the result is
stored in a memory location, which is represented as a variable in a program. This is
the purpose of assignment statements. This necessary attention to memory cells,

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


2
https://jntuhbtechadda.blogspot.com/
whose values represent the state of the program, results in a relatively low-level
programming methodology. A program in an assembly language often must also store
the results of partial evaluations of expressions.
A purely functional programming language does not use variables or assignment
statements, thus freeing the programmer from concerns related to the memory cells, or
state, of the program. Without variables, iterative constructs are not possible, for they
are controlled by variables. Repetition must be specified with recursion rather than
with iteration. Programs are function definitions and function application
specifications, and executions consist of evaluating function applications. Without
variables, the execution of a purely functional program has no state in the sense of
operational and denotation semantics. The execution of a function always produces
the same result when given the same parameters. This feature is called referential
transparency. It makes the semantics of purely functional languages far simpler than
the semantics of the imperative languages (and the functional languages that include
imperative features). It also makes testing easier, because each function can be tested
separately, without any concern for its context.
A functional language provides a set of primitive functions, a set of functional forms
to construct complex functions from those primitive functions, a function application
operation, and some structure or structures for representing data. These structures are
used to represent the parameters and values computed by functions. If a functional
language is well defined, it requires only a relatively small number of primitive
functions.
Although early functional languages were often implemented with interpreters, many
programs written in functional programming languages are now compiled.

Tail Recursion – Writing recursive functions that can be automatically converted to


iteration

Imperative languages usually provide only limited support for functional


programming. Most of them include function definition and calling facilities.

FUNCTIONAL PROGRAMMING LANGUAGE LISP

It was the first language developed in the category of functional programming


languages. The oldest and mostly widely used language is LISP.

There are two primitive types available in LISP they are atoms and lists.

Atom in lisp referred to the most fundamental basic data type. There are two types of
atoms they are
1. A literal atom that represents symbols
2. A numeric atom which represents numbers

Lists are widely used in list processing. LISP was originally used in lists as its data
structure because they were though to be an essential part of list processing. Two
types of lists are
1. Simple List which does not contain any sub lists
2. Nested List which contain sub lists specified in the inner parenthesis.

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


3
https://jntuhbtechadda.blogspot.com/
Numeric Atoms or Numbers

An Integer, Float or the hardware representation used for the numbers in LISP.

Strings
Strings are expressed as string of symbols.

STRUCTURED DATA TYPES


Some vector type or array data object is provided by most of the LISP
implementations. The following are the function

mkvect(bound)
A datatype of type vector is created by this function whose script ranges from 0 to a
given bound. Each vector component contains a pointer to the LISP data object which
are initially set to nil.

getv(vector,subscript)
A pointer stored at a specified subscript in the argument vector is returned by this
function.

putv
It is used to assign a new value to a particular vector component

OPERATIONS ON ATOMS AND LISTS

atom – differentiates between pointer to a list of word or a pointer to an atom.

numberp – to determine whether an atom is literal atom or number

eq- to determine whether two literals atoms are equal or not

Zerop-checks for zero value


greaterp- checks for greater value
lessp- checks for lesser value

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


4
https://jntuhbtechadda.blogspot.com/
LISP defines two operations cdr and car .

Car L returns the first element


Cdr L returns all the list elements except first element.

SEMANTIC CONDITIONS OF AND LET

COND Semantics

Syntax:

Cond<clause 1> <clause 2>

Every cond expression consists of clause which in term is of the form

(<test 1> <expression 1> …..<test n><expression n>)

The expressions with in a clause is evaluated by executing the test expression of


sequential classes. This evaluation results either true or false.

LET Semantics

LET binds the parameters specified with in the expression. The LET expression
computes the initial value before binding the values.

Syntax:
LET<bindings><body>

The binding is of the form


((<variable 1><initial value 1>)…)
In the above syntax <initial value> is an expression and <body> specifies sequence of
one or more expressions.

LISP INTREPRETER

The computation theory deals with the process of computations using a model. A
universal computing machine resembles universal turing machine and is constructed
to simulate all other machines present in the model. Based on this concept a universal
LISP function that can compute any LISP function has been constructed.
For Constructing universal LISP functions the fundamental requirement is that it must
allow functions to be represented in the same way in which data is represented. As
parenthesized list notation is used for representing LISP data the function definitions
and function calls are also expressed in list notation.
An interpreter for LISP can be written in LISP. Such an interpreter, which is not a
large program, describes the operational semantics of LISP, in LISP.

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


5
https://jntuhbtechadda.blogspot.com/
Cambridge Polish Notation

The Cambridge polish notation denotes a prefix notation for describing the LISP
function call as follows

(function_name arg_1, …..aar_n)


Lambda Notation:
The lambda notation is used to describe function definitions. It must be modified in
order to associate functions to names so that a reference to the function is made by
itself and by some other functions.

(function_name(LAMBDA(arg_1…arg_n)expr))

LISP Program segment that Generates factorial of N

The factorial of a given number n in LISP can be determined using defun keyword.
The function definition is as follows

(defun (factorial n)
(if(=n 0)
1
(*n factorial (-n 1)))
))

The above factorial function returns 1 if the entered number n is 1 else it makes a
recursive call to the factorial function to compute the factorial of a given number.

Fibonacci Number

(defun fib(n)
(if (or (=n 0) (=n 1))
1
(+(fib(-n 1))(fib(-n 2)))))

Initially if(n=0) or if(n=1) then a value 1 is returned else fib function is called
recursively. This recursive process is repeated till the required Fibonacci series is
obtained.

SCHEMES

Scheme interpreters are readily available (and free) for a wide variety of computers.
The Scheme language, which is a dialect of LISP, was developed at MIT in the mid-
1970s. It is characterized by its small size, its exclusive use of static scoping, and its
treatment of functions as first-class entities.

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


6
https://jntuhbtechadda.blogspot.com/
Scheme functions can be the values of expressions, elements of lists, passed as
parameters, and returned from functions. Early versions of LISP did not provide all of
these capabilities.

The Scheme Interpreter:

A Scheme interpreter in interactive mode is an infinite read-evaluate-print loop.


It repeatedly reads an expression typed by the user interprets the expression, and
displays the resulting value. This form of interpreter is also used by Ruby and Python.
Expressions are interpreted by the function EVAL.

Primitive Numeric Functions:


Scheme includes primitive functions for the basic arithmetic operations. These are +,
−, *, and /, for add, subtract, multiply, and divide. * and + can have zero or more
parameters. If * is given no parameters, it returns 1; if + is given no parameters, it
returns 0. + adds all of its parameters together. * multiplies all its parameters together.
/ and − can have two or more parameters. In the case of subtraction, all but the first
parameter are subtracted from the first. Division is similar to subtraction.

There are a large number of other numeric functions in Scheme, among them
MODULO, ROUND, MAX, MIN, LOG, SIN, and SQRT. SQRT returns the square
root of its numeric parameter, if the parameter’s value is not negative. If the parameter
is negative, SQRT yields a complex number.

Defining Functions
A Scheme program is a collection of function definitions.
In Scheme, a nameless function actually includes the word LAMBDA, and is called
a lambda expression. For example,
(LAMBDA (x) (* x x))
Output Functions
Scheme includes a few simple output functions, but when used with the interactive
interpreter, most output from Scheme programs is the normal output from the
interpreter, displaying the results of applying EVAL to top-level functions.
Scheme includes a formatted output function, PRINTF, which is similar to the printf
function of C.

Numeric Predicate Functions:


A predicate function is one that returns a Boolean value (some representation of either
true or false). Scheme includes a collection of predicate functions for numeric data.

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


7
https://jntuhbtechadda.blogspot.com/
Control Flow:
Scheme uses three different constructs for control flow: one similar to the selection
construct of the imperative languages and two based on the evaluation control used in
mathematical functions.

The Scheme two-way selector function, named IF, has three parameters: a predicate
expression, a then expression, and an else expression. A call to IF has the form

(IF predicate then_expression else_expression)

Tail Recursion Scheme

A function is tail recursive if its recursive call is the last operation in the function.
This means that the return value of the recursive call is the return value of the
nonrecursive call to the function.

List Functions, Functional Forms( Functional Composition, An Apply to all function


form), Same as Previous.

ML(META LANGUAGE):

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


8
https://jntuhbtechadda.blogspot.com/
Meta Language abbreviated as ML is a language consisting of static types , string
typing and an applicative approach for program execution. Although ML is similar to
scheme there exists a number of differences. The most important difference is ML is
strongly typed language where as scheme is a typeless language, ML uses syntax
definition that is similar to that of the imperative language.

Value Declaration Statements:

The value declaration statements are used to bind the names to values.

Syntax
Val identifier= expression;

Expressions, Functions and Exception in ML

Ml Supports arithmetic, Boolean, string , Selection control flow and list expressions.

All arithmetic expressions are evaluated according to operators

String expressions are specified by using double Quotes.

Functions in ML can be declared with in the program.

Syntax
fun function_name(formal_paramters)=expression.

Exceptions definition can be as


exception name of the expression

FEATURES OF ML(META LANGUAGE):

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


9
https://jntuhbtechadda.blogspot.com/
1. ML is a functional language and its syntax is closely related to imperative
languages like Java, C++
2. It is a strongly typed language consisting of type declarations
3. It allows the declaration of variable types and expressions type to be made at
the compile time
4. It relates types to objects but not to their names
5. It can handle a raised exception caused due to error
6. It include module facility for implementing abstract data type module facility
is also provided
7. It enables declaration of function to be made with in the program.
8. It allows the manipulations performed by the function to be defined for
various forms of parameters.
9. It allows the execution of recursive function as it support static type checking.
10. It executes the conditional statement using selection control flow
11. It detects many errors prior to execution thereby making it a highly secure
language.
12. It increases the efficiency factor as the information regarding the size and
allocation is pre determined by the programmers.

APPLICATION OF FUNCTIONAL PROGRAMMING LANGUAGES

Functional Programming languages finds its applications in many areas

1. LISP is versatile and powerful language that is used in list processing and
symbolic computation
2. LISP Includes Knowledge Representation, Machine Learning, Natural
Language Processing, Intelligent Training Systems, Modelling of Speech and
Vision.
3. LISP is also used in writing the systems software for the LISP machine
4. It is oftenly used in the construction of various experimental systems
5. Scheme another FPL is used to teach preliminary programming courses in
some universities
6. Use of ML are confined to research laboratories and universities.

IMPERATIVE LANGUAGES AND ITS FEATURES

The language that are directly based on the Von-Neumann architecture are called
imperative languages.

1. In Imperative Languages maintaining cooperation among multiple concurrent


tasks is the responsibility of the programmer
2. Concurrent program execution is difficult to understand in case of imperative
languages
3. Efficiency of imperative programming languages is more
4. These languages have complex syntactic and semantic structures.

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


10
https://jntuhbtechadda.blogspot.com/
5. The program is statically divided into concurrent parts by the programmer
6. Involves increased labor for constructing the programs
7. Concurrent program execution is difficult to design and use

COMAPRISION OF FUNCTIONAL AND IMPERATIVE PROGRAMMING


LANGAUGES

FPL IPL
1. In these languages the programmers These languages are directly based on
need not be concerned with the variables the Von –Neumann architecture , hence
because the memory cell are not the programmers must manage the
abstracted into the language variables and assign the values to them.
2. Efficiency is Less 2. Efficiency is more
3. Less Labor is required for constructing 3. Increased Labor is required for
the programs constructing the programs
4. These Languages have simple syntactic 4. These Languages have complex
structures syntactic structures
5. Their semantics are simpler than the 5. They have complex semantics
imperative languages
6. Concurrent execution is easy as the 6. Concurrent execution is difficult to
programs are first translating into graphs design and use
which in turn can be executed through
graph reduction methods
7.Programmer is not concerned with the 7. Cooperation among the multiple
cooperation synchronization concurrent tasks is the responsibility of
the programmer
8. Execution of concurrent programs is 8. Concurrent programs execution is
easily understand difficult to understand
9.The program is dynamically divided 9.The program is statically divided into
into concurrent parts by the programmer concurrent parts by the programmer.

Programming that uses a form of symbolic logic as a programming language is often


called logic programming, and languages based on symbolic logic are called logic
programming languages, or declarative languages. The most widely used
programming language is PROLOG.

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


11
https://jntuhbtechadda.blogspot.com/
The syntax of logic programming languages is remarkably different from that of the
imperative and functional languages. The semantics of logic programs also bears little
similarity to that of imperative-language programs.

A proposition can be thought of as a logical statement that may or may not be true. It
consists of objects and the relationships among objects. Formal logic was developed
to provide a method for describing propositions, with the goal of allowing those
formally stated propositions to be checked for validity. Symbolic logic can be used
for the three basic needs of formal logic: to express propositions, to express the
relationships between propositions, and to describe how new propositions can be
inferred from other propositions that are assumed to be true. There is a close
relationship between formal logic and mathematics. In fact, much of mathematics can
be thought of in terms of logic. The fundamental axioms of number and set theory are
the initial set of propositions, which are assumed to be true. Theorems are the
additional propositions that can be inferred from the initial set. The particular form of
symbolic logic that is used for logic programming is called first-order predicate
calculus.

PREDICATE CALCULUS
Propositions

The objects in logic programming propositions are represented by simple terms,


which are either constants or variables. A constant is a symbol that represents an
object.
The simplest propositions, which are called atomic propositions, consist of compound
terms. A compound term is one element of a mathematical relation, written in a form
that has the appearance of mathematical function notation.
The names, symbols, and meanings of the predicate calculus logical connectors are as
follows:

Clausal Form:
Problem with predicate calculus is that there are too many different ways of stating
propositions that have the same meaning; that is, there is a great deal of redundancy.
This is not such a problem for logicians, but if predicate calculus is to be used in an
automated (computerized) system, it is a serious problem. To simplify matters, a
standard form for propositions is desirable. Clausal form, which is a relatively simple
form of propositions, is one such standard form. All propositions can be expressed in
clausal form.

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


12
https://jntuhbtechadda.blogspot.com/
AN OVERVIEW OF LOGIC PROGRAMMING
Languages used for logic programming are called declarative languages, because
programs written in them consist of declarations rather than assignments and control
flow statements. These declarations are actually statements, or propositions, in
symbolic logic.
One of the essential characteristics of logic programming languages is their semantics,
which is called declarative semantics. The basic concept of this semantics is that
there is a simple way to determine the meaning of each statement, and it does not
depend on how the statement might be used to solve a problem.

Declarative semantics is considerably simpler than the semantics of the imperative


languages. For example, the meaning of a given proposition in a logic programming
language can be concisely determined from the statement itself. In an imperative
language, the semantics of a simple assignment statement requires examination of
local declarations, knowledge of the scoping rules of the language, and possibly even
examination of programs in other files just to determine the types of the variables in
the assignment statement.

Programming in both imperative and functional languages is primarily procedural,


which means that the programmer knows what is to be accomplished by a program
and instructs the computer on exactly how the computation is to be done.

Programming in a logic programming language is nonprocedural. Programs in such


languages do not state exactly how a result is to be computed but rather describe the
form of the result. What is needed to provide this capability for logic programming
languages is a concise means of supplying the computer with both the relevant
information and a method of inference for computing desired results. Predicate
calculus supplies the basic form of communication to the computer, and resolution
provides the inference technique.

Example: The difference between procedural and nonprocedural systems is


sorting. In a language like Java, sorting is done by explaining in a Java program all of
the details of some sorting algorithm to a computer that has a Java compiler. The
computer, after translating the Java program into machine code or some interpretive
intermediate code, follows the instructions and produces the sorted list.

In a nonprocedural language, it is necessary only to describe the characteristics of


the sorted list: It is some permutation of the given list such that for each pair of
adjacent elements, a given relationship holds between the two elements.

PROGRAMMING WITH PROLOG

Terms:
A Prolog term is a constant, a variable, or a structure. A constant is either an atom
or an integer. Atoms are the symbolic values of Prolog and are similar to their
counterparts in LISP. In particular, an atom is either a string of letters, digits, and

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


13
https://jntuhbtechadda.blogspot.com/
underscores that begins with a lowercase letter or a string of any printable ASCII
characters delimited by apostrophes.
A variable is any string of letters, digits, and underscores that begins with an
uppercase letter or an underscore ( _ ). Variables are not bound to types by
declarations. The binding of a value, and thus a type, to a variable is called an
instantiation. Instantiation occurs only in the resolution process. A variable that has
not been assigned a value is called uninstantiated.
Structures represent the atomic propositions of predicate calculus, and their general
form is the same:
functor(parameter list)

The functor is any atom and is used to identify the structure. The parameter list can be
any list of atoms, variables, or other structures.

Fact Statements

Prolog statements begins with those statements used to construct the hypotheses, or
database of assumed information—the statements from which new information can be
inferred.
Prolog has two basic statement forms; these correspond to the headless and headed
Horn clauses of predicate calculus. The simplest form of headless Horn clause in
Prolog is a single structure, which is interpreted as an unconditional assertion, or fact.
Logically, facts are simply propositions that are assumed to be true. Prolog statement
is terminated by a period.

Rule Statements

The other basic form of Prolog statement for constructing the database corresponds
to a headed Horn clause.
Conjunctions contain multiple terms that are separated by logical AND operations. In
Prolog, the AND operation is implied. The structures that specify atomic propositions
in a conjunction are separated by commas, so one could consider the commas to be
AND operators.
Goal Statements
The theorem is in the form of a proposition that we want the system to either prove or
disprove. In Prolog, these propositions are called goals, or queries.

The Inferencing Process of Prolog


Queries are called goals. When a goal is a compound proposition, each of the facts
(structures) is called a subgoal. To prove that a goal is true, the inferencing process
must find a chain of inference rules and/or facts in the database that connect the goal
to one or more facts in the database.
The process of proving a subgoal is done through a proposition matching process, it is
sometimes called matching. In some cases, proving a subgoal is called satisfying that
subgoal.
There are two opposite approaches to attempting to match a given goal to a fact in the
database. The system can begin with the facts and rules of the database and attempt to
find a sequence of matches that lead to the goal. This approach is called bottom-up
resolution, or forward chaining. The alternative is to begin with the goal and

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


14
https://jntuhbtechadda.blogspot.com/
attempt to find a sequence of matching propositions that lead to some set of original
facts in the database. This approach is called top-down resolution, or backward
chaining.

Simple Arithmetic
Prolog supports integer variables and integer arithmetic. Originally, the arithmetic
operators were functors, so that the sum of 7 and the variable X was formed with

+ (7, X)

Prolog now allows a more abbreviated syntax for arithmetic with the is operator. This
operator takes an arithmetic expression as its right operand and a variable as its left
operand. All variables in the expression must already be instantiated, but the left-side
variable cannot be previously instantiated. For example, in

A is B / 17 + C.

Prolog does not have assignment statements in the same sense as imperative
languages. They are simply not needed in most of the programming for which Prolog
was designed.

Prolog has a built-in structure named trace that displays the instantiations of values to
variables at each step during the attempt to satisfy a given goal. trace is used to
understand and debug Prolog programs.

List Structures
Atomic propositions, which are also called structures, are actually a form of records.
The other basic data structure supported is the list. Lists are sequences of any number
of elements, where the elements can be atoms, atomic propositions, or any other
terms, including other lists. Prolog uses the syntax of ML and Haskell to specify lists.
The list elements are separated by commas, and the entire list is delimited by square
brackets.

DEFICIENCIES OF PROLOG

Resolution Order Control

Prolog, for reasons of efficiency, allows the user to control the ordering of pattern
matching during resolution. In a pure logic programming environment, the order of
attempted matches that take place during resolution is nondeterministic, and all
matches could be attempted concurrently.

The Closed-World Assumption

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


15
https://jntuhbtechadda.blogspot.com/
The nature of Prolog’s resolution sometimes creates misleading results. The only
truths, as far as Prolog is concerned, are those that can be proved using its database. It
has no knowledge of the world other than its database. When the system receives a
query and the database does not have information to prove the query absolutely, the
query is assumed to be false. Prolog can prove that a given goal is true, but it cannot
prove that a given goal is false. It simply assumes that, because it cannot prove a goal
true, the goal must be false. In essence, Prolog is a true/fail system, rather than a
true/false system.

The Negation Problem


Another problem with Prolog is its difficulty with negation.

Intrinsic Limitations
A fundamental goal of logic programming, is to provide nonprocedural programming;
that is, a system by which programmers specify what a program is supposed to do but
need not specify how that is to be accomplished.

APPLICATIONS OF LOGIC PROGRAMMING

Relational Database Management Systems

These are the systems which stores data in tabular form. Relational Calculus is used
to perform queries on such databases. Tables containing the information can be
described by Prolog structures and the relationships between the tables can be
explained by Prolog rules.

Advantages:
1. Only single language is required for implementing RDBMS. All the queries
related to data definitions, data manipulations and input and output functions
can be done by using a single logic programming language.
2. Deductive capability is built in the logic programming languages, which is
useful for implementing RDBMS. Deducing data from conventional RDBMS
is not possible as it only contains facts but not inference rules.

Disadvantage:
Use of logic programming for implementing RDBMS is a slow process

Expert Systems
Expert systems are computer systems that have been developed for imitating human
expertise in same domain.
Natural-Language Processing
Logic programming is used in natural language processing in providing interfaces to
computer software systems such as intelligent databases and knowledge based
systems.
Education

Logic programming such as micro prolog can be used in the field of education which
provides the advantage as it introduces computing.

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


16
https://jntuhbtechadda.blogspot.com/
APPLICATIONS OF PROLOG
• Intelligent data base retrieval
• Natural language understanding
• Expert systems
• specification language
• Machine learning
• Robot planning
• Automated reasoning
• Problem solving

MULTIPARADIGM LANGUAGES

A multi-paradigm programming language is a programming language that supports


more than one programming paradigm. The design goal of such languages is to allow
programmers to use the most suitable programming style and associated language
constructs for a particular job, considering that no single paradigm solves all problems
in the easiest or most efficient way.

Ex: C#, which includes imperative and object-oriented paradigms as well as some
support for functional programming with features like delegates (allowing functions
to be treated as first-order objects), type inference, anonymous
functions and Language Integrated Query. Other examples are F# and Scala, which
provides similar functionality to C# but also includes full support for functional
programming (including currying, pattern matching, algebraic data types, lazy
evaluation, tail recursion, immutability, etc.). Perhaps the most extreme example
is Oz, which has subsets that adhere to logic (Oz descends from logic
programming), functional, object-oriented, dataflow concurrent, and other paradigms.
Oz was designed over a ten-year period to combine in a harmonious way concepts
that are traditionally associated with different programming paradigms. Lisp, while
often taught as a functional language, is known for its malleability and thus its ability
to engulf many paradigms.

A multi-paradigm programming language is a programming language that supports


more than one programming paradigm. The central idea of a multiparadigm language
is to provide a framework in which programmers can work in a variety of styles,
freely intermixing constructs from different paradigms. The design goal of such
languages is to allow programmers to use the best tool for a job, admitting that a
single paradigm cannot solve all problems in the easiest or most efficient way.

Ex: Supporting this view, JavaScript supports, or infact uses various styles. For
example, its syntax follows a C language like structure, which is a procedural
language, and at the same time JavaScript copies many names and naming
conventions from an object-oriented programming language, Java, but the two
languages are otherwise unrelated and have very different semantics. The key design
principles within JavaScript are taken from the Self and Scheme programming
languages.
Ex:

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


17
https://jntuhbtechadda.blogspot.com/
C++ is a multi-paradigm language
• Procedural programming with functions
• Object-oriented programming with classes
• Generic programming with templates, typedefs

Dr.G.NAGA SATISH,M.Sc(CS)., M.Tech(CSE)., M.Phil(CS).,Ph.D(CSE)


18
https://jntuhbtechadda.blogspot.com/

You might also like