diff --git a/src/compiler.cairo b/src/compiler.cairo index a9f388aa..c2436c56 100644 --- a/src/compiler.cairo +++ b/src/compiler.cairo @@ -20,6 +20,7 @@ pub impl CompilerTraitImpl of CompilerTrait { // Add the opcodes to the dict opcodes.insert('OP_0', Opcode::OP_0); opcodes.insert('OP_1', Opcode::OP_1); + opcodes.insert('OP_DEPTH', Opcode::OP_DEPTH); opcodes.insert('OP_ADD', Opcode::OP_ADD); Compiler { opcodes } } diff --git a/src/opcodes/opcodes.cairo b/src/opcodes/opcodes.cairo index 6a516e7b..1c5c12b7 100644 --- a/src/opcodes/opcodes.cairo +++ b/src/opcodes/opcodes.cairo @@ -1,6 +1,7 @@ pub mod Opcode { pub const OP_0: u8 = 0; pub const OP_1: u8 = 81; + pub const OP_DEPTH: u8 = 116; pub const OP_ADD: u8 = 147; use shinigami::engine::Engine; @@ -123,7 +124,7 @@ pub mod Opcode { 113 => not_implemented(ref engine), 114 => not_implemented(ref engine), 115 => not_implemented(ref engine), - 116 => not_implemented(ref engine), + 116 => opcode_depth(ref engine), 117 => not_implemented(ref engine), 118 => not_implemented(ref engine), 119 => not_implemented(ref engine), @@ -174,6 +175,11 @@ pub mod Opcode { engine.dstack.push_int(a + b); } + fn opcode_depth(ref engine: Engine) { + let depth: i64 = engine.dstack.len().into(); + engine.dstack.push_int(depth); + } + fn not_implemented(ref engine: Engine) { panic!("Opcode not implemented"); } diff --git a/src/opcodes/tests/test_opcodes.cairo b/src/opcodes/tests/test_opcodes.cairo index 1124ecba..3cc24fee 100644 --- a/src/opcodes/tests/test_opcodes.cairo +++ b/src/opcodes/tests/test_opcodes.cairo @@ -51,3 +51,59 @@ fn test_op_add() { let expected_stack = array!["\0\0\0\0\0\0\0\x02"]; assert_eq!(dstack, expected_stack.span(), "Stack is not equal to expected"); } + +#[test] +fn test_op_depth_empty_stack() { + let program = "OP_DEPTH"; + let mut compiler = CompilerTraitImpl::new(); + let bytecode = compiler.compile(program); + let mut engine = EngineTraitImpl::new(bytecode); + + let res = engine.step(); + assert!(res, "Execution of step failed"); + + let dstack = engine.get_dstack(); + assert_eq!(dstack.len(), 1, "Stack length is not 1"); + + let expected_stack = array!["\0\0\0\0\0\0\0\0"]; + assert_eq!(dstack, expected_stack.span(), "Stack is not equal to expected for empty stack"); +} + +#[test] +fn test_op_depth_one_item() { + let program = "OP_1 OP_DEPTH"; + let mut compiler = CompilerTraitImpl::new(); + let bytecode = compiler.compile(program); + let mut engine = EngineTraitImpl::new(bytecode); + + let _ = engine.step(); + let res = engine.step(); + assert!(res, "Execution of step failed"); + + let dstack = engine.get_dstack(); + assert_eq!(dstack.len(), 2, "Stack length is not 2"); + + let expected_stack = array!["\0\0\0\0\0\0\0\x01", "\0\0\0\0\0\0\0\x01"]; + assert_eq!(dstack, expected_stack.span(), "Stack is not equal to expected for one item"); +} + +#[test] +fn test_op_depth_multiple_items() { + let program = "OP_1 OP_1 OP_ADD OP_1 OP_DEPTH"; + let mut compiler = CompilerTraitImpl::new(); + let bytecode = compiler.compile(program); + let mut engine = EngineTraitImpl::new(bytecode); + + let _ = engine.step(); + let _ = engine.step(); + let _ = engine.step(); + let _ = engine.step(); + let res = engine.step(); + assert!(res, "Execution of step failed"); + + let dstack = engine.get_dstack(); + assert_eq!(dstack.len(), 3, "Stack length is not 3"); + + let expected_stack = array!["\0\0\0\0\0\0\0\x02", "\0\0\0\0\0\0\0\x01", "\0\0\0\0\0\0\0\x02"]; + assert_eq!(dstack, expected_stack.span(), "Stack is not equal to expected for multiple items"); +}