COS 333: Chapter 1, Part 2
Summary
TLDRThis script delves into the foundational concepts of programming languages, exploring the influences shaping their design, such as computer architecture and methodologies. It outlines various paradigms including imperative, functional, and logic programming, each with unique approaches to computation. The discussion also covers implementation methods like compilation, interpretation, and hybrid systems, highlighting their trade-offs in efficiency and portability. Finally, it touches on programming environments and tools that aid developers in coding, debugging, and profiling software.
Takeaways
- đ The lecture discusses preliminary concepts in programming languages, including influences on language design, language categories (paradigms), implementation methods, and programming environments.
- đ Influences on programming language design are primarily computer architecture and programming methodologies, with von Neumann architecture significantly impacting the nature of programming languages.
- đ§ Imperative programming languages, such as C, C++, and Java, are dominant due to their close modeling of the von Neumann computer architecture, focusing on variables, assignments, and efficient iteration.
- đ The evolution of programming languages has been driven by the development of new software methodologies, leading to the introduction of features like functions, modules, data abstraction, and object-oriented programming.
- đ ïž Programming language implementation methods include compilation, interpretation, and hybrid systems, each with their advantages and disadvantages in terms of execution speed, error reporting, and portability.
- đ The compilation process involves several phases: lexical analysis, syntax analysis, semantic analysis, and code generation, resulting in efficient machine code execution.
- đ Pure interpretation offers advantages like better error reporting and portability but suffers from slower execution speeds due to the need to decode high-level statements at runtime.
- đ€ Hybrid implementation systems, like the Java Virtual Machine, balance compilation and interpretation, offering improved error reporting and execution speeds while maintaining portability.
- đ Just-In-Time (JIT) systems are a type of hybrid implementation that compiles sub-programs into machine code on-the-fly, improving execution speed for subsequent calls.
- đ ïž Programming environments encompass a collection of tools that support software development, ranging from simple command-line tools in Unix-like systems to integrated development environments (IDEs) like Visual Studio and NetBeans.
- đ The course will continue to explore the history and evolution of major programming languages in subsequent chapters, providing a deeper understanding of language development over time.
Q & A
What are the main factors that influence the design of a programming language?
-The main factors that influence the design of a programming language are computer architecture and programming methodologies. Computer architecture refers to the prevalent computing hardware at the time of language development, while programming methodologies involve the software development processes and paradigms that shape the features and capabilities of the language.
Why is the von Neumann architecture significant to the development of programming languages?
-The von Neumann architecture is significant because it is the most prevalent computer architecture, and it influences the nature of programming languages by dictating how data and instructions are stored and processed. Most modern computers follow this architecture, which is why many programming languages are designed to work closely with it.
What is imperative programming and how does it relate to the von Neumann architecture?
-Imperative programming is a paradigm where programs are written as a sequence of commands for the computer to perform. It closely relates to the von Neumann architecture by modeling the use of variables as memory cells and assignments as the data transfer between memory and CPU, reflecting the architecture's design.
Why are iteration structures efficient in imperative programming languages?
-Iteration structures are efficient in imperative programming languages because they can leverage the sequential storage of values in memory. By using a counter and incrementing it, programs can easily move through memory locations, making iteration a fast and straightforward process.
How has the evolution of programming methodologies led to the development of new programming languages?
-As new programming methodologies are developed, they introduce new ways of thinking about software development. This evolution necessitates the creation of new programming languages that support these paradigms, leading to the development of languages that better accommodate the methodologies' requirements and features.
What are the three main programming language paradigms discussed in the script?
-The three main programming language paradigms discussed are imperative programming, functional programming, and logic programming. Each paradigm has its own approach to computation and problem-solving, catering to different aspects of software development.
How does functional programming differ from imperative programming?
-Functional programming differs from imperative programming in that it relies on the application of mathematical functions to parameters, without the use of variables, assignments, or iteration. It focuses on pure functions and avoids side effects, leading to a different programming style that is more declarative in nature.
What is logic programming and how does it operate?
-Logic programming is a paradigm where programs are expressed as a set of facts and rules. The programming language uses an inference engine to reason about these facts and rules to answer queries. It is a declarative approach where the focus is on the relationships between data and the logic used to derive conclusions.
What are the three main implementation methods for high-level programming languages?
-The three main implementation methods for high-level programming languages are compilation, pure interpretation, and hybrid implementation systems. Each method has its own advantages and disadvantages in terms of execution speed, portability, and ease of use.
Why is pure interpretation less efficient than compilation?
-Pure interpretation is less efficient than compilation because it involves decoding high-level statements at runtime, which is more time-consuming than executing pre-translated machine code. Additionally, the interpreter has to handle the full source program and symbol table during execution, leading to higher memory and storage requirements.
How does a hybrid implementation system, like the Java Virtual Machine, improve upon pure interpretation?
-A hybrid implementation system, such as the Java Virtual Machine, improves upon pure interpretation by translating the high-level code into an intermediate bytecode, which is then interpreted by a virtual machine. This approach allows for better error reporting and potentially faster execution than pure interpretation, while still maintaining portability across different platforms.
What is the role of programming environments in supporting software development?
-Programming environments provide a collection of tools that support various aspects of software development, such as code formatting, debugging, and performance profiling. They can range from simple command-line tools in Unix-like systems to complex visual environments like Microsoft's Visual Studio, which integrate multiple development tools into a unified interface.
Outlines
đ Influences on Programming Language Design
This paragraph delves into the foundational aspects of programming languages, focusing on the factors influencing their design. It emphasizes the impact of computer architecture and programming methodologies on language features and problem-solving approaches. The Von Neumann architecture's influence on programming languages is highlighted, illustrating how languages have evolved alongside changes in computing hardware and software development methodologies.
đ„ïž The Von Neumann Architecture and Imperative Programming
The second paragraph explores the relationship between the Von Neumann architecture and imperative programming languages, which dominate the field due to their close alignment with this architecture. It explains how features like variables, assignments, and iteration are abstract models of the Von Neumann computer's memory and CPU interaction. The paragraph also discusses the inefficiency of recursion in this context and the preference for iterative structures.
đ§ Evolution of Programming Methodologies and Languages
This section traces the historical development of programming languages in relation to evolving programming methodologies. It starts from the simplistic languages of the 1950s, designed for single-task scientific applications, to the rise of programmer efficiency in the 1960s, leading to more readable languages and structured programming methodologies. The paragraph also covers the shift towards data-oriented computation in the 1970s and the emergence of object-oriented programming in the 1980s, reflecting the ongoing adaptation of languages to support new methodologies.
đ Programming Language Paradigms and Categories
The fourth paragraph introduces the concept of programming language paradigms, categorizing them into imperative, functional, and logic programming. It discusses the prevalence of imperative programming languages and their roots in the imperative model, including object-oriented, scripting, and visual languages. The paragraph also provides a brief overview of functional programming, characterized by the application of mathematical functions, and logic programming, which relies on facts and rules for reasoning.
đ Implementation Methods for High-Level Programming Languages
This paragraph examines the mechanisms for translating high-level programming languages into executable code, discussing compilation, interpretation, and hybrid systems. It explains that compilation involves translating a program into machine language for efficient execution, while interpretation involves real-time translation by an interpreter, which is less efficient but offers better error reporting. Hybrid systems, exemplified by Java, balance these approaches for small to medium-sized applications.
đ ïž Compilation Process and Its Phases
The focus of this paragraph is the detailed process of compilation, which includes lexical analysis, syntax analysis, semantic analysis, and code generation. It describes how a source program is broken down into lexical units, transformed into a parse tree, and then into intermediate code, which is finally converted into machine code. The paragraph also mentions the role of a symbol table in maintaining information throughout the compilation process.
đ Advantages and Disadvantages of Pure Interpretation
The sixth paragraph discusses pure interpretation as an implementation method, highlighting its advantages, such as better error reporting and portability, and disadvantages, including slower execution and higher memory requirements. It explains that interpretation is suitable for small programs and situations where efficiency is not the primary concern, and notes the resurgence of pure interpretation in web scripting languages.
đ Hybrid Implementation Systems and JIT Compilation
This section introduces hybrid implementation systems as a compromise between full compilation and pure interpretation, often resulting in better error reporting and faster execution. It describes how intermediate code, such as Java bytecode, is interpreted and how Just-In-Time (JIT) systems compile sub-programs into machine code for improved subsequent execution speeds, making them a delayed form of compilation.
đ ïž Tools and Environments for Programming
The final paragraph discusses programming environments as a collection of tools that support software development in a given programming language. It contrasts the primitive tool provision in Unix-like operating systems with the integrated, complex visual environments found in modern development platforms like Microsoft's Visual Studio.NET and NetBeans, which cater to the diverse needs of software developers.
đ Conclusion of Chapter One and Preview of Chapter Two
The concluding paragraph of the chapter summarizes the fundamentals covered in the course so far and provides a preview of the next chapter, which will explore the history and evolution of major programming languages, setting the stage for a deeper understanding of their development and impact on the field.
Mindmap
Keywords
đĄProgramming Language Design
đĄInfluences
đĄProgramming Language Paradigms
đĄCompilation
đĄVon Neumann Architecture
đĄImperative Programming
đĄFunctional Programming
đĄLogic Programming
đĄHybrid Implementation Systems
đĄJust-In-Time (JIT) Systems
Highlights
Influences on programming language design include computer architecture and programming methodologies.
Programming languages are developed to work with the prevalent computer architecture at the time of their creation.
Almost all modern computers follow the von Neumann architecture, which significantly influences programming languages.
Imperative programming languages model the von Neumann architecture closely, using variables and assignments to represent memory cells and data piping.
Iterative structures like while loops and for loops are efficient in imperative languages due to the sequential storage of values in memory.
Recursion is discouraged in imperative programming languages due to high memory consumption and slow execution.
The evolution of programming languages is tied to the evolution of software development methodologies.
In the 1950s and 1960s, programming languages were simplistic, focusing on machine efficiency and ad hoc development.
The rise of programmer efficiency in the late 1960s led to more readable languages and structured programming methodologies.
Data abstraction and sophisticated data structures emerged in the late 1970s, focusing on efficient data representation and processing.
Object-oriented programming, introduced in the 1980s, combined data abstraction with inheritance and polymorphism.
Modern programming languages support component-based development, as seen in .NET programming languages.
Language categories or paradigms include imperative, functional, and logic programming, with imperative being the most prevalent.
Functional programming relies on mathematical functions and does not support variables or assignments.
Logic programming is distinct, using facts and rules for reasoning and proving statements through an inferencing engine.
Hybrid implementation systems, like Java's, balance compilation and interpretation for portability and efficiency.
Just-In-Time (JIT) systems compile sub-programs into machine code for faster subsequent calls, acting as a delayed compiler.
Programming environments encompass tools like debuggers and profilers that support software development.
Unix-like operating systems provide programming tools through terminal-based programs, while modern environments offer integrated visual tools.
Transcripts
this is the second part of chapter one
where we will continue our discussion on
some preliminaries related to
programming language concepts
these are the topics we'll be discussing
in this lecture
so we'll start off with a discussion on
various influences on programming
language design
so in other words what factors are there
that affect a programming language
and make the programming language what
it is in terms
of what features the language supports
and how it approaches solving
certain problems that all programming
languages must solve
then we'll be moving on to language
categories also referred to as
programming language paradigms
um so far you will primarily only have
experience with one of those paradigms
possibly two but we'll be outlining very
briefly
what the other paradigms are which we'll
be discussing later
on in this course next we'll be looking
at
implementation methods so here we are
discussing
how a system moves from a program
written in a high-level programming
language
to something that can actually execute
and so far you
should only have had exposure to one of
these approaches namely compilation but
there are other approaches that a
programming language can use
as well and then finally we'll be
looking very briefly
at programming environments so here
we're talking about
the set of tools that surround a
programming language
to allow you to do things such as
debugging for example
or memory profiling
when we discuss influences on
programming language design
we're talking about factors in the real
world
that affect the nature of a programming
language
now we can identify two main
contributing influences to language
design
firstly there is computer architecture
and secondly there are programming
methodologies now we'll be discussing
each of these in more detail
in the coming slides but to begin with
if we look at computer architecture we
see that programming languages are
developed so that they can work
with a particular prevalent computer
architecture that exists at the time
so in other words whenever a high-level
programming language
is developed it is developed with the
computing hardware in mind that the
programming language
needs to work with in other words
programs written in that high-level
programming language
must execute on the computer
architecture that is most widely used at
the time
now as you should recall from first-year
computer science
in cos151 all modern computers or almost
all modern computers
follow what's referred to as the von
neumann architecture
so what this means is the von neumann
architecture
is a major influence on the nature of
programming languages
both when programming languages were
first evolving
right through until the present day with
new languages that are being developed
secondly we have programming
methodologies so
when we're talking about a program
methodology we're talking about
a software development methodology in
other words the process that one goes
through in order to develop
software so examples of these
then these methodologies might be
for example the waterfall model or
object-oriented software development and
you will
learn about a number of these in the
third year project subject crop cos
301 so whenever a new
software development methodology then is
developed then this is a new way of
thinking about
developing a program and what this then
means is we have a new programming
paradigm
that evolves which then means that we
need to then develop
new programming languages that support
that paradigm
so as the thinking surrounding the
development of software projects
evolves so too then do programming
languages evolve in order to support
those methodologies
let's focus for a moment on the
influence that computer architecture has
on the nature of a programming language
so we've seen that the most prevalent
computer architecture these days
is the von neumann architecture
so to recap what we know about the von
neumann architecture
all computers that follow this
architecture store
both data and programs in a single
shared memory and this
is the core concept that was introduced
by john
von neumann after whom the architecture
is named
we also see that the shared memory
is separated from the cpu where the cpu
is responsible for actually executing
instructions
and because of the separation we also
see that instructions and data must be
piped
from the shared memory of the computer
to the cpu for processing
and in a similar fashion the results of
the processing must be piped from the
cpu
to the computer's memory now let's look
at
imperative programming languages which
are far and away
the most popular programming languages
these days
so an imperative programming language is
the kind of programming language that
you will be familiar with
so far through your studies languages
like c
plus and java so what we see is that
imperative programming languages
actually very closely model the
architecture of
a von neumann computer so
imperative programming languages rely
very heavily on the notion of a variable
which allows us to store a value with a
name
associated so a variable
is actually then an abstract model of a
memory cell
which we see in a von neumann computer
in a similar fashion imperative
programming languages also rely very
heavily on
assignments because we need some
mechanism
for placing a value in a variable
so assignment statements then are
actually abstract models
of this piping mechanism between the
computer's memory
and its cpu so for example if we assign
the results of a computation to a
variable
what we are actually modeling is
piping the result of a computation which
has been produced by the cpu
from the cpu to memory for storage
we also see within imperative languages
that iteration is very efficient
while recursion is discouraged so
iteration
is efficient because we have values that
are stored sequentially within memory
and therefore iteration can be used very
simply
by incrementing a counter
to allow us to move from one memory
location to another
and therefore access values that are
stored in sequence
within the shared memory recursion
on the other hand is discouraged because
every time that we perform a recursive
call we need to allocate
a stack frame and then deallocate that
stack frame
when a recursive call terminates
so what this means then is that
recursion will consume a lot of
resources in terms of memory and it is
also
a very slow approach to achieving
repeated executions of a set of
computations
so what this means then is that
imperative programming languages rely
very heavily
on iterative structures such as while
loops
and for loops so
this very close modeling then of the von
neumann architecture by imperative
programming languages
is actually the core most important
reason
why imperative programming languages are
so dominant these days
because imperative languages model the
von neumann architecture which
is the most prevalent architecture today
it then stands to reason
that these programming languages should
also be the most prevalent
so here we have a diagram representing
the von neumann architecture just to
illustrate
what i discussed on the previous slide
we have our
shared memory over here which stores
instructions and data
we have our cpu over here which performs
processing
and then we have the pipeline that
connects
the memory and the cpu so variables
are then simulations of locations within
memory
assignments are simulations of this
pipelining
moving instructions and data back and
forth between
memory and the cpu
now that we've discussed the influence
that computer architecture has
on the nature of programming languages
we can move on to the influence that
program methodologies
have on the nature of programming
languages so what we see
is over time more and more sophisticated
program methodologies were used within
the computing industry
which then also resulted in more and
more sophisticated programming languages
being developed
in order to support these methodologies
so if we look at the dawn of high-level
programming languages
in the 1950s and the early 1960s
we see that the applications that were
being developed were very simple
typically one was looking at primarily
scientific applications
that were designed for one programmer's
use
in other words not more widely used than
one single person
and the programs were also designed for
one very clear
very specific task so
what this meant then was that
programmers were not really using
very sophisticated program methodologies
programs were mostly being developed
on an ad hoc basis and programmers were
much more worried about
machine efficiency so what this resulted
in was that the programming languages
from this era were fairly simplistic
programming languages they didn't have
a lot of features that would make them
easier to use
for programmers and what we see is
that the control structures and
other features included within
programming languages of this time
were modeled very closely on how the
computing systems of the day
actually operated moving on a little
then
into the late 1960s what we see is
the rise of the idea that people
efficiency in other words the efficiency
of programmers who are actually writing
programs
was becoming more and more important and
actually overshadowing
machine efficiency so we then
see in that era an increase in the
readability of the programming languages
as well as the introduction of better
more sensible
control structures so hand in hand with
this
we then also see the evolution of the
structured programming methodology
which led to the ideas of top-down
design
and stepwise refinement so what this
resulted in
directly was the introduction of the
first abstraction mechanisms in
high-level programming languages
so things like functions and modules
were
introduced within programming languages
in the late 1960s
and what this allowed programmers to do
was to structure their programs in a
more sensible fashion
they would be easier to write as well as
debug and this then ultimately resulted
in the more efficient writing of
programs by the actual programmers
themselves
then in the late 1970s we
see a movement from process-oriented
computation
to data oriented computation so in other
words less of a focus
on how the results were actually
computed
and more of a focus on how those results
were actually
represented so what we see then in
programming languages
in the late 1970s is a focus on data
abstraction
more sophisticated data structures more
ways to store and represent data
and process that data in a more
efficient fashion
we see the introduction of concepts like
linked list structures for example
in this time and then in the middle
1980s
we see the rise of object-oriented
programming
so this was an extension of what
happened in the 1970s
with even more of a focus on the data
representation aspect of programs
but also then associating behavior with
these data structures so we see then
that programming languages from this era
starting with the programming language
small talk
introduced the concepts of data
abstraction as well as inheritance and
polymorphism
and these ideas together then combine
and give
us the notion of object-oriented
programming
now this evolution is still continuing
today
what we see in more modern times
is the rise of component-based
development
and this has led to even more
sophisticated programming languages
languages like the.net programming
languages which allow for
component based development we won't be
focusing on that
too much within this course but we will
get to some more detail
on c sharp which is one of the dot net
programming languages
we'll now look at the different language
categories that we will be discussing
through the remainder of this course so
language categories
are fairly often referred to as
programming
language paradigms now our discussion
will focus on
three main paradigms imperative
programming functional programming
and logic programming we won't be
focusing in too much detail
on markup and programming language
hybrids
now the main focus of our discussion
throughout this course will be on
imperative programming languages and
this is because the vast majority of
programming languages
are imperative in nature i would
estimate
that probably about 80 percent of high
level programming languages out there
today
could be classified as imperative
programming languages
so we already touched on imperative
programming languages when we were
discussing the influence that computer
architecture has
on the nature of programming languages
and there we saw that
imperative programming languages focus
on support for variables as well as
assignment
statements and they also offer support
for
efficient iteration by means of
structures such as while loops and
for loops now our discussion will also
consider
object oriented programming languages to
fall
under the category of imperative
languages and the same
is true for scripting languages and
visual languages
some texts consider oo programming
scripting
and visual languages to be separate
paradigms
however the textbook that we're using
places these all
under the umbrella of imperative
programming languages
and the reason for this is that
object-oriented
languages scripting languages and visual
languages all have their roots within
the imperative model
so if we are considering examples of
imperative programming languages
we're basically talking about languages
that you up to this point should be
familiar with
so languages like c c plus and java also
scripting languages such as perl and
javascript
and then visual languages such as the
dot
net programming languages the next
category or paradigm that we'll be
looking at
is functional programming and functional
programming is not
very different from imperative
programming however the philosophy of
functional programming is
fairly different so all computation
within a functional programming language
is done by means of applying
mathematical functions
to parameters also what is core
to pure functional programming languages
is that they don't support variables at
all
which means of course that they then
can't support assignments
and they also can't then support
iteration because iteration typically
relies on loop control variables
so in that sense functional languages
operate in a very different fashion to
imperative programming languages however
the notion
of a function is something that you will
be familiar with
from languages like c plus and java
so some examples then the functional
programming languages include lisp the
very first functional programming
language
scheme which is a dialect of lisp which
we'll be looking at in some detail a bit
later on in this course
and then ml and if sharp
now what we see in terms of functional
programming languages is that
they are definitely not as widely
represented as imperative programming
languages in terms of the languages that
are out there today
however functional programming is
becoming much more popular these days
and there are a number of companies out
there that are interested in
hiring people familiar with functional
programming languages so this is
definitely a paradigm to keep an eye on
then the third category or paradigm that
we'll be focusing on
is logic programming and this is
completely unlike imperative programming
and functional programming so within a
logic programming language such as
prologue which we'll be discussing later
on in this course
we define facts and we define rules that
can be used
to reason about these facts and these
rules
are then context independent in other
words they specified
in no particular order we can then
issue queries to our logic programming
language essentially asking the language
whether it can prove the truth
of a particular statement and then the
logic language will use
a system that it maintains behind the
scenes referred to as an inferencing
engine
and it will reason based on the facts
and rules that you've provided
to the language and then
try to prove whether the query that has
been provided to it
is true or not
and then lastly we have hybrid
markup and programming language systems
and so these don't really classify
as fully featured programming languages
in their own right
essentially markup languages are
typically
used to specify the structure of a
document so we're talking about things
like html
and xml here and some of these markup
languages have over time
been extended in order to support some
programming concepts
such as simple selection statements and
possibly loops and this allows then
for a more sophisticated specification
of what a document for example a web
document
needs to look like and it allows
specification
of dynamic structure within these
documents
so examples then of these hybrid
languages are jstl and xslt
as i've said we won't really be focusing
on
these in any kind of further detail
later on in the course
other than this brief mentioning of
these approaches next we'll look at
implementation methods for high-level
programming languages
and what we are talking about here is
the mechanism that is used
to go from a program written in a
high-level language which obviously
can't be interpreted by a computer
and then moving that into something that
actually can be executed by a computer
so the three main approaches here and
the one that you will be most familiar
with at this stage
is compilation so what we're talking
about here then
is a situation where programs written in
a high level language
are translated down into machine
language
and then this machine language forms
then an executable which can then
actually be run
on its own so at the point where we have
an executable we can then essentially
discard the program written in the
high-level programming language
because it is not required for the
execution
of the machine level instructions so
the useful compilation then is typically
for very large commercial applications
usually where efficiency is very
important
the second approach that we have
is referred to as pure interpretation so
in this case
there isn't a complete translation of a
program
from a high level representation down
into machine language
here high level programs are interpreted
by
another program which is referred to as
an interpreter so in other words the
translation of the high level program
down into something that can actually be
executed
happens at run time by means
of the interpreter so what this means
then is that pure interpretation is
usually not quite as efficient as
compilation is
the primary use for pure interpretation
is for small programs
because such programs usually execute
fairly quickly anyway
and therefore we don't have to go
through all of the trouble of performing
a full compilation
but also in application areas where
efficiency
is not at all an issue
and then in the third place we have
hybrid implementation systems and
and these systems came to the fore with
the
rise of the java programming language
so in hybrid implementation systems we
see a compromise between compilers
and pure interpreters and these hybrid
systems try to strike a balance between
the two
and sort of leverage the advantages
of both compilation and pure
interpretation
so the use of hybrid implementation
systems is typically for small to medium
sized systems
where efficiency is important but it's a
secondary concern
other concerns such as the portability
of the program code for example might be
more important than
efficiency so in the next few slides
we'll be looking at
each of these implementation methods in
some more detail
now the implementation method for a high
level programming language can be
incorporated into
a layered view of a computer system
so this holds for any implementation
system
whether it is a full compilation process
pure interpretation or some sort of
hybrid system
so in this layered view we have the
basic machine
that executes machine level instructions
right at the core
and then surrounding that we have a
macro instruction interpreter
and then an operating system
that passes through then instructions
to the macro instruction interpreter
however importantly on top of the
operating system
we then have a collection of compilers
interpreters and hybrid systems so for
example
we might have a c compiler
we might have an interpreter for lisp
and we might have some sort of virtual
machine
for a language like java for example
so each of these compilers interpreters
or hybrid systems then essentially form
a kind of a virtual computer so in the
case then
of a c compiler the virtual computer
that we have constructed
is then a computer that runs on
c code and then this is translated down
by means of the compiler to something
that eventually can be executed
on the bare machine right at the core of
the model
in a similar fashion a pure interpreter
such as the lisp interpreter
then is a virtual computer that executes
lisp commands
and those are then translated down into
something that can be executed by the
machine
and the same is then also true for a
hybrid system such as the java
virtual machine we'll now look
at each of the three implementation
methods in more detail
starting off with compilation so when we
talk about compilation we're talking
about
the full complete translation of a high
level program which is written in a
source language
such as c c plus plus or java for
example
down into machine code which is written
in a machine language
appropriate for the specific machine
architecture that the program
must run on now what we see with
compilation
is that the translation process is very
slow and there are a few reasons for
this
and firstly the full program needs to be
translated not just a portion of the
program that is currently
executing so this means that
the full translation process will then
take a lot of time because there's a lot
of code that needs to be processed
additionally we see that there are
several
phases that the translation process has
to go through which is relatively
time consuming and then finally there
may
also be a number of optimization steps
that need to be performed
in order to produce efficient machine
code
as the final result of the compilation
process
so very slow translation but in return
for the slow translation
we get very fast execution and this is
because the final result of the
compilation process
is machine code which is very close to
the low-level machine representation and
therefore
executes very efficiently now the
compilation process as i mentioned
goes through several phases the first
phase is lexical analysis
so in this phase the characters within
the source
program are converted into lexical units
and lexical units
are the components that a program is
built up out of so things like
identifiers for variable names
would be lexical units also things
like operators for example plus and
minus symbols denoting addition and
subtraction operations
would also be lexical units
now in the next phase these lexical
units are then taken
and they are transformed into a parse
tree
where the parse tree then represents the
syntactic
structure of the program in the high
level programming
language source so at this point we've
only analyzed the
syntax of our program we haven't
actually looked at the semantic
meaning of the program so that is done
in the next phase
semantic analysis and here the past tree
then
is processed in order to generate
an intermediate code representation
this intermediate code representation
can't yet be executed by the machine
so the final phase code generation then
runs through the intermediate code
and it converts it into machine code
that can actually be executed by the
computer itself
this diagram very simply illustrates the
compilation process that we've just
discussed so we start off with our
source
program written in a high level
programming language like c
or c plus plus we then go
on to the lexical analyzer which
produces
lexical units as results
um the syntax analyzer then performs the
next step which takes the lexical units
and generates a parse tree
from those units the pause tree is then
moved on to the intermediate code
generator
and potentially there may then be a
number of optimizations that need to be
performed there
and the result of that then is the
intermediate code
the intermediate code then is passed on
to the code
generator which generates then machine
language code
which can then finally be executed by
the computer
um with of course the addition of input
data
in most cases and then we finally have
results that are produced at the end of
this process
throughout the compilation process we
also have a symbol table that is
maintained
and the details on the specifics of
these various phases however
we will leave out for the remainder of
this discussion
because this is a compiler construction
related issue and not the focus of this
course
we'll now look at the second main
implementation method
namely pure interpretation now with pure
interpretation there's no translation
process
that converts our high level program
down into machine instructions
instead we have a program referred to as
an interpreter that
directly executes the source program
now the main advantage of peer
interpretation is that it is much
easier for programmers to use and this
is primarily
because the error reporting is a lot
better
so in the case of a compiled programming
language such as c
plus you should recall that any runtime
error such as a memory fault
simply causes the program to terminate
and there is no error reporting that
refers
to a specific line within the source
program where the error occurred however
in the case of pure interpretation we're
directly executing the source program
code
so if an error occurs we know exactly
which line
caused that error and that can then be
reported to the programmer
and this of course then speeds along
the debugging process and makes it a lot
easier for programmers
another advantage associated with pure
interpretation
is that purely interpreted programming
languages
are usually much more portable than
compiled programming languages
so with a compiled programming language
the translation has occurred for a
specific machine
architecture and usually that executable
code then can't just be ported
to a different system with different
hardware and possibly a different
operating system and in the case of
interpretation
usually the source program does not need
to change
for different architectures it's only
the interpreter that needs to be changed
for the specific computing platform
that the program will be executed on now
the main disadvantage with peer
interpretation
is that we see much slower execution
so usually purely interpreted
programming languages
are between 10 and 100 times slower
than compiled programming languages
so one of the reasons for this is that
instead of decoding machine language
instructions
we are now decoding high level
statements
now decoding machine language
instructions of course is very efficient
because it essentially happens on a
hardware level
however decoding high level statements
is usually a much
more involved process and therefore
takes up
more time another reason for the slower
execution
comes into play when we are talking
about loop structures
so in the case of a compiled programming
language the loop body would be
translated once
and then for each iteration of the loop
that loop body would then simply be
jumped to
and executed however in the case of a
purely interpreted programming language
the body of the loop would have to be
decoded
for each individual iteration of the
loop structure and this obviously slows
things down
because there are many more decoding
steps that need to be performed
also very often purely interpreted
programming languages require a lot more
space in terms of
both memory but sometimes also hard
drive storage space
and this is because the full source
program needs to be available during the
execution
of the program and also the full symbol
table
also needs to be present at runtime
during execution
so what we see then is that peer
interpretation these days is relatively
rare
amongst traditional high-level
programming languages
we will see in chapter 2 that peer
interpretation
however was actually a much earlier
approach
to program execution than full
compilation was
we do see however that more recently
there's
been a comeback of pure interpretation
in the context of web scripting
languages
such as javascript and php so what i'd
like you to do
at this point is pause the video and
consider
why you think pure interpretation is
appropriate
for web-based scripting languages
specifically
this diagram very simply illustrates the
interpretation process
so we simply have then our source
program
and that source program is fed into our
interpreter the interpreter also then
receives input data
from the user or possibly input files or
some other source
and then the interpreter directly
executes the source program
and then produces results by means
of that execution
the last implementation method is the
hybrid implementation system
so hybrid implementation systems take
various forms
but in general they are a compromise
between a full compiler and a pure
interpreter so typically a hybrid
implementation system
begins with a program written in
a high level language and this code then
is translated down to an intermediate
language
this intermediate language then is
interpreted
and the intermediate language is
designed to allow for easy and efficient
interpretation so in general what we see
then
is that hybrid implementation systems
incorporate the best of both worlds
and they very often have much better
error reporting than
a fully compiled language and they are
much faster than
pure interpretation usually is
so two examples then of hybrid
implementation systems
firstly we have pill programs and perl
programs
are partially compiled in order to
detect
errors before they are interpreted
now much more interesting example is the
java system where a typical java
system is hybrid in nature there are
some compilers for java that will
translate java directly into machine
code
however the major majority of systems
are hybrid implementation systems
so here when we compile a java program
then we produce an intermediate code
form which is referred to as bytecode
so if you compile a java program and it
produces
a dot class file and that dot class file
is actually then the intermediate byte
code
so this byte code then is portable
between different machine architectures
you can use the same bytecode on
for example a windows computer or an
apple mac or a linux system for example
now the specific machine architecture
then
must have a bytecode interpreter
as well as a runtime system implemented
for it
so in other words there is then a
different code interpreter and runtime
system
for each individual machine that the
java byte code
needs to be able to execute on and
together the
bytecode interpreter and the runtime
system
is then referred to as the java virtual
machine
so what this means then is that there is
only one portability
issue from the perspective of the
language designers and that is
developing a java virtual machine
for a specific platform but once that
has been done
then any program written in java that
has been translated down into bytecode
can execute then on this virtual machine
and therefore will be portable between
different systems
here is a diagram illustrating a hybrid
implementation system
so we can see that the first few steps
of
a full compilation procedure are
executed
we have our source program which is fed
into a lexical analyzer the lexical
analyzer produces lexical units which
are passed on
to the syntax analyzer the syntax
analyzer builds parse trees
out of the lexical units and then the
parse trees
are sent onto the intermediate code
generator
which generates the intermediate code
in the form of something like bytecode
in the case of java
once we have the intermediate code the
remaining compilation
process steps are not executed in order
to generate
machine level code we now simply have
an interpreter which then
executes on the intermediate code of
course
it will typically accept some sort of
input data
and then finally it will then generate
results from the execution of this
intermediate code
a specific and very interesting example
of a hybrid implementation system
is referred to as a just in time
implementation system
just in time implementation systems are
usually referred to as
jit systems so a jet
system will first translate the
entire program to an intermediate
language in exactly the way that we've
just
seen for any hybrid implementation
system
however things change in terms of how
sub-program
calls are dealt with so a sub program
is something like a function or a method
or a procedure in a programming language
so whenever a sub program is called then
the intermediate language
for that sub program is compiled down
into machine code this machine code
version is then
obviously executed for the call to the
sub
program however it's kept around
essentially it is cached
for subsequent calls so what this means
then is that the first call to the
sub-program will be slower
because the compilation process has to
take place
however every subsequent call to the
sub-program will then be faster because
we already have the machine code
version of that sub program so
in essence then a jet system is a
delayed compiler it only compiles what
needs to be compiled based on the
execution
of the program so jet systems
are seen in a few cases a lot
of modern java implementations
use jet systems and we also
see that the net languages developed by
microsoft are also implemented using
jitter systems
finally we'll take a quick look at
programming environments
so when we talk about programming
environments we're talking about
the collection of tools that surround a
programming language
and support the use of that programming
language for the development
of software now these tools can take a
variety of different forms
we might for example have automatic code
formatters or code beautifiers
that can format format our code
according to
a specific standard we can also have
debuggers
and we can have code profilers for
example
that we can use to analyze the memory
usage and overall performance
of programs we've written while
they are executing now there are
different ways that these tools can be
provided to a programmer
and a very early example of this is the
unix operating system
when i say unix operating system i mean
the unix-like operating systems which
also
incorporate linux so the unix operating
system is an older operating system
and therefore the collection of tools is
provided in a fairly primitive fashion
by means
of separate programs that can be
executed within a terminal
so for example under the linux operating
system we have the gnu debugger
which is gdb and that is a separate
program that can be executed within a
terminal now of course these days modern
unix-like operating systems use visual
front-ends such as kde
or gnome however these visual front-ends
behind
the scenes still run the lower level
terminal based tools that are provided
within the program
programming environments within
unix-like operating systems
more modern programming environments
have very complex visual environments
that are
very large and very
complicated and support the work of a
software developer in a lot of different
ways
so one example of this is microsoft's
visual studio.net platform
a very complex environment where all of
these various tools have been integrated
into the visual environment and
therefore they are directly
accessible to the programmer
through the visual environment directly
through the editor
so this environment then within visual
studio can be used to build both
web and non-web-based applications in
all of the
net programming languages and therefore
we have support for multiple different
languages that can interface
all through the same visual environment
netbeans is another example of a
relatively
complex visual environment very much
like visual studio.net however it is
developed
for java web applications
right so that concludes our discussion
on chapter one
we've discussed all of the fundamentals
which
we will be using throughout the
remainder
of the chapters that we will be covering
within this course
in the next lecture we will be moving on
to
chapter two where we will look at a
history
of the evolution of the major
programming languages
5.0 / 5 (0 votes)