The Sapbot VM Book

Table of Contents

1. Introduction to Sapbot VM

Sapbot VM is a simple virtual machine designed for educational purposes and basic programming tasks. It provides a minimalistic instruction set and memory model that allows for writing and executing simple programs.

The VM is implemented in both Go and JavaScript, making it portable across different platforms. It supports basic arithmetic operations, conditional branching, memory manipulation, and input/output operations.

Note: Sapbot VM is not designed for high-performance computing or complex applications. It's primarily an educational tool to understand how virtual machines and interpreters work at a basic level.

2. Architecture Overview

The Sapbot VM consists of several key components:

The VM executes programs line by line, with each line containing an instruction and its operands. The program counter automatically increments after each instruction unless modified by control flow instructions.

Memory Model

Sapbot VM uses a simple memory model where memory is represented as a map/dictionary with integer keys (memory cell addresses) and values that can be of different types (integers, floats, strings, etc.).

type Memory map[int]interface{}

Memory cells are automatically initialized to 0 when accessed if they haven't been set before.

3. Data Types

Sapbot VM supports several data types that can be used in instructions and stored in memory:

Prefix Name Example Description
V Integer V3 Represents an integer value (3 in this case)
M Memory Reference M3 References the value in memory cell 3
T Text Thello Represents a text/string value ("hello")
F Float F0.5 Represents a floating-point number (0.5)
S Stack Reference S1:3 References the value at index 3 in stack 1
H Heap Reference H1:5 References the value at address 5 in heap 1
A Array Reference A10:3 References the value at index 3 in the array starting at memory cell 10

Example Usage:

LOAD;V0;V5      ; Load value 5 into memory cell 0
DEBUG;TM3      ; Print the value from memory cell 3
ADD;V1;V2;M0   ; Add values 1 and 2, store result in memory cell 0

; New data type examples:
STACK_CREATE;V10  ; Create a stack and store its ID in memory cell 10
STACK_PUSH;M10;V5 ; Push value 5 onto the stack
STACK_POP;M10;V20 ; Pop value from stack and store in memory cell 20

HEAP_CREATE;V11   ; Create a heap and store its ID in memory cell 11
HEAP_SET;M11;V0;V42 ; Set value 42 at address 0 in the heap
HEAP_GET;M11;V0;V21 ; Get value from address 0 in the heap and store in memory cell 21

ARRAY_SET;V100;V0;V7 ; Set value 7 at index 0 in the array starting at memory cell 100
ARRAY_GET;V100;V0;V22 ; Get value from index 0 in the array and store in memory cell 22

4. Instruction Set Reference

Sapbot VM provides a set of instructions for performing various operations. Each instruction follows the format:

INSTRUCTION;ARG1;ARG2;...

Where arguments can be immediate values (V, T, F) or memory references (M).

Instruction Format Description Example
LOAD LOAD;CELL;VALUE Stores a value in a memory cell LOAD;V0;V3
DEBUG DEBUG;VALUE Prints a value to the console DEBUG;Thello
GOTO GOTO;LINE Jumps to a specific line number GOTO;V50
NOT NOT;VALUE;TO Logical NOT operation NOT;V1;V3
ADD ADD;A;B;TO Adds two values, stores result ADD;V5;V5;V0
SUB SUB;A;B;TO Subtracts B from A, stores result SUB;V5;V5;V0
DIV DIV;A;B;TO Divides A by B, stores result DIV;V10;V2;V1
MUL MUL;A;B;TO Multiplies A and B, stores result MUL;V5;V5;V0
MOD MOD;A;B;TO Modulo operation (A % B) MOD;V7;V3;V2
NOP NOP No operation (does nothing) NOP
ALB ALB;A;B;TO Jump to TO if A < B (A Less than B) ALB;V0;V5;V30
AQB AQB;A;B;TO Jump to TO if A == B (A equals B) AQB;V0;V5;V30
ABB ABB;A;B;TO Jump to TO if A > B (A greater than B) ABB;V0;V5;V30
AND AND;A;B;TO Logical AND operation AND;V1;V1;V3
OR OR;A;B;TO Logical OR operation OR;V0;V1;V3
DEBINP DEBINP;CELL Prompts for user input, stores in cell DEBINP;V3
PARSEINT PARSEINT;IN;OUT Parses a string as integer PARSEINT;M0;V1
RND RND;MAX;TO Generates random number (0 to MAX-1) RND;V100;V0
STACK_CREATE STACK_CREATE;TO Creates a new stack and stores its ID in TO STACK_CREATE;V10
STACK_PUSH STACK_PUSH;STACK_ID;VALUE Pushes a value onto the specified stack STACK_PUSH;M10;V5
STACK_POP STACK_POP;STACK_ID;TO Pops a value from the specified stack and stores it in TO STACK_POP;M10;V20
HEAP_CREATE HEAP_CREATE;TO Creates a new heap and stores its ID in TO HEAP_CREATE;V11
HEAP_SET HEAP_SET;HEAP_ID;ADDRESS;VALUE Sets a value at the specified address in the heap HEAP_SET;M11;V0;V42
HEAP_GET HEAP_GET;HEAP_ID;ADDRESS;TO Gets a value from the specified address in the heap and stores it in TO HEAP_GET;M11;V0;V21
ARRAY_SET ARRAY_SET;BASE_ADDRESS;INDEX;VALUE Sets a value at the specified index in the array ARRAY_SET;V100;V0;V7
ARRAY_GET ARRAY_GET;BASE_ADDRESS;INDEX;TO Gets a value from the specified index in the array and stores it in TO ARRAY_GET;V100;V0;V22
CALL CALL;ADDRESS Jumps to the specified address (basic function call) CALL;V100
RET RET Returns from a function call (basic) RET

