Execution
How RAM programs are executed
Compilation Pipeline
The RAM compiler follows a multi-stage pipeline to transform source code into executable instructions:
- Lexer: Scans the raw source code text and breaks it down into tokens (keywords, identifiers, literals, operators)
- Parser: Applies grammatical rules to construct a structured representation of the program
- Concrete Syntax Tree (CST): A detailed, lossless tree that mirrors the original source code structure
- Abstract Syntax Tree (AST): A simplified tree that represents the semantic structure of the program
- ItemTree: Extracts definitions from the AST
- High-level Intermediate Representation (HIR): A semantic representation of the program
- Analysis Pipeline: Performs various analyses on the HIR, including control flow analysis, data flow analysis, and instruction validation
- VM Program: Translates the analyzed HIR into a format for execution by the virtual machine
- Virtual Machine Execution: The VM interprets the generated program, executing instructions sequentially
Execution Process
When you run a RAM program, the following steps occur:
- The source code is read from the file
- The code is parsed and transformed through the compilation pipeline
- The resulting VM program is loaded into the virtual machine
- The VM initializes its memory and registers
- The VM executes instructions one by one, updating memory and registers as needed
- Execution continues until a HALT instruction is encountered or an error occurs
- The final state of memory and any output produced are returned
Control Flow
The execution of a RAM program is normally sequential, with instructions executed in order. However, control flow can be altered using jump instructions:
JUMP label: Unconditionally jumps to the specified labelJGTZ label: Jumps to the label if the accumulator is greater than zeroJZERO label: Jumps to the label if the accumulator is zeroJNEG label: Jumps to the label if the accumulator is negative
These instructions change the instruction pointer, causing execution to continue from a different point in the program.
Error Handling
During execution, various errors can occur:
- Syntax errors: Detected during parsing (e.g., invalid instruction format)
- Semantic errors: Detected during analysis (e.g., undefined label)
- Runtime errors: Detected during execution (e.g., division by zero)
When an error is detected, execution is typically halted, and an error message is displayed.
Debugging
The RAM VM provides several features to help with debugging:
- Detailed error messages with line and column information
- Memory state inspection
- Step-by-step execution
- Control flow visualization
These features can be accessed through the CLI or programmatically.
Example
Here's an example of how a simple RAM program is executed:
Execution trace:
- Initialize sum (address 1) to 0
- Initialize counter (address 2) to 5
- Load counter (5) into accumulator
- Since accumulator > 0, continue to
cont - Load sum (0) into accumulator
- Add counter (5) to accumulator, resulting in 5
- Store updated sum (5) in address 1
- Load counter (5) into accumulator
- Subtract 1, resulting in 4
- Store updated counter (4) in address 2
- Jump back to
loop - ... (repeat steps 3-11 with decreasing counter values)
- Eventually, counter becomes 0
- Jump to
end - Halt execution
After execution, address 1 contains 15 (the sum of numbers from 1 to 5).
The RAM VM is designed to provide a balance between faithfulness to the theoretical model and practical usability. The execution model is simple enough to understand but powerful enough to implement complex algorithms.