0% found this document useful (0 votes)
34 views

Chapter One: Introduction Programming Languages

The document discusses programming languages and their design. It begins by defining a programming language as a formal language used to communicate instructions to machines, particularly computers. Programming languages can be used to create programs that control machine behavior or express algorithms. The document then discusses key considerations in evaluating and designing programming languages, including supporting various parts of the software development lifecycle and managing complexity. It notes there are difficult tradeoffs in language design between features that make programming easier versus testing or optimization. The document concludes by outlining attributes of good programming languages such as clarity, naturalness for the application, support for abstraction, and ease of program verification.

Uploaded by

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

Chapter One: Introduction Programming Languages

The document discusses programming languages and their design. It begins by defining a programming language as a formal language used to communicate instructions to machines, particularly computers. Programming languages can be used to create programs that control machine behavior or express algorithms. The document then discusses key considerations in evaluating and designing programming languages, including supporting various parts of the software development lifecycle and managing complexity. It notes there are difficult tradeoffs in language design between features that make programming easier versus testing or optimization. The document concludes by outlining attributes of good programming languages such as clarity, naturalness for the application, support for abstraction, and ease of program verification.

Uploaded by

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

Chapter One: Introduction

Programming Languages
A programming language is a formal constructed language designed to communicate
instructions to a machine, particularly a computer. Programming languages can be used to create
programs to control the behavior of a machine or to express algorithms. A programming
language is:
• A tool for instructing machines
• A means of communicating between programmers
• A notation for algorithms
• A way of expressing relationships between concepts
• A means for controlling computerized devices
Programming languages are the medium of expression in the art of computer programming.
An ideal programming language will make it easy for programmers to write programs briefly and
clearly. Because programs are meant to be understood, modified, and maintained over their
lifetime, a good programming language will help others read programs and understand how they
work.
Programming languages are the medium of expression in the art of computer programming.
An ideal programming language will make it easy for programmers to write programs briefly and
clearly. Because programs are meant to be understood, modified, and maintained over their
lifetime, a good programming language will help others read programs and understand how they
work. Software design and construction are complex tasks. Many software systems consist of
interacting parts. These parts, or software components, may interact in complicated ways. To
manage complexity, the interfaces and communication between components must be designed
carefully. A good language for large-scale programming will help programmers manage the
interaction among software components effectively. In evaluating programming languages, we
must consider the tasks of designing, implementing, testing, and maintaining software, asking
how well each language supports each part of the software life cycle.

There are many difficult trade-offs in programming language design. Some language features
make it easy for us to write programs quickly, but may make it harder for us to design testing

1
tools or methods. Some language constructs make it easier for a compiler to optimize programs,
but may make programming cumbersome. Because different computing environments and
applications require different program characteristics, different programming language designers
have chosen different trade-offs. In fact, virtually all successful programming languages were
originally designed for one specific use. This is not to say that each language is good for only
one purpose. However, focusing on a single application helps language designers make
consistent, purposeful decisions. A single application also helps with one of the most difficult
parts of language design: leaving good ideas out.

Why study programming languages?

1. To improve your ability to develop effective algorithms

Many languages provide features that can be extremely useful when used properly but waste a
large amount of time when used improperly. Algorithms behave similarly, so the habit of making
correct decisions with a programming language can carry over to making correct decisions with
an algorithm.

2. To improve your use of your existing programming language

By understanding exactly how the features in a programming language are implemented, you
learn how to effectively use them. When you know how the language components such as
lists/arrays/strings work, you can use them more efficiently.

3. To increase your vocabulary of useful programming constructs

When thinking about a set of data/program structures to solve a problem, it's typical to only think
about the structures that are immediately available within the programming language you're
working with. By knowing the constructs of other programming languages, you can find one that
fits your scenario better and possibly implement it yourself.

4. To allow a better choice of programming language

Some languages are better suited than others for particular projects. You can reduce effort by
picking the one that works best.

2
5. To make it easier to learn a new language

A thorough knowledge of programming language constructs and implementation techniques


allows programmers to learn new languages more easily.

