optional · CSS study notes
I.14 Types of Programming Languages
⬆️ Back to: P-I.I. Introduction to Computing
🧭
Page Outline — click a heading to jump. Past-paper questions sit in the last section.
🎯
Exam pattern (2016–2026): 2017 Q3(a) language types and conversion (8) · 2024 MCQ Q14 (cross compiler).
CSS Computer Science (Optional) — Paper-I, Section-A, Topic I, p.24-28. Covers: Types of Programming Languages.
Definition
- Programming Language: a formal, artificial language made up of a defined vocabulary and set of grammar/syntax rules, used to write instructions (a program) that a computer can execute — the means of communication between a programmer and a machine.
- Every programming language ultimately must be translated (or already be) in the binary machine code the CPU can directly execute — languages differ in how close their syntax is to that machine code versus to human/natural language.
Classification of Programming Languages
Programming languages are classified along three largely independent axes — an exam question may ask about any one of them:
- By level/generation: how close the language is to machine code vs human language (Low-level ↔ High-level; 1GL-5GL).
- By translation method: how the code is converted into something the CPU can run (Compiled, Interpreted, Hybrid).
- By programming paradigm: the style/approach used to structure a solution (Procedural, OOP, Functional, Logic-based, Scripting).
By Level: Low-Level vs High-Level
- Low-level languages
- Definition: close to the hardware/machine code; minimal or no translation needed.
- Includes: Machine language (1GL), Assembly language (2GL).
- Pros/Cons: very fast, gives direct hardware control — but hard to read/write, and not portable across different CPU architectures.
- High-level languages
- Definition: closer to human/natural language; must be translated by a compiler or interpreter before the CPU can run them.
- Includes: 3GL and above (C, Java, Python, SQL, Prolog, etc.).
- Pros/Cons: easier to read, write, and maintain, and portable across machines — but requires a translation step and can be less hardware-efficient than low-level code.
- Exam angle: "differentiate low-level and high-level languages" is a very common short-answer question — the core answer is closeness to hardware vs closeness to human language, plus the resulting portability/translation trade-off.
By Generation
| Generation | Description | Example |
|---|---|---|
| 1GL — Machine Language | Raw binary instructions the CPU executes directly; no translation needed; extremely hardware-specific (low-level) | Binary opcodes |
| 2GL — Assembly Language | Uses mnemonic codes (MOV, ADD) instead of raw binary; requires an assembler to convert to machine code (low-level) | Assembly |
| 3GL — High-Level Language | Human-readable syntax, portable across machines; requires a compiler/interpreter (high-level) | C, C++, Java, Python |
| 4GL — Very High-Level Language | Task-specific, closer to natural language, often used for database queries/report generation (high-level) | SQL |
| 5GL — Constraint/Logic-Based | Programs specify goals/constraints rather than step-by-step instructions; the system determines how to achieve them (high-level) | Prolog |
By Translation Method
- Compiled languages: entire program translated to machine code before execution — faster execution, but must fully recompile after any change (C, C++).
- Interpreted languages: translated and executed line-by-line — easier to debug interactively, but generally slower (Python, JavaScript in early engines).
- Hybrid (bytecode-based): compiled to an intermediate bytecode, then run by a virtual machine, often with Just-In-Time compilation — combines portability with reasonable speed (Java, C#).
By Programming Paradigm
- Procedural
- Definition: code organized as a sequence of instructions grouped into procedures/functions that operate on data passed to them.
- How it works: executes top-to-bottom, calling procedures/functions in a defined order; data and functions kept separate.
- Examples: C, Pascal, FORTRAN.
- Pros/Cons: simple and efficient for straightforward, linear tasks — but harder to manage/extend as programs grow large.
- Object-Oriented (OOP)
- Definition: code organized around objects/classes bundling data (attributes) and behaviour (methods) together.
- How it works: relies on encapsulation (hiding internal details), inheritance (reusing/extending classes), and polymorphism (one interface, many implementations).
- Examples: C++, Java, Python (also supports OOP).
- Pros/Cons: promotes code reuse and easier maintenance for large, complex systems — but adds design overhead and a steeper learning curve for simple tasks.
- Functional
- Definition: computation expressed as evaluation of mathematical functions, avoiding changing state or mutable data.
- How it works: functions take inputs and return outputs with no side effects (pure functions) — same input always gives the same output.
- Examples: Haskell, Lisp, functional-style features in Python/JavaScript.
- Pros/Cons: easier to test, debug, and parallelize (no shared mutable state) — but can feel less intuitive for imperative/step-by-step thinkers.
- Logic-based
- Definition: programs expressed as facts and rules; results derived through inference/pattern-matching rather than step-by-step commands.
- How it works: the programmer states what is true (facts/rules); a built-in inference engine works out how to answer queries.
- Examples: Prolog.
- Pros/Cons: well suited to AI, NLP, and rule-based expert systems — but poorly suited to numeric/performance-heavy computation.
- Scripting
- Definition: typically interpreted, lightweight languages used for automation and "gluing" other systems/programs together.
- How it works: executes commands directly (often line-by-line) without a separate compile step.
- Examples: Bash, Python, JavaScript.
- Pros/Cons: fast to write/modify, ideal for automation/prototyping — but generally slower at runtime than compiled languages for heavy computation.
MCQ Traps
- 1GL needs no translator; 2GL needs an assembler; 3GL+ needs a compiler or interpreter — a very commonly tested sequence.
- Java is not purely interpreted — it compiles to bytecode first, then the JVM interprets/JIT-compiles that bytecode (hybrid model), a frequent trick-question setup.
- SQL is a 4GL, not a 3GL — its task-specific, near-natural-language design is what pushes it up a generation.
- Low-level ≠ "bad" and high-level ≠ "always better" — low-level languages trade readability for speed/hardware control; the right choice depends on the task, not a strict quality ranking.
- Level/generation, translation method, and paradigm are independent classifications — e.g., Python is high-level (3GL+), interpreted, and supports multiple paradigms (procedural, OOP, functional) all at once.
✅ Self-Test Questions (with Answers)
Q1. Define a programming language, and explain what determines whether it's "low-level" or "high-level."
Ans: A programming language is a formal, artificial language consisting of a defined vocabulary and a set of grammar/syntax rules, used to write instructions (a program) that a computer can execute. It is the medium of communication between programmer and machine. Every such language must ultimately end up as the binary machine code the CPU directly executes — either because it already is that code, or because a translator converts it.
What determines the level is how close the language's syntax sits to machine code versus to human language — a spectrum often described as the level of abstraction from the hardware.
- Low-level languages are close to the hardware. They deal directly in registers, memory addresses and individual CPU instructions, and require little or no translation. They comprise machine language (1GL) and assembly language (2GL). They are very fast and give direct hardware control, but are difficult to read and write and are not portable, because the instruction set differs from one CPU architecture to another.
- High-level languages are close to human language, using statements such as
if,whileandprintthat abstract away registers and addresses entirely. They cover 3GL and above — C, Java, Python, SQL, Prolog. They are easier to read, write, maintain and debug, and are portable across machines, but require a compiler or interpreter and may be less hardware-efficient than hand-written low-level code.
| Aspect | Low-level | High-level |
|---|---|---|
| Closeness to | The machine | Human language |
| Translation needed | None (1GL) or an assembler (2GL) | Compiler or interpreter |
| Portability | None - tied to one CPU architecture | High - recompile or reinterpret elsewhere |
| Readability | Very difficult | Easy |
| Execution speed | Fastest | Slightly slower, though optimisers narrow the gap |
| Typical use | Device drivers, embedded systems, boot code | Applications, web, databases, AI |
- MCQ trap: low-level does not mean "bad" and high-level does not mean "always better". The choice depends on the task — an embedded controller or a device driver may genuinely need assembly.
Q2. Place C, SQL, and Prolog into their correct programming language generations.
Ans:
- C → third generation (3GL). It is a high-level, general-purpose, procedural language with human-readable syntax (
if,for,while) that must be compiled and is portable across machines. Developed by Dennis Ritchie at Bell Labs in 1972. A common nuance: C is sometimes called a "middle-level" language because it offers pointers and direct memory manipulation, but in the generation scheme it is firmly 3GL. - SQL → fourth generation (4GL). Structured Query Language is task-specific (database manipulation) and declarative — you state what data you want, not how to fetch it — and its syntax is close to natural English (
SELECT name FROM students WHERE marks > 80). That task-specificity and near-natural-language design is exactly what pushes it up a generation. - Prolog → fifth generation (5GL). PROgramming in LOGic is a constraint/logic-based language in which the programmer states facts and rules, and a built-in inference engine determines how to satisfy a query. Developed in 1972 by Alain Colmerauer, it is associated with AI and expert systems.
| Generation | Description | Translator needed | Example |
|---|---|---|---|
| 1GL - Machine language | Raw binary opcodes executed directly | None | Binary opcodes |
| 2GL - Assembly | Mnemonics such as MOV, ADD, JMP | Assembler | NASM, MASM assembly |
| 3GL - High-level | Human-readable, portable, general-purpose | Compiler or interpreter | C, C++, Java, Python |
| 4GL - Very high-level | Task-specific, declarative, near-English | Database or report engine | SQL |
| 5GL - Logic/constraint | State goals and constraints, not steps | Inference engine | Prolog |
- MCQ trap: SQL is a 4GL, not a 3GL — frequently tested.
Q3. Why is Java described as a "hybrid" between compiled and interpreted languages?
Ans: Because Java uses both translation methods in sequence, rather than one or the other. The process has two stages:
- Compilation. The
javaccompiler translates Java source code (.java) intobytecode(.classfiles) — but not into machine code for any real processor. Bytecode is the instruction set of an imaginary, idealised machine. - Interpretation / JIT execution. At runtime the Java Virtual Machine (JVM) — a different JVM implementation for each platform — interprets that bytecode, and its JIT (Just-In-Time) compiler additionally compiles frequently executed "hot" code into native machine code on the fly, caching it for reuse.
The purpose of this design is to combine the strengths of both models and capture Java's slogan, "Write Once, Run Anywhere (WORA)". Portability comes from the compiled stage stopping at bytecode: one compiled .class file runs unchanged on Windows, Linux, macOS or Android, because the platform-specific part is the JVM, not the program. A purely compiled language such as C, by contrast, must be recompiled for every target architecture. Speed comes from the JIT stage: the program avoids the heavy runtime penalty of pure interpretation, approaching native performance on long-running code. The JVM also supplies runtime safety — bytecode verification, sandboxing and automatic garbage collection.
The cost is a slower startup (the JVM must load and warm up) and higher memory use than a native binary. C# uses the identical model, compiling to CIL/MSIL executed by the .NET CLR.
- MCQ trap: Java is not "purely interpreted" — a favourite trick option. It is compiled to bytecode, then interpreted/JIT-compiled.
Q4. Give one example each of a procedural, object-oriented, and functional language.
Ans:
- Procedural: C. Code is organised as a sequence of instructions grouped into procedures/functions that operate on data passed to them; data and functions are kept separate and execution proceeds top to bottom through ordered function calls. Other examples: Pascal, FORTRAN, COBOL.
- Object-oriented: Java. Code is organised around objects and classes that bundle data (attributes) together with behaviour (methods), built on encapsulation, inheritance, polymorphism and abstraction. Other examples: C++, C#, Smalltalk.
- Functional: Haskell. Computation is expressed as the evaluation of mathematical functions, avoiding changing state and mutable data; pure functions have no side effects, so the same input always yields the same output. Other examples: Lisp, Erlang, F#, Scala.
Two further paradigms complete the set: logic-based (Prolog), where facts and rules are stated and an inference engine derives answers; and scripting (Bash, JavaScript), lightweight interpreted languages used for automation and gluing systems together.
- Important caveat: most modern languages are multi-paradigm. Python supports procedural, object-oriented and functional styles simultaneously; JavaScript and Scala likewise. Naming a language's dominant paradigm is safe, but claiming it supports only one is usually wrong.
Q5. What distinguishes a 4GL from a 3GL?
Ans: Three linked differences: declarative versus procedural style, task-specific versus general-purpose scope, and closeness to natural language.
A 3GL such as C or Java is procedural (imperative): the programmer must specify exactly how to achieve a result, step by step — open the file, loop through every record, test each one, accumulate matches. It is general-purpose, usable for anything from an operating system to a game. A 4GL such as SQL is declarative: the programmer states what result is required, and the system's engine works out the procedure. It is task-specific, designed for a narrow domain — typically database querying, report generation or form design.
Worked contrast. To find students scoring above 80:
- 3GL (C, conceptually): open the data file; declare a loop; read each record in turn; compare its marks field with 80; if greater, copy the record to an output list; advance; close the file — roughly 15–20 lines specifying every step.
- 4GL (SQL):
SELECT name FROM students WHERE marks > 80;— one line stating only the desired outcome. The database engine chooses the access path, decides whether to use an index, and optimises the execution plan.
| Aspect | 3GL | 4GL |
|---|---|---|
| Style | Procedural - specify HOW | Declarative - specify WHAT |
| Scope | General-purpose | Task-specific, usually data-oriented |
| Syntax | Structured but technical | Close to natural English |
| Lines of code needed | Many | Far fewer |
| Control over execution | Full and explicit | Delegated to the engine |
| Typical user | Professional programmer | Analyst or power user |
| Examples | C, C++, Java, Python | SQL, report generators, MATLAB |
The trade-off: 4GLs give dramatically higher productivity within their domain but less control and no general-purpose capability — you cannot write an operating system in SQL.
Q6. Explain the core principles of object-oriented programming and how they differ from the procedural paradigm.
Ans: Object-Oriented Programming (OOP) organises a program around objects — self-contained units that bundle data (attributes) together with the behaviour (methods) that operates on that data — created from templates called classes. Its four core principles are:
- Encapsulation — bundling data and methods inside one unit and hiding the internal details behind a controlled public interface. A
BankAccountobject keepsbalanceprivate and exposes onlydeposit()andwithdraw(), so no outside code can set a negative balance directly. This protects data integrity. - Inheritance — a class may derive from another, reusing and extending its attributes and methods.
SavingsAccount extends BankAccountinherits everything and addscalculateInterest(), eliminating duplicated code and expressing an "is-a" relationship. - Polymorphism — one interface, many implementations. A single call
account.calculateInterest()behaves differently depending on the actual object type at runtime, so new account types can be added without modifying existing code. - Abstraction — exposing only essential features and hiding complexity. A programmer calls
withdraw(5000)without knowing how the ledger is updated internally.
How this differs from the procedural paradigm: the fundamental contrast is that procedural programming separates data from the functions that act on it, whereas OOP binds them together. In C, a struct holds the data and free-standing functions manipulate it — any function anywhere can reach in and alter the data, and as a program grows, tracking which function touched which variable becomes unmanageable. OOP makes each object responsible for its own state, which is why it scales to large systems.
| Aspect | Procedural | Object-oriented |
|---|---|---|
| Basic unit | Function or procedure | Object / class |
| Data and behaviour | Kept separate | Bundled together |
| Data access | Largely global and open | Encapsulated and controlled |
| Code reuse | By calling functions again | By inheritance and composition |
| Scales to large systems | Poorly | Well |
| Approach | Top-down decomposition | Bottom-up modelling of entities |
| Examples | C, Pascal, FORTRAN | Java, C++, C# |
When each wins: procedural code is simpler and more efficient for short, linear tasks and remains standard in embedded and systems programming; OOP pays for its design overhead and steeper learning curve only once a system is large enough that maintainability matters.
Q7. Why is Prolog well suited to AI and rule-based applications but poorly suited to numeric computation?
Ans: Because Prolog's execution model is logical inference, not arithmetic evaluation — which is precisely what one class of problem needs and the other does not.
Why it suits AI and rule-based systems. In Prolog the programmer states facts (parent(ali, hassan).) and rules (grandparent(X,Z) :- parent(X,Y), parent(Y,Z).), and a built-in inference engine answers queries by unification, pattern-matching and backtracking — automatically trying alternatives and retreating when a path fails. The programmer therefore writes only the knowledge, not the search algorithm, which maps almost perfectly onto the structure of expert systems, natural-language parsing, theorem proving, diagnostic systems and constraint problems. A medical expert system's rules ("if fever and rash and no vaccination, then suspect measles") translate into Prolog nearly verbatim, and backward chaining is supplied free. Encoding the same reasoning in C would mean hand-building the entire inference and backtracking machinery.
Why it is poor at numeric computation. The same design works against it:
- No native imperative arithmetic model. Prolog variables are logical, not mutable storage — once bound, they cannot be reassigned. There is no
x = x + 1; iteration must be expressed through recursion, which is clumsy and costly for numeric loops. - Heavy interpretive overhead. Every step involves unification and a backtracking stack, so a numeric inner loop runs orders of magnitude slower than the equivalent compiled C or FORTRAN, which map almost directly onto CPU arithmetic instructions.
- No vectorisation or hardware math support. Prolog offers nothing comparable to FORTRAN's array handling, BLAS/LAPACK libraries, SIMD instructions or GPU offloading — the infrastructure numerical computing depends on.
- Arithmetic is bolted on. The
is/2operator exists but is an imperative exception to the declarative model, and is neither elegant nor fast.
Conclusion: use Prolog where the problem is reasoning over symbolic relationships, and C/FORTRAN/Python-with-NumPy where the problem is* crunching numbers*. The mismatch is one of paradigm, not of quality.
Q8. Classify Python across the level, translation-method, and paradigm axes at once.
Ans: Python is:
- Level axis: a high-level language, third generation (3GL) and beyond. Its syntax is very close to natural language (
for item in list:), and it abstracts away memory management (automatic garbage collection), pointers and data types (dynamic typing) entirely. Its very high level of abstraction and expressive standard library lead some to describe it as "3GL+" or approaching 4GL productivity in specific domains. - Translation axis: interpreted — more precisely, a hybrid leaning heavily to interpretation. The reference implementation CPython compiles source to
.pycbytecode and then executes that bytecode on the Python Virtual Machine. It is conventionally and correctly labelled interpreted, because no standalone native executable is produced and code runs line by line at runtime. Variants blur this further: PyPy adds a JIT compiler, and Cython/Nuitka compile to C. - Paradigm axis: multi-paradigm. Python genuinely supports procedural programming (plain functions and top-to-bottom scripts), object-oriented programming (classes, inheritance, polymorphism — in fact everything in Python is an object), functional programming (
map,filter,lambda, comprehensions, first-class functions), and scripting (automation, glue code, shell replacement).
| Axis | Python's classification |
|---|---|
| Level / generation | High-level, 3GL and above |
| Translation method | Interpreted via bytecode on a virtual machine |
| Paradigm | Multi-paradigm - procedural, OOP, functional, scripting |
| Typing | Dynamically and strongly typed |
| Typical domains | Data science, AI/ML, web backends, automation |
The exam point being tested: these three axes are independent. A strong answer classifies a language on all of them at once rather than attaching one label — and Python is the ideal illustration, since it is simultaneously high-level, interpreted and multi-paradigm.
CSS angle: Python's low barrier to entry is central to Pakistan's IT-export and freelancing push — DigiSkills, NAVTTC and PSEB training programmes lean on it because a trainee can reach employable data-analysis or web-backend work far faster than through C++ or Java.
📜 Past-Paper Questions & MCQs (CSS 2016–2026)
2017 · Paper-I · Q3(a) · 8 marks
Q. Three types of languages exist for programming computers: machine, low-level and high-level languages. Elucidate these three types, giving details of the conversion process from low-level and high-level language into machine language.
Quick revision + exam-ready model answer
Quick revision — key points
- Machine code executes directly
- Assembly mnemonics require an assembler
- High-level source requires compilation or runtime execution
- Explain phases, linker and loader with a translation flow
Exam-ready answer — structured
Introduction / direct answer: Machine language consists of the processor's directly executable binary instructions.
Main explanation
- It is hardware-specific and difficult for humans to read. Assembly language represents those instructions through mnemonics such as MOV and ADD; an assembler translates assembly into object/machine code.
- High-level languages such as C, C++ and Python provide abstractions, readable constructs and libraries, improving productivity and portability. A compiler analyses high-level source code (lexical, syntactic and semantic analysis), optimises where applicable, and generates target code; an assembler may process generated assembly before linking produces an executable.
- An interpreter executes source or an intermediate representation through a runtime rather than necessarily creating a stand-alone native executable. Pipeline: high-level source → compiler → object files → linker → executable → CPU; alternatively assembly source → assembler → object code.
- Cross-compilation means producing binaries for a different target machine or environment.
MCQs
2024 P-I · Q14. A high-level language compiler that runs on one computer and generates code for another is known as:
- (A) One-pass compiler
- (B) Multipass compiler
- (C) Cross compiler ✅
- (D) None of these
- Answer: (C) Cross compiler.
- Why: a cross compiler runs on a host machine (say an x86 laptop) but produces code for a different target (say an ARM microcontroller or an Android phone). One-pass and multipass describe how many times a compiler reads the source, not which machine the output is for.