Appendix B — The BANNER Intermediate Representation
Every high-level abstraction is a well-intentioned lie told to the programmer to shield them from the cold, mechanical reality of the hardware. When we write in HULK, we inhabit a world of rich objects, nested expressions, and elegant recursion—a world where the complexity of the machine is hidden behind a veil of syntactic grace. However, the silicon upon which this logic eventually runs is fundamentally indifferent to such elegance. To a processor, there are no “objects” with “methods,” nor are there “types” in the way we understand them; there is only memory, registers, and a relentless sequence of primitive operations. The BANNER Intermediate Representation (IR) is the site of the great reconciliation—it is Phase 1 of a structural audit where high-level intent is methodically stripped of its finery and translated into the explicit, linear, and minimalist language of raw execution.
The transition from a language as expressive as HULK to raw machine code is too steep a cliff to be traversed in a single leap. Direct compilation would force the compiler to manage complex tasks simultaneously: register allocation and stack frame management would have to be handled while simultaneously unraveling deep semantic structures like inheritance hierarchies and dynamic dispatch. BANNER exists to decouple these concerns. By providing a “Three-Address Code” (3AC) architecture, it offers a representation that is close enough to the machine to be easily translated into assembly or bytecode, yet abstract enough to remain portable and amenable to systematic optimization.
In the minimalist world of BANNER, the lush landscapes of HULK are flattened into a linear sequence of explicit instructions. Every complex mathematical expression is decomposed into a series of simple assignments involving temporary variables, ensuring that no instruction ever performs more than one fundamental operation. Control flow structures like if-else blocks and while loops are stripped of their structured sugar and reduced to the raw mechanics of labels and conditional jumps. This “flattening” process is not merely a simplification; it is a rigorous accounting of every operation the CPU must eventually perform. In BANNER, the ambiguity of high-level scope is replaced by the absolute clarity of GOTO and LABEL.
Perhaps the most significant shift in BANNER is the loss of high-level type safety in favor of a “everything is a number” philosophy. While HULK enforces a strict type system, BANNER treats all values as 32-bit integers, where the meaning of a value is defined entirely by how it is used. An integer might be a literal constant, a memory address, or a pointer to a virtual method table. This transparency reveals the true cost of object-oriented programming: attribute access becomes a calculated offset, and a method call becomes a dynamic lookup. By enforcing this level of explicitness, BANNER allows the compiler to perform optimizations that would be impossible at a higher level, serving as the indispensable foundation upon which the final binary is built.
B.2 The Instruction Set: A Minimalist Vocabulary
The elegance of HULK’s expression-based syntax is nowhere to be found in the BANNER instruction set. Instead, we are left with a sparse collection of primitives that reflect the iterative, step-by-step nature of physical execution. Every operation is explicit, every memory access is calculated, and every jump is absolute. By reducing the language to these few atomic actions, we ensure that the final translation to machine code is a systematic mapping of BANNER instructions to their CPU equivalents.
B.2.0.1 Data Movement and Arithmetic
At its most basic level, a program is a sequence of transformations applied to data. In BANNER, these transformations are expressed through three-address assignments—a format where every instruction has at most two operands and one result. No matter how complex a mathematical expression might be in HULK, it must be decomposed into a series of operations where a single operator is applied to its inputs.
Example: The HULK expression z = (x + y) * 2 cannot be represented as a single instruction. It must be broken down into discrete steps using temporary local variables to hold intermediate results—preserving the strict three-address format required by the IR.
t1 = x + y ;
t2 = t1 * 2 ;
z = t2 ;B.2.0.2 Memory Management
In a high-level language, memory management is often “invisible”—objects simply appear when needed and disappear when they are no longer reachable. In BANNER, the creation of every object and array is a deliberate act that must be explicitly requested from the runtime. This explicitness forces the compiler to account for the physical reality of heap allocation.
Example: When a programmer instantiates a class or creates a fixed-size buffer, the BANNER representation uses ALLOCATE to reserve space for a structured type or ARRAY to request a contiguous block of memory—returning a pointer that will be treated as a 32-bit integer.
p = ALLOCATE Point ; # Reserves memory for a 'Point' instance
a = ARRAY 10 ; # Reserves a block for 10 elementsB.2.0.3 Object Interaction
Once an object is allocated, interacting with its internal state requires direct manipulation of its memory layout. BANNER does not understand high-level properties; it understands memory offsets relative to a base address. The GETATTR and SETATTR instructions are the primary tools for reading from and writing to the fields defined in the .TYPES section.
Example: Updating the x coordinate of a Point object involves identifying the correct attribute label—which the backend eventually translates to a numerical offset—and performing a store operation. Reading that value back requires a corresponding load into a local variable.
val = 42 ;
SETATTR p Point_x val ; # Writes 42 into the 'x' attribute of object 'p'
curr = GETATTR p Point_x ; # Reads the value back into 'curr'B.2.0.4 Control Flow
High-level control structures like if statements and while loops are essentially “syntactic sugar” for conditional and unconditional jumps. BANNER strips away this structure, relying instead on a flat system of labels and jumps. This mimics how a CPU’s instruction pointer moves through memory—branching only when specific conditions are met.
Example: A conditional check is implemented by evaluating a predicate and then using IF ... GOTO to jump to a specific label. If the condition is not met, execution simply continues to the next instruction—effectively creating the “else” or “exit” logic.
LABEL check_zero ;
IF x GOTO non_zero ;
PRINT "is zero" ;
GOTO end ;
LABEL non_zero ;
PRINT "is not zero" ;
LABEL end ;B.2.0.5 The Call Stack and Method Invocation
The most complex part of BANNER is the management of function calls and dynamic dispatch. Since BANNER is a flat language, it must explicitly handle the passing of arguments and the retrieval of return values. This is achieved through a sequence of PARAM instructions that prepare the environment before a CALL (for static functions) or VCALL (for virtual methods) is executed.
Example: Invoking a method move(dx, dy) on a Point object requires passing the object itself—the self pointer—followed by its arguments. A VCALL is then used to look up the correct function implementation in the object’s virtual method table based on the provided type.
PARAM p ; # Pass the object instance (self)
PARAM 10 ; # Pass dx
PARAM 20 ; # Pass dy
r = VCALL Point move ; # Perform dynamic dispatch for 'move'
RETURN r ; # Send the result back to the callerB.4 Technical Deep Dive: “Everything is a Number”
At the heart of the BANNER architecture lies a radical commitment to architectural minimalism: the “everything is a number” philosophy. In the high-level world of HULK, developers reason about complex types—strings, boolean flags, and polymorphic class instances—but as these abstractions descend into the BANNER Intermediate Representation, they are stripped of their semantic metadata and reduced to a uniform 32-bit integer format. This homogenization is not merely a technical convenience; it is a fundamental design choice that aligns the IR with the mechanical reality of the hardware, where the distinction between a memory address, a numerical literal, and a bitmask is entirely a matter of perspective.
In this environment, the meaning of a value is not inherent to the value itself but is instead derived from the context of its usage—a concept we might call contextual semantics. When a BANNER instruction performs an arithmetic operation like x = y + z, the virtual machine treats the operands as raw numerical data to be manipulated by the ALU. However, when the same variables appear in a memory-oriented instruction like x = GETATTR y z, the interpretation shifts dramatically: y is suddenly treated as a pointer to a base address in the heap, while z is interpreted as a numerical offset within that object’s structure. This flexibility allows for a highly compact instruction set, but it requires that the compiler maintains an absolute, unwavering map of what every number “represents” at any given point in execution.
This design shift fundamentally reallocates the burden of semantic safety from the runtime to the compiler’s semantic analyzer. Unlike more “helpful” virtual machines—such as the JVM or the Python interpreter—the BANNER VM performs no runtime type-checking or safety audits on its instructions. If a compiler emits a GETATTR call on a value that is actually a string literal or a mathematical constant, the VM will dutifully attempt to dereference that memory location, likely resulting in a segmentation fault or the retrieval of garbage data. By removing these safety checks from the execution loop, BANNER achieves a level of performance closer to native code, operating on the assumption that the preceding compilation phases have already “proven” the correctness of the instruction stream.
For the Rust-based backend, this minimalist approach creates a fascinating dichotomy of efficiency and complexity. On one hand, the VM’s core execution loop is exceptionally lean, as it can leverage Rust’s primitive integer types and direct memory access without the overhead of constant type-tagging or dynamic dispatch overhead. On the other hand, it necessitates a sophisticated heap management and garbage collection system. Since the VM itself cannot distinguish a pointer from a literal 32-bit integer, the backend must employ advanced techniques—such as shadow stacks or pointer tagging—to ensure that the garbage collector can safely identify reachable objects without accidentally “collecting” a valid memory address that looks like a large number. This tension between IR simplicity and backend robustness is the defining characteristic of the BANNER ecosystem.
B.5 Conclusion: The Unseen Foundation
The journey from the high-level elegance of HULK to the minimalist, three-address world of BANNER represents more than just a technical translation; it is a fundamental shift in how we conceptualize computation. BANNER serves as what we might call “assembly for the mind”—a simplified yet remarkably powerful model that captures the essence of execution without the suffocating complexity of physical hardware. By stripping away the abstractions of classes, inheritance, and nested expressions, BANNER reveals the underlying mechanical logic that drives every software system. It is here, in this intermediate space, that the true architecture of a program is laid bare, offering a level of clarity that is often lost in the dense syntax of high-level languages or the cryptic mnemonics of machine code.
From a pragmatic perspective, BANNER is the architectural pivot point that enables both optimization and portability. By decoupling the front-end analysis of HULK from the back-end details of the machine, BANNER provides a stable platform for intermediate passes. It is at this stage that a compiler can perform dead-code elimination, constant folding, and common subexpression elimination with surgical precision, independent of whether the final target is an x86 processor, an ARM chip, or a custom virtual machine. This separation of concerns is the hallmark of professional compiler design, ensuring that the “what” of the programmer’s intent is preserved while the “how” of its execution is refined for maximum efficiency.
Ultimately, BANNER is the final, indispensable piece of the HULK-to-Machine puzzle. It is the bridge that spans the chasm between human-readable intent and silicon-executable instructions. Without this intermediate foundation, the task of building a compiler would be an overwhelming exercise in managing conflicting complexities. With BANNER, however, the process becomes a series of manageable, logical steps. It serves as a reminder that even the most sophisticated systems are built upon simple, atomic foundations—and that understanding these foundations is the key to mastering the art of software engineering.
As you move forward into the implementation of the backend and the nuances of the garbage collector, keep the minimalist spirit of BANNER in mind. It is a testament to the idea that power does not always come from complexity, but often from the rigorous application of simple rules. BANNER invites us to look beneath the surface of our high-level tools and appreciate the unseen machinery that makes modern computing possible. In the end, the most robust foundations are often those that remain hidden, quietly supporting the weight of the abstractions we build upon them.