6. To make it easier to design a new language

Though you may not be making the next C or Java programming language, it's actually fairly
common to create a form of programming language on a small scale within a project.

Role of Programming Languages


Newer languages like Java and C++ have been greatly influenced by the languages before them.
These influences include:

 Computer capabilities
 Speed of modern computers
 OS software between programming language and hardware
 Applications
 Applications are no longer only for military, science, business
 PCs, Internet, and gaming have new requirements languages must fill
 Programming methods
 Language designs have changed to reflect good programming practices
 Implementation methods
 Better implementation methods affected feature choices in languages
 Theoretical studies
 Formal mathematical methods have deepened our understanding of languages
 Strengths and weaknesses of language features have been deeply evaluated
 Standardization
 The need for programs to move from computer to computer led to standards
 These standards shape how the language is designed

3
All languages have shortcomings, but some are still much better than others. External forces can
influence language popularity, but programmers ultimately decide what languages live and die.

Attributes of a good programming language


There are a lot of reasons why one programming language could be viewed as preferable to
another.

Clarity, simplicity, unity

 The language must provide a framework for thinking about algorithms


 The language must provide a way to express ideas of algorithm implementations
 Its concepts should be simple so they can be used in developing algorithms
 The language should have a minimum number of concepts (conceptual integrity)
 Language syntax determines ease of writing, reading, testing, modifying code
 Cryptic syntax may be easy to write but is usually hard to read
 Constructs that mean different things should look different.

Naturalness for the application

 Language syntax should allow the program structure to reflect the algorithm
 Examples of algorithms differing in structure are:
 sequential
 concurrent
 logic
 The language should provide the following tools for solving a problem:
 appropriate data structures
 appropriate operations
 appropriate control structures
 a natural syntax for the problem

4
Support for abstraction

 There is always a gap between abstract data structures and primitive data structures.
 The language should allow data structures, data types, and operations to be defined and
maintained as self-contained abstractions.
 Ada developed for lack of abstraction in Pascal, C++ for lack of abstraction in C

Ease of program verification

 Reliability of programs is a huge concern


 Methods of testing program correctness:
 formal verification
 desk checking
 testing via input data
 A combination of the above methods are used for large projects
 Hard program verification may outweigh language features
 Simple syntax/semantics makes program verification simpler

Programming environment

 A weak language with a good environment can be easier than a strong language
 Factors that influence the programming environment include:
 reliable, efficient, well-documented implementation
 Special editors
 Special testing packages
 Version control
 Smalltalk designed around a programming environment

Portability of programs

 Transportability of the computer a program is developed on to other computers


 A language should be widely available
 A language's definition is independent of a particular machine
 ADA, FORTRAN, C have standardized definitions for portable application dev

5
Cost of use

 Cost of program execution


 Main focus of early programming years
 Speed not a high concern anymore
 10% or 20% execution time tolerated for other benefits
 Cost of program translation
 Student programs are compiled frequently but executed few times
 A fast compiler is important for programming education
 Cost of program creation, testing, use
 Smalltalk and Perl can help solve problems with minimum investment in
programmer time and energy.
 Programming time minimized, but execution time may be larger in comparison to
other languages.
 Cost of program maintenance
 Studies show largest cost is over the life of the program, not initial
 Maintenance includes repair of errors and enhancements
 A language that makes it easy to adjust programs may be cheaper in the long run

6
Chapter Two: Language Design Issues
1. Programming Environment

A programming environment is the environment in which programs are created and


tested, and it tends to have less influence on language design than the operating environment in
which programs are expected to be executed. A programming environment consists primarily of
a set of support tools and a command language for invoking them. Each support tool is another
program that may be used by the programmer as an aid during one or more of the stages of
creation of a program. Typical tools in a programming environment include editors, debuggers,
verifiers, test data generators, and pretty printers.

1.1 Effects on Language Design

Programming environments have affected language design primarily in two major areas:
features aiding separate compilation and assembly of a program from components, and features
aiding program testing and debugging.