Note: All instructions that perform comparisons or jumps (ALB, AQB, ABB) will jump to the specified line number if the condition is true. The program counter is automatically incremented after each instruction unless explicitly changed by a GOTO or jump instruction.

5. Program Format

Sapbot VM programs can be written in two formats:

JSON Object Format

Each line number is a key in a JSON object, with the instruction as the value:

{
    "10": "DEBUG;THello, World!",
    "20": "LOAD;V0;V5",
    "30": "DEBUG;M0"
}

JSON Array Format

Instructions are listed in an array, with implicit line numbers starting from 0:

[
    "DEBUG;THello, World!",
    "LOAD;V0;V5",
    "DEBUG;M0"
]

Example (fibonacci.svm):

{
    "10":"LOAD;V0;V0",
    "20":"LOAD;V1;V1",
    "30":"LOAD;V2;V0",
    "40":"ADD;M2;V1;V2",
    "50":"DEBUG;M1",
    "60":"ADD;M0;M1;V3",
    "70":"LOAD;V0;M1",
    "80":"LOAD;V1;M3",
    "90":"ALB;M2;V20;V40"
}

Note: The JSON object format allows for non-sequential line numbers, which is useful for programs with jumps and branches. The array format is simpler but requires sequential execution.

6. Example Programs

Hello World

The simplest program that prints "Hello, World!":

[
    "DEBUG;THello, World!"
]

Fibonacci Sequence

A program that calculates and prints Fibonacci numbers:

{
    "10":"LOAD;V0;V0",      ; Initialize first Fibonacci number (0)
    "20":"LOAD;V1;V1",      ; Initialize second Fibonacci number (1)
    "30":"LOAD;V2;V0",      ; Initialize counter
    "40":"ADD;M2;V1;V2",    ; Calculate next Fibonacci number
    "50":"DEBUG;M1",        ; Print current Fibonacci number
    "60":"ADD;M0;M1;V3",    ; Update previous number
    "70":"LOAD;V0;M1",      ; Load current into M0
    "80":"LOAD;V1;M3",      ; Load next into M1
    "90":"ALB;M2;V20;V40"  ; Loop if counter < 20
}

Number Guessing Game

A simple game where the user guesses a random number:

{
    "10": "RND;V100;V0",            ; Generate random number (1-100)
    "20": "ADD;M0;M0;V1",          ; Increment to make range 1-100
    "30": "DEBUG;TGuess a number between 1 and 100:",
    "40": "DEBINP;V3",             ; Get user input
    "50": "PARSEINT;M3;V4",        ; Convert input to integer
    "60": "AQB;M4;M0;V200",        ; Check if guess equals target
    "70": "ALB;M4;M0;V300",        ; Check if guess is less than target
    "80": "DEBUG;TToo high! Try again.",
    "90": "GOTO;V30",              ; Try again
    "200": "DEBUG;TCongratulations! You guessed the number!",
    "210": "GOTO;V9999",           ; End program
    "300": "DEBUG;TToo low! Try again.",
    "310": "GOTO;V30"              ; Try again
}

Advanced Features Example

A program that demonstrates the new advanced features of Sapbot VM:

