|
@@ -4,6 +4,7 @@ import { EmptyCodeBoxError, FailedToParseCodeBoxError, WrongStackSizeError } fro
|
|
|
import { CodeBoxOptions, OrdinalDirection } from "./types.js";
|
|
|
import { charToDecimal, deepClone } from "./common.js";
|
|
|
import { Node } from "typescript";
|
|
|
+import { InstructionDictionary } from "./Instructions.js";
|
|
|
|
|
|
export class CodeBox {
|
|
|
/**
|
|
@@ -188,195 +189,195 @@ export class CodeBox {
|
|
|
}
|
|
|
|
|
|
switch (instruction) {
|
|
|
- case this.NOP:
|
|
|
+ case InstructionDictionary.NOP:
|
|
|
break;
|
|
|
// Numbers
|
|
|
- case "1":
|
|
|
- case "2":
|
|
|
- case "3":
|
|
|
- case "4":
|
|
|
- case "5":
|
|
|
- case "6":
|
|
|
- case "7":
|
|
|
- case "8":
|
|
|
- case "9":
|
|
|
- case "0":
|
|
|
- case "a":
|
|
|
- case "b":
|
|
|
- case "c":
|
|
|
- case "d":
|
|
|
- case "e":
|
|
|
- case "f":
|
|
|
+ case InstructionDictionary.HEX_0:
|
|
|
+ case InstructionDictionary.HEX_1:
|
|
|
+ case InstructionDictionary.HEX_2:
|
|
|
+ case InstructionDictionary.HEX_3:
|
|
|
+ case InstructionDictionary.HEX_4:
|
|
|
+ case InstructionDictionary.HEX_5:
|
|
|
+ case InstructionDictionary.HEX_6:
|
|
|
+ case InstructionDictionary.HEX_7:
|
|
|
+ case InstructionDictionary.HEX_8:
|
|
|
+ case InstructionDictionary.HEX_9:
|
|
|
+ case InstructionDictionary.HEX_10:
|
|
|
+ case InstructionDictionary.HEX_11:
|
|
|
+ case InstructionDictionary.HEX_12:
|
|
|
+ case InstructionDictionary.HEX_13:
|
|
|
+ case InstructionDictionary.HEX_14:
|
|
|
+ case InstructionDictionary.HEX_15:
|
|
|
this.stacks[this.currentStackIndex]!.push(parseInt(instruction, 16));
|
|
|
break;
|
|
|
// Operators
|
|
|
- case "+": {
|
|
|
+ case InstructionDictionary.OPERATOR_ADD: {
|
|
|
const x = this.stacks[this.currentStackIndex]!.pop();
|
|
|
const y = this.stacks[this.currentStackIndex]!.pop();
|
|
|
this.stacks[this.currentStackIndex]!.push(y + x);
|
|
|
break;
|
|
|
}
|
|
|
- case "-": {
|
|
|
+ case InstructionDictionary.OPERATOR_SUBTRACT: {
|
|
|
const x = this.stacks[this.currentStackIndex]!.pop();
|
|
|
const y = this.stacks[this.currentStackIndex]!.pop();
|
|
|
this.stacks[this.currentStackIndex]!.push(y - x);
|
|
|
break;
|
|
|
}
|
|
|
- case "*": {
|
|
|
+ case InstructionDictionary.OPERATOR_MULTIPLY: {
|
|
|
const x = this.stacks[this.currentStackIndex]!.pop();
|
|
|
const y = this.stacks[this.currentStackIndex]!.pop();
|
|
|
this.stacks[this.currentStackIndex]!.push(y * x);
|
|
|
break;
|
|
|
}
|
|
|
- case ",": {
|
|
|
+ case InstructionDictionary.OPERATOR_DIVIDE: {
|
|
|
const x = this.stacks[this.currentStackIndex]!.pop();
|
|
|
const y = this.stacks[this.currentStackIndex]!.pop();
|
|
|
this.stacks[this.currentStackIndex]!.push(y / x);
|
|
|
break;
|
|
|
}
|
|
|
- case "%": {
|
|
|
+ case InstructionDictionary.OPERATOR_MODULO: {
|
|
|
const x = this.stacks[this.currentStackIndex]!.pop();
|
|
|
const y = this.stacks[this.currentStackIndex]!.pop();
|
|
|
this.stacks[this.currentStackIndex]!.push(y % x);
|
|
|
break;
|
|
|
}
|
|
|
- case "(": {
|
|
|
+ case InstructionDictionary.OPERATOR_LESS_THAN: {
|
|
|
const x = this.stacks[this.currentStackIndex]!.pop();
|
|
|
const y = this.stacks[this.currentStackIndex]!.pop();
|
|
|
this.stacks[this.currentStackIndex]!.push(y < x ? 1 : 0);
|
|
|
break;
|
|
|
}
|
|
|
- case ")": {
|
|
|
+ case InstructionDictionary.OPERATOR_GREATER_THAN: {
|
|
|
const x = this.stacks[this.currentStackIndex]!.pop();
|
|
|
const y = this.stacks[this.currentStackIndex]!.pop();
|
|
|
this.stacks[this.currentStackIndex]!.push(y > x ? 1 : 0);
|
|
|
break;
|
|
|
}
|
|
|
- case "=": {
|
|
|
+ case InstructionDictionary.OPERATOR_EQUAL_TO: {
|
|
|
const x = this.stacks[this.currentStackIndex]!.pop();
|
|
|
const y = this.stacks[this.currentStackIndex]!.pop();
|
|
|
this.stacks[this.currentStackIndex]!.push(y === x ? 1 : 0);
|
|
|
break;
|
|
|
}
|
|
|
// String mode
|
|
|
- case "\"":
|
|
|
- case "'": {
|
|
|
+ case InstructionDictionary.STRING_MODE_DOUBLE:
|
|
|
+ case InstructionDictionary.STRING_MODE_SINGLE: {
|
|
|
this.pointer.stringMode = !!this.pointer.stringMode ? 0 : charToDecimal(instruction);
|
|
|
break;
|
|
|
}
|
|
|
// Dive, Rise, and Fisherman
|
|
|
- case "u": {
|
|
|
+ case InstructionDictionary.DIVE: {
|
|
|
this.pointer.hasDove = true;
|
|
|
break;
|
|
|
}
|
|
|
- case "O": {
|
|
|
+ case InstructionDictionary.RISE: {
|
|
|
this.pointer.hasDove = false;
|
|
|
break;
|
|
|
}
|
|
|
- case "`": {
|
|
|
+ case InstructionDictionary.FISHERMAN: {
|
|
|
this.fisherman();
|
|
|
break;
|
|
|
}
|
|
|
// Movement
|
|
|
- case "^": {
|
|
|
+ case InstructionDictionary.MOVE_UP: {
|
|
|
this.moveUp();
|
|
|
break;
|
|
|
}
|
|
|
- case ">": {
|
|
|
+ case InstructionDictionary.MOVE_RIGHT: {
|
|
|
this.moveRight();
|
|
|
break;
|
|
|
}
|
|
|
- case "v": {
|
|
|
+ case InstructionDictionary.MOVE_DOWN: {
|
|
|
this.moveDown();
|
|
|
break;
|
|
|
}
|
|
|
- case "<": {
|
|
|
+ case InstructionDictionary.MOVE_LEFT: {
|
|
|
this.moveLeft();
|
|
|
break;
|
|
|
}
|
|
|
// Mirrors
|
|
|
- case "/": {
|
|
|
+ case InstructionDictionary.MIRROR_FORWARD: {
|
|
|
this.reflectForward();
|
|
|
break;
|
|
|
}
|
|
|
- case "\\": {
|
|
|
+ case InstructionDictionary.MIRROR_BACKWARD: {
|
|
|
this.reflectBack();
|
|
|
break;
|
|
|
}
|
|
|
- case "|": {
|
|
|
+ case InstructionDictionary.MIRROR_HORIZONTAL: {
|
|
|
this.horizontalMirror();
|
|
|
break;
|
|
|
}
|
|
|
- case "_": {
|
|
|
+ case InstructionDictionary.MIRROR_VERTICAL: {
|
|
|
this.verticalMirror();
|
|
|
break;
|
|
|
}
|
|
|
- case "#": {
|
|
|
+ case InstructionDictionary.MIRROR_OMNI: {
|
|
|
this.omniMirror();
|
|
|
break;
|
|
|
}
|
|
|
// Trampolines
|
|
|
- case "!": {
|
|
|
+ case InstructionDictionary.TRAMPOLINE_CLASSIC: {
|
|
|
this.pointer.move();
|
|
|
break;
|
|
|
}
|
|
|
- case "?": {
|
|
|
+ case InstructionDictionary.TRAMPLOINE_CONDITIONAL: {
|
|
|
if (this.stacks[this.currentStackIndex]!.pop() === 0) { this.pointer.move(); }
|
|
|
break;
|
|
|
}
|
|
|
// Stack manipulation
|
|
|
- case "&": {
|
|
|
+ case InstructionDictionary.STACK_REGISTER: {
|
|
|
this.stacks[this.currentStackIndex]!.readWriteRegister();
|
|
|
break;
|
|
|
}
|
|
|
- case ":": {
|
|
|
+ case InstructionDictionary.STACK_DUPLICATE: {
|
|
|
this.stacks[this.currentStackIndex]!.duplicate();
|
|
|
break;
|
|
|
}
|
|
|
- case "~": {
|
|
|
+ case InstructionDictionary.STACK_REMOVE: {
|
|
|
this.stacks[this.currentStackIndex]!.remove();
|
|
|
break;
|
|
|
}
|
|
|
- case "$": {
|
|
|
+ case InstructionDictionary.STACK_SWAP_TWO: {
|
|
|
this.stacks[this.currentStackIndex]!.swapTwo();
|
|
|
break;
|
|
|
}
|
|
|
- case "@": {
|
|
|
+ case InstructionDictionary.STACK_SWAP_THREE: {
|
|
|
this.stacks[this.currentStackIndex]!.swapThree();
|
|
|
break;
|
|
|
}
|
|
|
- case "{": {
|
|
|
+ case InstructionDictionary.STACK_SHIFT_LEFT: {
|
|
|
this.stacks[this.currentStackIndex]!.shiftLeft();
|
|
|
break;
|
|
|
}
|
|
|
- case "}": {
|
|
|
+ case InstructionDictionary.STACK_SHIFT_RIGHT: {
|
|
|
this.stacks[this.currentStackIndex]!.shiftRight();
|
|
|
break;
|
|
|
}
|
|
|
- case "r": {
|
|
|
+ case InstructionDictionary.STACK_REVERSE: {
|
|
|
this.stacks[this.currentStackIndex]!.reverse();
|
|
|
break;
|
|
|
}
|
|
|
- case "l": {
|
|
|
+ case InstructionDictionary.STACK_LENGTH: {
|
|
|
this.stacks[this.currentStackIndex]!.pushLength();
|
|
|
break;
|
|
|
}
|
|
|
- case "[": {
|
|
|
+ case InstructionDictionary.STACK_SPLIT: {
|
|
|
this.spliceStack(this.stacks[this.currentStackIndex]!.pop());
|
|
|
break;
|
|
|
}
|
|
|
- case "]": {
|
|
|
+ case InstructionDictionary.STACK_COLLAPSE: {
|
|
|
this.collapseStack();
|
|
|
break;
|
|
|
}
|
|
|
- case "I": {
|
|
|
+ case InstructionDictionary.STACK_INDEX_INCREMENT: {
|
|
|
this.currentStackIndex++;
|
|
|
if (this.currentStackIndex > this.stacks.length) {
|
|
|
throw new RangeError("stack index out of bounds");
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
- case "D": {
|
|
|
+ case InstructionDictionary.STACK_INDEX_DECREMENT: {
|
|
|
this.currentStackIndex--;
|
|
|
if (this.currentStackIndex < 0) {
|
|
|
throw new RangeError("stack index out of bounds");
|
|
@@ -384,50 +385,50 @@ export class CodeBox {
|
|
|
break;
|
|
|
}
|
|
|
// Output
|
|
|
- case "n": {
|
|
|
+ case InstructionDictionary.OUTPUT_DECIMAL: {
|
|
|
output = this.stacks[this.currentStackIndex]!.pop();
|
|
|
break;
|
|
|
}
|
|
|
- case "o": {
|
|
|
+ case InstructionDictionary.OUTPUT_ASCII: {
|
|
|
output = String.fromCharCode(this.stacks[this.currentStackIndex]!.pop());
|
|
|
break;
|
|
|
}
|
|
|
// Time
|
|
|
- case "S": {
|
|
|
+ case InstructionDictionary.TIME_SLEEP: {
|
|
|
setTimeout(this.run.bind(this), this.stacks[this.currentStackIndex]!.pop() * 100);
|
|
|
this.pointer.move();
|
|
|
output = true;
|
|
|
break;
|
|
|
}
|
|
|
- case "s": {
|
|
|
+ case InstructionDictionary.TIME_SECONDS: {
|
|
|
this.stacks[this.currentStackIndex]!.push(this.dateTime.getUTCSeconds());
|
|
|
break;
|
|
|
}
|
|
|
- case "m": {
|
|
|
+ case InstructionDictionary.TIME_MINUTES: {
|
|
|
this.stacks[this.currentStackIndex]!.push(this.dateTime.getUTCMinutes());
|
|
|
break;
|
|
|
}
|
|
|
- case "h": {
|
|
|
+ case InstructionDictionary.TIME_HOURS: {
|
|
|
this.stacks[this.currentStackIndex]!.push(this.dateTime.getUTCHours());
|
|
|
break;
|
|
|
}
|
|
|
// Code box manipulation
|
|
|
- case "g": {
|
|
|
+ case InstructionDictionary.CODE_BOX_FETCH: {
|
|
|
this.pushFromCodeBox();
|
|
|
break;
|
|
|
}
|
|
|
- case "p": {
|
|
|
+ case InstructionDictionary.CODE_BOX_PLACE: {
|
|
|
this.placeIntoCodeBox();
|
|
|
break;
|
|
|
}
|
|
|
// Functions
|
|
|
- case ".": {
|
|
|
+ case InstructionDictionary.JUMP: {
|
|
|
const [y, x] = this.stacks[this.currentStackIndex]!.popMany(2);
|
|
|
this.pointer.X = x as number;
|
|
|
this.pointer.Y = y as number;
|
|
|
break;
|
|
|
}
|
|
|
- case "C": {
|
|
|
+ case InstructionDictionary.JUMP_STORED: {
|
|
|
// Store the pointer's coordinates on the stack beneath our current one
|
|
|
const currCoords = new Stack([this.pointer.X, this.pointer.Y]);
|
|
|
this.stacks.splice(this.currentStackIndex, 0, currCoords);
|
|
@@ -437,7 +438,7 @@ export class CodeBox {
|
|
|
this.pointer.Y = y as number;
|
|
|
break;
|
|
|
}
|
|
|
- case "R": {
|
|
|
+ case InstructionDictionary.RETURN: {
|
|
|
// Remove the stored coordinates from the previous C call
|
|
|
const storedCoords = this.stacks.splice(this.currentStackIndex - 1, 1).pop() as Stack;
|
|
|
this.currentStackIndex--;
|
|
@@ -445,7 +446,7 @@ export class CodeBox {
|
|
|
this.pointer.X = storedCoords.pop();
|
|
|
break;
|
|
|
}
|
|
|
- case ";":
|
|
|
+ case InstructionDictionary.EXIT:
|
|
|
output = true;
|
|
|
break;
|
|
|
default:
|