Separate compilation. In the construction of any large program it is ordinarily desirable to have
different programmers or programming groups design, code, and test parts of the program before
a final assembly of all the components into a complete program. This requires the language to be
structured so that individual subprograms or other parts can be separately compiled and
executed, without the other parts, and then later merged without change into the final program.

Separate compilation is made difficult by the fact that in compiling one subprogram, the
compiler may need information about other subprograms or shared data objects, such as:

1. The specification of the number, order, and type of parameters expected by any
subprogram called allows the compiler to check whether a call of the external subprogram is
valid. The language in which the other subprogram is coded may also need to be known so
that the compiler may set up the appropriate "calling sequence" of instructions to transfer
data and control information to the external subprogram during execution in the form

7
expected by that subprogram.

2. The declaration of data type for any variable referenced is needed to allow the compiler to
determine the storage representation of the external variable so that the reference may be
compiled using the appropriate accessing formula for the variable (e.g., the correct offset
within the common environment block).

3. The definition of a data type that is defined externally but is used to declare any local
variable within the subprogram is needed to allow the compiler to allocate storage and
compute accessing formulas for local data.

To provide this information about separately compiled subprograms, shared data objects, and
type definitions either

(1) the language may require that the information be redeclared within the subprogram
(in FORTRAN),

(2) it may prescribe a particular order of compilation to require compilation of each


subprogram to be preceded by compilation of the specification of all called subprograms
and shared data (in Ada and to some extent in Pascal), or

(3) it may require the presence of a library containing the relevant specifications during
compilation so that the compiler may retrieve them as needed (in Ada and C++).

The term independent compilation is usually used for option (1). Each subprogram may
be independently compiled without any external information; the subprogram is entirely self-
contained. Independent compilation has the disadvantage that ordinarily there is no way to check
the consistency of the information about external subprograms and data that are re-declared in
the subprogram. If the declarations within the subprogram do not match the actual structure of
the external data or subprogram then a subtle error appears in the final assembly stage that will
not have been detected during testing of the independently compiled program parts.

Options (2) and (3) require a means for specifications of subprograms, type definitions, and
common environments to be given or placed in a library prior to the compilation of a
subprogram. Usually it is desirable to allow the body (local variables and statements) of a

8
subprogram to be omitted, with only the specification given. The body may be complied
separately later. In Ada, for example, every subprogram, task, or package is split into two parts, a
specification and a body, which may be separately compiled or placed in a library as required in
order to allow compilation of other subprograms. A subprogram call made to a subprogram that
has not yet been compiled is termed a stub. A subprogram containing stubs may be executed, and
when a stub is reached, the call causes a system diagnostic message to be printed (or other action
taken) rather than an actual call on the subprogram. Thus, a separately compiled subprogram
may be executed for testing purposes even though code for some of the routines it calls is not yet
available.

Another aspect of separate compilation that affects language design is in the use of
shared names. If several groups are writing portions of a large program, it is often difficult to
ensure that the names used by each group for subprograms, common environments, and shared
type definitions are distinct. A common problem is to find, during assembly of the final complete
program, that several subprograms or other program units have the same names. Often this
means a tedious and time-consuming revision of already tested code. Languages employ three
methods to avoid this problem:

1. Each shared name, such as in an extern statement in C, must be unique and it is the
obligation of the programmer to ensure that this is so. Naming conventions must be adopted
at the outset so that each group has a distinct set of names they may use for subprograms
(e.g., "all names used by your group must begin with QQ"). For example, names used
within the standard C #include files are usually prefixed with _, so programmers should
avoid variables names beginning with the underscore.

2. Languages often use scoping rules to hide names. If one subprogram is contained within
another subprogram, only the names in the outermost subprogram are known to other
separately compiled subprograms. Languages like Pascal, C, and Ada use this mechanism. 

3. Names may be known by explicitly adding their definitions from an external library. This is
the basic mechanism of inheritance in object-oriented languages. By including an
externally defined class definition into a subprogram, other objects defined by that class
become known, as in Ada and C++ . In Ada, names may also be overloaded so that several
objects may have the same name. As long as the compiler can resolve which object is