{
    "10": "DEBUG;T=== Advanced Sapbot VM Example ===",
    "20": "DEBUG;TThis program demonstrates the new features:",
    "30": "DEBUG;T- Stack operations",
    "40": "DEBUG;T- Heap operations",
    "50": "DEBUG;T- Array operations",
    "60": "DEBUG;T- Error handling",

    "70": "DEBUG;T",
    "80": "DEBUG;T=== Stack Example ===",

    "90": "STACK_CREATE;V100",        ; Create a stack and store its ID in cell 100
    "100": "STACK_PUSH;M100;V1",     ; Push value 1 onto the stack
    "110": "STACK_PUSH;M100;V2",     ; Push value 2 onto the stack
    "120": "STACK_PUSH;M100;V3",     ; Push value 3 onto the stack
    "130": "DEBUG;TStack contents:",
    "140": "STACK_POP;M100;V200",    ; Pop value from stack and store in cell 200
    "150": "DEBUG;M200",             ; Print the popped value
    "160": "STACK_POP;M100;V200",    ; Pop value from stack and store in cell 200
    "170": "DEBUG;M200",             ; Print the popped value
    "180": "STACK_POP;M100;V200",    ; Pop value from stack and store in cell 200
    "190": "DEBUG;M200",             ; Print the popped value

    "200": "DEBUG;T",
    "210": "DEBUG;T=== Heap Example ===",

    "220": "HEAP_CREATE;V101",       ; Create a heap and store its ID in cell 101
    "230": "HEAP_SET;M101;V0;V10",   ; Set value 10 at address 0 in the heap
    "240": "HEAP_SET;M101;V1;V20",   ; Set value 20 at address 1 in the heap
    "250": "HEAP_SET;M101;V2;V30",   ; Set value 30 at address 2 in the heap
    "260": "DEBUG;THeap contents:",
    "270": "HEAP_GET;M101;V0;V201",  ; Get value from address 0 in the heap and store in cell 201
    "280": "DEBUG;M201",             ; Print the value
    "290": "HEAP_GET;M101;V1;V201",  ; Get value from address 1 in the heap and store in cell 201
    "300": "DEBUG;M201",             ; Print the value
    "310": "HEAP_GET;M101;V2;V201",  ; Get value from address 2 in the heap and store in cell 201
    "320": "DEBUG;M201",             ; Print the value

    "330": "DEBUG;T",
    "340": "DEBUG;T=== Array Example ===",

    "350": "LOAD;V102;V50",         ; Use memory cell 50 as the base address for our array
    "360": "ARRAY_SET;V102;V0;V100", ; Set value 100 at index 0 in the array
    "370": "ARRAY_SET;V102;V1;V200", ; Set value 200 at index 1 in the array
    "380": "ARRAY_SET;V102;V2;V300", ; Set value 300 at index 2 in the array
    "390": "DEBUG;TArray contents:",
    "400": "ARRAY_GET;V102;V0;V202", ; Get value from index 0 in the array and store in cell 202
    "410": "DEBUG;M202",             ; Print the value
    "420": "ARRAY_GET;V102;V1;V202", ; Get value from index 1 in the array and store in cell 202
    "430": "DEBUG;M202",             ; Print the value
    "440": "ARRAY_GET;V102;V2;V202", ; Get value from index 2 in the array and store in cell 202
    "450": "DEBUG;M202",             ; Print the value

    "460": "DEBUG;T",
    "470": "DEBUG;T=== Function-like Example ===",

    "480": "LOAD;V103;V500",        ; Set the address of our "function" to 500
    "490": "CALL;M103",              ; Call the "function"
    "500": "DEBUG;TInside function-like block",
    "510": "DEBUG;TThis demonstrates basic function support",
    "520": "RET",                   ; Return from the function

    "530": "DEBUG;T",
    "540": "DEBUG;T=== Program Complete ===",
    "550": "GOTO;V9999"              ; End program
}

7. Implementations

Sapbot VM has been implemented in two languages:

Go Implementation (run.go)

The Go implementation provides the core VM functionality with these key components:

type SVM struct {
    pc   int
    mem  Memory
    code map[int]string
}

Key features:

JavaScript Implementation (run.js)

The JavaScript implementation uses Node.js and provides similar functionality:

var mem = new Proxy({}, {
    get: function(target, prop) {
        return prop in target ? target[prop] : 0;
    }
});

Key features:

Note: Both implementations can run the same programs, though there might be minor differences in error handling and edge cases.

8. Advantages and Disadvantages of Sapbot VM

Advantages

Disadvantages

Comparison with Other Systems

Feature Sapbot VM Brainfuck Scratch Lua C Python Java VM HTML5
Educational Value ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐
Performance ⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
Complexity ⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐ ⭐⭐
Difficulty to Write Code ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐
Difficulty to Write Runtime ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐
Extensibility ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐

Best Use Cases: Sapbot VM is ideal for educational purposes, teaching basic computing concepts, and simple programming experiments. It's not suitable for production applications or complex software development.

9. Conclusion

Sapbot VM has evolved from a simple educational tool to a more robust virtual machine that can handle more complex programming tasks while maintaining its educational value. The enhanced architecture now includes support for stacks, heaps, arrays, and improved error handling, making it more suitable for practical applications while remaining backward compatible with existing programs.

The VM's dual implementation in Go and JavaScript demonstrates how the same virtual machine design can be realized in different programming languages, each with their own idioms and approaches. The recent enhancements have significantly expanded its capabilities while preserving the simplicity that makes it an excellent learning tool.

Sapbot VM now serves as a versatile platform for:

The enhanced Sapbot VM maintains its educational value while offering more production-ready features. The improved memory model, better error handling, and additional data structures make it more suitable for practical applications without sacrificing the simplicity that makes it an excellent teaching tool.

For those interested in further extending Sapbot VM, potential improvements could include:

With its enhanced features, Sapbot VM now provides a more solid foundation for both educational purposes and practical applications. It serves as an excellent platform for those interested in computer architecture, virtual machines, and interpreter design, while also being more capable for real-world programming tasks.