The Ovum Intermediate Language (Ovum bytecode) is a stack-based virtual machine instruction set that serves as the compilation target for Ovum source code. This document describes the bytecode syntax, structure, and available commands.
See also: bytecode command list and bytecode examples.
Ovum bytecode follows a stack-based execution model where operations consume values from the stack and push results back onto the stack. The syntax uses WASM-like code blocks enclosed in curly braces {}.
OIL follows a consistent convention for all stack operations: operands are pushed from right to left (the rightmost operand is pushed first, the leftmost operand is pushed last).
This convention applies to:
Function Arguments:
LoadLocal 0, the next at LoadLocal 1, etc.)This means that for a function call foo(a, b, c), the bytecode should:
c (rightmost argument)b (middle argument)a (leftmost argument)fooInside the function, LoadLocal 0 will access a, LoadLocal 1 will access b, and LoadLocal 2 will access c.
Binary Operations:
For binary operations like a + b, a * b, a < b, etc., the right operand is pushed first, then the left operand:
b (right operand)a (left operand)IntAdd, IntMultiply, IntLessThan)Examples:
// Function definition: fun Add(x: Int, y: Int): Int
function:2 _Global_Add_int_int {
LoadLocal 0 // x (first argument, leftmost)
LoadLocal 1 // y (second argument, rightmost)
IntAdd
Return
}
// Function call: Add(5, 3)
PushInt 3 // Push rightmost argument first
PushInt 5 // Push leftmost argument last
Call _Global_Add_int_int
// Binary operation: x + y
LoadLocal 1 // y (right operand)
LoadLocal 0 // x (left operand)
IntAdd
// Comparison: i <= 5
PushInt 5 // 5 (right operand)
LoadLocal 1 // i (left operand)
IntLessEqual
// String concatenation: "Hello" + "World"
PushString "World" // right operand
PushString "Hello" // left operand
StringConcat
If statements consist of separate condition blocks and execution blocks connected by the then keyword. The syntax supports if, else if, and else branches:
{
// If condition is true, execute this block
if {
LoadLocal 0
PushInt 0
IntGreaterThan
} then {
PushString "Positive number"
Print
}
// Optional else if branches
else if {
LoadLocal 0
PushInt 0
IntLessThan
} then {
PushString "Negative number"
Print
}
// Default else block
else {
PushString "Zero"
Print
}
}
While loops consist of separate condition blocks and execution blocks connected by the then keyword. For loops are reduced to while loops during compilation:
{
// Initialize loop variable
PushInt 0
SetLocal 0
// While loop
while {
LoadLocal 0
PushInt 10
IntLessThan
} then {
// Execution block
LoadLocal 0
IntToString
Print
// Increment loop variable
LoadLocal 0
PushInt 1
IntAdd
SetLocal 0
}
}
The init-static block is a unique block that must appear exactly once in a bytecode file. It contains initialization code that is executed before the Main function is called, primarily for setting up static variables:
// Static initialization block (must be unique, executed before Main)
init-static {
PushInt 42
SetStatic 0 // Set static variable at index 0
PushString "Initialized"
SetStatic 1 // Set static variable at index 1
PushFloat 3.14
SetStatic 2 // Set static variable at index 2
}
Functions are defined with optional keywords and contain a sequence of bytecode instructions:
// Basic function
function:2 _Global_CalculateSum_int_int {
LoadLocal 0
LoadLocal 1
IntAdd
Return
}
// Pure function with argument descriptions
// Arguments: int (int), int (int)
pure(int, int) function:2 _Global_IsEven_int_int {
LoadLocal 0
PushInt 2
IntModulo
PushInt 0
IntEqual
Return
}
// Pure function with mixed argument types
// Arguments: String, int
pure(String, int) function:2 _Global_StringRepeat_String_int {
LoadLocal 0 // String reference
LoadLocal 1 // Int copy
Call _Global_StringRepeatImpl_String_int
Return
}
// Function with no JIT optimization
no-jit function:1 _Global_DebugPrint_Object {
LoadLocal 0
CallVirtual _ToString_<C>
PrintLine
Return
}
// Main function (entry point)
function:1 _Global_Main_StringArray {
PushString "Hello, World!"
PrintLine
PushInt 0
Return
}
VTable is a data structure that maps method names to their implementations. It is used to resolve method calls at runtime. VTable is stored in the object itself and is accessed by the object’s vtable index. VTable is also used to resolve field access at runtime.
VTable definitions map interface methods and field information to their implementations and contains class size information in bytes:
vtable <ClassName> {
size: <size> // Includes vtable index (4 bytes) + badge (4 bytes) + field sizes in bytes
interfaces {
<InterfaceName>,<InterfaceName>, ...
}
methods {
<methodNameWithoutClassName>: <realFunctionName>
<methodNameWithoutClassName>: <realFunctionName>
...
}
vartable {
<fieldName>: <typename|Object>@<offset> // typename for fundamental types, Object for user-defined types
<fieldName>: <typename|Object>@<offset> // typename for fundamental types, Object for user-defined types
...
}
}
Function names are mangled to include fully qualified class names for method resolution:
_Global_<functionName>_<arg1Type>_<arg2Type>_..._<argNType>_<ClassName>_<methodName>_<constFlag>_<arg1Type>_<arg2Type>_..._<argNType>_<OuterClass>_<InnerClass>_<methodName>_<constFlag>_<arg1Type>_<arg2Type>_..._<argNType>Note: Namespaces are included in the class and function names, e.g.
_test_FooBar_Intfortest::FooBar(a : Int)function.
Argument mutability indicators:
<M> - Mutable argument (var parameter)<C> - Const argument (default, immutable parameter, omitted)Const method flag:
<M> - Mutable method (can modify object state)<C> - Const method (cannot modify object state)// Source code
fun Foo(a: Int, b: bool, var s: String): String { ... }
class MathUtils implements IComparable {
fun Add(a: Int, b: Int): Int { ... }
pure fun IsEven(n: int): Bool { ... }
mut fun IncrementCounter(): Void { ... }
override fun IsLess(other: Object): Bool { ... }
}
fun Main(args: StringArray): Int { ... }
// Mangled names
_Global_Foo_Int_bool_<M>String
_MathUtils_Add_<M>_Int_Int
_MathUtils_IsEven_<C>_int
_MathUtils_IncrementCounter_<M>
_MathUtils_IsLess_<C>_Object
_Global_Main_StringArray