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
use std::collections::{BTreeMap, BTreeSet};

use crate::instruction::{Instruction, OpCode};

use super::super::HighLevelEmitter;

impl HighLevelEmitter {
    pub(crate) fn with_program(instructions: &[Instruction]) -> Self {
        let mut emitter = Self {
            program: instructions.to_vec(),
            // Trace comments default to ON to preserve historical rendering
            // (golden tests assert their presence). Disable with
            // `set_emit_trace_comments(false)` for clean human-readable output.
            emit_trace_comments: true,
            ..Self::default()
        };
        for (index, instruction) in instructions.iter().enumerate() {
            emitter.index_by_offset.insert(instruction.offset, index);
        }
        emitter.analyze_do_while_loops();
        emitter.pre_register_backward_jump_labels();
        emitter
    }

    pub(crate) fn set_argument_labels(&mut self, labels: &[String]) {
        for (index, label) in labels.iter().enumerate() {
            self.argument_labels.insert(index, label.clone());
        }
        let starts_with_initslot = self
            .program
            .first()
            .is_some_and(|instruction| instruction.opcode == OpCode::Initslot);
        if !starts_with_initslot {
            self.stack.extend(labels.iter().rev().cloned());
        }
    }

    pub(crate) fn set_callt_labels(&mut self, labels: Vec<String>) {
        self.callt_labels = labels;
    }

    pub(crate) fn set_callt_param_counts(&mut self, counts: Vec<usize>) {
        self.callt_param_counts = counts;
    }

    pub(crate) fn set_callt_returns_value(&mut self, returns: Vec<bool>) {
        self.callt_returns_value = returns;
    }

    pub(crate) fn set_method_labels_by_offset(&mut self, labels: &BTreeMap<usize, String>) {
        self.method_labels_by_offset = labels.clone();
    }

    pub(crate) fn set_method_arg_counts_by_offset(&mut self, counts: &BTreeMap<usize, usize>) {
        self.method_arg_counts_by_offset = counts.clone();
    }

    pub(crate) fn set_call_targets_by_offset(&mut self, targets: &BTreeMap<usize, usize>) {
        self.call_targets_by_offset = targets.clone();
    }

    pub(crate) fn set_calla_targets_by_offset(&mut self, targets: &BTreeMap<usize, usize>) {
        self.calla_targets_by_offset = targets.clone();
    }

    pub(crate) fn set_noreturn_method_offsets(&mut self, offsets: &BTreeSet<usize>) {
        self.noreturn_method_offsets = offsets.clone();
    }

    pub(crate) fn set_inline_single_use_temps(&mut self, enabled: bool) {
        self.inline_single_use_temps = enabled;
    }

    pub(crate) fn set_emit_trace_comments(&mut self, enabled: bool) {
        self.emit_trace_comments = enabled;
    }

    pub(crate) fn set_returns_void(&mut self, value: bool) {
        self.returns_void = value;
    }
}