navm 0.1.4

A simple VM intended to be used in scripting languages


To use this package, run the following command in your project's root directory:

A VM designed to be fast, intended for use in scripting languages.

It's sometimes written navm instead of NaVM, both are the same

Getting Started

These instructions will get you a copy of NaVM with its very basic instuctions, which will serve as a demo. Remember, NaVM is not built to be a standalone application, it's meant to be used as a library (originally built for QScript, but everyone's free to use it).

See source/app.d to see how to add external functions, and use it in your program.

Prerequisites

You need to have these present on your machine:

  1. dub
  2. dlang compiler (only dmd is tested)
  3. Internet connection (for dub to fetch NaVM and its dependencies)

Building

Run:

dub fetch navm

to download this package, and then run:

dub build navm -b=release -c=demo

to fetch dependencies and build NaVM. Following this, you will have the NaVM binary (named demo) with very basic functionality.

You can now run NaVM bytecode using:

~/.dub/packages/navm-*/navm/demo path/to/bytecodefile

This binary also has 5 external functions:

  • ID: 0, call using `ExecuteFunctionExternal 0 n` where n is number of integers to pop from stack and writeln(int) to terminal
  • ID: 1, call using `ExecuteFunctionExternal 1 n` where n is number of doubles (floats) to pop from stack and writeln(double) to terminal
  • ID: 2, call using `ExecuteFunctionExternal 2 n` where n is number of strings to pop from stack and write to terminal
  • ID: 3, call using `ExecuteFunctionExternal 3 n` writes n number of newline characters to terminal
  • ID: 4, call using `ExecuteFunctionExternal 4 0` reads a line from stdin, pushes it to stack

Syntax

Although you do not need to actually write following this if you are using NaVM in a library, you can programmatically add instructions to functions, this still exists.(See source/bytecodedefs.d : NaFunction)

The syntax is as follows:

def 20 # this defines function with function id = 0, which has space for 20 elements on stack
	FirstInstruction [InstructionArgument0] [Argument1]
	SecondInstruction # comment
	ThirdInstruction
# comment
	FourthInstruction
	
def 15 # another function begins from here (id = 1), which has space for 15 elements on stack
FirstInstruction		# Indentation is not necesarry, go crazy (i don't recommend it tho)
	SecondInstructions
	...

The bytecode is divided into functions. Each function definition begins with the keyword def, followed by the required stack length (separate using whitespace). Function ID is automatically assigned, starting with 0. This is to avoid using assoc_arrays, to improve performace. After that, each line is an instruction or a comment, or whitespace, until the next function definition is found.

Instructions are written in either of these ways: Tab %instruction% %arguments% or: %instruction% %arguments% Tabs or spaces can be used to indent, but indentation is not necesary, and you can use more than 1 tab/space to indent. Instructions are not case sensitive, ExecuteFunction is the same as eXeCuTeFuNcTiOn.

License

NaVM is licensed under the MIT License - see LICENSE for details

Instructions

Here's a list of instructions that NaVM has out of the box. You can easily add more (Add name, argument count, and other info to source/navm/bytecodedefs.d and implement those instructions in source/navm/navm.d

Calling functions:
  • `ExecuteFunction [function id - integer>=0] [n - integer>=0]` pops `n` number of elements from stack. Calls a function defined in bytecode, pushes the elements in that function's stack in the same order they were. Pushes the return value from that function to stack.
  • `ExecuteFunctionExternal [function id - integer>=0] [n - integer>=0]` pops `n` number of elements from stack. Calls an external function with the elements popped as arguments. Pushes the return value from that function to stack.

Keep in mind that these functions push `NaData()` to stack if function did not return any meaningful data, so if you don't need to use the return value, or the function doesn't return meaningful data, follow these instructions with a `Pop` instruction.

Arithmetic operators
For integers
  • `MathAddInt` Pops A (integer), then B (integer). Pushes A + B (integer) to stack.
  • `MathSubtractInt` Pops A (integer), then B (integer). Pushes A - B (integer) to stack.
  • `MathMultiplyInt` Pops A (integer), then B (integer). Pushes A * B (integer) to stack.
  • `MathDivideInt` Pops A (integer), then B (integer). Pushes A / B (integer) to stack.
  • `MathModInt` Pops A (integer), then B (integer). Pushes A % B (integer) to stack.
For floating point (double)
  • `MathAddDouble` Pops A (double), then B (double). Pushes A + B (double) to stack.
  • `MathSubtractDouble` Pops A (double), then B (double). Pushes A - B (double) to stack.
  • `MathMultiplyDouble` Pops A (double), then B (double). Pushes A * B (double) to stack.
  • `MathDivideDouble` Pops A (double), then B (double). Pushes A / B (double) to stack.
  • `MathModDouble` Pops A (double), then B (double). Pushes A % B (double) to stack.