9
actually referenced, no change is needed in the calling program.

Testing and debugging. Most languages contain some features to aid program testing and
debugging. A few typical examples are:  

1. Execution trace features. Prolog, LISP and many other interactive languages provides
features that allow particular statements and variables to be tagged for "tracing" during
execution. Whenever a tagged statement is executed or a tagged variable is assigned a new
value, execution of the program is interrupted and a designated trace subprogram is called
(which typically prints appropriate debugging information).

2. Breakpoints. In an interactive programming environment, languages often provide a feature


where the programmer can specify points in the program as breakpoints. When a breakpoint
is reached during execution, execution of the program is interrupted and control is given to
the programmer at a terminal. The programmer may inspect and modify values of variables
and then restart the program from the point of interruption.

3. Assertions. An assertion is a conditional expression inserted as a separate statement in a


program, e.g.,

assert( X > 0 and A = 1 ) or ( X = 0 and A > B+10 )

The assertion states the relationships that must hold among the values of the variables at that
point in the program. When the assertion is "enabled," the compiler inserts code into the
compiled program to test the conditions stated. During execution, if the conditions fail to
hold, then execution is interrupted and an exception handler is invoked to print a message or
take other action. After the program is debugged, the assertions may be "disabled" so that
the compiler generates no code for their checking. They then become useful comments that
aid in documenting the program. This is a simple concept that exists in several languages,
including C++.

2. Virtual Computers

10
A computer is an integrated set of algorithms and data structures capable of storing and
executing program. We considered ways in which a given computer might be constructed:

1. Through a hardware realization, representing the data structures and algorithms directly
with physical devices.
2. Through a firmware realization, representing the data structures and algorithms by
microprogramming a suitable hardware computer.
3. Through a virtual machine, representing the data structures and algorithms by programs
and data structures in some other programming language.
4. Through some combination of these techniques, representing various parts of the
computer directly in hardware, in microprograms, or by software simulation as
appropriate.

Virtual Computers and Language Implementations


Each time the language is implemented on a different computer, the implementer tends to see a
slightly (or very) different virtual computer in the language definition. Thus, two different
implementations of the same language may utilize a different set of data structures and
operations in the implementation, particularly for data structures and operations that are hidden
in the program syntax. Each implementer has wide latitude in determining the virtual computer
structures that are the basis for a particular implementation.

When a programming language is being implemented on a particular computer, the implementer


first determines the virtual computer that represents an interpretation of the semantics of the
language and then constructs that virtual computer out of the hardware and software elements
provided by the underlying computer. The implementer must also determine precisely what is to
be done during translation of a program and what during execution.
Three factors lead to differences among implementations of the same language:

1. Differences in each implementer’s conception of the virtual computer that is implicit in


the language definition.
2. Differences in the facilities provided by the host computer on which the language is to be
implemented.

11
3. Differences in the choices made by each implementer as to how to simulate the virtual
computer elements using the facilities provided by the underlying computer and how to
construct the translator so as to support these choices of virtual computer representation.

Hierarchies of Virtual Machines


The virtual machine that a programmer uses to create an application is in fact formed from a
hierarchy of virtual computers. At the bottom, there must, of course, lie an actual hardware
computer. However, the ordinary programmer not often has any direct dealing with this
computer. Instead, this hardware computer is successively transformed by layers of software (or
microprograms) into a virtual machine that may be radically different. The second level of
virtual computer (or the third if a microprogram forms the second level) is usually defined by the
complex collection of routines known as the operating system.

12
Typically the operating system provides simulations for a number of new operations and data
structures that are not directly provided by the hardware (e.g., external file structures or time-of-
day functions).

3. Binding and Binding Time


The binding of a program element to a particular characteristic or property is simply the choice
of the property from a set of possible properties. The time during program formulation or
processing when this choice is made is termed the binding time of that property for that element.

Classes of Binding Times


