02_ir_design

IR Design

Intermediate Representation (IR) Design

Purpose

The ARES Intermediate Representation (IR) is a bridging layer. It sits between your high-level code and the final program the system writes. It takes the complex tree of your logic and turns it into a simple, linear list of instructions. This is a critical step because it allows the system to optimize your code without needing to know which language it will eventually run in.

Why it exists

Directly translating a complex tree into C++ or Python is difficult and can lead to messy code. The IR exists to simplify the problem. By turning everything into a universal list of steps, the system can perform math optimizations, remove unused parts of the code, and handle complex logic like "if" statements and "loops" in a consistent way. It provides a single source of truth for the logic of your program.

How it works

The IR uses a system called Three-Address Code. This means every instruction is very simple, usually involving only two inputs and one output.

  1. Flattening expressions. A complex math step like a + b * c is broken into two simple steps: first calculate b * c, then add a to the result.
  2. Using temporary bins. The system uses an infinite number of virtual bins (called "registers") like t0 and t1 to store the results of these small steps.
  3. Naming locations. For loops and skips, the system uses "labels" to mark specific lines in the code. It can then tell the computer to jump to a specific label based on a condition.
  4. Universal commands. Standard commands like READ, PRINT, and JUMP are used so that the logic remains the same regardless of the final language.

Intuition

Think of the IR like a set of simplified instructions for building furniture from a complex blueprint. The blueprint shows the finished product (the Tree), but the instructions tell you exactly which two pieces to join first, where to put the next screw, and which step to skip if you already have a part assembled. The instructions are written in a simple way that anyone can follow, no matter what tools they are using.

Implementation details

The logic for creating the IR is in src/ir/lowering.ts. It goes through every part of your code tree and emits these simple instructions.

  • Binary Operations: Math like addition or multiplication is turned into a BINARY_OP instruction.
  • Decisions: An if statement is turned into a JUMP_IF_FALSE instruction that points to a specific label.

Trace example

This is what happens when the system processes if x > 0 { print x }:

  1. Calculate if x > 0 and store the result in t0.
  2. JUMP to a label called L0 if t0 is false.
  3. Execute the PRINT command for x.
  4. LABEL L0: This is the point the system jumps to if the condition was false, skipping the print command.

Related Entities

  • 03_optimizer.md: Explains how the system makes this list of instructions even faster.
  • src/ir/lowering.ts: The actual code that generates this representation.
ARES