From 8262f672ff57e147735ba14e2f0ccac6f554c109 Mon Sep 17 00:00:00 2001
From: Patrice Tisserand
Date: Thu, 25 Jul 2024 23:49:47 +0200
Subject: [PATCH] feat: #17 add `OP_MIN` opcode
---
src/compiler.cairo | 1 +
src/opcodes/opcodes.cairo | 28 ++++++++++++++
src/opcodes/tests/test_opcodes.cairo | 57 ++++++++++++++++++++++++++++
3 files changed, 86 insertions(+)
diff --git a/src/compiler.cairo b/src/compiler.cairo
index 15889c81..6fee912b 100644
--- a/src/compiler.cairo
+++ b/src/compiler.cairo
@@ -37,6 +37,7 @@ pub impl CompilerTraitImpl of CompilerTrait {
opcodes.insert('OP_16', Opcode::OP_16);
opcodes.insert('OP_DEPTH', Opcode::OP_DEPTH);
opcodes.insert('OP_ADD', Opcode::OP_ADD);
+ opcodes.insert('OP_MIN', Opcode::OP_MIN);
Compiler { opcodes }
}
diff --git a/src/opcodes/opcodes.cairo b/src/opcodes/opcodes.cairo
index 28111098..4e8bfec8 100644
--- a/src/opcodes/opcodes.cairo
+++ b/src/opcodes/opcodes.cairo
@@ -18,6 +18,7 @@ pub mod Opcode {
pub const OP_16: u8 = 96;
pub const OP_DEPTH: u8 = 116;
pub const OP_ADD: u8 = 147;
+ pub const OP_MIN: u8 = 163;
use shinigami::engine::Engine;
use shinigami::stack::ScriptStackTrait;
@@ -171,6 +172,22 @@ pub mod Opcode {
145 => not_implemented(ref engine),
146 => not_implemented(ref engine),
147 => opcode_add(ref engine),
+ 148 => not_implemented(ref engine),
+ 149 => not_implemented(ref engine),
+ 150 => not_implemented(ref engine),
+ 151 => not_implemented(ref engine),
+ 152 => not_implemented(ref engine),
+ 153 => not_implemented(ref engine),
+ 154 => not_implemented(ref engine),
+ 155 => not_implemented(ref engine),
+ 156 => not_implemented(ref engine),
+ 157 => not_implemented(ref engine),
+ 158 => not_implemented(ref engine),
+ 159 => not_implemented(ref engine),
+ 160 => not_implemented(ref engine),
+ 161 => not_implemented(ref engine),
+ 162 => not_implemented(ref engine),
+ 163 => opcode_min(ref engine),
_ => not_implemented(ref engine)
}
}
@@ -195,6 +212,17 @@ pub mod Opcode {
engine.dstack.push_int(depth);
}
+ fn opcode_min(ref engine: Engine) {
+ let a = engine.dstack.pop_int();
+ let b = engine.dstack.pop_int();
+
+ engine.dstack.push_int(if a < b {
+ a
+ } else {
+ b
+ });
+ }
+
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 741fca19..b68cf2dd 100644
--- a/src/opcodes/tests/test_opcodes.cairo
+++ b/src/opcodes/tests/test_opcodes.cairo
@@ -199,3 +199,60 @@ fn test_op_depth_multiple_items() {
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");
}
+
+#[test]
+fn test_op_min_min_first() {
+ let program = "OP_1 OP_2 OP_MIN";
+ 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_min_min_second() {
+ let program = "OP_2 OP_1 OP_MIN";
+ 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_min_same_value() {
+ let program = "OP_1 OP_1 OP_MIN";
+ 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");
+}