diff --git a/src/Push3Interpreter.sol b/src/Push3Interpreter.sol index fa8bd78..3871fab 100644 --- a/src/Push3Interpreter.sol +++ b/src/Push3Interpreter.sol @@ -23,7 +23,9 @@ contract Push3Interpreter { NOOP, // 0 INTEGER_PLUS, // 1 INTEGER_MINUS, // 2 - INTEGER_MULT // 3 + INTEGER_MULT, // 3 + INTEGER_DUP, // 4 + INTEGER_POP // 5 } // ----------------------------------------------------- @@ -202,6 +204,14 @@ contract Push3Interpreter { temp[count] = makeInstruction(OpCode.INTEGER_MULT); count++; } + else if (tokenType == 0x06) { + temp[count] = makeInstruction(OpCode.INTEGER_DUP); + count++; + } + else if (tokenType == 0x07) { + temp[count] = makeInstruction(OpCode.INTEGER_POP); + count++; + } else { // unknown => NOOP temp[count] = makeInstruction(OpCode.NOOP); @@ -295,6 +305,18 @@ contract Push3Interpreter { intTop++; } } + else if (op == OpCode.INTEGER_DUP) { + if (intTop >= 1) { + int256 a = intStack[intTop - 1]; + intStack[intTop] = a; + intTop++; + } + } + else if (op == OpCode.INTEGER_POP) { + if (intTop >= 1) { + intTop -= 1; + } + } } else if (tag == CodeTag.INT_LITERAL) { int32 val = extractInt32(topDesc); diff --git a/test/Push3Interpreter.t.sol b/test/Push3Interpreter.t.sol index 4c1b106..8ef693f 100644 --- a/test/Push3Interpreter.t.sol +++ b/test/Push3Interpreter.t.sol @@ -174,6 +174,61 @@ contract Push3InterpreterTest is Test { assertEq(finalIntStack[0], 30, "Should be 10 * 3 = 30"); } + function test_Dup() public view { + + bytes memory code = hex"030006020000000A06"; + + uint256 sublistDesc = interpreter.makeDescriptor( + Push3Interpreter.CodeTag.SUBLIST, + 0, + 9, + 0 + ); + + uint256[] memory initCodeStack = new uint256[](0); + uint256[] memory initExecStack = new uint256[](1); + initExecStack[0] = sublistDesc; + + int256[] memory initIntStack = new int256[](0); + + // Run + ( + , + , + int256[] memory finalIntStack + ) = interpreter.runInterpreter(code, initCodeStack, initExecStack, initIntStack); + + assertEq(finalIntStack.length, 2, "finalIntStack should have length 1"); + assertEq(finalIntStack[0], finalIntStack[1], "The top 2 values on the stack should be equal."); + } + + function test_Pop() public view { + + bytes memory code = hex"030006020000000A07"; + + uint256 sublistDesc = interpreter.makeDescriptor( + Push3Interpreter.CodeTag.SUBLIST, + 0, + 9, + 0 + ); + + uint256[] memory initCodeStack = new uint256[](0); + uint256[] memory initExecStack = new uint256[](1); + initExecStack[0] = sublistDesc; + + int256[] memory initIntStack = new int256[](0); + + // Run + ( + , + , + int256[] memory finalIntStack + ) = interpreter.runInterpreter(code, initCodeStack, initExecStack, initIntStack); + + assertEq(finalIntStack.length, 0, "finalIntStack should be empty"); + } + /** * @notice Test with an unknown token (0xF0). * We expect the parser to treat it as "unknown => NOOP"