Elements of Computer Programs and Programming Languages

Elements of Computer Programs and Programming Languages

  • May 20, 2024
  • 11 min read
  • Programming concepts
Table of Contents

What can we liken computer programs to? To me, they’re like instruction manuals.

From a functional perspective, an instruction manual provides step-by-step instructions, in natural language, for performing a particular task. Similarly, a computer program consists of instructions, in a programming language , that describe how a computer can solve a specific problem.

From a structural viewpoint, an instruction manual is simply a set of sequences of characters that adhere to a natural language syntax (well-formed). For instance, “Important computer programs are.” is not a syntactically valid sentence in English, but “Computer programs are important.” is. Likewise, a computer program is a set of sequences of characters that adhere to a programming language syntax (rules).

Like instruction manuals with multiple documents or pages, computer programs can span multiple files, each containing a sequence of characters.

Just as instruction manuals reference each other, computer programs can refer to other computer programs, called dependencies. Computer programs specifically written for other programs are known as libraries.

An instruction manual may be written in one natural language but used by someone speaking another, with a translator bridging the gap. Similarly, computer programs are often written in a human-readable language, then translated to machine code computers understand. This translation is called compilation, done by a special program called compiler.

Some programming languages skip compilation, using a special computer program called an interpreter to directly execute the code. Interpreters can be likened to emulators of a computer that understand a code representation other than machine code.

This article gives a basic overview of the elements of computer programs and programming languages, focusing on the program syntax and dependencies.

A Bottom-up View of Computer Programs

As we mentioned earlier, a computer program is essentially a series of characters that follow the syntax of a programming language. These characters can be grouped to form what we call tokens.

Let’s consider the following Python program for illustration.

1# Define a function for the greeting
2def print_greeting(name):
3    print("Hello, %s!" % name)

This sample program is displayed with formatting and highlights for humans to easily understand. In fact, it is simply the following character sequence ( and represent single white space and new line characters, respectively):

#⌴Define⌴a⌴function⌴for⌴the⌴greeting↵
def⌴print_greeting(name):↵
⌴⌴⌴⌴print("Hello,⌴%s!"⌴%⌴name)↵

The sequence is split into tokens following the Python programming language syntax.

Character stream abstraction: Tokenization
Character stream abstraction: Tokenization

Similarly to English where words do not have the same nature (verb, subject, etc.), the tokens in the program do not have the same nature.

Tokens

Based on the syntax rules of programming languages, tokens fall into one of the following categories:

  • Keywords (also known as reserved words): Predefined words in a programming language that have special meanings and cannot be used for other purposes within the code. They typically represent control flow structures, data types, or other language-specific features.

  • Identifiers: Names given to various elements in a program, such as variables, functions, classes, or modules. They serve as labels to refer to these elements within the code and must follow specific naming rules defined by the programming language.

  • Literals: Constant values specified in the program.

  • Operators: Symbols or words that perform operations on operands (variables or values). These operations can include arithmetic, logical, relational, and assignment operations, among others.

  • Separators (also known as delimiters or punctuators): Symbols used to separate different elements of code or to indicate the beginning or end of specific constructs. Common separators include commas, semicolons, parentheses, braces, and brackets.

  • Comments: Annotations within the code that are ignored by the compiler or interpreter. They are used to add explanatory notes, document code, or temporarily disable code segments. Comments improve code readability and maintainability for developers.

Note

Some languages such as C /C++ and Rust specify code documentation in the form of comments. Python , on the other hand, specifies code documentation as string literals.

Higher-level Constructs

The tokens of a program can also be syntactically grouped to form a sequence of expressions, instructions, declarations and types. These are further grouped to form program units (e.g. blocks , functions , modules and more, depending on the programming language syntax).

  • Expression/Instruction/Statement: These are fundamental building blocks of a program, representing actions to be executed. Expressions produce values, instructions perform specific tasks, and statements are complete units of code. Statements are simple or compound (contain other statements). Simple statements are instructions.

  • Block: A block is a group of statements properly enclosed. It’s used to create a single unit of execution, often associated with control flow structures like loops and conditionals.

  • Conditional/Match: Conditionals are control structures that execute different code based on specified conditions. Match statements are more versatile and allow for pattern matching, providing multiple branches based on the value being matched.

  • Loop: Loops enable repetitive execution of code blocks until a certain condition is met. They come in various forms like for, while, and do-while, each with its own use cases.

  • Function/Procedure/Lambda/Closure: Functions are reusable blocks of code that perform a specific task, taking input parameters and optionally returning a value. Procedures are similar but don’t return a value. Lambdas, or anonymous functions, are small, inline functions often used as arguments to higher-order functions. Closures are functions that capture variables from their surrounding scope.

  • Declaration/Definition: These represent the process of introducing a new variable, function, or other entities into the program’s scope, typically accompanied by specifying its type and initial value (if applicable).

  • Macro (Meta-programming): Macros are language features that allow code to generate or modify other code during compilation. They’re used to create domain-specific languages, reduce code duplication, and automate repetitive tasks.

  • Module: Modules are organizational units used to group related code together, promoting encapsulation and code organization. They help manage complexity by dividing code into manageable units.

  • Package: Packages are collections of modules or libraries bundled together for distribution. They often include metadata describing the package’s name, version, and dependencies, making it easy to reuse and share code across projects.

