kestell.org

Quartz

Quartz & Zircon form an end-to-end toolchain for a custom programming language. It includes Quartz, a high-level, imperative language, and Zircon, a cross-platform, stack-based virtual machine that runs the compiled Quartz bytecode.

Quartz

Quartz is a simple, dynamically-typed, imperative language.

Example

A program to calculate the 10th Fibonacci number:

fib(n) {
  if (n <= 1) {
    return n;
  }

  return fib(n - 1) + fib(n - 2);
}

main() {
  return fib(10);
}

Compilation Pipeline

The Quartz compiler transforms source code into Zircon bytecode through the following stages:

  1. Lexing & Parsing: The source code is tokenized and parsed into an Abstract Syntax Tree (AST).
  2. Lowering to IR: The AST is converted into a lower-level Intermediate Representation (IR) for analysis and optimization.
  3. Bytecode Emission: The IR is translated into Zircon bytecode, ready for execution by the virtual machine.

Zircon

Zircon is a stack-based virtual machine designed to execute bytecode generated by the Quartz compiler.

Zircon Bytecode

Bytecode File Format

A compiled .zirc file has the following binary structure:

  1. Magic Number: A 4-byte sequence (ZRCN) to identify the file type.
  2. Version: A single byte indicating the bytecode version.
  3. Constant Pool: A table of constants (numbers, strings) used by the program.
    • uint32: Number of constants.
    • For each constant:
      • byte: Type of the constant.
      • ...: The constant’s value.
  4. Functions: A table of all functions defined in the program.
    • uint32: Number of functions.
    • For each function:
      • int32: Number of arguments.
      • uint32: Number of instructions.
      • For each instruction:
        • byte: The opcode.
        • ushort (optional): The operand, if the opcode requires one.

Bytecode Reference

Opcode Hex Operand(s) Description
Stack Operations
PushConst 0x01 2-byte const index Pushes a constant from the constant pool onto the stack.
Pop 0x02 None Pops the top value from the stack.
Dup 0x03 None Duplicates the value at the top of the stack.
Swap 0x04 None Swaps the top two values on the stack.
PushNil 0x05 None Pushes a nil value onto the stack.
Arithmetic
Add 0x10 None Pops two numbers, adds them, and pushes the result.
Subtract 0x11 None Pops two numbers, subtracts the top from the second, and pushes the result.
Multiply 0x12 None Pops two numbers, multiplies them, and pushes the result.
Divide 0x13 None Pops two numbers, divides the second by the top, and pushes the result.
Modulo 0x14 None Pops two numbers, performs modulo, and pushes the result.
Negate 0x15 None Pops a number, negates it, and pushes the result.
Logical Operations
And 0x20 None Pops two booleans, performs a logical AND, and pushes the result.
Or 0x21 None Pops two booleans, performs a logical OR, and pushes the result.
Not 0x22 None Pops a boolean, inverts it, and pushes the result.
Comparison Operations
Equal 0x30 None Pops two values, checks for equality, and pushes the boolean result.
GreaterThan 0x31 None Pops two numbers, compares them (>), and pushes the boolean result.
LessThan 0x32 None Pops two numbers, compares them (<), and pushes the boolean result.
Control Flow
Jump 0x40 2-byte address Sets the instruction pointer to the specified address.
JumpIfTrue 0x41 2-byte address Pops a value; if true, jumps to the specified address.
JumpIfFalse 0x42 2-byte address Pops a value; if false, jumps to the specified address.
I/O
Print 0x60 None Pops a value and prints its string representation to the console.
Variables
GetLocal 0x70 2-byte local index Pushes the value of a local variable onto the stack.
SetLocal 0x71 2-byte local index Pops a value and assigns it to a local variable.
GetGlobal 0x72 2-byte global index Pushes the value of a global variable onto the stack.
SetGlobal 0x73 2-byte global index Pops a value and assigns it to a global variable.
Functions
Call 0x80 2-byte function index Calls a function, setting up a new call frame.
Return 0x81 None Returns from the current function.
Array Operations
NewArray 0x90 None Pops a size, creates an array, and pushes it onto the stack.
GetElement 0x91 None Pops an index and an array, and pushes the element at that index.
SetElement 0x92 None Pops a value, an index, and an array, and sets the element.
ArrayLength 0x93 None Pops an array and pushes its length.
Object Operations
NewObject 0xA0 None Creates a new, empty object (dictionary) and pushes it.
GetProperty 0xA1 2-byte const index Pops an object, gets a property by name (from const pool), and pushes it.
SetProperty 0xA2 2-byte const index Pops a value and an object, and sets a property by name.
VM Control
Halt 0xFF None Stops the virtual machine.

Source

The source for Quartz is available on GitHub.