neo-decompiler 0.10.1

Neo N3 NEF decompiler: parse, disassemble, lift bytecode to high-level pseudocode and C# skeletons, with a CLI, JSON reports, and optional WebAssembly bindings.
Documentation
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;
}