Turbo Pascal (7.0)

This assessment applies the coupling account — coupling as access to a shared resource, and the coupling floor [1], [2] — and the knowledge-embodiment theorem [3]; the language is assessed against its official reference [4].

1 Assessment

This page assesses Turbo Pascal in five parts: core coupling — what the language’s own constructs force; ecosystem coupling — what the surrounding platform, tooling, and community cost; engineering readiness — whether the artifact can be reproduced, verified, observed, worked in quickly, connected to other languages, and governed openly; the profile — the unscored facts a score cannot express; and the scoring detail — the mechanism marks and the arithmetic behind every score. A ✅ bullet marks a construct that helps. A ⚠️ or ❌ bullet marks a cost; the scoring model does not price every cost named here.

Core coupling 39/100 · Ecosystem coupling 54/100 · Engineering readiness 42/100

1.1 Core coupling

1.1.1 Type

  • ✅ Strong static typing is enforced at compile time: Every variable, parameter, and function result has a declared type, and an assignment between incompatible types is rejected
  • ✅ Enumerated and subrange types state a value domain: type TDay = (Mon, Tue, Wed, Thu, Fri) and a subrange such as 1..31 narrow the domain in the declaration
  • ✅ A typed pointer names what it addresses: ^T is a pointer to T, so an assignment between pointers of different types is an error
  • ❌ A variant record is an unchecked union: record ... case Tag: T of ... end names the alternatives, but the compiler does not require the tag to be tested before a field is read (T4)
  • ❌ No generics: A container is written for one element type, or it stores Pointer values and casts them, so reuse across types is untyped (T5)
  • ✅ A unit is the namespace and a real module boundary: The interface section is what a uses clause sees, and the implementation section is private to the unit

1.1.2 Construction

  • ✅ A uses clause states each dependency: The compiler rejects a call into a unit that is not listed, so the dependency edge is written in the source
  • ✅ interface and implementation separate the contract from the code: A caller compiles against the declarations only
  • ✅ An object declares its own construction and destruction: An object type declares constructor Init and destructor Done, and New(P, Init) runs the constructor together with the allocation
  • ✅ Unit initialization and finalization run in dependency order: A unit’s startup code runs before the program body and its shutdown code runs after it
  • ❌ Mutability is the default: A var is writable and reassignable, and only a const marks a value fixed (C2)
  • ⚠️ A class hierarchy couples a derived object to its base: Object-oriented programming arrived in version 5.5, and an object type derives from one base, so shared behaviour is reached through that single-inheritance chain

1.1.3 Memory

  • ❌ Every heap allocation is manual: New and Dispose, or GetMem and FreeMem, are the ways to use the heap, and the programmer writes the matching release (M1)
  • ❌ Nothing runs when a variable leaves its scope: There is no release tied to scope, and a destructor is a method the programmer must call (M3)
  • ❌ No ownership model: A typed pointer may alias, dangle, or be disposed twice, and the compiler does not track it (M4)
  • ✅ The run-time library owns the heap: New, Dispose, Mark, and Release give a defined heap with a stack-like mark and release discipline
  • ✅ A String value carries its own length: A String[255] short string stores its length in the first byte, so a string operation needs no terminator
  • ⚠️ Real-mode addressing bounds the heap: In the 16-bit memory models the heap lies in the data segment, so the model’s segment limit caps one allocation

1.1.4 Error

  • ❌ The default failure path is a halt or an error code: An unhandled run-time error stops the program with a run-time error number, and an I/O failure is reported through IOResult when checking is off (Er1)
  • ❌ No composable result type: A failure cannot be carried in the type of a function’s result, so the caller learns of it from an error code or an exception (Er4)
  • ✅ try/except/finally is a structured path: Version 7 added exception handling, and the finally block runs on every exit from the statement
  • ✅ raise names the failure: raise EDivByZero.Create raises an object from the SysUtils exception hierarchy
  • ⚠️ The exceptions are unchecked: Nothing in a signature states which exceptions a routine may raise, so the recovery path depends on a convention
  • ⚠️ Two error styles coexist: {$I-} with IOResult checks one call at a time, while try/except covers a block, so a program mixes both

