import { ensureAvailable, popCount, topLiteral } from "./entry-stack-state.js";
export function applyIndexedStackInstruction(mnemonic, state) {
switch (mnemonic) {
case "PICK":
return applyPick(state);
case "ROLL":
return applyRoll(state);
case "XDROP":
return applyXdrop(state);
case "REVERSEN":
return applyReversen(state);
default:
return false;
}
}
function applyPick(state) {
const depth = checkedDepth(state);
if (depth === null) {
return false;
}
popCount(state, 1);
ensureAvailable(state, depth + 1);
state.stack.push(state.stack[state.stack.length - 1 - depth] ?? null);
return true;
}
function applyRoll(state) {
const depth = checkedDepth(state);
if (depth === null) {
return false;
}
popCount(state, 1);
ensureAvailable(state, depth + 1);
const from = state.stack.length - 1 - depth;
const [value] = state.stack.splice(from, 1);
state.stack.push(value ?? null);
return true;
}
function applyXdrop(state) {
const depth = checkedDepth(state);
if (depth === null) {
return false;
}
popCount(state, 1);
ensureAvailable(state, depth + 1);
state.stack.splice(state.stack.length - 1 - depth, 1);
return true;
}
function applyReversen(state) {
const count = checkedDepth(state);
if (count === null) {
return false;
}
popCount(state, 1);
ensureAvailable(state, count);
const boundedCount = Math.min(count, state.stack.length);
const start = state.stack.length - boundedCount;
state.stack.splice(start, boundedCount, ...state.stack.slice(start).reverse());
return true;
}
function checkedDepth(state) {
const depth = topLiteral(state);
return Number.isInteger(depth) && depth >= 0 ? depth : null;
}