Skip to ContentGo to accessibility pageKeyboard shortcuts menu
OpenStax Logo
Introduction to Computer Science

7.1 Programming Language Foundations

Introduction to Computer Science7.1 Programming Language Foundations

Learning Objectives

By the end of this section, you will be able to:

  • Describe what HLLs are
  • Summarize choosing appropriate HLLs
  • Outline the history of HLLs
  • Describe the implementation of HLLs

A high-level programming language is designed to be easy for humans to read, write, and understand. It abstracts away most of the complexities of the underlying hardware and machine code, allowing programmers to focus on solving problems and designing software without needing to manage the low-level details of the computer’s architecture.

What Are HLLs?

High-level programming languages give humans the ability to direct computers to perform tasks and applications. There are many HLLs to choose from. Java is a popular choice for its ability to run on various operating systems (i.e., Windows, macOS, Linux) and mobile platforms (Android). This is called cross-platform compatibility. For development specifically targeting Windows systems, C# is another strong option. Additionally, to create the visual elements of a website, programmers can utilize HTML and CSS. HTML provides the structure and content of the web page, while CSS controls how web pages are styled and presented. Over time, many HLLs have evolved into a mature set of tools that are used to create modern applications (Figure 7.2).

HLLs: Foundations (1950–1972) – C, BCPL, ALGOL, COBOL, LISP, Fortran, A-O, Plankalkül; Revolution (1972–991) – Perl, Haskell, Objective-C, C++, Smalltalk; Evolution (1991–2000) – JavaScript, Ruby, Python, Java; Divergence (2000–present) - GO, Rust, Kotlin, Clojure, Elixir.
Figure 7.2 High-level programming languages have advanced from the foundational languages in the middle of the 20th century to more than 2500 HLLs that exist today. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)

Learning Motivations

Studying the fundamental concepts provided by various HLLs is necessary to choose them correctly, employ them effectively, and program efficiently. From a user point of view, examining HLL concepts helps the user get better at thinking and expressing algorithms. From an implementor’s point of view, understanding HLL concepts helps programmers abstract away from (virtual) machines and become better at specifying what they want the hardware to do without getting down into the bits. In the end, studying HLL concepts helps programmers make better use of whatever HLL they use.

Implementing Abstraction

One way to relate to abstraction is as a way of thinking and expressing algorithms to indicate what the programmer wants the hardware to do. For example, the following statement represents one form of abstraction in the Java programming language:

System.out.println("Hello world!");

It tells the computer’s operating system at a high-level of abstraction to output a string of characters, which practically consists of moving the pixels that form characters one by one to a hardware device.

Implementing a high level of tasks would be impossible without abstraction. For example, you would not want to program an invoicing application in 1s and 0s (machine language); abstraction allows a programmer to build it in an English-like syntax.

Abstraction may be taken to much higher levels. It is one of three central principles (along with encapsulation and inheritance) in such object-oriented HLLs as C++, Java, C#, and Python. Various programming paradigms were introduced in Chapter 4 Linguistic Realization of Algorithms: Low-Level Programming Languages, particularly the mechanisms of object-oriented programming (OOP) and its standards, perspectives, or sets of ideas that may be used to describe the structure and methodologies of an HLL. Object-oriented HLLs help organize software design around data, or objects, rather than functions and logic, as we will discuss in Alternative Programming Models.

Choosing Appropriate HLLs

Studying and understanding HLL concepts allows us to make most efficient use of them by becoming familiar with various criteria that may be used to evaluate them, which helps us choose the most appropriate language for a project. Some of these criteria are listed in Table 7.1, which also shows how they are related to the characteristics of an HLL. These criteria are as follows:

  • readability: measures how easily an HLL can be read and understood
  • writability: measures how easily an HLL can be used to create and modify programs
  • reliability: measures conformance to specifications

There are many other criteria including scalability, cost, flexibility, efficiency, portability, and maintainability. These can be used to identify which HLL is best suited for a given task.

