Simple Stack-Based Virtual Machine in JavaScript
This challenge asks you to implement a basic virtual machine (VM) in JavaScript. Virtual machines allow you to execute code written in a custom instruction set, providing a layer of abstraction and potentially enabling portability or security features. This exercise will focus on a simple stack-based VM, which uses a stack to store and manipulate data during execution.
Problem Description
You are to create a JavaScript class called VirtualMachine that can execute a program represented as an array of instructions. Each instruction is a number representing a specific operation. The VM should maintain an internal stack to store data and execute the instructions sequentially.
Key Requirements:
- Instruction Set: The VM will support the following instructions:
1: PUSH <value> - Pushes the givenvalueonto the stack.<value>is an integer immediately following thePUSHinstruction.2: POP - Removes the top element from the stack.3: ADD - Pops the top two elements from the stack, adds them, and pushes the result back onto the stack.4: SUB - Pops the top two elements from the stack, subtracts the second from the first, and pushes the result back onto the stack.5: MUL - Pops the top two elements from the stack, multiplies them, and pushes the result back onto the stack.6: DIV - Pops the top two elements from the stack, divides the first by the second, and pushes the result back onto the stack. Handle division by zero by pushing 0 onto the stack.0: HALT - Stops the execution of the VM.
- Stack: The VM should use an array as its internal stack.
- Execution: The
VirtualMachineclass should have a method calledrun(program)that takes an array of instructions (program) as input and executes them. - Error Handling: If an invalid instruction is encountered, or if there are not enough elements on the stack for an operation like
POP,ADD,SUB,MUL, orDIV, therunmethod should throw an error with a descriptive message. - Output: The
runmethod should return the final state of the stack after execution.
Expected Behavior:
The VM should execute the instructions in the provided program, manipulating the stack according to the instruction set. The run method should return the stack's contents after the HALT instruction is executed or if the program terminates due to an error.
Edge Cases to Consider:
- Empty program: Should return an empty stack.
- Program ending without a HALT instruction: Should throw an error.
- Invalid instructions: Should throw an error.
- Insufficient stack elements for operations: Should throw an error.
- Division by zero: Should push 0 onto the stack.
- Negative numbers: The VM should correctly handle negative numbers in PUSH and arithmetic operations.
Examples
Example 1:
Input: [1, 5, 1, 2, 3, 0]
Output: [ 6 ]
Explanation: PUSH 5, PUSH 1, ADD (5 + 1 = 6), POP, MUL (6 * 1 = 6), HALT. The stack contains only 6.
Example 2:
Input: [1, 10, 1, 2, 4, 0]
Output: [ 20 ]
Explanation: PUSH 10, PUSH 1, MUL (10 * 1 = 10), POP, PUSH 2, MUL (10 * 2 = 20), HALT. The stack contains only 20.
Example 3:
Input: [1, 8, 1, 2, 6, 0]
Output: [ 1 ]
Explanation: PUSH 8, PUSH 1, DIV (8 / 1 = 8), POP, PUSH 2, MUL (8 * 2 = 16), HALT. The stack contains only 16.
Example 4: (Edge Case - Division by Zero)
Input: [1, 8, 1, 0, 6, 0]
Output: [ 0 ]
Explanation: PUSH 8, PUSH 1, DIV (8 / 1 = 8), POP, PUSH 0, DIV (8 / 0 = Error handled, push 0), HALT. The stack contains only 0.
Constraints
- The
programarray will contain only integers. - The values pushed onto the stack via the
PUSHinstruction will be integers within the range of -1000 to 1000. - The
runmethod should complete execution within a reasonable time (e.g., less than 1 second for programs with up to 1000 instructions). - The stack size should be dynamically allocated and capable of holding a reasonable number of integers (e.g., at least 100).
Notes
- Consider using a class to encapsulate the VM's state (the stack) and behavior (the
runmethod). - Think about how to handle errors gracefully and provide informative error messages.
- The instruction set is intentionally simple to focus on the core concepts of a virtual machine.
- You can add more instructions to the instruction set if you want to extend the functionality of the VM, but it's not required for this challenge.
- Focus on clarity and readability of your code. Good variable names and comments are encouraged.