1.1.5 Concurrency

  • ❌ The language has no concurrency construct: There is no thread type, no task, and no synchronisation primitive; concurrent work in DOS is expressed with an interrupt procedure (K5)
  • ⚠️ The only shared state is a global variable: With no concurrency construct in the language, a global variable is what the main code and an interrupt procedure both reach, and nothing guards the access
  • ⚠️ A thread-local variable needs a successor compiler: threadvar gives a variable one copy per thread in Delphi and Free Pascal, but Turbo Pascal creates no thread and the DOS target has none
  • ⚠️ An interrupt procedure must be declared as such: The interrupt directive saves the registers, and the protection is a declaration rather than a checked protocol
  • ⚠️ Reentrancy is the programmer’s concern: An interrupt procedure that calls a library routine can corrupt state the interrupted code was using
  • ⚠️ Cooperative concurrency came from an add-on: A terminate-and-stay-resident program or a library simulated multitasking outside the language

1.1.6 Platform

  • ❌ The main target is 16-bit DOS: The compiler produces real-mode DOS executables, and version 7 was the last release of the line (P3)
  • ❌ A compiled unit is a private object format: A .TPU file is Turbo Pascal’s own unit format, and no other language’s linker consumes it
  • ✅ Free Pascal and Delphi compile the same source: Both accept Turbo Pascal units, so the source is not frozen to the original compiler
  • ✅ The compiler is a self-contained toolchain: One executable compiles a program, and the IDE runs the edit-compile-run cycle
  • ⚠️ The memory model is a compile-time choice: {$M} selects tiny, small, compact, large, or huge, and the model bounds the code and the data segments
  • ⚠️ Real-mode addressing shows in the source: near and far pointers and segment arithmetic appear once a program leaves the small model

1.1.7 Trade-offs (not coupling)

  • The one-pass compiler is a deliberate speed choice: Compilation is nearly instant, and the price is a modest optimiser
  • The integrated IDE is the intended way to work: The compiler, the editor, and the debugger are one program
  • The 16-bit limit belongs to the target machine: The segment size is a property of the processor mode, not only of the language
  • Turbo Vision is supplied and not required: The text-mode GUI library is an optional dependency of the program
  • The goto statement remains in the language: A jump is available for the case where a structured form is awkward
  • Pascal is a teaching language by design: The readable syntax and the strong typing were written for instruction

1.2 Ecosystem coupling

1.2.1 Performance

  • ✅ The compiler emits native 8086 machine code: There is no interpreter and no run-time compiler between the source and the processor
  • ✅ Compilation is very fast: The one-pass compiler makes the edit-compile-run cycle take seconds
  • ✅ A compiled program starts immediately: A DOS .EXE needs no runtime initialisation beyond the loader
  • ⚠️ The optimiser does little global work: The algorithm and the data layout dominate the result
  • ⚠️ The 16-bit target caps the work: The real-mode segment limit bounds the data one program can address
  • ⚠️ A far pointer costs extra cycles: A segment override and a far access element are slower than a register operation

1.2.2 Ecosystem

  • ❌ The ecosystem is legacy and discontinued: Borland ended Turbo Pascal after version 7 in favour of Delphi, so the tool and package field is historical (Ec3)
  • ✅ Free Pascal, Delphi, and Virtual Pascal continue the language: Each is a compatible implementation, so much Turbo Pascal code still compiles today
  • ✅ A large body of published material exists: The era’s books, tutorials, and the Turbo Vision source remain available
  • ✅ The compiler is a single small program: Nothing else must be installed to build a program
  • ⚠️ Reuse is by source: A unit is shared as .PAS source rather than as a resolved package with a version
  • ⚠️ The tooling runs in DOS or an emulator: The IDE and the debugger need a DOS machine or an emulator on a current computer