Although there is no simple categorization of the various types of bindings, a few main binding
times may be distinguished if we recall our basic assumption that the processing of a program,
regardless of the language, always involves a translation step followed by execution of the
translated program:
1. Execution time (run time): Many bindings are performed during program execution. These
include bindings of variables to their values, as well as (in many languages) the binding
of variables to particular storage locations. Two important subcategories may be distinguished:
a. On entry to a subprogram or block: In most languages, bindings are restricted to occur only
at the time of entry to a subprogram or block during execution. For example, in C and C++, the
binding of formal to actual parameters and the binding of formal parameters to particular storage
locations may occur only on entry to a subprogram.
b. At arbitrary points during execution: Some bindings may occur at any point during
execution of a program. The most important example here is the basic binding of variables to
values through assignment, whereas some languages like LISP, Smalltalk, and ML permit the
binding of names to storage locations to also occur at arbitrary points in the program.

2. Translation time (compile time): Three different classes of translation time bindings may be
distinguished:

a. Bindings chosen by the programmer: In writing a program, the programmer consciously


makes many decisions regarding choices of variable names, types for variables, program

13
statement structures, and so on that represent bindings during translation. The language translator
makes use of these bindings to determine the final form of the object program.
b. Bindings chosen by the translator: Some bindings are chosen by the language translator or
without direct programmer specification. For example, the relative location of a data object in the
storage allocated for a procedure is generally handled without knowledge or intervention by the
programmer. How arrays are stored and how descriptors for the arrays, if any, are created are
decisions made by the language translator. Different implementations of a given language may
choose to provide these features in different ways.
c. Bindings chosen by the loader: A program usually consists of several subprograms that must
be merged into a single executable program. The translator typically binds variables to addresses
within the storage designated for each subprogram. However, this storage must be allocated
actual addresses within the physical computer that will execute the program. This occurs during
load time (also called link time).

3. Language implementation time: Some aspects of a language definition may be the same for
all programs that are run using a particular implementation of a language, but they may vary
between implementations. For example, often the details associated with the representations of
numbers and arithmetic operations are determined by the way that arithmetic is done in the
underlying hardware computer. A program written in the language that uses a feature whose
definition has been fixed at implementation time will not necessarily run on another
implementation of the same language; even more troublesome, it may run and give different
results.

4. Language definition time: Most of the structure of a programming language is fixed at the
time the language is defined, in the sense of specification of the alternatives available to a
programmer when writing a program. For example, the possible alternative statement forms, data
structure types, program structures, and so on are all fixed at language definition time.

To illustrate the variety of bindings and binding times, consider the simple assignment statement
written in a language L. We might inquire into the buildings and binding times of the following
elements of this statement:

14
X=X+10
1. Set of types for Variable X. Variable X in the statement usually has a data type associated
with it, such as real, integer, or Boolean. The set of allowable types for X is often fixed at
language definition time (e.g., only type’s real, integer, Boolean, set, and character might be
allowed). Alternatively, language may allow each program to define new types, as in C, Java,
and Ada, so that the set of possible types for X is fixed at translation time.
2. Type of variable X. The particular data type associated with variable X is often fixed at
translation time through an explicit declaration in the program such as float X , which is the c
designation for a real data type. In other languages, such as Smalltalk and Perl, the data type of X
may be found at execution time through assignment of a value of a particular type to X. In these
languages, X may refer to an integer at one point and to a string at a later point in the same
program.
3. Set of possible values for variable X. If X has data type real, then its value at any point
during execution is one of a set of bit sequences representing real numbers. The precise set
of possible values for X is determined by the real numbers that can be represented and
manipulated in the virtual computer defining the language, which ordinarily is the set of real
numbers that can be represented conveniently in the underlying hardware computer.
4. Value of Variable X. At any point during program execution, a particular value is bound to
Variable X. This value is determined at execution time through assignment of a value to X. The
assignment X=X+10 changes the binding of X, replacing its old value by a new one that is 10
more than the old one.
5.  Representation of the constant 10.The integer 10 has both a representation as a constant int
he text of the program, using the string 10, and a representation at execution time,commonly as a
sequence of bits. The choice of decimal representation in the program (i.e.,using 10 for ten) is
usually made at language definition time, whereas the choice of a particular sequence of bits to
represent 10 at execution time is usually made at
language implementation time.

