From 28c78f9486a5843ec5af0c77c7628ac70ce50965 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Fri, 4 Nov 2022 14:22:40 -0300 Subject: [PATCH 01/20] Add dict_manager --- src/dict_manager.rs | 27 +++++++++++++++++++++++++++ src/lib.rs | 1 + src/memory_segments.rs | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/dict_manager.rs diff --git a/src/dict_manager.rs b/src/dict_manager.rs new file mode 100644 index 00000000..173dc54a --- /dev/null +++ b/src/dict_manager.rs @@ -0,0 +1,27 @@ +use crate::{ + memory_segments::PySegmentManager, relocatable::PyMaybeRelocatable, utils::to_py_error, +}; +use cairo_rs::hint_processor::builtin_hint_processor::dict_manager::DictManager; +use num_bigint::BigInt; +use pyo3::{pyclass, pymethods, PyResult}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; + +#[pyclass(unsendable)] +pub struct PyDictManager { + pub(crate) manager: Rc>, +} + +#[pymethods] +impl PyDictManager { + pub fn new_dict( + &mut self, + segments: &mut PySegmentManager, + initial_dict: HashMap, + ) -> PyResult { + Ok(self + .manager + .borrow_mut() + .new_dict(&mut segments.vm.borrow_mut(), initial_dict) + .map_err(to_py_error)?) + } +} diff --git a/src/lib.rs b/src/lib.rs index 72bf910f..8ad0c606 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ pub mod cairo_run; pub mod cairo_runner; +mod dict_manager; pub mod ids; mod memory; mod memory_segments; diff --git a/src/memory_segments.rs b/src/memory_segments.rs index dff76e50..fa2d4046 100644 --- a/src/memory_segments.rs +++ b/src/memory_segments.rs @@ -9,7 +9,7 @@ use std::{cell::RefCell, rc::Rc}; #[pyclass(name = "MemorySegmentManager", unsendable)] pub struct PySegmentManager { - vm: Rc>, + pub(crate) vm: Rc>, } #[pymethods] From e05eeb8a950c49c1cbd98e14289595fff6d159c4 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Thu, 10 Nov 2022 12:47:32 -0300 Subject: [PATCH 02/20] Create new structs --- src/dict_manager.rs | 65 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/src/dict_manager.rs b/src/dict_manager.rs index 173dc54a..3fb2d77d 100644 --- a/src/dict_manager.rs +++ b/src/dict_manager.rs @@ -1,9 +1,14 @@ use crate::{ - memory_segments::PySegmentManager, relocatable::PyMaybeRelocatable, utils::to_py_error, + memory_segments::PySegmentManager, + relocatable::{PyMaybeRelocatable, PyRelocatable}, + utils::to_py_error, +}; +use cairo_rs::{ + hint_processor::builtin_hint_processor::dict_manager::{DictManager, DictTracker, Dictionary}, + types::relocatable::Relocatable, }; -use cairo_rs::hint_processor::builtin_hint_processor::dict_manager::DictManager; use num_bigint::BigInt; -use pyo3::{pyclass, pymethods, PyResult}; +use pyo3::prelude::*; use std::{cell::RefCell, collections::HashMap, rc::Rc}; #[pyclass(unsendable)] @@ -11,17 +16,65 @@ pub struct PyDictManager { pub(crate) manager: Rc>, } +#[pyclass(unsendable)] +pub struct PyDictTracker { + pub(crate) tracker: Rc>, +} + +#[pyclass(unsendable)] +pub struct PyDictionary { + pub(crate) dictionary: Rc>, +} + #[pymethods] impl PyDictManager { + #[new] + pub fn new() -> Self { + PyDictManager { + manager: Rc::new(RefCell::new(DictManager::new())), + } + } + pub fn new_dict( &mut self, segments: &mut PySegmentManager, initial_dict: HashMap, - ) -> PyResult { + py: Python, + ) -> PyResult { + Ok(PyMaybeRelocatable::from( + self.manager + .borrow_mut() + .new_dict(&mut segments.vm.borrow_mut(), initial_dict) + .map_err(to_py_error)?, + ) + .to_object(py)) + } + + pub fn new_default_dict( + &mut self, + segments: &mut PySegmentManager, + default_value: BigInt, + initial_dict: Option>, + py: Python, + ) -> PyResult { + Ok(PyMaybeRelocatable::from( + self.manager + .borrow_mut() + .new_default_dict(&mut segments.vm.borrow_mut(), &default_value, initial_dict) + .map_err(to_py_error)?, + ) + .to_object(py)) + } + + pub fn get_tracker(&mut self, dict_ptr: &PyRelocatable, py: Python) -> PyResult<&mut PyObject> { Ok(self .manager .borrow_mut() - .new_dict(&mut segments.vm.borrow_mut(), initial_dict) - .map_err(to_py_error)?) + .get_tracker_mut(&Relocatable { + segment_index: dict_ptr.segment_index, + offset: dict_ptr.offset, + }) + .map_err(to_py_error)? + .to_object(py)) } } From 389f73eb79557a6172f40503ea2d23292a1c17f0 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Thu, 10 Nov 2022 12:52:02 -0300 Subject: [PATCH 03/20] Merge memory segments --- src/memory_segments.rs | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/memory_segments.rs b/src/memory_segments.rs index fa2d4046..bafda8ae 100644 --- a/src/memory_segments.rs +++ b/src/memory_segments.rs @@ -1,4 +1,5 @@ use crate::{ + memory::PyMemory, relocatable::{PyMaybeRelocatable, PyRelocatable}, utils::to_py_error, vm_core::PyVM, @@ -9,14 +10,19 @@ use std::{cell::RefCell, rc::Rc}; #[pyclass(name = "MemorySegmentManager", unsendable)] pub struct PySegmentManager { - pub(crate) vm: Rc>, + vm: Rc>, + #[pyo3(get)] + memory: PyMemory, } #[pymethods] impl PySegmentManager { #[new] - pub fn new(vm: &PyVM) -> PySegmentManager { - PySegmentManager { vm: vm.get_vm() } + pub fn new(vm: &PyVM, memory: PyMemory) -> PySegmentManager { + PySegmentManager { + vm: vm.get_vm(), + memory, + } } pub fn add(&self) -> PyResult { @@ -84,12 +90,18 @@ impl PySegmentManager { .map(|x| PyMaybeRelocatable::from(x).to_object(py)) .map_err(to_py_error) } + + pub fn add_temporary_segment(&mut self) -> PyResult { + Ok(PyRelocatable::from( + self.vm.borrow_mut().add_temporary_segment(), + )) + } } #[cfg(test)] mod test { use super::PySegmentManager; - use crate::{relocatable::PyMaybeRelocatable, vm_core::PyVM}; + use crate::{memory::PyMemory, relocatable::PyMaybeRelocatable, vm_core::PyVM}; use cairo_rs::{bigint, types::relocatable::Relocatable}; use num_bigint::{BigInt, Sign}; use pyo3::{Python, ToPyObject}; @@ -101,7 +113,7 @@ mod test { BigInt::new(Sign::Plus, vec![1, 0, 0, 0, 0, 0, 17, 134217728]), false, ); - let segments = PySegmentManager::new(&vm); + let segments = PySegmentManager::new(&vm, PyMemory::new(&vm)); assert!(segments.add().is_ok()); } @@ -112,7 +124,7 @@ mod test { BigInt::new(Sign::Plus, vec![1, 0, 0, 0, 0, 0, 17, 134217728]), false, ); - let segments = PySegmentManager::new(&vm); + let segments = PySegmentManager::new(&vm, PyMemory::new(&vm)); let ptr = segments.add().unwrap(); segments @@ -210,4 +222,15 @@ mod test { .is_none()); }); } + + #[test] + fn add_temporary_segment_test() { + let mut vm = PyVM::new( + BigInt::new(Sign::Plus, vec![1, 0, 0, 0, 0, 0, 17, 134217728]), + false, + ); + let memory = PyMemory::new(&vm); + let mut segments = PySegmentManager::new(&mut vm, memory); + assert!(segments.add_temporary_segment().is_ok()); + } } From dc8d66dc13ed998dd14252884770d32d298cebe2 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Thu, 10 Nov 2022 12:58:17 -0300 Subject: [PATCH 04/20] Expose vm --- src/memory_segments.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory_segments.rs b/src/memory_segments.rs index bafda8ae..d51edfec 100644 --- a/src/memory_segments.rs +++ b/src/memory_segments.rs @@ -10,7 +10,7 @@ use std::{cell::RefCell, rc::Rc}; #[pyclass(name = "MemorySegmentManager", unsendable)] pub struct PySegmentManager { - vm: Rc>, + pub(crate) vm: Rc>, #[pyo3(get)] memory: PyMemory, } From abfc657d55498e0010ccb727fd3fbaa47047fcf3 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Mon, 14 Nov 2022 09:48:51 -0300 Subject: [PATCH 05/20] Add Dict tracker and Dict --- src/cairo_runner.rs | 6 ++++ src/dict_manager.rs | 80 ++++++++++++++++++++++++++++++++------------- src/relocatable.rs | 9 +++++ 3 files changed, 72 insertions(+), 23 deletions(-) diff --git a/src/cairo_runner.rs b/src/cairo_runner.rs index ecf5a101..d17f0df6 100644 --- a/src/cairo_runner.rs +++ b/src/cairo_runner.rs @@ -1,4 +1,5 @@ use crate::{ + dict_manager::PyDictManager, relocatable::{PyMaybeRelocatable, PyRelocatable}, utils::to_py_error, vm_core::PyVM, @@ -84,11 +85,16 @@ impl PyCairoRunner { trace_file: Option<&str>, memory_file: Option<&str>, hint_locals: Option>, + py: Python, ) -> PyResult<()> { let end = self.initialize()?; if let Some(locals) = hint_locals { self.hint_locals = locals } + self.hint_locals.insert( + "__dict_manager".to_string(), + PyDictManager::new().into_py(py), + ); if trace_file.is_none() { self.pyvm.vm.borrow_mut().disable_trace(); } diff --git a/src/dict_manager.rs b/src/dict_manager.rs index 3fb2d77d..ebffd469 100644 --- a/src/dict_manager.rs +++ b/src/dict_manager.rs @@ -8,22 +8,22 @@ use cairo_rs::{ types::relocatable::Relocatable, }; use num_bigint::BigInt; -use pyo3::prelude::*; -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use pyo3::{exceptions::PyAttributeError, prelude::*}; +use std::collections::HashMap; -#[pyclass(unsendable)] +#[pyclass] pub struct PyDictManager { - pub(crate) manager: Rc>, + pub manager: DictManager, } -#[pyclass(unsendable)] +#[pyclass] pub struct PyDictTracker { - pub(crate) tracker: Rc>, + pub tracker: DictTracker, } -#[pyclass(unsendable)] +#[pyclass] pub struct PyDictionary { - pub(crate) dictionary: Rc>, + pub dictionary: Dictionary, } #[pymethods] @@ -31,7 +31,7 @@ impl PyDictManager { #[new] pub fn new() -> Self { PyDictManager { - manager: Rc::new(RefCell::new(DictManager::new())), + manager: DictManager::new(), } } @@ -41,13 +41,13 @@ impl PyDictManager { initial_dict: HashMap, py: Python, ) -> PyResult { - Ok(PyMaybeRelocatable::from( + let res = Ok(PyMaybeRelocatable::from( self.manager - .borrow_mut() .new_dict(&mut segments.vm.borrow_mut(), initial_dict) .map_err(to_py_error)?, ) - .to_object(py)) + .to_object(py)); + res } pub fn new_default_dict( @@ -59,22 +59,56 @@ impl PyDictManager { ) -> PyResult { Ok(PyMaybeRelocatable::from( self.manager - .borrow_mut() .new_default_dict(&mut segments.vm.borrow_mut(), &default_value, initial_dict) .map_err(to_py_error)?, ) .to_object(py)) } - pub fn get_tracker(&mut self, dict_ptr: &PyRelocatable, py: Python) -> PyResult<&mut PyObject> { - Ok(self - .manager - .borrow_mut() - .get_tracker_mut(&Relocatable { - segment_index: dict_ptr.segment_index, - offset: dict_ptr.offset, - }) - .map_err(to_py_error)? - .to_object(py)) + pub fn get_tracker(&mut self, dict_ptr: &PyRelocatable) -> PyResult { + Ok(PyDictTracker { + tracker: self + .manager + .get_tracker_mut(&Relocatable { + segment_index: dict_ptr.segment_index, + offset: dict_ptr.offset, + }) + .map_err(to_py_error)? + .clone(), + }) + } +} + +#[pymethods] +impl PyDictTracker { + pub fn __getattr__(&self, name: &str, py: Python) -> PyResult { + if name == "current_ptr" { + return Ok(PyMaybeRelocatable::from(&self.tracker.current_ptr).to_object(py)); + } + + if name == "data" { + return Ok(PyDictionary { + dictionary: self.tracker.data.clone(), + } + .into_py(py)); + } + + Err(PyAttributeError::new_err(name.to_string())) + } + + pub fn __setattr__(&mut self, name: &str, val: PyRelocatable) -> PyResult<()> { + if name == "current_ptr" { + self.tracker.current_ptr.offset = val.offset; + return Ok(()); + } + Err(PyAttributeError::new_err(name.to_string())) + } +} + +#[pymethods] +impl PyDictionary { + #[getter] + pub fn __getitem__(&self, key: &BigInt) -> Option<&BigInt> { + self.dictionary.get(key) } } diff --git a/src/relocatable.rs b/src/relocatable.rs index a96f066e..061f3709 100644 --- a/src/relocatable.rs +++ b/src/relocatable.rs @@ -182,6 +182,15 @@ impl From for PyMaybeRelocatable { } } +impl From<&Relocatable> for PyMaybeRelocatable { + fn from(val: &Relocatable) -> Self { + PyMaybeRelocatable::RelocatableValue(PyRelocatable { + segment_index: val.segment_index, + offset: val.offset, + }) + } +} + impl From for PyMaybeRelocatable { fn from(val: PyRelocatable) -> Self { PyMaybeRelocatable::RelocatableValue(val) From 75fbc8fde3dbab0b62a14b17840c931c021e5d64 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Mon, 14 Nov 2022 16:02:05 -0300 Subject: [PATCH 06/20] Modify structs --- src/dict_manager.rs | 118 ++++++++++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 38 deletions(-) diff --git a/src/dict_manager.rs b/src/dict_manager.rs index ebffd469..b4a242e7 100644 --- a/src/dict_manager.rs +++ b/src/dict_manager.rs @@ -4,26 +4,20 @@ use crate::{ utils::to_py_error, }; use cairo_rs::{ - hint_processor::builtin_hint_processor::dict_manager::{DictManager, DictTracker, Dictionary}, + hint_processor::builtin_hint_processor::dict_manager::DictManager, types::relocatable::Relocatable, }; use num_bigint::BigInt; -use pyo3::{exceptions::PyAttributeError, prelude::*}; -use std::collections::HashMap; +use pyo3::{ + exceptions::{PyAttributeError, PyKeyError}, + prelude::*, +}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; -#[pyclass] +#[pyclass(unsendable)] pub struct PyDictManager { - pub manager: DictManager, -} - -#[pyclass] -pub struct PyDictTracker { - pub tracker: DictTracker, -} - -#[pyclass] -pub struct PyDictionary { - pub dictionary: Dictionary, + pub manager: Rc>, + pub last_tracker: Relocatable, } #[pymethods] @@ -31,7 +25,8 @@ impl PyDictManager { #[new] pub fn new() -> Self { PyDictManager { - manager: DictManager::new(), + manager: Rc::new(RefCell::new(DictManager::new())), + last_tracker: Relocatable::from((0, 0)), } } @@ -43,6 +38,7 @@ impl PyDictManager { ) -> PyResult { let res = Ok(PyMaybeRelocatable::from( self.manager + .borrow_mut() .new_dict(&mut segments.vm.borrow_mut(), initial_dict) .map_err(to_py_error)?, ) @@ -59,36 +55,46 @@ impl PyDictManager { ) -> PyResult { Ok(PyMaybeRelocatable::from( self.manager + .borrow_mut() .new_default_dict(&mut segments.vm.borrow_mut(), &default_value, initial_dict) .map_err(to_py_error)?, ) .to_object(py)) } - pub fn get_tracker(&mut self, dict_ptr: &PyRelocatable) -> PyResult { - Ok(PyDictTracker { - tracker: self - .manager - .get_tracker_mut(&Relocatable { - segment_index: dict_ptr.segment_index, - offset: dict_ptr.offset, - }) - .map_err(to_py_error)? - .clone(), + pub fn get_tracker(&mut self, dict_ptr: &PyRelocatable) -> PyResult { + self.manager + .borrow_mut() + .trackers + .get_mut(&dict_ptr.segment_index) + .unwrap() + .current_ptr + .offset = dict_ptr.offset; + self.last_tracker = Relocatable::from((dict_ptr.segment_index, dict_ptr.offset)); + Ok(PyDictManager { + manager: self.manager.to_owned(), + last_tracker: self.last_tracker.to_owned(), }) } -} -#[pymethods] -impl PyDictTracker { pub fn __getattr__(&self, name: &str, py: Python) -> PyResult { if name == "current_ptr" { - return Ok(PyMaybeRelocatable::from(&self.tracker.current_ptr).to_object(py)); + return Ok(PyRelocatable::from( + self.manager + .borrow_mut() + .trackers + .get_mut(&self.last_tracker.segment_index) + .unwrap() + .current_ptr + .to_owned(), + ) + .into_py(py)); } if name == "data" { - return Ok(PyDictionary { - dictionary: self.tracker.data.clone(), + return Ok(PyDictManager { + manager: self.manager.to_owned(), + last_tracker: self.last_tracker.to_owned(), } .into_py(py)); } @@ -98,17 +104,53 @@ impl PyDictTracker { pub fn __setattr__(&mut self, name: &str, val: PyRelocatable) -> PyResult<()> { if name == "current_ptr" { - self.tracker.current_ptr.offset = val.offset; + self.manager + .borrow_mut() + .trackers + .get_mut(&val.segment_index) + .unwrap() + .current_ptr + .offset = val.offset; return Ok(()); } Err(PyAttributeError::new_err(name.to_string())) } -} -#[pymethods] -impl PyDictionary { #[getter] - pub fn __getitem__(&self, key: &BigInt) -> Option<&BigInt> { - self.dictionary.get(key) + pub fn __getitem__(&self, key: PyMaybeRelocatable, py: Python) -> PyResult { + match key { + PyMaybeRelocatable::Int(key) => Ok(PyMaybeRelocatable::from( + self.manager + .borrow_mut() + .trackers + .get_mut(&self.last_tracker.segment_index) + .unwrap() + .get_value(&key) + .map_err(to_py_error)?, + ) + .to_object(py)), + PyMaybeRelocatable::RelocatableValue(_) => Err(PyKeyError::new_err(key.to_object(py))), + } + } + + #[setter] + pub fn __setitem__( + &mut self, + key: PyMaybeRelocatable, + val: PyMaybeRelocatable, + ) -> PyResult<()> { + match (key, val) { + (PyMaybeRelocatable::Int(key), PyMaybeRelocatable::Int(val)) => { + self.manager + .borrow_mut() + .trackers + .get_mut(&self.last_tracker.segment_index) + .unwrap() + .insert_value(&key, &val); + + Ok(()) + } + _ => todo!(), + } } } From 4ba36d071665ec6232c0d8cc42f729562455c401 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Mon, 14 Nov 2022 17:24:24 -0300 Subject: [PATCH 07/20] Fix dereferencing ids --- src/dict_manager.rs | 10 ++++++---- src/ids.rs | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/dict_manager.rs b/src/dict_manager.rs index b4a242e7..1bcad62d 100644 --- a/src/dict_manager.rs +++ b/src/dict_manager.rs @@ -1,4 +1,5 @@ use crate::{ + ids::PyTypedId, memory_segments::PySegmentManager, relocatable::{PyMaybeRelocatable, PyRelocatable}, utils::to_py_error, @@ -62,15 +63,16 @@ impl PyDictManager { .to_object(py)) } - pub fn get_tracker(&mut self, dict_ptr: &PyRelocatable) -> PyResult { + pub fn get_tracker(&mut self, dict_ptr: &PyTypedId) -> PyResult { + let ptr_addr = dict_ptr.hint_value.clone(); self.manager .borrow_mut() .trackers - .get_mut(&dict_ptr.segment_index) + .get_mut(&ptr_addr.segment_index) .unwrap() .current_ptr - .offset = dict_ptr.offset; - self.last_tracker = Relocatable::from((dict_ptr.segment_index, dict_ptr.offset)); + .offset = ptr_addr.offset; + self.last_tracker = Relocatable::from((ptr_addr.segment_index, ptr_addr.offset)); Ok(PyDictManager { manager: self.manager.to_owned(), last_tracker: self.last_tracker.to_owned(), diff --git a/src/ids.rs b/src/ids.rs index 24293e0d..fe298f08 100644 --- a/src/ids.rs +++ b/src/ids.rs @@ -97,6 +97,34 @@ impl PyIds { } .into_py(py)); } + + let chars = cairo_type.chars().rev(); + let clear_ref = chars + .skip_while(|c| c == &'*') + .collect::() + .chars() + .rev() + .collect::(); + + if self.struct_types.contains_key(clear_ref.as_str()) { + let addr = + compute_addr_from_reference(hint_ref, &self.vm.borrow(), &self.ap_tracking)?; + + let dereferenced_addr = self + .vm + .borrow() + .get_relocatable(&addr) + .map_err(to_py_error)? + .into_owned(); + + return Ok(PyTypedId { + vm: self.vm.clone(), + hint_value: dereferenced_addr, + cairo_type: clear_ref.to_string(), + struct_types: Rc::clone(&self.struct_types), + } + .into_py(py)); + } } Ok( @@ -145,9 +173,9 @@ struct CairoStruct { } #[pyclass(unsendable)] -struct PyTypedId { +pub struct PyTypedId { vm: Rc>, - hint_value: Relocatable, + pub hint_value: Relocatable, cairo_type: String, struct_types: Rc>>, } From 8250fe8bc2c1855d02931d4071ec090eced579fd Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Mon, 14 Nov 2022 17:28:50 -0300 Subject: [PATCH 08/20] Uncomment tests --- hints_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hints_tests.py b/hints_tests.py index 6f0bb69f..6b7b3151 100644 --- a/hints_tests.py +++ b/hints_tests.py @@ -33,7 +33,7 @@ def test_program(program_name: str): test_program("memset") test_program("dict_new") test_program("dict_read") - # test_program("dict_write") # ValueError: Custom Hint Error: AttributeError: 'PyTypeId' object has no attribute 'segment_index' + test_program("dict_write") # ValueError: Custom Hint Error: AttributeError: 'PyTypeId' object has no attribute 'segment_index' test_program("dict_update") test_program("default_dict_new") # test_program("squash_dict") # ValueError: Custom Hint Error: ValueError: Failed to get ids value From b568348d6deb7df013364541550366ccf8b1aa8e Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Mon, 14 Nov 2022 17:46:09 -0300 Subject: [PATCH 09/20] Fix tests --- src/cairo_run.rs | 25 +++++--- src/cairo_runner.rs | 144 ++++++++++++++++++++++++++------------------ 2 files changed, 100 insertions(+), 69 deletions(-) diff --git a/src/cairo_run.rs b/src/cairo_run.rs index 37882435..d97fe0bb 100644 --- a/src/cairo_run.rs +++ b/src/cairo_run.rs @@ -1,6 +1,7 @@ #[cfg(test)] mod test { use crate::cairo_runner::PyCairoRunner; + use pyo3::Python; use std::fs; #[test] @@ -9,9 +10,11 @@ mod test { let program = fs::read_to_string(path).unwrap(); let mut runner = PyCairoRunner::new(program, Some("main".to_string()), None, false).unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .expect("Couldn't run program"); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .expect("Couldn't run program"); + }); } #[test] @@ -25,9 +28,11 @@ mod test { false, ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .expect("Couldn't run program"); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .expect("Couldn't run program"); + }); } #[test] @@ -36,8 +41,10 @@ mod test { let program = fs::read_to_string(path).unwrap(); let mut runner = PyCairoRunner::new(program, Some("main".to_string()), None, false).unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .expect("Couldn't run program"); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .expect("Couldn't run program"); + }); } } diff --git a/src/cairo_runner.rs b/src/cairo_runner.rs index c3952645..9f054421 100644 --- a/src/cairo_runner.rs +++ b/src/cairo_runner.rs @@ -634,9 +634,11 @@ mod test { ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); + }); let new_segment = runner.add_segment(); assert_eq!( new_segment, @@ -667,9 +669,11 @@ mod test { ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); + }); let expected_output: Vec = vec![RelocatableValue(PyRelocatable { segment_index: 2, @@ -699,9 +703,11 @@ mod test { ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); + }); let expected_output = PyRelocatable::from((1, 8)); @@ -723,9 +729,11 @@ mod test { false, ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, Some("main")) - .unwrap(); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, Some("main")) + .unwrap(); + }); // Make a copy of the builtin in order to insert a second "fake" one // BuiltinRunner api is private, so we can create a new one for this test let fake_builtin = (*runner.pyvm.vm).borrow_mut().get_builtin_runners_as_mut()[0] @@ -766,9 +774,11 @@ mod test { ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); + }); let expected_output = PyRelocatable::from((1, 0)); @@ -790,9 +800,11 @@ mod test { ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); + }); // Make a copy of the builtin in order to insert a second "fake" one // BuiltinRunner api is private, so we can create a new one for this test @@ -828,9 +840,11 @@ mod test { ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); + }); // Insert os_context in the VM's stack: // * range_check segment base in (1, 41) @@ -864,10 +878,10 @@ mod test { let program = fs::read_to_string(path).unwrap(); let mut runner = PyCairoRunner::new(program, Some("main".to_string()), None, false).unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); assert_eq!( 24, runner @@ -885,10 +899,10 @@ mod test { let program = fs::read_to_string(path).unwrap(); let mut runner = PyCairoRunner::new(program, Some("main".to_string()), None, false).unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); assert_eq!( 0, runner @@ -1101,9 +1115,11 @@ mod test { false, ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); + }); assert_eq! { PyRelocatable::from((1,2)), runner.get_initial_fp().unwrap() @@ -1306,19 +1322,22 @@ mod test { false, ) .unwrap(); - assert!(runner - .cairo_run_py( - false, - None, - None, - None, - Some(HashMap::from([( - "__find_element_max_size".to_string(), - Python::with_gil(|py| -> PyObject { 100.to_object(py) }), - )])), - None, - ) - .is_ok()); + Python::with_gil(|py| { + assert!(runner + .cairo_run_py( + false, + None, + None, + None, + py, + Some(HashMap::from([( + "__find_element_max_size".to_string(), + 100.to_object(py) + ),])), + None + ) + .is_ok()); + }); } #[test] @@ -1332,19 +1351,22 @@ mod test { false, ) .unwrap(); - assert!(runner - .cairo_run_py( - false, - None, - None, - None, - Some(HashMap::from([( - "__find_element_max_size".to_string(), - Python::with_gil(|py| -> PyObject { 1.to_object(py) }), - )])), - None - ) - .is_err()); + Python::with_gil(|py| { + assert!(runner + .cairo_run_py( + false, + None, + None, + None, + py, + Some(HashMap::from([( + "__find_element_max_size".to_string(), + 1.to_object(py) + ),])), + None + ) + .is_err()); + }); } #[test] @@ -1354,9 +1376,11 @@ mod test { let mut runner = PyCairoRunner::new(program, None, Some("small".to_string()), false).unwrap(); - runner - .cairo_run_py(false, None, None, None, None, Some("main")) - .expect("Call to PyCairoRunner::cairo_run_py() failed."); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, Some("main")) + .expect("Call to PyCairoRunner::cairo_run_py() failed."); + }); } /// Test that `PyCairoRunner::get()` works as intended. @@ -1373,7 +1397,7 @@ mod test { .unwrap(); runner - .cairo_run_py(false, None, None, None, None, None) + .cairo_run_py(false, None, None, None, py, None, None) .expect("Call to PyCairoRunner::cairo_run_py"); let mut ap = runner.get_ap().unwrap(); From 7d315992a6c9bf4c7a3ab6a7775a8fb87f0b7a9a Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Tue, 15 Nov 2022 15:48:10 -0300 Subject: [PATCH 10/20] Clean up and modify refereces --- src/dict_manager.rs | 116 +++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 60 deletions(-) diff --git a/src/dict_manager.rs b/src/dict_manager.rs index 1bcad62d..577dfbc8 100644 --- a/src/dict_manager.rs +++ b/src/dict_manager.rs @@ -9,16 +9,19 @@ use cairo_rs::{ types::relocatable::Relocatable, }; use num_bigint::BigInt; -use pyo3::{ - exceptions::{PyAttributeError, PyKeyError}, - prelude::*, -}; +use pyo3::{exceptions::PyKeyError, prelude::*}; + use std::{cell::RefCell, collections::HashMap, rc::Rc}; #[pyclass(unsendable)] pub struct PyDictManager { pub manager: Rc>, - pub last_tracker: Relocatable, +} + +#[pyclass(unsendable)] +pub struct PyDictTracker { + pub manager: Rc>, + pub key: Relocatable, } #[pymethods] @@ -27,24 +30,22 @@ impl PyDictManager { pub fn new() -> Self { PyDictManager { manager: Rc::new(RefCell::new(DictManager::new())), - last_tracker: Relocatable::from((0, 0)), } } pub fn new_dict( - &mut self, + &self, segments: &mut PySegmentManager, initial_dict: HashMap, py: Python, ) -> PyResult { - let res = Ok(PyMaybeRelocatable::from( + Ok(PyMaybeRelocatable::from( self.manager .borrow_mut() .new_dict(&mut segments.vm.borrow_mut(), initial_dict) .map_err(to_py_error)?, ) - .to_object(py)); - res + .to_object(py)) } pub fn new_default_dict( @@ -63,59 +64,56 @@ impl PyDictManager { .to_object(py)) } - pub fn get_tracker(&mut self, dict_ptr: &PyTypedId) -> PyResult { + pub fn get_tracker(&mut self, dict_ptr: &PyTypedId) -> PyResult { let ptr_addr = dict_ptr.hint_value.clone(); self.manager - .borrow_mut() - .trackers - .get_mut(&ptr_addr.segment_index) - .unwrap() - .current_ptr - .offset = ptr_addr.offset; - self.last_tracker = Relocatable::from((ptr_addr.segment_index, ptr_addr.offset)); - Ok(PyDictManager { - manager: self.manager.to_owned(), - last_tracker: self.last_tracker.to_owned(), + .borrow() + .get_tracker(&ptr_addr) + .map_err(to_py_error)?; + Ok(PyDictTracker { + manager: self.manager.clone(), + key: ptr_addr, }) } +} - pub fn __getattr__(&self, name: &str, py: Python) -> PyResult { - if name == "current_ptr" { - return Ok(PyRelocatable::from( - self.manager - .borrow_mut() - .trackers - .get_mut(&self.last_tracker.segment_index) - .unwrap() - .current_ptr - .to_owned(), - ) - .into_py(py)); - } - - if name == "data" { - return Ok(PyDictManager { - manager: self.manager.to_owned(), - last_tracker: self.last_tracker.to_owned(), - } - .into_py(py)); - } - - Err(PyAttributeError::new_err(name.to_string())) - } - - pub fn __setattr__(&mut self, name: &str, val: PyRelocatable) -> PyResult<()> { - if name == "current_ptr" { +#[pymethods] +impl PyDictTracker { + #[getter] + pub fn get_current_ptr(&self, py: Python) -> PyResult { + Ok(PyRelocatable::from( self.manager .borrow_mut() - .trackers - .get_mut(&val.segment_index) - .unwrap() + .get_tracker_mut(&self.key) + .map_err(to_py_error)? .current_ptr - .offset = val.offset; - return Ok(()); + .clone(), + ) + .into_py(py)) + } + + #[getter] + pub fn get_data(&self, py: Python) -> PyObject { + PyDictTracker { + manager: self.manager.clone(), + key: self.key.clone(), } - Err(PyAttributeError::new_err(name.to_string())) + .into_py(py) + } + + #[setter] + pub fn set_current_ptr(&mut self, val: PyRelocatable) -> PyResult<()> { + self.manager + .borrow_mut() + .get_tracker_mut(&self.key) + .map_err(to_py_error)? + .current_ptr + .offset = val.offset; + self.key = Relocatable { + segment_index: val.segment_index, + offset: val.offset, + }; + Ok(()) } #[getter] @@ -124,9 +122,8 @@ impl PyDictManager { PyMaybeRelocatable::Int(key) => Ok(PyMaybeRelocatable::from( self.manager .borrow_mut() - .trackers - .get_mut(&self.last_tracker.segment_index) - .unwrap() + .get_tracker_mut(&self.key) + .map_err(to_py_error)? .get_value(&key) .map_err(to_py_error)?, ) @@ -145,9 +142,8 @@ impl PyDictManager { (PyMaybeRelocatable::Int(key), PyMaybeRelocatable::Int(val)) => { self.manager .borrow_mut() - .trackers - .get_mut(&self.last_tracker.segment_index) - .unwrap() + .get_tracker_mut(&self.key) + .map_err(to_py_error)? .insert_value(&key, &val); Ok(()) From 75c6e432a75d2c6fa0a062c9eb9f6a5033a4af79 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Tue, 15 Nov 2022 15:53:27 -0300 Subject: [PATCH 11/20] Remove todo --- src/dict_manager.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dict_manager.rs b/src/dict_manager.rs index 577dfbc8..6ba56b85 100644 --- a/src/dict_manager.rs +++ b/src/dict_manager.rs @@ -137,8 +137,9 @@ impl PyDictTracker { &mut self, key: PyMaybeRelocatable, val: PyMaybeRelocatable, + py: Python, ) -> PyResult<()> { - match (key, val) { + match (&key, val) { (PyMaybeRelocatable::Int(key), PyMaybeRelocatable::Int(val)) => { self.manager .borrow_mut() @@ -148,7 +149,7 @@ impl PyDictTracker { Ok(()) } - _ => todo!(), + _ => Err(PyKeyError::new_err(key.to_object(py))), } } } From 0d22b0b26cb1abee2d55793ec2813ebed90b4349 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Tue, 15 Nov 2022 16:15:38 -0300 Subject: [PATCH 12/20] Improve asterix stripping --- src/ids.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/ids.rs b/src/ids.rs index fe298f08..3306b216 100644 --- a/src/ids.rs +++ b/src/ids.rs @@ -98,15 +98,10 @@ impl PyIds { .into_py(py)); } - let chars = cairo_type.chars().rev(); - let clear_ref = chars - .skip_while(|c| c == &'*') - .collect::() - .chars() - .rev() - .collect::(); - - if self.struct_types.contains_key(clear_ref.as_str()) { + if self + .struct_types + .contains_key(cairo_type.trim_end_matches("*")) + { let addr = compute_addr_from_reference(hint_ref, &self.vm.borrow(), &self.ap_tracking)?; @@ -120,7 +115,7 @@ impl PyIds { return Ok(PyTypedId { vm: self.vm.clone(), hint_value: dereferenced_addr, - cairo_type: clear_ref.to_string(), + cairo_type: cairo_type.trim_end_matches("*").to_string(), struct_types: Rc::clone(&self.struct_types), } .into_py(py)); From 94065d3ae3d81ec8d787ef304bdbdcbdaf3b8d2d Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Tue, 15 Nov 2022 16:16:15 -0300 Subject: [PATCH 13/20] Make fields private --- src/dict_manager.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dict_manager.rs b/src/dict_manager.rs index 6ba56b85..0ee32f9a 100644 --- a/src/dict_manager.rs +++ b/src/dict_manager.rs @@ -15,13 +15,13 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc}; #[pyclass(unsendable)] pub struct PyDictManager { - pub manager: Rc>, + manager: Rc>, } #[pyclass(unsendable)] pub struct PyDictTracker { - pub manager: Rc>, - pub key: Relocatable, + manager: Rc>, + key: Relocatable, } #[pymethods] From 5c1dfac56929caf952e141723ef6581db99345be Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Tue, 15 Nov 2022 16:16:33 -0300 Subject: [PATCH 14/20] Ignore clippy warnings --- src/cairo_runner.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/cairo_runner.rs b/src/cairo_runner.rs index 5212fad6..0b4a6682 100644 --- a/src/cairo_runner.rs +++ b/src/cairo_runner.rs @@ -78,6 +78,7 @@ impl PyCairoRunner { } #[pyo3(name = "cairo_run")] + #[allow(clippy::too_many_arguments)] pub fn cairo_run_py( &mut self, print_output: bool, @@ -719,22 +720,22 @@ mod test { ) .unwrap(); - runner - .cairo_run_py(false, None, None, None, None, None) - .unwrap(); + Python::with_gil(|py| { + runner + .cairo_run_py(false, None, None, None, py, None, None) + .unwrap(); - let expected_output: Vec = vec![ - RelocatableValue(PyRelocatable { - segment_index: 2, - offset: 0, - }), - RelocatableValue(PyRelocatable { - segment_index: 3, - offset: 0, - }), - ]; + let expected_output: Vec = vec![ + RelocatableValue(PyRelocatable { + segment_index: 2, + offset: 0, + }), + RelocatableValue(PyRelocatable { + segment_index: 3, + offset: 0, + }), + ]; - Python::with_gil(|py| { assert_eq!( runner .get_program_builtins_initial_stack(py) From f79bc1e6968b5865aa1e19fe0d31f8b77124cb3b Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Wed, 16 Nov 2022 10:29:16 -0300 Subject: [PATCH 15/20] Fix clippy warnings --- src/dict_manager.rs | 10 ++++++++-- src/ids.rs | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/dict_manager.rs b/src/dict_manager.rs index 0ee32f9a..dfd9e5a0 100644 --- a/src/dict_manager.rs +++ b/src/dict_manager.rs @@ -24,6 +24,12 @@ pub struct PyDictTracker { key: Relocatable, } +impl Default for PyDictManager { + fn default() -> Self { + PyDictManager::new() + } +} + #[pymethods] impl PyDictManager { #[new] @@ -139,13 +145,13 @@ impl PyDictTracker { val: PyMaybeRelocatable, py: Python, ) -> PyResult<()> { - match (&key, val) { + match (&key, &val) { (PyMaybeRelocatable::Int(key), PyMaybeRelocatable::Int(val)) => { self.manager .borrow_mut() .get_tracker_mut(&self.key) .map_err(to_py_error)? - .insert_value(&key, &val); + .insert_value(key, val); Ok(()) } diff --git a/src/ids.rs b/src/ids.rs index 3306b216..7c7490e1 100644 --- a/src/ids.rs +++ b/src/ids.rs @@ -100,7 +100,7 @@ impl PyIds { if self .struct_types - .contains_key(cairo_type.trim_end_matches("*")) + .contains_key(cairo_type.trim_end_matches('*')) { let addr = compute_addr_from_reference(hint_ref, &self.vm.borrow(), &self.ap_tracking)?; @@ -115,7 +115,7 @@ impl PyIds { return Ok(PyTypedId { vm: self.vm.clone(), hint_value: dereferenced_addr, - cairo_type: cairo_type.trim_end_matches("*").to_string(), + cairo_type: cairo_type.trim_end_matches('*').to_string(), struct_types: Rc::clone(&self.struct_types), } .into_py(py)); From 92fd3b2be1788f735e9df9bf6eed1490a7b88c97 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Wed, 16 Nov 2022 16:51:24 -0300 Subject: [PATCH 16/20] Add test tags --- cairo_programs/squash_dict.cairo | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cairo_programs/squash_dict.cairo b/cairo_programs/squash_dict.cairo index bfe4ccfb..f8c25f42 100644 --- a/cairo_programs/squash_dict.cairo +++ b/cairo_programs/squash_dict.cairo @@ -64,6 +64,7 @@ func squash_dict{range_check_ptr}( squashed_dict=squashed_dict, big_keys=big_keys) %{ + #TEST vm_exit_scope() %} return (squashed_dict=squashed_dict) @@ -173,7 +174,10 @@ func squash_dict_inner( [ap] = dict_accesses_end_minus1 - cast(last_loop_locals.access_ptr, felt) [ap] = [last_loop_locals.range_check_ptr]; ap++ tempvar n_used_accesses = last_loop_locals.range_check_ptr - range_check_ptr - %{ assert ids.n_used_accesses == len(access_indices[key]) %} + %{ + #TEST + assert ids.n_used_accesses == len(access_indices[key]) + %} # Write last value to dict_diff. last_loop_locals.value = dict_diff.new_value From 0c6e4407564840b5d53be07e89161214729f6110 Mon Sep 17 00:00:00 2001 From: Juan-M-V <102986292+Juan-M-V@users.noreply.github.com> Date: Wed, 16 Nov 2022 17:13:55 -0300 Subject: [PATCH 17/20] Update hints_tests.py --- hints_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hints_tests.py b/hints_tests.py index 6b7b3151..5e13aa9d 100644 --- a/hints_tests.py +++ b/hints_tests.py @@ -33,7 +33,7 @@ def test_program(program_name: str): test_program("memset") test_program("dict_new") test_program("dict_read") - test_program("dict_write") # ValueError: Custom Hint Error: AttributeError: 'PyTypeId' object has no attribute 'segment_index' + test_program("dict_write") test_program("dict_update") test_program("default_dict_new") # test_program("squash_dict") # ValueError: Custom Hint Error: ValueError: Failed to get ids value From e161553224a93a40221c3bdb258e9214144a9c5d Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Wed, 16 Nov 2022 17:16:40 -0300 Subject: [PATCH 18/20] Remove test comment --- hints_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hints_tests.py b/hints_tests.py index 5e13aa9d..626289c3 100644 --- a/hints_tests.py +++ b/hints_tests.py @@ -36,7 +36,7 @@ def test_program(program_name: str): test_program("dict_write") test_program("dict_update") test_program("default_dict_new") - # test_program("squash_dict") # ValueError: Custom Hint Error: ValueError: Failed to get ids value + test_program("squash_dict") # test_program("dict_squash") # Custom Hint Error: AttributeError: 'PyTypeId' object has no attribute 'segment_index' test_program("ids_size") test_program("split_felt") From 525c20070da57af1555954096e0467be64ce4882 Mon Sep 17 00:00:00 2001 From: Juan-M-V Date: Thu, 17 Nov 2022 10:41:34 -0300 Subject: [PATCH 19/20] Uncomment test --- hints_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hints_tests.py b/hints_tests.py index 46992e89..27073c69 100644 --- a/hints_tests.py +++ b/hints_tests.py @@ -33,7 +33,7 @@ def test_program(program_name: str): test_program("memset") test_program("dict_new") test_program("dict_read") - #test_program("dict_write") + test_program("dict_write") test_program("dict_update") test_program("default_dict_new") # test_program("squash_dict") # ValueError: Custom Hint Error: ValueError: Failed to get ids value From 85619ee14fab9fb14a961ee1c3425d34c5f09e45 Mon Sep 17 00:00:00 2001 From: Juan-M-V <102986292+Juan-M-V@users.noreply.github.com> Date: Mon, 28 Nov 2022 10:31:58 -0300 Subject: [PATCH 20/20] Update ids.rs --- src/ids.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ids.rs b/src/ids.rs index f320b519..e3814752 100644 --- a/src/ids.rs +++ b/src/ids.rs @@ -166,7 +166,7 @@ struct CairoStruct { } #[pyclass(unsendable)] -pub struct PyTypedId { +pub(crate) struct PyTypedId { vm: Rc>, pub hint_value: Relocatable, cairo_type: String,