1.2.3 Evolution

  • ❌ The language is discontinued: Borland ended the line in 1995 and moved it to Delphi and Object Pascal, so no version followed 7.0 (V3)
  • ❌ The definition is frozen at 7.0: The language does not change, so a missing feature or a defect is permanent (V2)
  • ✅ The reach of the tool was historically large: Over 400 000 copies were sold in the first two years, which made Pascal accessible to a generation of programmers
  • ✅ The successors accept the source: Delphi and Object Pascal keep the unit, the static typing, and most of the syntax
  • ✅ A port is an adjustment rather than a rewrite: Free Pascal compiles a unit with little change outside the platform-specific code
  • ⚠️ The platform-specific part is real work: DOS interrupts, direct video memory, inline machine code, and .TPU linkage have no direct counterpart on a current target

1.2.4 Domain

  • ✅ Structured programming instruction is the native domain: The readable syntax and the strong typing were designed for teaching
  • ✅ DOS application and tool development fit the target: A compiled .EXE needed no runtime and ran on any PC of the era
  • ✅ Turbo Vision covers text-mode GUI work: The bundled library provides windows, menus, and dialogs on a character screen
  • ✅ A small number-crunching utility is a natural use: A scientific or engineering program was a common Turbo Pascal program
  • ⚠️ New development does not choose it: The domain today is legacy maintenance and education
  • ⚠️ Hardware access sits outside the language: A program that drives a device uses the BIOS, a DOS interrupt, or inline code

1.2.5 Learning

  • ✅ The syntax is small and readable: begin/end, var, procedure, if/then/else, and for/to cover the language
  • ✅ The compiler reports an error immediately: The short edit-compile-run cycle makes a mistake cheap to find
  • ✅ The IDE integrates a debugger: Step, watch, and breakpoint are keystrokes away
  • ⚠️ Pointers and manual memory are the hard part: The syntax is gentle and the heap discipline is not
  • ⚠️ Real-mode addressing is a second subject: Near and far pointers and segments must be learned for system work
  • ⚠️ The semicolon rule catches a beginner: A semicolon separates statements, so the last statement of a block takes none

1.2.6 Syntax

  • ❌ The syntax is verbose: begin/end, unit/interface/implementation, try/except/end, and every declaration keyword are spelled out (S1)
  • ✅ Keywords are words rather than symbols: if, then, do, of, and end carry the structure
  • ✅ Blocks are bracketed consistently: begin/end closes every compound statement, including the body of a procedure
  • ✅ A declaration names the variable before its type: var Count: Integer reads in one direction
  • ⚠️ A statement separator, not a terminator: The semicolon rule is a rule to learn rather than a decoration
  • ⚠️ A nested field needs its qualifier or a with: Reading a record inside a record is verbose without the with statement

1.2.7 Testing

  • ❌ There is no test framework in the toolchain: A test is a program that runs and compares, and nothing in the distribution runs a suite (G1)
  • ❌ The debugger is the era’s tool: The IDE steps and watches variables, with no assertion or coverage support (G2)
  • ✅ A failed run-time check reports the detail: The run-time library prints the error number, the address, and the register contents
  • ✅ A check is a few lines of Pascal: A comparison and a halt write a test without a framework
  • ⚠️ A test suite is a program the programmer writes: No runner, no fixture loader, and no report come with the toolchain

1.2.8 Security

  • ✅ The type system rejects a mismatch at compile time: A pointer to one type cannot take a pointer to another without a written cast
  • ✅ The dangerous cast is one written site: Pointer and a type cast put the risk where the programmer wrote it
  • ✅ A check can be switched on: {$R+} adds range checking to an array index and to a subrange assignment
  • ⚠️ Manual memory management admits the classic faults: An overrun and a use-after-free are possible, and the compiler does not check them
  • ⚠️ {$I-} disables an I/O check: After that directive a failed file operation must be tested through IOResult
  • ⚠️ inline machine code bypasses the type system: An inline(...) statement writes raw opcodes into the compiled program

1.3 Engineering readiness

