neo-decompiler 0.11.0

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 super::super::*;

#[test]
fn eliminate_dead_temps_strips_unused_arithmetic_expression() {
    // After dispatch + inlining, an unused temp computed from a pure
    // expression should be removed. Previously only literal/identifier
    // RHS were considered "pure" and arithmetic temps survived as
    // `var tN = loc1 * 3;` lines that did nothing.
    let mut statements = vec!["let t1 = loc1 * 3;".to_string(), "return;".to_string()];

    HighLevelEmitter::eliminate_dead_temps(&mut statements);

    assert!(
        statements[0].is_empty(),
        "dead temp with arithmetic rhs should be cleared: {statements:?}"
    );
    assert_eq!(statements[1], "return;");
}

#[test]
fn eliminate_dead_temps_keeps_calls_for_their_side_effects() {
    // Function or syscall calls may have side effects (storage writes,
    // notifications, throws) so even an unused temp must stay.
    let mut statements = vec![
        "let t0 = syscall(\"System.Storage.Get\", t1);".to_string(),
        "return;".to_string(),
    ];

    HighLevelEmitter::eliminate_dead_temps(&mut statements);

    assert_eq!(
        statements[0], "let t0 = syscall(\"System.Storage.Get\", t1);",
        "temps holding call results must not be eliminated: {statements:?}"
    );
}

#[test]
fn eliminate_dead_temps_keeps_used_temps() {
    let mut statements = vec!["let t0 = loc1 + 1;".to_string(), "return t0;".to_string()];

    HighLevelEmitter::eliminate_dead_temps(&mut statements);

    assert_eq!(statements[0], "let t0 = loc1 + 1;");
    assert_eq!(statements[1], "return t0;");
}

#[test]
fn eliminate_dead_temps_keeps_potentially_throwing_division_or_indexing() {
    // DIV and MOD throw on zero; PICKITEM throws on out-of-bounds. An
    // unused temp built from these operators must not be silently dropped
    // because that would hide a runtime exception the bytecode would have
    // raised.
    let mut statements = vec![
        "let t0 = a / b;".to_string(),
        "let t1 = c % d;".to_string(),
        "let t2 = arr[i];".to_string(),
        "return;".to_string(),
    ];

    HighLevelEmitter::eliminate_dead_temps(&mut statements);

    assert_eq!(statements[0], "let t0 = a / b;");
    assert_eq!(statements[1], "let t1 = c % d;");
    assert_eq!(statements[2], "let t2 = arr[i];");
}