Characteristic Readability Writability Reliability
Simplicity: a manageable set of features and constructs
Orthogonality: a relatively small set of primitive constructs can be combined in a relatively small number of ways
Data types: adequate predefined constructs to hold data
Syntax design: form and meaning via self-descriptive constructs and meaningful keywords
Supports abstraction: hides all but the relevant data about an object in order to reduce complexity and increase efficiency  
Expressivity: relatively convenient ways of specifying operations  
Type checking: built-in testing for type mismatches    
Exception handling: support for catching run-time errors and specifying corrective measures    
Restricted aliasing: presence of two or more distinct referencing methods for the same memory location    
Table 7.1 Criteria for Measuring Characteristics of HLLs

Learning New HLLs

Studying the concepts of HLLs makes it easier to learn new HLLs since most have similarities in syntax, structure, and semantics. There are also several best practices that apply to different HLLs. A best practice is the most accepted style and structure of code that can be used to ensure proper software development, which makes it possible to learn new languages easily once a programmer has mastered a given one. The HLLs that are most used as teaching languages today are Java, C++, and Python. Java and C++ are languages that take a significant amount of study to master, while Python is considered a much simpler language to learn.

Best Use of HLLs

Programmers have to figure out how HLLs support certain features. For example, a variable gives a name to a memory location that is used in any HLL to hold a value. However, different languages use variables differently. Java is a strongly typed language, meaning that a variable may only contain a value of one of the language’s defined data types for its entire existence. Therefore, a variable that is a number cannot become a string of text. JavaScript is weakly typed so a variable may at different times hold values of any of the language data types. It may be storing a number, then later, the same variable may store a string of characters.

Another example is the use of pointers in C and C++. As visible in Figure 7.3, the pointer is the variable that holds actual computer memory addresses, but they do not exist in Java. However, understanding how C handles memory makes it easier to understand how data is passed from one place to another in Java or C#.

Image of AC pointer variable “a” (storage address 0002, content 1008) pointing to variable “b” (storage address 1008).
Figure 7.3 A C pointer variable “a” holds the memory address of the “b” variable. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)

Languages Are Purpose Driven

Let’s again contrast C/C++ and JavaScript. Much of the syntax and grammar are the same, as are the flow of control structures of the language.

So why pick one over the other? The answer is that languages are designed to fulfill certain purposes. C/C++ is a general-purpose programming language. As such, it is powerful for applications that include both systems programming and object-oriented graphical user interface (GUI) programming, JavaScript is intended for web programming.

Although programming languages differ in syntax, they all have libraries or packages that are installed as part of the language development environment. These libraries expose various functions via an application programming interface (API). These functions support the tasks for which the language is purposed while not requiring additional coding. The following illustrates the use of a C++ library function that prints a string to the screen:

cout << "Hello world!";

JavaScript’s API contains a comprehensive set of features that enable the manipulation and dynamic behavior of web pages. A JavaScript API function that prints to the web page:

document.write("Hello world!");

Technology in Everyday Life

Using Map APIs to Navigate Your World

APIs are toolkits for programmers. They provide building blocks that make it easier to create software applications. API functionality can also help people with everyday life situations. For example, Google provides a JavaScript Maps API for customizing map content to display on web pages. Imagine you are planning a road trip. You can then use the Maps API to create a customer map with your planned route, stops, and estimated travel times. Now imagine you own a coffee shop. The Maps API can then help you display your location and operating hours on a map, making it easier for customers to find you. Want to learn more about building apps with APIs? Check out the Maps JavaScript API resource.

Google the APIs for an HLL that we have mentioned and find some functionality that applies to everyday life. Think of an app you use every day. How do you think it might use APIs? Provide a couple of scenarios to explain your choice.

History of HLLs

The evolution of HLLs began so that programmers could write programs in a familiar notation rather than using numbers (machine languages) or mnemonics (assembly languages). While there may be similarities in syntax among them, there are distinct purposes for which their development occurred. There is a much larger variety of HLLs than the ones mentioned in this section, but we will be looking at a few up close.