1.3.1 Reproducibility

  • ❌ Builds are not byte-reproducible by default.
  • ❌ Dependencies resolve without a lock by default.

1.3.2 Supply chain

  • ⚠️ Published packages carry no signed provenance by default.

1.3.3 Observability

  • ⚠️ No stable tracing and metrics standard.
  • ⚠️ The standard library has no structured logging.

1.3.4 Feedback

  • ⚠️ No fast in-editor analysis.

1.3.5 Interop

  • ⚠️ No maintained portable target.

1.3.6 Governance

  • ⚠️ One vendor decides the language’s direction.
  • ⚠️ The specification is not public.

1.4 Profile

Unscored, and kept separate from every score on purpose. The profile records what a mechanism price cannot express: what a running program costs, how well a coding model and an agent work in the language, and whether a safety-critical path exists.

1.4.1 Energy and cost

What this axis asks: what does a running program cost in energy and time?

  • ✅ Compiles to native code: the fastest class in the language energy and time benchmarks [5], [6]. A causal re-analysis attributes the difference to execution time [7].

1.4.2 AI and agent readiness

What this axis asks: how well does a coding model and an agent work in this language?

  • ❌ Sparse training data: models write it unreliably [8].

1.4.3 Safety certification

What this axis asks: is there a certified or standards-qualified path to a safety-critical system?

  • ⚠️ No certified or standards-qualified path for safety-critical systems.

1.5 Scoring detail

1.5.1 Core coupling Dimensions

Dimension Mechanism Description Present Cost
Type T1 dynamic no static check — 0
T2 weak static — 0
T3 dynamic/duck dispatch — 0
T4 no sum types ✅ −4
T5 no generics ✅ −4
T6 no namespaces — 0
T7 type erasure/reflection — 0
T8 operator overloading — 0
T9 inheritance required for polymorphism — 0
T10 no null-safety — 0
T11 no module boundary — 0
T12 no effect tracking ✅ −8
T13 async/sync colouring — 0
T14 unchecked foreign boundary ✅ −4
Type subtotal −15 (−20)
Construction C1 global mutable state by default — 0
C2 no immutability by default ✅ −4
C3 constructors coupled to allocation — 0
C4 no constructor/validation — 0
Construction subtotal −4
Memory M1 manual deallocation ✅ −15
M2 GC non-deterministic pauses — 0
M3 no RAII ✅ −4
M4 no ownership model ✅ −8
Memory subtotal −15 (−27)
Error Er1 no structured path ✅ −15
Er2 unchecked exceptions only — 0
Er3 errors ignored/non-exhaustive — 0
Er4 no composable result type ✅ −4
Error subtotal −15 (−19)
Concurrency K1 GIL/no parallel — 0
K2 shared mutable state default — 0
K3 manual sync no race detection — 0
K4 no structured concurrency — 0
K5 no primitives ✅ −4
Concurrency subtotal −4
Platform P1 cannot function outside one vendor/domain — 0
P2 single-vendor but other uses — 0
P3 legacy/discontinued platform ✅ −8
Platform subtotal −8

Core Dimensions score: 39/100 — total cost = −61 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

1.5.2 Ecosystem coupling Dimensions

Dimension Mechanism Description Present Cost
Performance R1 interpreted no AOT/JIT — 0
R2 GC pauses — 0
R3 JIT warmup — 0
Performance subtotal 0
Ecosystem Ec1 no package manager — 0
Ec2 fragmented tooling — 0
Ec3 small/niche/discontinued ✅ −8
Ec4 proprietary — 0
Ec5 platform-locked tooling — 0
Ec6 monoculture — 0
Ec7 legacy burden — 0
Ecosystem subtotal −8
Evolution V1 breaking changes — 0
V2 frozen ✅ −4
V3 discontinued ✅ −15
V4 glacial standards — 0
Evolution subtotal −15 (−19)
Domain D1 domain/vendor lock-in — 0
D2 poor domain fit — 0
D3 framework forces architecture — 0
Domain subtotal 0
Learning L1 steep — 0
L2 large surface/multi-paradigm — 0
L3 sparse docs — 0
Learning subtotal 0
Syntax S1 verbose ✅ −8
S2 inconsistent — 0
S3 punctuation-heavy — 0
Syntax subtotal −8
Testing G1 weak tooling ✅ −8
G2 poor debugging ✅ −8
G3 runtime-only errors — 0
Testing subtotal −15 (−16)
Security Q1 memory-unsafe — 0
Q2 dynamic/weak typing risk — 0
Q3 known vulnerability/injection — 0
Security subtotal 0

Meta Dimensions score: 54/100 — total cost = −46 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

1.5.3 Engineering readiness Dimensions

Dimension Mechanism Description Present Cost
Reproducibility Y1 build not reproducible ✅ −8
Y2 dependencies not pinned ✅ −8
Reproducibility subtotal −15 (−16)
Supply chain Y3 no signed provenance ✅ −8
Y4 registry without namespacing — 0
Supply chain subtotal −8
Observability Y5 no stable tracing standard ✅ −8
Y6 no structured logging ✅ −4
Observability subtotal −12
Feedback Y7 slow build — 0
Y8 no fast in-editor analysis ✅ −4
Feedback subtotal −4
Interop Y9 no foreign-function interface — 0
Y10 no portable target ✅ −4
Interop subtotal −4
Governance Y11 single-vendor governance ✅ −8
Y12 closed specification ✅ −8
Governance subtotal −15 (−16)

Readiness Dimensions score: 42/100 — total cost = −58 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

Verdict: Turbo Pascal’s core score is held down by the mechanisms of its era rather than by a missing idea: the heap is manual, no release is tied to scope, and a failure is a run-time error number or an unchecked exception. Its one strong structural feature is the unit, where interface and implementation draw a real boundary and the uses clause writes each dependency into the source. Main strengths: strong static typing, near-instant native compilation, a gentle readable syntax, and a live path to Free Pascal and Delphi. Main weaknesses: no generics, unchecked variant records, no concurrency construct in the language, and a 16-bit target whose toolchain, ecosystem, and platform are all historical.


The formal development. The definitions, theorems, and proofs behind this page are published in:

All published papers

References

[1]
Y. Loth, “On the nature of coupling: All coupling as shared resource access.” Zenodo, Aug. 2026. doi: 10.5281/zenodo.21925122.
[2]
Y. Loth, “Coupling as a consequence of cohesion: Decomposition, the coupling floor, and domain-imposed coupling.” Zenodo, Aug. 2026. doi: 10.5281/zenodo.21925201.
[3]
Y. Loth, “On the nature of cohesion: Cohesion as correctness relative to a partitioning rule.” Zenodo, Jul. 2026. doi: 10.5281/zenodo.21703193.
[4]
ISO/IEC JTC 1/SC 22, “Programming languages — Pascal.” International Organization for Standardization; International Standard ISO/IEC 7185, Geneva, Switzerland, 1990.
[5]
R. Pereira et al., “Energy efficiency across programming languages: How do energy, time, and memory relate?” in Proceedings of the 10th ACM SIGPLAN international conference on software language engineering (SLE), 2017, pp. 256–267. doi: 10.1145/3136014.3136031.
[6]
R. Pereira et al., “Ranking programming languages by energy efficiency,” Science of Computer Programming, 2021, doi: 10.1016/j.scico.2021.102609.
[7]
N. van Kempen, H.-J. Kwon, D. T. Nguyen, and E. D. Berger, “It’s not easy being green: On the energy efficiency of programming languages,” in Proceedings of the 40th IEEE/ACM international conference on automated software engineering (ASE), 2025. doi: 10.1109/ASE63991.2025.00131.
[8]
S. Joel, J. J. Wu, and F. H. Fard, “A survey on LLM-based code generation for low-resource and domain-specific programming languages,” ACM Transactions on Software Engineering and Methodology, 2025, doi: 10.1145/3770084.