Comparison Operators
  • `IsSame` Pops 2 values from stack, pushes 1 (integer) to stack if both have same value, else, pushes 0 (integer).
  • `IsSameArray` Pops 2 arrays from stack (arrays, not referece to array). Pushes 1 (integer) to stack if both are same (length, and elements), else, pushes 0 (integer)
  • `IsSameArrayRef` Pops 2 references to arrays from stack. Pushes 1 (integer) to stack if both are same (length, and elements), else, pushes 0 (integer)
  • `IsGreaterInt` Pops A (integer), then B (integer). Pushes 1 (integer) if A > B, else, pushes 0 (integer)
  • `IsGreaterSameInt` Pops A (integer), then B (integer). Pushes 1 (integer) if A >= B, else, pushes 0 (integer)
  • `IsGreaterDouble` Pops A (double), then B (double). Pushes 1 (integer) if A > B, else, pushes 0 (integer)
  • `IsGreaterSameDouble` Pops A (double), then B (double). Pushes 1 (integer) if A >= B, else, pushes 0 (integer)
  • `Not` Pops A (integer). Pushes !A
  • `And` Pops A (integer) and then B (integer). Pushes A && B
  • `Or` Pops A (integer) and then B (integer). Pushes A || B
Stack
  • `Push [arg0 - any data type]` Pushes arg0 to stack
  • `PushFrom [index - integer>=0]` Reads value at index on stack, pushes it. Value at index is not removed from stack.
  • `PushRefFrom [index - integer>=0]` Pushes reference to value at index on stack.
  • `WriteTo [index - integer>=0]` Pops a value from stack, writes it to index on stack.
  • `WriteToRef` Pops a reference, then pops a value. Writes value to reference.
  • `Deref` Pops a reference from stack. Pushes the value being referenced
  • `Pop` Pops 1 value from stack
  • `PopN [n - integer >= 0]` Pops n number of values from stack
Jumps
  • `Jump [index - integer>=0]` Jump execution to instruction at index. Be careful using this, make sure you have used `Pop` to clear stack of unneeded elements
  • `JumpIf [index - integer>=0]` Pops integer from stack. If it is 1, jumps execution to instruction at index. Be careful using this, make sure you have used `Pop` to clear stack of unneeded elements
Arrays
  • `MakeArray [n - integer>0]` Pops n number of elements from stack, puts them in an array (in the order they were added to stack). Pushes array to stack.
  • `ArrayRefElement` Pops a reference to array, then an index (integer). Pushes reference-to-element at index on array.
  • `ArrayElement` Pops an array, then an index (integer). Pushes reference-to-element at index on array.
  • `ArrayLength` Pops an array. Pushes length of stack (integer) to stack.
  • `ArrayLengthSet` Pops a reference to array, then length (integer). Sets length of array to length
  • `Concatenate` Pops an array a1 (not reference, array), then pops another array a2. Pushes new array a1 ~ a2.
  • `AppendElement` Pops a reference to array, then an element. Appends element at end of array.
  • `AppendArrayRef` Pops reference to array r1, pops another r2. Then does *r1 = *r1 ~ *r2
  • `AppendArray` Pops reference to array r1, then pops an array (not reference). Then does *r1 = *r1 ~ r2
Data type conversion
  • `IntToDouble` Pops an integer from stack. Pushes a double with same value.
  • `IntToString` Pops an integer from stack. Pushes a string representation of it.
  • `DoubleToInt` Pops a double from stack. Pushes integer part of it (as a integer) to stack.
  • `DoubleToString` Pops a double from stack. Pushes string representation of it.
  • `StringToInt` Pops a string, reads integer from it, pushes the integer.
  • `StringToDouble` Pops a string, reads a double from it, pushes the double.
Misc.
  • `ReturnVal` Pops a value from stack, sets it as the return value of currently executing function. Does NOT terminate execution
  • `Terminate` Terminates execution of function. Must be called at end of function, or it'll segfault
Authors:
  • Nafees
Dependencies:
utils
Versions:
0.2.3 2020-Feb-09
0.2.2 2020-Jan-30
0.2.1 2020-Jan-24
0.2.0 2020-Jan-19
0.1.4 2020-Jan-13
Show all 12 versions
Download Stats:
  • 0 downloads today

  • 0 downloads this week

  • 5 downloads this month

  • 14 downloads total

Score:
0.8
Short URL:
navm.dub.pm