Fortran

In the early 1950s, IBM created one of the first HLL compilers for the Fortran language, which is one of the single biggest advances in computing. While Fortran was mostly used in mathematics and science, it could be easily read. Fortran makes it possible for programmers to comment their code by starting program lines with “!”. It uses conditional statements with goto statements to branch out to different parts of the code. It also uses “do...end do” iterative statements. It was also the first HLL to use a compiler, computer software that converts source code from one language to another.

! Compute the average
Average = Sum / List_Len
! Count the values that are greater than the average
Do Counter = 1, List_Len
   If (Int_List(Counter) > Average) Then
      Result = Result + 1
   End If
End Do

COBOL

Common Business-Oriented Language (COBOL) was developed to be a high-level language for business that was standardized by the American National Standards Institute (ANSI) group in 1968. COBOL represents a distinct milestone in the evolution of computer science because of the ways in which it differed from Fortran.

The following code snippet illustrates reading an inventory record and computing the available stock:

100-PRODUCE-REORDER-LINE.
   PERFORM 110-READ-INVENTORY-RECORD.
   IF CARD-EOF-SWITCH IS NOT EQUAL TO "Y"
      PERFORM 120-CALCULATE AVAILABLE STOCK
      IF AVAILABLE STOCK IS LESS THAN BAL-REORDER-POINT
         PERFORM 130-PRINT-REORDER-LINE

110- READ-INVENTORY-RECORD.
   READ BAL-FWD-FILE RECORD
      AT END
         MOVE "Y" TO CARD-EOF-SWITCH.

. . . .

We can see that COBOL has a very different type of syntax than Fortran. It is purposed differently as it is very aligned to business applications and the programming of specific business activities that make up business processes.

BASIC

Beginner’s All-Purpose Symbolic Instruction Code (BASIC) was developed in 1971. It is a programming language that has enjoyed widespread use. A variation of BASIC referred to as Visual Basic (VB) was the language responsible for much of the development work performed on the new generations of personal computers as it was easy to learn and read. Today it has evolved into Visual Basic .NET.

The following code snippet illustrates the same computation and comparison of an average we did in Fortran but this time in BASIC:

REM Compute the average
average = sum / listlen
REM Count the values that are greater than the average
FOR counter = 1 to listlen
   IF intlist(Counter) > average
      THEN result = result + 1
   End If
NEXT

Note that the BASIC syntax has its roots in Fortran but is more efficient.

Pascal and C

The programming languages introduced so far follow the imperative language paradigm that emphasize a “tell the computer what to do” approach. Pascal and C distinguish themselves by being both procedural and imperative languages, and they were invented at approximately the same time. A procedural language allows programmers to group statements into blocks of code within the scope of which variables may be defined and manipulated independently from the rest of a program. These blocks can be named, in which case it allows programmers to create functions or procedures that can be called from other parts of a program. Similar to other imperative languages, both Pascal and C also focus on evaluating expressions and storing results in variables (e.g., a = 10; b = 5; c = a + b).

The following Pascal code snippet illustrates the same computation and comparison of the average computed previously in BASIC:

{ Compute the average }
average := sum / listlen;
{ Count the values that are greater than the average }
for counter := 1 to listlen do
   if (intlist[counter] > average) then
      result := result + 1;

The introduction of procedures in Pascal improved programs’ readability by allowing programmers to write more modular code. Pascal became the preferred teaching language during the 1970s and early 1980s.

Pascal was overshadowed in commercial applications by C, which came into existence after the initial work on the UNIX operating system was completed in the late 1960s. That first OS version was written in assembly language, yet in the early 1970s, C became a better alternative. At the time, it was the perfect language for creating operating systems and was a huge commercial success.

The following C code snippet illustrates the same computation and comparison of the same computed average:

/* Compute the average */
average = sum / listlen;
/* Count the values that are greater than the average */
for (counter = 0; counter < listlen; counter++)
    if (intlist[counter] > average) result++;

The introduction of functions in the C language improved programs’ readability and writability by allowing programmers to write more modular code. The C language runtime was also more efficient. C became the preferred language for commercial applications during the 1970s and early 1980s.

C++ and Objective C

By the mid-1980s, businesses started focusing on user experience (UX), the overall experience of a person using a computer application, especially in terms of how easy or pleasing it is to use, and the user interface (UI), the point at which human users interact with a computer, website, or application. Windows-based UIs were adopted as new paradigms, which drove the creation of standards, perspectives, and sets of ideas that should be used to describe the structure and methodologies of an HLL. This resulted in the adoption of the OOP paradigm and the creation of OOP languages. The shift to OOP allowed software to focus on data and objects.

The C++ programming language extended the middle-level language features of C with OOP features that facilitated the expression of real-world requirements in programs, including in particular the support of graphical user interfaces (GUIs). Microsoft adopted C++ as the programming language for its Windows systems.

The syntax of the code in C++ for basic computation is exactly the same as the C code shown previously. There are major syntactical additions in C++ to support OOP. It became the preferred language during the mid-1980s and early 1990s and for the programming of GUIs. The code in Figure 7.4 illustrates the basics of Windows GUI programming using C++ and the Win32 API to create a simple “Hello World!” application with a graphical user interface (GUI).

Images of code in C++ and Win32 API.
Figure 7.4 This GUI shows the “Hello World!” application using C++ and the Win32 API. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)

Objective-C is another hybrid language from the 1980s that makes use of imperative procedural, and object-oriented features. Apple adopted it to power their operating systems development efforts and became popular for a while as Apple’s only accepted language for programming apps for iPhones, later replaced by Swift.

Java

Consumer electrical devices, such as microwaves and interactive TVs, called for the invention of another OOP language: Java. Java evolved into a platform-independent, general-purpose language for computational devices, usable for everything from PCs and MACs to Androids and Samsung refrigerators. To this day, it remains one of the most widely used languages for teaching OOP and is one of the most popular HLLs in the world.

As shown in Figure 7.5, the syntax of the code in Java for typical computations is similar to that of the C code shown earlier. This is the case for most modern HLLs introduced since 1990.

Image showing Java Containers with a Frame (top-level container) and a Panel (Partitions). Java Components visible with Label (with TextField), and Buttons.
Figure 7.5 These are some of the elements available from the Java GUI API. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)

Scripting Languages

A scripting language is characterized by placing a list of code statements into a file, referred to as a script. Script statements are typically interpreted line by line rather than being compiled as complete units to produce executable programs. There are advantages and disadvantages to interpreting and compiling methods, which we will cover in Implementation Approaches.

The most popular scripting languages employ C-like syntax, but they are purposed for different applications. For example, the JavaScript and PHP scripting languages are purposed for programming web applications.

Concepts In Practice

HLLs and Web Applications

Most HLLs that are used to develop web applications are scripting languages. These include JavaScript, PHP, ASP.NET, and Python. JavaScript is nearly universal for front-end (browser, client-side) applications. Web servers such as the Apache web server and Microsoft’s Internet Information Services (IIS) server support a Common Gateway Interface (CGI) that allows the invocation of server-side programs including scripts.

Some of these scripting languages are now bolstered by web frameworks that are designed to support the development of applications in the particular languages. For example, the most popular framework for web applications today in JavaScript is React. The most popular one for Python is Django. A guide to web frameworks may be found at the Statista website.

C#

In 2000, Microsoft announced C# would be its flagship language. It also has the same fundamental syntax as C++ and Java. However, it is purposed to support Windows applications by closely tying in with Microsoft’s net framework, but it can also be used on Linux and macOS. Net C# is a multi-language, component-based software development tool designed to play nicely with all of the .Net languages including C#, Visual Basic.Net, and Managed C++.

Industry Spotlight

HLLs in Industry

HLLs are important in every industry. One example is Python. Part of its purpose is to support data analytics to process complex data, a major focus of many industries today. It does this with built-in analytics tools in its API which can process raw data and produce information and graphics that can be used to make business decisions. For example, a company interested in generating a graphical representation of its products’ sales across various regions during the past year may use Python data analytics and plotting libraries.

Can you elaborate on how useful it will be to know about HLLs in an industry of your choice (e.g., finance, gaming, travel)? Hint: Think about industries which tend to specialize in specific areas.

Logic-Based Languages

Logic-based programming languages are those which incorporate a syntax to represent facts and rules about approaches to problems. They have been used to support rule-based approaches as part of the development of artificial intelligence (AI), the simulation of human intelligence by machines such as computers.

The most common language for logic-based programming is Prolog. It is used for both AI and linguistics programming. It is actually an older HLL first developed in 1972 and has stayed with us, receiving extensive updating as AI developed. Figure 7.6 illustrates on the left side how facts and rules can be specified in Prolog. The query window on the right side illustrates how the Prolog fact database can be queried to leverage available rules.

Image showing (left) Program Window displaying facts and rule specifications in Prolog; (right) Query Window illustrating how the Prolog fact database can be queried to leverage available rules.
Figure 7.6 This sample program and query show the details of how to use Prolog. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)

The Implementation of HLLs

All computer languages can be grouped into particular categories. These are based upon support for certain programming paradigms (standards, perspectives, or sets of ideas that may be used to describe the structure and methodologies of an HLL). These paradigms include imperative/procedural, logical, functional, object-oriented, event-driven (the behavior of programs is controlled by actions (events) which are listened for and then acted upon or handled), and parallel programming (dividing a program into concurrent processes). Our modern HLLs are almost always hybrid combinations of these. We will learn about this in more detail in the following subsections of this chapter.

Imperative/Procedural Programming

As we have discussed, imperative HLLs take the “tell the computer what to do” approach. This approach is different from that of declarative HLLs that tell a program to obtain information without prescribing how the program should go about doing it. Declarative languages are used to interact with systems that are programmed to figure out these details. An example of a declarative language is Structured Query Language (SQL), which is used to specify a query that a database system can process to store or retrieve data. Imperative languages typically focus on evaluating expressions and storing results in variables. There are other shared features of these languages, such as iteration (looping or repetition).

Procedural languages extend the imperative paradigm. They make use of procedure calls to change the flow of control. A procedure (function) can be called from anywhere in a program to have it perform a particular job. Some of the languages that support this paradigm are Fortran, COBOL, Pascal, Visual Basic, Ada, C, C++, and C#. Scripting languages, including Python, JavaScript, and PHP, may also be of this type.

Event-Driven Programming

Most imperative languages also embrace event-driven programming. This paradigm allows the generation of events (for example, as a user clicks on a button). In general, computer operating systems constantly process events of various types that result from interaction with users or are generated by application programs or computer hardware. In event-driven programming, a program is told to listen for selected events, such as the single-click on a particular object (e.g., a button on a UI). The programmer establishes an event handler to deal with the event whenever it is triggered.

Parallel Programming

This paradigm refers to the computer’s ability to process multiple tasks at the same time, which is especially useful in modern multicore systems. However, a program may not be allowed to execute across multiple cores without proper synchronization. For example, the program in one core may need a result or data item that is being produced by the program in another core. Therefore, effective parallel programming must have the tools by which to synchronize processes. The Ada programming language introduced built-in support for concurrent programming using tasks and protected objects. Ada tasks are defined with the task keyword and have their own declarations and executable parts. While tasks help structure programs in concurrent flows, protected objects safeguard shared data, ensuring that only one task can access them at a time to avoid race conditions and deadlocks. Other examples of HLLs that support parallel programming include C++, Java, and C.

Implementation Approaches

As we have learned, language implementations are commonly differentiated into those based on compilation and those based on interpretation. Many modern languages make use of a hybrid execution style.

Pure Compilation

