import { asCount, replaceWithUnknowns, reverseTop } from "./type-support.js";
export function handleStackInstruction(ins, stack, unk, cloneValue, popU) {
switch (ins.opcode.mnemonic) {
case "CLEAR":
stack.length = 0;
return true;
case "DEPTH":
stack.push({ ty: "integer", lit: stack.length, origins: [] });
return true;
case "DROP":
popU();
return true;
case "DUP":
stack.push(stack.length ? cloneValue(stack[stack.length - 1]) : unk());
return true;
case "SWAP":
if (stack.length >= 2) {
const last = stack.length - 1;
const value = stack[last];
stack[last] = stack[last - 1];
stack[last - 1] = value;
}
return true;
case "OVER":
stack.push(stack.length >= 2 ? cloneValue(stack[stack.length - 2]) : unk());
return true;
case "NIP":
if (stack.length >= 2) stack.splice(stack.length - 2, 1);
return true;
case "ROT": {
const top = stack.pop();
const mid = stack.pop();
const bottom = stack.pop();
if (top !== undefined && mid !== undefined && bottom !== undefined) {
stack.push(mid, top, bottom);
}
return true;
}
case "TUCK": {
const top = stack.pop();
const second = stack.pop();
if (top !== undefined && second !== undefined) {
stack.push(top, second, cloneValue(top));
}
return true;
}
case "PICK": {
const depth = asCount(popU().lit);
if (depth !== null) {
const pos = stack.length - 1 - depth;
if (pos >= 0) {
stack.push(cloneValue(stack[pos]));
return true;
}
}
stack.push(unk());
return true;
}
case "ROLL": {
const depth = asCount(popU().lit);
if (depth !== null && depth < stack.length) {
const [value] = stack.splice(stack.length - 1 - depth, 1);
stack.push(value);
} else {
popU();
replaceWithUnknowns(stack);
stack.push(unk());
}
return true;
}
case "XDROP": {
const depth = asCount(popU().lit);
if (depth !== null && depth < stack.length) {
stack.splice(stack.length - 1 - depth, 1);
return true;
}
popU();
replaceWithUnknowns(stack);
return true;
}
case "REVERSE3":
reverseTop(stack, 3);
return true;
case "REVERSE4":
reverseTop(stack, 4);
return true;
case "REVERSEN": {
const depth = asCount(popU().lit);
if (depth !== null) {
reverseTop(stack, depth);
} else {
replaceWithUnknowns(stack);
}
return true;
}
default:
return false;
}
}