A basic virtual machine for dynamically-typed languages. To build, just do cargo build
.
$ rockvm file.bin # execute the file by calling the function "main" in the class named "$self"
$ rockvm file.bin -d # disassemble the file
This is a little-endian VM.
u32: magic number
u8: version
u32: count
then 'count' String
u32: number of classes
then 'count' Class
'ROCK' in ASCII (or 0x4B434F52 in LE)
Must be 1.
u16: length
then 'length' bytes
String: name
String: super type
u8: count
then 'count' fields
u8: count
then 'count' functions
String: name
bytecode: default value
String: name
u8: arity (number of parameters)
u8: number of local variables
bytecode: body of the function
u8/u16: u8 for a field's default value, u16 for a function's body
then that many bytes
Pops the current call frame.
Pushes a constant on the stack.
The next byte tells the type of constant, some have following bytes for the actual data:
null
: 1
.
bool
: 2
then 0
for false
or 1
(or any non 0
) for true
.
integer
: 3
then 4 bytes containing the integer in little-endian.
float
: 4
then 4 bytes containing the float in little-endian.
string
: 5
then 2 bytes containing an index in the strings
array.
Negates the top value on the stack (int or float only).
Pops 2 values from the stack and pushes their sum.
If one of the value is a string, it converts the other to a string and concatenates them.
Pops 2 values from the stack and pushes their difference.
Pops 2 values from the stack and pushes their product.
Pops 2 values from the stack and pushes their fraction.
Pushes true
.
Pushes false
.
Pushes null
.
Negates the top of the stack if it's a bool.
Pops 2 values from the stack and pushes true
if they are equals, false
otherwise.
Pops 2 values from the stack and pushes true
if they are equals, false
otherwise.
Pops 2 values from the stack and pushes true
if they are equals, false
otherwise.
Pushes a closure on the stack. Takes the next 2 bytes to get an index into the strings
array to get the name.
Warning: doesn't capture anything at the moment.
Pops the top of the stack.
Pushes on the stack a global variable. Takes the next 2 bytes to get an index into the strings
array to get the name.
Pops on the stack and stores it in a global variable. Takes the next 2 bytes to get an index into the strings
array to get the name.
Then pushes null
.
Takes the next 2 bytes to get an index into the strings
array to get the name.
Takes the next byte to know how many arguments are on the stack.
Identical to OP_JUMP
but jumps backwards.
Warning: the offset is in opcode
not in byte
.
Takes the next 2 bytes to get the index of a local variable on the stack. And pushes it on the stack.
Takes the next 2 bytes to get the index of a local variable on the stack.
Pops the top of the stack and stores it in that local variable.
Then pushes null
.
Takes the next 2 bytes to get an index into the strings
array to get the type name.
Pushes on the stack a variable of that type.
Takes the next 2 bytes to get an index into the strings
array to get the field name.
Pushes on the stack the field of that name from the object at index 0 in the callframe.
Takes the next 2 bytes to get an index into the strings
array to get the field name.
Pops off the stack a variable and stores it in the field of that name in the object at index 0 in the callframe.
The next byte is a forwards offset to jump to.Jumps if the top value of the stack is true
.
Warning: the offset is in opcode
not in byte
.
The next byte is a forwards offset to jump to.
Warning: the offset is in opcode
not in byte
.
Duplicates the top value of the stack.
Identical to OP_JUMP_IF
but jumps backwards.
Warning: the offset is in opcode
not in byte
.
The first 2 bytes are an index into the strings
array to get the filename to import (.rock
is automatically added).
The next 2 bytes are the number of arguments.
Each argument has that format:
- 2 bytes for the name in the symbol in the imported file, that is an index into the
strings
array. - 2 bytes for the name for the symbol once in the importer file, that is an index into the
strings
array. (if you don't want to rename the symbol, set both to the same index)
Identical to OP_CALL
except it calls the same named method in the parent class.
Dump the current stack.