In pure compilation, programs are translated directly into machine language. The compiler takes the entire high-level source code program and produces an equivalent object code. The compiler is not used in the actual execution of the program; the object program is launched by the operating system and executes on the underlying machine from start to finish as shown in Figure 7.7.

Illustration of a Source code program (high-level source code) passing through a Compiler and resulting in an Object code program (binary zeroes and ones)
Figure 7.7 A sample C++ source program is compiled into machine language to run on a particular platform. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)

The advantages of pure compilation are better performance and better code analysis to detect source code typing errors. The disadvantage is that the compiled program is platform dependent and must be recompiled for other target machines. Examples of purely compiled languages include C and C++.

Pure Interpretation

In pure interpretation, programs are translated by another program known as an interpreter. The interpreter executes the program line by line. Because the interpreter executes the program, it is not platform dependent and is designed to execute code for the platform on which it resides. The disadvantages of interpretation are the slower execution speed due to having to both translate and run each line. Examples of purely interpreted languages are JavaScript, PHP, and Python.

Hybrid Implementation

Some language implementation systems are a mix of compilers and interpreters which is known as hybrid implementation, a method of language translation which involves the use of both a compiler and an interpreter. The compiler first translates the HLL programs to an intermediate language, a language that is generated from programming source code, but that the CPU cannot typically execute directly. Some hybrid implementations allow easy interpretation during execution using just-in-time (JIT) translation, in which intermediate language is translated and executed exactly when needed. This method is much faster than pure interpretation.

Java is a good example of a hybrid implementation system, purposed to give the language platform independence. As illustrated in Figure 7.8, the compiler translates the HLL source code to intermediate bytecode, object code produced by Java compilation which is then interpreted by the Java virtual machine (JVM), the Java interpreter that translates bytecode into executable code. This enables the same source to be used on all platforms for which a JVM has been constructed.

Chart starting at Source code, then Java compiler, to Byte code, to Java virtual machine (JVM), and separating out to Windows, Linux, and Mac.
Figure 7.8 A Java source program is compiled into an intermediate language then interpreted to produce and execute object code to run on a particular platform. (attribution: Copyright Rice University, OpenStax, under CC BY 4.0 license)

C#, and the other .NET languages, are implemented with a different JIT system. The compiler produces managed code into which the .NET languages are translated. The runtime environment is known as the Common Language Runtime (CLR), which takes managed code and provides a JIT execution that allows all the languages to play nicely with each other. This hybrid implementation is purposed for cross-language in addition to cross-platform compatibility.

Think It Through

HLLs and TechWorks

Come up with one application for TechWorks that will implement a particular part of the business (e.g., finance, sales, advertising). Briefly state the application and its objective. For this application, what will you choose as an implementation HLL—compiled, interpreted, or hybrid? Explain why.

Programming Environments

Programming environments include a collection of tools used in software development. Depending on which operating system and HLL you are using, there are many options for a software development environment. This bundle of tools targeted for a specific HLL that helps with source code editing, compilation and/or interpretation, debugging, styling, and other useful programming tasks.

Citation/Attribution

This book may not be used in the training of large language models or otherwise be ingested into large language models or generative AI offerings without OpenStax's permission.

Want to cite, share, or modify this book? This book uses the Creative Commons Attribution License and you must attribute OpenStax.

Attribution information
  • If you are redistributing all or part of this book in a print format, then you must include on every physical page the following attribution:
    Access for free at https://openstax.org/books/introduction-computer-science/pages/1-introduction
  • If you are redistributing all or part of this book in a digital format, then you must include on every digital page view the following attribution:
    Access for free at https://openstax.org/books/introduction-computer-science/pages/1-introduction
Citation information

© Oct 29, 2024 OpenStax. Textbook content produced by OpenStax is licensed under a Creative Commons Attribution License . The OpenStax name, OpenStax logo, OpenStax book covers, OpenStax CNX name, and OpenStax CNX logo are not subject to the Creative Commons license and may not be reproduced without the prior and express written consent of Rice University.