6. Properties of the operator +. The choice of symbol + to represent the addition operation is
made at language definition time. However, it is common to allow the same symbol + to be
overloaded by representing real addition, integer addition, complex addition, and so on,

15
depending on the context. In a compiled language, it is common to make the determination
of which operation is represented by + at compile time. The mechanism for specifying the
binding desired is usually the typing mechanism for variables: If X is type integer, then the +in
X+10 represent real addition, and so on.

In summary, for a language like C, the symbol + is bound to a set of addition operations at
language definition time, each addition operation in the set is defined at language
implementation time, each particular use of the symbol + in a program is bound to a particular
addition operation at translation time, and the particular value of each particular addition
operation for its operands is determined only at execution time.

Importance of Binding Times


A language like FORTRAN, in which most bindings are made during translation, early in the
processing of a program, is said to have early binding; languages with late binding, such as ML
or HTML, delay most bindings until execution time. The advantages and disadvantages of early  
binding versus late binding revolve around a conflict between efficiency and flexibility. In
languages where execution efficiency is a prime consideration, such as FORTRAN, Pascal, and
C, it is common to design the language so that as many bindings as possible may be performed
during translation. Where flexibility is the prime determiner, as in ML and LISP, most bindings
are delayed until execution time so that they may be made data dependent. In a language
designed for both efficient and flexibility, such as Ada, multiple options are often available that
allow choices of binding times.

4. Language Paradigms
There are four basic computational models that describe most programming today: imperative,
applicative, rule based, and object oriented.

Imperative / procedural languages


Imperative or procedural languages are command-driven or statement-oriented languages. The
basic concept is the machine state, the set of all values for all memory locations in the computer.

16
A program consists of a sequence of statements, and the execution of each statement causes the
computer to change the value of one or more locations in its memory, that is, to enter a new state.
The syntax of such languages generally has the form
statement 1;
statement 2;

Program development consists of building the successive machine states needed to arrive at the
solution. This is often the first view one has of programming and many widely used languages
(e.g., C, C++, FORTRAN, ALGOL, PL/I, Pascal, Ada, Smalltalk, and COBOL) support this
model.

Applicative / functional languages

An alternative view of the computation performed by a programming language is to look at the


function that the program represents rather than just the state changes as the program executes,
statement by statement. We can achieve this by looking at the desired result rather than at the
available data. In other words, rather than looking at the sequence of states that the machine must
pass through in achieving an answer, the question to be asked is: What is the function that must
be applied to the initial machine state by accessing the initial set of variables and combining
them in specific ways to get an answer? Languages that emphasize this view are called
applicative or functional languages.

Program development proceeds by developing functions from previously developed functions to


build more complex functions that manipulate the initial set of data until the final function can be
used to compute an answer from the initial data. Rather than looking at the successive machine
states of a computation, we consider the successive functional transformations that we must
make on data to arrive at our answer. The syntax of such languages generally is similar to

 functionn(…function2(function1(data))…)

LISP and ML are two functional languages that support this model.

17
Rule-based / declarative languages
Rule-based languages execute by checking for the presence of a certain enabling condition and,
when present, executing an appropriate action. The most common rule-based language is Prolog,
also called a logic programming language, because the basic enabling conditions are certain
classes of predicate logic expressions. Execution of a rule-based language is similar to an
imperative language except that statements are not sequential. Enabling conditions determine the
order of execution. The syntax of such languages generally is similar to the following:

enabling condition1→action1

enabling condition2→action 2


enabling conditionn→actionn

The common business application of decision tables is a form of rule-based programming.

Object-oriented programming

In this case, complex data objects are built, then a limited set of functions are designed to operate
on those data. Complex objects are designed as extensions of simpler objects, inheriting
properties of the simpler object. By building concrete data objects, an object-oriented program
gains the efficiency of imperative languages. By building classes of functions that use a
restricted set of data objects, we build the flexibility and reliability of the applicative model

18

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy