What Came First - the Program or the Programming Language?
STATUS: Operational mostly.
ORIGIN: A question that should probably have remained a meme.
Abstract
Programming has historically progressed through increasingly abstract layers between human intention and machine execution. From direct operational control to assembly languages, compilers, high-level languages, frameworks, and AI-assisted generation, each new layer has reduced the amount of machine-specific detail a human must directly manage.
This paper examines the structural consequences of that progression.
We define four conceptual layers: operational execution \(K₀\), formal programming abstraction \(K₁\), human intention \(K₂\), and human-verifiable revision and auditability \(K₃\). We further distinguish between innovation rate \(F\), validation rate \(V\), technological evolution rate \(E\), and absorption capacity \(A\).
Two forms of accumulating systemic debt are proposed. Verification debt arises when implemented novelty exceeds the rate at which it can be meaningfully validated:
Absorption debt arises when technological evolution exceeds the capacity of the surrounding technological environment to integrate, document, maintain, explain, and stabilise that change:
When both conditions persist, a technological system may become increasingly capable while simultaneously losing relative ground in verification, explainability, and systemic integration. This condition is formulated as the Technological Absorption Paradox.
The paper further introduces the concept of Semantic Intent Programming, in which the primary human contribution shifts from explicit procedural implementation toward structured semantic contracts containing intent, constraints, verification criteria, diagnostic requirements, and failure behaviour.
The central argument is that future programming systems should not be evaluated solely by how efficiently they generate behaviour, but by how effectively they preserve human understanding, verification, diagnostic access, and responsible control over the systems they produce.
Definitions
1. Historical Bootstrap: Before the Programming Language
The question “what came first - the program or the programming language?” appears circular only if programming is assumed to require a pre-existing high-level language.
Historically, that assumption is false.
Early computational behaviour could be specified directly through machine instructions, wiring configurations, switch settings, punched media, and other forms of physical or symbolic control. In these systems, the distinctions between program, language, and machine configuration were less sharply separated than in modern software development.
Within the present framework, such forms of direct executable control belong primarily to the operational layer \(K₀\).
Operational execution does not logically require a prior high-level programming abstraction.
A formal programming layer \(K₁\), however, must ultimately acquire operational existence through some executable substrate. A compiler, interpreter, assembler, virtual machine, or equivalent mechanism must itself run somewhere.
The relationship is therefore better represented as a bootstrap sequence:
Once established, such abstraction layers may become partially self-hosting. A compiler may compile a newer compiler; a language implementation may be rewritten in the language it implements; toolchains may recursively generate later versions of themselves.
The recursion is historical and developmental rather than logically originless. Each later abstraction ultimately depends upon an operational substrate that precedes it.
The central consequence is not circular causation, but progressive mediation.
What happens when the abstraction layer becomes sufficiently powerful that the programmer can produce operational behaviour without directly observing or understanding the mechanisms that generate it?
2. From Operational Code to Formal Abstraction: \(K₀\) and \(K₁\)
The transition from \(K₀\) to \(K₁\) marks a fundamental change in the structure of programming.
At the operational layer \(K₀\), behaviour is represented in a form directly executable by a machine or execution environment. At \(K₁\), the programmer instead works through a formal abstraction capable of generating, constraining, or transforming operational behaviour.
The existence of \(T₁₀\) introduces a distinction between expressed behaviour and executed behaviour.
Abstraction is valuable precisely because it removes detail. However, hidden detail may still become operationally significant.
This produces an abstraction gap:
As \(Gₐ\) increases, direct source inspection becomes progressively less sufficient for explaining system behaviour. At high \(Gₐ\), the programmer increasingly diagnoses a transformation system rather than a single body of source code.
3. From Formal Instruction to Human Intention: \(K₂\)
Traditional programming may be represented as:
Generative and AI-assisted systems alter this arrangement.
This does not imply that \(K₁\) disappears. Formal programming representations may still exist internally or remain available for inspection. The important distinction is that \(K₁\) need no longer be the primary interface through which the human expresses intent.
At \(K₁\), the programmer primarily describes procedure. At \(K₂\), the programmer increasingly describes desired behaviour, constraints, and acceptable outcomes.
We may distinguish \(I_h\), implementation information supplied explicitly by the human, and \(I_s\), implementation information introduced by the transformation system.
As automated generation becomes more extensive, an increasing proportion of operational structure may originate from the system rather than from direct human authorship.
Which transformation from intention to execution produced the wrong behaviour?
4. Verification, Revision, and the Role of \(K₃\)
When software behaviour is produced through increasingly complex transformation systems, successful execution alone is insufficient.
\(K₃\) denotes the combination of representations and mechanisms through which a human operator can meaningfully inspect, explain, test, revise, and diagnose the transformation from intention to execution.
The requirement is stronger than mere observability. A system may produce logs without being understandable. Intermediate representations may exist without being meaningfully connected to the original intent.
If the only explanation of a system is generated by the same opaque mechanism that created the behaviour being investigated, verification becomes partially self-referential.
The danger is not that such a system must fail. The danger is that when failure occurs, our ability to identify, localise, explain, and correct the failure may have degraded relative to the complexity of the system producing it.
5. Verification Debt: When \(F > V\)
Let \(F\) denote the rate at which new functionality, behaviour, architecture, or implementation is introduced. Let \(V\) denote the rate at which those changes can be meaningfully validated.
Verification can, in principle, keep pace.
New implementation accumulates faster than it can be validated.
Verification debt should be treated as a backlog rather than as a quantity that can only accumulate. Its rate of change is therefore:
This allows previously accumulated verification debt to decrease whenever validation capacity exceeds the rate of new implementation, while preventing the conceptual debt from becoming negative.
Verification debt differs from conventional technical debt. It describes implementation that exists, and may even function, without having been examined sufficiently to establish confidence in its correctness, limits, interactions, or failure modes.
Human-addressable structure, semantic function names, structured exception logging, traceable state transitions, and explicit diagnostic modes reduce the cost of verification.
A diagnostic system need not explain everything continuously; it must preserve enough human-addressable checkpoints to localise failure efficiently.
6. Absorption Debt: When \(E > A\)
Verification debt concerns whether individual changes can be tested and understood. Absorption debt concerns the wider technological environment.
Let \(E\) denote technological evolution rate and \(A\) the capacity of the surrounding environment to integrate, document, maintain, govern, understand, and stabilise that change.
When technological evolution proceeds faster than the environment can stabilise it, absorption debt accumulates:
Absorption debt is likewise treated as a backlog that may either accumulate or be reduced:
When absorption capacity exceeds the rate of technological evolution, previously accumulated absorption debt can therefore be reduced.
The technological system may become capable of producing change faster than it can validate, integrate, and stabilise that change.
7. The Technological Absorption Paradox
Under this condition, the system produces change faster than it can verify it and evolves faster than the wider environment can absorb it.
Because both components are now dynamic backlogs, combined systemic debt may increase or decrease over time depending on whether verification and absorption capacities catch up with the rates of implementation and technological evolution.
Technological capability may increase while epistemic control and systemic stability come under increasing pressure.
A technological system can become increasingly capable of producing advancement while simultaneously becoming less capable of fully understanding, validating, and integrating the advancement it produces.
The paradox concerns not inevitable collapse, but the possibility of successful operation under declining interpretability and absorptive control.
A system may become easier to instruct while becoming harder to understand.
8. Consequences for Software Design and AI-Generated Code
If abstraction reduces direct human authorship, software must preserve alternative forms of human addressability.
AI-generated systems should preserve human-addressable structure by default.
| Example | Why it matters | Practical example |
|---|---|---|
| Semantic function and module names | Gives humans a stable vocabulary for identifying behaviour | applyMultiplier() rather than zyz() |
| Structured exception handling | Preserves context when execution fails | Record stage, inputs, expected state, observed state, and stack information |
| Human-readable state labels | Makes runtime behaviour understandable without reading implementation | FREE_SPIN_START, PAYOUT_CALC, WIN_DISPLAY |
| Explicit diagnostic modes | Allows detailed tracing only when required | const DEBUG = false; activates detailed tracing when enabled |
| Semantic execution checkpoints | Efficiently localises failure boundaries | Last OK → ERROR → first OK after recovery |
| Traceable event boundaries | Shows which operation began, completed, or failed | BONUS_START → MULTIPLIER_APPLY → BONUS_END |
| Context-rich logging | Converts raw exceptions into actionable information | “Expected multiplier 4; observed null” |
| State snapshots | Preserves runtime conditions surrounding failure | Wager, symbols, multiplier, round ID, active mode |
| Provenance information | Connects implementation back to the intent that generated it | “Generated from bonus specification v1.4” |
| Testable interfaces | Allows generated components to be independently verified | Test payout calculation separately from complete game execution |
| Human-to-system identifiers | Allows non-authors to report faults meaningfully | “Failure occurs between PAYTABLE_LOOKUP and MULTIPLIER_APPLY” |
compared with:
Both structures may execute correctly. Only the second gives a human operator a meaningful vocabulary for locating failure.
Systems that automate implementation should also automate the preservation of inspectability.
9. Toward Semantic Intent Programming
Traditional programming systems largely require the human to express behaviour through formal syntax, functions, operators, control structures, and types.
A semantic intent system instead begins with meaning.
A structured semantic specification may contain:
Example: Semantic Access-Control Specification
Different linguistic formulations may express the same semantic rule:
The source text is therefore no longer identical with the program. It is evidence of an intended meaning.
Different expressions may map to the same normalised semantic model \(Mₛ\), provided they express sufficiently equivalent intent.
We call this paradigm Semantic Intent Programming.
The defining property is not unrestricted natural language. The defining property is that the formal object being programmed is increasingly the semantic contract rather than the exact human-authored procedure.
The system should identify ambiguity, missing constraints, contradictory requirements, unverifiable goals, underspecified failure behaviour, and assumptions introduced by the system itself.
This does not eliminate formalism. It relocates formalism from syntax toward meaning, invariants, constraints, verification, and observable behaviour.
10. Discussion and Perspective
The future of programming may depend less on eliminating complexity than on changing where complexity is managed.
The programmer becomes less exclusively an author of procedure and increasingly an author of semantic contracts.
This is not a reduction in rigor. It is a relocation of rigor.
Existing programming languages would not necessarily disappear. They may instead become increasingly infrastructural. Assembly did not disappear when higher-level languages emerged, and machine code did not disappear when compilers became dominant.
Likewise, \(K₁\) may remain essential while becoming partially internalised within \(S\).
A mature semantic programming environment should preserve semantic versioning of intent, constraint histories, generated verification obligations, implementation provenance, change explanations, diagnostic mappings, and explicit records of assumptions introduced during generation.
Semantic Intent Programming is not automatically a solution to the Technological Absorption Paradox. It becomes useful only when paired with mechanisms that increase both validation and absorption capacity.
The quality of a future programming system should be measured not only by how efficiently it creates behaviour, but by how well it preserves human control over that behaviour.
The programming language of the future may therefore be less concerned with telling machines exactly what to do and more concerned with specifying what must be true when they are finished.
11. Conclusion
The question that began this paper - what came first, the program or the programming language? - appears simple only at first glance.
Historically, executable behaviour preceded modern high-level programming languages.
Generative systems continue the historical movement toward abstraction. Humans may increasingly operate at \(K₂\), while transformation systems produce substantial parts of \(K₀\).
This creates a new requirement: \(K₃\).
Without sufficiently capable revision and verification structures, systems may become easier to instruct while becoming harder to understand.
When \(F > V\), verification debt accumulates. When \(E > A\), absorption debt accumulates.
A technological system can become increasingly capable of producing advancement while becoming less capable of fully understanding, validating, and absorbing the advancement it produces.
The problem is not technological progress itself. The problem is asymmetric progress.
Semantic Intent Programming represents one possible direction. Its primary human artefact is not necessarily source code, but a semantic contract defining intention, constraints, verification requirements, diagnostics, and failure behaviour.
This does not eliminate formalism. It relocates it.
Systems that automate implementation should also automate the preservation of inspectability.
The future of programming may therefore depend less on whether machines can write code.
The more consequential question is:
Can machines generate increasingly complex systems without breaking the human ability to understand, verify, and responsibly control what has been generated?
The next step should not be the disappearance of rigor.
It should be the movement of rigor toward meaning.
The program came first.
The programming language followed.
The next programming language may not primarily describe the program at all. It may describe what the program is required to mean.
Methodological Note
The notation and equations used throughout this paper are conceptual models, not claims of universal quantitative measurement.
Verification debt and absorption debt are modelled as non-negative dynamic backlogs. They may accumulate when implementation or technological evolution outpaces the corresponding capacity for validation or absorption, and they may decrease when those capacities later exceed the incoming rate of change.
The purpose of the equations is to formalise structural relationships rather than provide directly measurable physical quantities. Where numerical interpretation is possible within a specific engineering environment, the models may potentially be developed into measurable metrics. No universal metric is assumed here.
Terminological Note
The term Semantic Intent Programming denotes a programming model in which human input primarily specifies intended meaning, constraints, verification obligations, diagnostic requirements, and acceptable outcomes rather than complete procedural implementation.
The term is descriptive rather than prescriptive. It does not imply that conventional programming languages disappear, nor that unrestricted natural language is sufficient for reliable software development.
Author’s Note
This paper began with a deceptively simple question:
What came first - the program or the programming language?
The question initially appeared to concern historical bootstrapping. It subsequently expanded into questions of abstraction, intention, verification, debugging, technological evolution, and the possibility that future technological systems may become easier to instruct while becoming harder to understand.
Acknowledgements
This paper originated, with some embarrassment, from a TikTok meme.
The authors also acknowledge the practical contribution of repeated debugging experience, through which the value of meaningful function names, semantic checkpoints, structured logging, and human-readable failure localisation became considerably clearer than abstract theory alone might have made it.
Special acknowledgement is due to Prof. Bøje Tertullian Verbum, whose anticipated response to several definitions remains:
“Everyone knows that!!”
No evidence has been found that this prevented him from reading the definitions anyway.
Revision note: the verification- and absorption-debt models were amended to allow accumulated debt to be reduced when validation or absorption capacity later exceeds the incoming rate of change.