Note

The word instruction is mostly used for low-level programming languages, e.g. Assembly language and LLVM intermediate representation . The word statement is mostly used for higher-level programming languages, e.g. C , C++ , Python and Rust .

Looking again at our sample program , at the highest level, it is a function that takes a name and prints a greeting message with that name.

Dependency in Computer Programs

Programming languages often provide ways for a program to reference or call another program, promoting modularity and reuse. Such references can be either internal or external.

Internal Dependency: This occurs between components within the same target program. Developers have control over both the dependent and dependee components.

External Dependency: This involves two separate programs, with the dependee program being external to the target (dependent) program. Here, the dependee program’s implementation is beyond the control of the dependent program’s developer.

Info

In this section, we examine the perspective of external dependencies of programs.

Note

A dependency is a program used by another program.

It can be either a:

  • Standalone program – a program that can be executed on its own.
  • Library – a program that cannot be executed on its own, but needs to be called by another program.

Programs can integrate dependencies written in various programming languages

A program and its dependency libraries contain code written in the program’s programming language. This can be viewed as though the programming language’s elements are a dependency of these. The sample Python program listed above is dependent on the Python programming language toolchain.

Program Dependencies
Program Dependencies

In a given programming language, the external dependencies of a program are either of the following 2 categories:

Provided Dependencies

These dependencies come with the programming language toolchain and are readily available for use.

Built-in library
A set of codes that are implemented in the compiler or interpreter. It is accessible throughout any program without the need for explicit importing or inclusion. It behaves as if it was an inherent part of the programming language itself.
In compiled programming languages, the compiler inserts the library’s implementation into the compiled program. In interpreted languages, the interpreter executes the code within the library when it’s called.
Built-in library’s functions are commonly referred to as intrinsic functions.
Standard library
A fundamental library required by the programming language specification to exist in all implementations of the language. It’s a library that all programs assume is available. However, it’s external to the programming language compiler or interpreter, meaning it’s not built into them. Thus, it must be explicitely “imported/included” within the calling program before use.
Typically, the standard library is included in programming language installation packages, although it’s not necessarily developed alongside the compiler or interpreter.
Some programming languages divide the standard library into multiple parts. For instance, in Rust, platform-specific functionalities of the standard library are separated to avoid requirements in restricted environments like embedded systems.
Programming toolchain (standalone programs)
Programming tools are essential for running a program. In the case of compiled programs, these tools are primarily required during the build process. Conversely, for interpreted programs, they are mainly utilized at runtime. For example, a Python program might rely on a specific version of the Python interpreter for execution.

In addition to dependencies provided by the programming language, programs may also rely on code not provided with the programming language’s toolchain.

Non-provided Dependencies

These dependencies are not bundled with the programming language toolchain. They are developed independently of both the programming language and the dependent program.

They are typically created to address common issues not covered by the provided dependencies.

Furthermore, they fall into two categories: first-party dependencies, provided by the same organization that develops the dependent program, or third-party dependencies, created and provided by external organizations.

Non-provided dependencies come in two forms:

Libraries
Non-provided libraries are developed separately from the programming language toolchain. They must be installed and “imported/included” by a program before use.
Most programming languages offer package management systems to facilitate the management non-provided dependency libraries of a program.
These libraries may rely on provided dependencies .
Some programming languages (e.g., Python) may incorporate widely used third-party libraries into their provided libraries in new language versions.
Standalone programs
Non-provided standalone programs are external executables that are not part of the programming language toolchain. They must be installed separately and are typically invoked by the dependent program as subprocesses or replacement processes. These programs are essential for the dependent program’s proper operation.
The use of standalone programs as program dependencies is most common in scripting languages such as Bash and Powershell .

Having introduced the 2 categories of non-provided program dependencies, let’s use the following example of a Python program to illustrate the different program dependencies.

Program Dependencies Illustration

Consider the following Python (version 3) program:

 1# Importing standard library module
 2import subprocess
 3
 4# Importing third party library function
 5from requests import get
 6
 7# Using third party library function
 8response = get('https://httpbin.org/ip')
 9ip = response.json().get('origin')
10
11# Using builtin function
12print('Your IP is: ' + ip)
13
14# Using standard library function to call another binary program ('ping')
15subprocess.run(['ping', ip])
  • requests is a third-party library that facilitates making HTTP requests. It is used to retrieve the program host’s public IP address.
  • print is a built-in library function, used to display the retrieved IP address.
  • The subprocess module, from the Python Standard Library , allows spawning new processes and is used to run the ping command.
  • ping is a third-party standalone program used for network diagnostics of the retrieved IP address.

Both the standard library module subprocess and the third-party library requests are imported before they are used in the Python program. However, the built-in library function print is not explicitly imported before it is used.

Key Takeaways

Computer programs, in their source code form (which is human-friendly), consist of sequences of characters logically arranged to adhere to a programming language’s syntax. They outline the instructions that the program needs to execute.

Programs often rely on code from sources outside themselves, known as external dependencies. Some of these dependencies come from the programming language itself, while others are supplied by first or third parties.

For developers learning a new language, it’s crucial to acquaint themselves with the provided dependencies so they can leverage existing functionality rather than reinventing it.