diff --git a/src/compiler.cairo b/src/compiler.cairo index 6444ac72..7552f501 100644 --- a/src/compiler.cairo +++ b/src/compiler.cairo @@ -39,7 +39,9 @@ pub impl CompilerTraitImpl of CompilerTrait { opcodes.insert('OP_DEPTH', Opcode::OP_DEPTH); opcodes.insert('OP_1ADD', Opcode::OP_1ADD); opcodes.insert('OP_ADD', Opcode::OP_ADD); + opcodes.insert('OP_GREATERTHAN', Opcode::OP_GREATERTHAN); opcodes.insert('OP_MAX', Opcode::OP_MAX); + opcodes.insert('OP_WITHIN', Opcode::OP_WITHIN); Compiler { opcodes } } diff --git a/src/opcodes/opcodes.cairo b/src/opcodes/opcodes.cairo index 6354b3e1..ce00de03 100644 --- a/src/opcodes/opcodes.cairo +++ b/src/opcodes/opcodes.cairo @@ -20,7 +20,9 @@ pub mod Opcode { pub const OP_DEPTH: u8 = 116; pub const OP_1ADD: u8 = 139; pub const OP_ADD: u8 = 147; + pub const OP_GREATERTHAN: u8 = 160; pub const OP_MAX: u8 = 164; + pub const OP_WITHIN: u8 = 165; use shinigami::engine::Engine; use shinigami::stack::ScriptStackTrait; @@ -186,11 +188,12 @@ pub mod Opcode { 157 => not_implemented(ref engine), 158 => not_implemented(ref engine), 159 => not_implemented(ref engine), - 160 => not_implemented(ref engine), + 160 => opcode_great_than(ref engine), 161 => not_implemented(ref engine), 162 => not_implemented(ref engine), 163 => not_implemented(ref engine), 164 => opcode_max(ref engine), + 165 => opcode_within(ref engine), _ => not_implemented(ref engine) } } @@ -225,6 +228,16 @@ pub mod Opcode { panic!("Opcode not implemented"); } + fn opcode_great_than(ref engine: Engine) { + let a = engine.dstack.pop_int(); + let b = engine.dstack.pop_int(); + engine.dstack.push_int(if b > a { + 1 + } else { + 0 + }); + } + fn opcode_max(ref engine: Engine) { let a = engine.dstack.pop_int(); let b = engine.dstack.pop_int(); @@ -234,4 +247,15 @@ pub mod Opcode { b }); } + + fn opcode_within(ref engine: Engine) { + let max = engine.dstack.pop_int(); + let min = engine.dstack.pop_int(); + let value = engine.dstack.pop_int(); + engine.dstack.push_int(if value >= min && value < max { + 1 + } else { + 0 + }); + } } diff --git a/src/opcodes/tests/test_opcodes.cairo b/src/opcodes/tests/test_opcodes.cairo index 29f593f6..40ac2b3a 100644 --- a/src/opcodes/tests/test_opcodes.cairo +++ b/src/opcodes/tests/test_opcodes.cairo @@ -52,6 +52,24 @@ fn test_op_add() { assert_eq!(dstack, expected_stack.span(), "Stack is not equal to expected"); } +#[test] +fn test_op_greater_than() { + let program = "OP_1 OP_0 OP_GREATERTHAN"; + let mut compiler = CompilerTraitImpl::new(); + let bytecode = compiler.compile(program); + let mut engine = EngineTraitImpl::new(bytecode); + let _ = engine.step(); + let _ = engine.step(); + let res = engine.step(); + assert!(res, "Execution of run 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\x01"]; + assert_eq!(dstack, expected_stack.span(), "Stack is not equal to expected"); +} + #[test] fn test_op_max() { let program = "OP_1 OP_0 OP_MAX"; @@ -70,6 +88,25 @@ fn test_op_max() { assert_eq!(dstack, expected_stack.span(), "Stack is not equal to expected"); } +#[test] +fn test_op_within() { + let program = "OP_1 OP_0 OP_1 OP_WITHIN"; + 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 res = engine.step(); + assert!(res, "Execution of run 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"); +} + fn test_op_depth_empty_stack() { let program = "OP_DEPTH"; let mut compiler = CompilerTraitImpl::new();