The NariVM is a portable virtual machine I created (and that was heavily optimized by Mario Rugiero), that is designed to help me implement programming languages. This is the documentation for the opcodes it supports.
Opcodes support inline arguments in certain cases. In that case, they are listed as:
Inline Arguments: Argument
The NariVM is stack based. Arguments and return values for the opcodes below are listed like this:
Arguments: Value 1
Value 2
Etc.
Return: Value 1
Value 2
Etc.
Where Value 1 is closer to the top of the stack and Value 2 is closer to the bottom after all values have been pushed to the stack. Values are popped from the top of the stack and inserted atop the stack as well.
The stack supports values of the Value
type. Values can be numbers (internally represented
as double
), strings (std::string
), tables (which are map
that map from std::string
to Value
), the nil value (non-value), iterators, and list limits.
NariVM Assembly (Nambly) to be compiled and executed by the NariVM must consist of lines of text with only a single opcode and its eventual arguments separated by spaces.
NariVM tries to convert between types transparently, so a string number can be added to an actual number, numbers and tables can be concatenated and substring-ed, etc.
Tables are always pushed to the stack by reference and garbage collected if references cease to exist. Other values are passed by value instead.
Most values in NariVM can evaluate to true or false. The number 0, the nil value, en empty table or an empty string are all false. All other values are true.
Pushes a value to the stack.
Inline Arguments: value
Pushes the nil value to the stack.
Pushes the list limit value to the stack.
Adds two values and pushes the result to the stack.
Arguments: Value2 (number)
Value1 (number)
Return: Value1 + Value2
Subtracts two values and pushes the result to the stack.
Arguments: Value2 (number)
Value1 (number)
Return: Value1 - Value2
Multiplies two values and pushes the result to the stack.
Arguments: Value2 (number)
Value1 (number)
Return: Value1 * Value2
Divides two values and pushes the result to the stack.
Arguments: Value2 (number)
Value1 (number)
Return: Value1 / Value2
Divides two values using integer division and pushes the result to the stack.
Arguments: Value2 (number)
Value1 (number)
Return: floor(Value1 / Value2)
Raises a number to the power of another number.
Arguments: Value2 (number)
Value1 (number)
Return: Value1 ^ Value2
Modulo operation between two integer values and pushes the result to the stack.
Arguments: Value2 (number)
Value1 (number)
Return: floor(Value1) % floor(Value2)
Compares two values and pushes 1
or 0
to the stack, depending on whether the comparison was true or false, respectively.
Arguments: Value2 (number)
Value1 (number)
Return: Value1 > Value2
Compares two values and pushes 1
or 0
to the stack, depending on whether the comparison was true or false, respectively.
Arguments: Value2 (number)
Value1 (number)
Return: Value1 < Value2
Compares two values and pushes 1
or 0
to the stack, depending on whether the comparison was true or false, respectively.
Arguments: Value2 (number)
Value1 (number)
Return: Value1 >= Value2
Compares two values and pushes 1
or 0
to the stack, depending on whether the comparison was true or false, respectively.
Arguments: Value2 (number)
Value1 (number)
Return: Value1 <= Value2
Compares two values and pushes 1
or 0
to the stack, depending on whether the comparison was true or false, respectively.
Arguments: Value2
Value1
Return: (type(Value1) == type(Value2) and Value1 == Value2) or number(Value1) == number(Value2)
Compares two values and pushes 1
or 0
to the stack, depending on whether the comparison was true or false, respectively.
Arguments: Value2
Value1
Return: not((type(Value1) == type(Value2) and Value1 == Value2) or number(Value1) == number(Value2))
Sets the value of the variable variable name
in the current scope to Value1
. If the variable exists,
its current value is replaced, otherwise it's created.
Inline Arguments: variable name
Arguments: Value1
Sets the value of the variable variable name
in the global scope to Value1
. If the variable exists,
its current value is replaced, otherwise it's created.
Inline Arguments: variable name
Arguments: Value1
Gets the value of the variable variable name
in the nearest scope. If the variable exists,
its current value is pushed to the stack, otherwise the nil value is.
Inline Arguments: variable name
Return: variable value
or nil
Takes the literal representation of two values and concatenates them.
Arguments: Value2 (number)
Value1 (number)
Return: Value1Value2
Substrings a string. If the start index is less than 0 it's reset to -1. Negative start indexes count
back from the end of the string (-1 being the last index, -2 the one before last, etc.) If number of characters
is out of bounds, it's capped to remaining character count. If the start index
is longer than the
string, an empty substring is returned.
Arguments: Number of characters
Start Index
String
Return: String[Start Index:Number of characters]
Replaces all instances of the string needle
with the string replacement
in the string haystack
Arguments: replacement
needle
haystack
Return: haystack.replace(needle, replacement)
Splits text
by the delimiter delimiter
.
The maximum number of splits to perform is defined by max_splits
. If max_splits
is -1, no maximum
number of splits is defined.
Empty cuts can be ommited from the final list by setting add_empties
to 1 (0 to keep them).
Arguments: text
delimiter
max_splits
add_empties
Return: table value with all cuts indexed numerically starting from 1
Splits text
by the any of the chars in delimiter
.
The maximum number of splits to perform is defined by max_splits
. If max_splits
is -1, no maximum
number of splits is defined.
Empty cuts can be ommited from the final list by setting add_empties
to 1 (0 to keep them).
Arguments: text
delimiter
max_splits
add_empties
Return: table value with all cuts indexed numerically starting from 1
Sets a tag in the code jump to.
Inline Arguments: tag name
Sets a comment in the code.
Inline Arguments: comment
Adds an execution tag so that if an error pops in a line after this one, NariVM can tell the user which line from the code that was compiled into this nambly generated the error.
Inline Arguments: line number
Adds an execution tag so that if an error pops in a line after this one, NariVM can tell the user which file contained the code that was compiled into the nambly that generated the error.
Inline Arguments: file name
Jumps execution to the location of the inline tag.
Inline Arguments: tag name
Jumps execution to the location of the inline tag, but also pushes the current code location to the return stack so that execution can later continue from this point.
Inline Arguments: tag name
Pops a location from the top of the return stack and returns to that location.
Pops a value from the stack. If the value can be considered false, jumps to the inline tag.
Inline Arguments: tag name
Arguments: value
Pushes an empty table value to the stack.
Return: table value
Sets the value
of a position
(casted to string) in a table
.
Arguments: value
index
table
Gets the value
of a position
(casted to string) in a table
. If the position is not
in the table, nil
is returned.
Arguments: index
table
Return: value
or nil
Like the pirates. Pops values to the stack and adds them to a table starting on position 1 and counting up until a list limit value is found. Nil values and iterator values cannot be added to tables and will raise a runtime error if a value with such typing is popped.
The generated table is then pushed into the stack.
Arguments: mutiple value
list limit
Return: table array
Duplicates the value atop the stack.
Arguments: value
Return: value
value
Prints the string representation of a value to the screen.
Arguments: value
Prints the prompt
and asks the user for input
.
Arguments: prompt
Return: input
Deletes the topmost value of the stack.
Arguments: value
Exits with exit code
.
Arguments: exit code
If a variable with this name exists in the uppermost scope or the global scope, it's deleted.
Inline Arguments: variable name
If the position index
exists in the table
, delete the position.
Inline Arguments: index
table
Opens the file at path filename
if it already existed, or creates it otherwise. The file is
prepared for reading from it and writing to it (overwriting all its contents).
Arguments: filename
Return: filename
Opens the file at path filename
if it already existed, or creates it otherwise. The file is
prepared for reading from it and appending to it.
Arguments: filename
Return: filename
Opens the file at path filename
if it already exists. The file is loaded as a read-only file.
Arguments: filename
Return: filename
Reads the previously opened file with name filename
. You should use the filename
returned
by the FORW
, FORA
and FORE
opcodes. If the file isn't open or it didn't exist and wasn't
created, nil
is returned when trying to read from it. Otherwise, its contents
are pushed to
the stack.
Arguments: filename
Return: contents
or nil
Closes the file filename
if it was open. You should use the filename
returned
by the FORW
, FORA
and FORE
opcodes.
Arguments: filename
Returns if the file filename
is open (1
) or not (0
). You should use the filename
returned
by the FORW
, FORA
and FORE
opcodes.
Arguments: filename
Return 1
or 0
Reads the next line
form the previously opened file with name filename
. You should use the filename
returned
by the FORW
, FORA
and FORE
opcodes. If the file isn't open, a runtime error is thrown.
If all lines have been already read, nil
is pushed.
Arguments: filename
Return: line
or nil
Writes a value
(as string) to the file filename
. You should use the filename
returned
by the FORW
, FORA
and FORE
opcodes. If the file isn't open, a runtime error is thrown.
If the file was opened for writing, it's contents are replaced by value
. Otherwise the value
is
appended to them.
Arguments: filename
Return: line
or nil
Negates the logical value of value
. If value
is not a number, a string or a table, an
error is thrown.
Arguments: value
Return: not value
ANDs the logical values of two values.
Arguments: value1
value2
Return: value1 and value2
ORs the logical values of two values.
Arguments: value1
value2
Return: value1 or value2
Trims whitespace around value
Arguments: value
Return: trimmed value
Pushes the number of characters or the number of elements in the string or table value
.
Arguments: value
Return: element count
Swaps the position in the stack of the two topmost values.
Arguments: value1
value2
Return: value2
value1
If the container
is a string, it checks if the substring value
is part of it.
If the container
is a table, it checks if contains the position with key value
.
Arguments: container
value
Return: 1
or 0
Rounds down a numerical value to the nearest integer.
Arguments: value
Return: floor(value)
Creates a new variable scope on top of the previous one.
Deletes the uppermost variable scope. If only the global scope remains, a runtime error is thrown.
Executes the sytem command command
and returns its exit code
, its stderr
output and its stdout
output.
Arguments: command
Return: stdout_value
stderr_value
exit_code_value
Sleeps for a number of seconds
.
Arguments: seconds
Given a table
, a new table
is pushed into the stack with all keys of table
indexed
into the new table
from 1 to n.
Arguments: table
Return: new table
Pushes an iterator for a table value
or a value
cast to string. An iterator is an object
that contains references to all elements of the original value
and can return them one after
the other.
Arguments: value
Return: iterator for value
Given an iterator
, if it still has elements in it, the next element is pushed into the stack
above the iterator
, which is not consumed. Otherwise, if the iterator is depleted, it's
consumed and nil
is pushed instead.
Arguments: iterator
Return: next element
iterator
or nil
Prints NariVM debug information to the screen.