From ae17dd370a7bbf6affeefb9fa6954965e8b52239 Mon Sep 17 00:00:00 2001 From: Edgar Date: Mon, 30 Sep 2024 23:19:07 +0200 Subject: [PATCH] Add test reproducing bug #808 (#810) * Fix snapshot clones. Extract if statement from function for better readability. * Fix broken MLIR bug. * add test reproducing bug #808 --------- Co-authored-by: Esteve Soler Arderiu Co-authored-by: Pedro Fontana --- tests/cases/stack.cairo | 84 +++++++++++++++++++++++++++++++++++++++++ tests/tests/cases.rs | 2 + 2 files changed, 86 insertions(+) create mode 100644 tests/cases/stack.cairo diff --git a/tests/cases/stack.cairo b/tests/cases/stack.cairo new file mode 100644 index 000000000..191ddc1fa --- /dev/null +++ b/tests/cases/stack.cairo @@ -0,0 +1,84 @@ +use core::nullable::{NullableTrait}; +use core::num::traits::Bounded; +use core::starknet::EthAddress; +use core::dict::{Felt252Dict, Felt252DictTrait}; + +#[derive(Destruct, Default)] +pub struct Stack { + pub items: Felt252Dict>, + pub len: usize, +} + +pub trait StackTrait { + fn new() -> Stack; + fn push(ref self: Stack, item: u256) -> Result<(), ()>; + fn pop(ref self: Stack) -> Result; + fn peek_at(ref self: Stack, index: usize) -> Result; + fn len(self: @Stack) -> usize; +} + +impl StackImpl of StackTrait { + #[inline(always)] + fn new() -> Stack { + Default::default() + } + + /// Pushes a new bytes32 word onto the stack. + /// + /// When pushing an item to the stack, we will compute + /// an index which corresponds to the index in the dict the item will be stored at. + /// The internal index is computed as follows: + /// + /// index = len(Stack_i) + i * STACK_SEGMENT_SIZE + /// + /// # Errors + /// + /// If the stack is full, returns with a StackOverflow error. + #[inline(always)] + fn push(ref self: Stack, item: u256) -> Result<(), ()> { + let length = self.len(); + + self.items.insert(length.into(), NullableTrait::new(item)); + self.len += 1; + println!("stack_push top {:?}", self.peek_at(0).unwrap()); + Result::Ok(()) + } + + /// Pops the top item off the stack. + /// + /// # Errors + /// + /// If the stack is empty, returns with a StackOverflow error. + #[inline(always)] + fn pop(ref self: Stack) -> Result { + self.len -= 1; + let item = self.items.get(self.len().into()); + println!("stack_pop top {:?}", item.deref()); + Result::Ok(item.deref()) + } + + #[inline(always)] + fn peek_at(ref self: Stack, index: usize) -> Result { + let position = self.len() - 1 - index; + let item = self.items.get(position.into()); + + Result::Ok(item.deref()) + } + + #[inline(always)] + fn len(self: @Stack) -> usize { + *self.len + } +} + +pub fn main() -> u256 { + let mut stack = StackImpl::new(); + + stack.push(0).unwrap(); + stack.push(0).unwrap(); + stack.push(0).unwrap(); + stack.push(0).unwrap(); + stack.push(0).unwrap(); + stack.push(4).unwrap(); + stack.pop().unwrap() +} diff --git a/tests/tests/cases.rs b/tests/tests/cases.rs index ed62870aa..547b7ba20 100644 --- a/tests/tests/cases.rs +++ b/tests/tests/cases.rs @@ -145,6 +145,8 @@ use test_case::test_case; #[test_case("tests/cases/cairo_vm/programs/struct_span_return.cairo")] #[test_case("tests/cases/cairo_vm/programs/tensor_new.cairo")] #[test_case("tests/cases/brainfuck.cairo")] +// EVM related +#[test_case("tests/cases/stack.cairo")] fn test_program_cases(program_path: &str) { compare_inputless_program(program_path) }