Module Internals

Internally, the Blaze interpreter uses an instance of a Blaze Virual Machine (VM). The VM is a stack machine, meaning that instructions assume that operands will be on the stack, and results placed onto the stack.

Take the following Blaze program:

func main() {
    var x = 2 + 3;
}

We can compile it by using blzc -s .\app.txt -d, where -d indicates to also store debug information (line numbers).

To dump the module information, use the the -d (as in dump) flag on the interpreter: blzi -m app.blzm -d, which produces the following output:

== INFORMATION ==
Version 1.0
Name '.\app.txt'
Debug? True

== CONSTANTS ==
0: String(main)
1: Number(2)
2: Number(5)

== VARIABLES ==
0: main (PRIVATE)

== FUNCTIONS ==
<anonymous> (# args: 0, # locals: 0, Varargs: False, # instructions: 4)
1       LDFUNC 1
        STVAR 0
0       LDNULL 0
        RET 0
main (# args: 0, # locals: 1, Varargs: False, # instructions: 6)
2       LDCONST 1
        LDCONST 2
        ADD 0
        STLOCAL 0
0       LDNULL 0
        RET 0

== CLASSES ==

Instruction Format

Each instruction consists of:

  • An opcode (1 byte): determines the instruction type.
  • Optional operands (1–4 bytes): depending on the instruction.

Operands include:

  • Constant indices: reference values in the constants table.
  • Variable indices: used to access locals or globals.
  • Offsets: for jumps and conditional branches.

If an operand doesn't fit in one byte, EXTENDED_ARG instructions are used to increase its size.

Constants Table

The constants table stores all literals used in the program: numbers and strings. Each constant has an index used by the instructions.

Constants can be loaded onto the stack by using the LDCONST instruction whose argument is an index into the constant table.

Variables Table

Each variable declared at module level is stored with its name and visibility and can be accessed using STVAR and LDVAR instructions.

Note

The parameter for STVAR and LDVAR is not a direct variable index. Instead, it refers to the index of a string constant that contains the name of the variable.

Functions Table

Each function is compiled to bytecode and stored with:

  • Name (optional)
  • Argument count
  • Whether it accepts varargs
  • Local count
  • Instruction count
  • Its bytecode instructions

Example Walkthrough

Take the main function from the bytecode dump from earlier:

main (# args: 0, # locals: 1, Varargs: False, # instructions: 6)
2       LDCONST 1
        LDCONST 2
        ADD 0
        STLOCAL 0
0       LDNULL 0
        RET 0

Here's what happens:

Instruction Stack Description
LDCONST 1 2 Push the constant 2 (index 1) onto the stack
LDCONST 2 2, 3 Push the constant 3 (index 2) onto the stack
ADD 5 Pop and add both values and push the result 5
STLOCAL 0 Pops and stores the result in the first local variable x
LDNULL null Pushes null to be returned from function
RET null Returns from the function

Note: ∅ denotes empty stack