1use std::{any::Any, collections::HashMap};
2
3use crate::Felt252;
4
5use crate::hint_processor::hint_processor_definition::HintReference;
6use crate::hint_processor::hint_processor_utils::{
7 compute_addr_from_reference, get_ptr_from_reference,
8};
9use crate::hint_processor::hint_processor_utils::{
10 get_integer_from_reference, get_maybe_relocatable_from_reference,
11};
12use crate::serde::deserialize_program::ApTracking;
13use crate::types::exec_scope::ExecutionScopes;
14use crate::types::relocatable::MaybeRelocatable;
15use crate::types::relocatable::Relocatable;
16use crate::vm::errors::hint_errors::HintError;
17use crate::vm::vm_core::VirtualMachine;
18
19#[macro_export]
54macro_rules! define_hint_string_map {
55 ($hint_set_name:ident, $(($hint_name:ident, $hint_str:expr $(, $feature_gate:expr)?)),+) => {
56 $(
57 $(#[cfg(feature = $feature_gate)])?
58 pub const $hint_name: &str = $hint_str;
59 )+
60
61 lazy_static::lazy_static! {
62 pub static ref $hint_set_name: HashMap<&'static str, &'static str> = {
63 let mut map = HashMap::new();
64 $(
65 $(#[cfg(feature = $feature_gate)])?
66 map.insert(stringify!($hint_name), $hint_name);
67 )+
68 map
69 };
70 }
71 }
72}
73
74pub(crate) fn enter_scope_with_n_from_var_name(
76 source_var_name: &str,
77 vm: &mut VirtualMachine,
78 exec_scopes: &mut ExecutionScopes,
79 ids_data: &HashMap<String, HintReference>,
80 ap_tracking: &ApTracking,
81) -> Result<(), HintError> {
82 let n: Box<dyn Any> = Box::new(get_integer_from_var_name(
83 source_var_name,
84 vm,
85 ids_data,
86 ap_tracking,
87 )?);
88 exec_scopes.enter_scope(HashMap::from([(String::from("n"), n)]));
89 Ok(())
90}
91
92pub fn insert_value_from_var_name(
94 var_name: &str,
95 value: impl Into<MaybeRelocatable>,
96 vm: &mut VirtualMachine,
97 ids_data: &HashMap<String, HintReference>,
98 ap_tracking: &ApTracking,
99) -> Result<(), HintError> {
100 let var_address = get_relocatable_from_var_name(var_name, vm, ids_data, ap_tracking)?;
101 vm.insert_value(var_address, value)
102 .map_err(HintError::Memory)
103}
104
105pub fn insert_value_into_ap(
107 vm: &mut VirtualMachine,
108 value: impl Into<MaybeRelocatable>,
109) -> Result<(), HintError> {
110 vm.insert_value(vm.get_ap(), value)
111 .map_err(HintError::Memory)
112}
113
114pub fn get_ptr_from_var_name(
116 var_name: &str,
117 vm: &VirtualMachine,
118 ids_data: &HashMap<String, HintReference>,
119 ap_tracking: &ApTracking,
120) -> Result<Relocatable, HintError> {
121 let reference = get_reference_from_var_name(var_name, ids_data)?;
122 match get_ptr_from_reference(vm, reference, ap_tracking) {
123 Ok(val) => Ok(val),
125 Err(HintError::WrongIdentifierTypeInternal) => Err(HintError::IdentifierNotRelocatable(
126 Box::<str>::from(var_name),
127 )),
128 _ => Err(HintError::UnknownIdentifier(Box::<str>::from(var_name))),
129 }
130}
131
132pub fn get_address_from_var_name(
134 var_name: &str,
135 vm: &mut VirtualMachine,
136 ids_data: &HashMap<String, HintReference>,
137 ap_tracking: &ApTracking,
138) -> Result<MaybeRelocatable, HintError> {
139 get_relocatable_from_var_name(var_name, vm, ids_data, ap_tracking).map(|x| x.into())
140}
141
142pub fn get_relocatable_from_var_name(
144 var_name: &str,
145 vm: &VirtualMachine,
146 ids_data: &HashMap<String, HintReference>,
147 ap_tracking: &ApTracking,
148) -> Result<Relocatable, HintError> {
149 ids_data
150 .get(var_name)
151 .and_then(|x| compute_addr_from_reference(x, vm, ap_tracking))
152 .ok_or_else(|| HintError::UnknownIdentifier(Box::<str>::from(var_name)))
153}
154
155pub fn get_integer_from_var_name(
159 var_name: &str,
160 vm: &VirtualMachine,
161 ids_data: &HashMap<String, HintReference>,
162 ap_tracking: &ApTracking,
163) -> Result<Felt252, HintError> {
164 let reference = get_reference_from_var_name(var_name, ids_data)?;
165 match get_integer_from_reference(vm, reference, ap_tracking) {
166 Ok(val) => Ok(val),
168 Err(HintError::WrongIdentifierTypeInternal) => {
169 Err(HintError::IdentifierNotInteger(Box::<str>::from(var_name)))
170 }
171 _ => Err(HintError::UnknownIdentifier(Box::<str>::from(var_name))),
172 }
173}
174
175pub fn get_maybe_relocatable_from_var_name<'a>(
177 var_name: &str,
178 vm: &'a VirtualMachine,
179 ids_data: &'a HashMap<String, HintReference>,
180 ap_tracking: &ApTracking,
181) -> Result<MaybeRelocatable, HintError> {
182 let reference = get_reference_from_var_name(var_name, ids_data)?;
183 get_maybe_relocatable_from_reference(vm, reference, ap_tracking)
184 .ok_or_else(|| HintError::UnknownIdentifier(Box::<str>::from(var_name)))
185}
186
187pub fn get_reference_from_var_name<'a>(
188 var_name: &'a str,
189 ids_data: &'a HashMap<String, HintReference>,
190) -> Result<&'a HintReference, HintError> {
191 ids_data
192 .get(var_name)
193 .ok_or_else(|| HintError::UnknownIdentifier(Box::<str>::from(var_name)))
194}
195
196pub fn get_constant_from_var_name<'a>(
197 var_name: &'static str,
198 constants: &'a HashMap<String, Felt252>,
199) -> Result<&'a Felt252, HintError> {
200 constants
201 .iter()
202 .find(|(k, _)| k.rsplit('.').next() == Some(var_name))
203 .map(|(_, n)| n)
204 .ok_or_else(|| HintError::MissingConstant(Box::new(var_name)))
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210
211 use crate::{
212 hint_processor::hint_processor_definition::HintReference, relocatable,
213 serde::deserialize_program::OffsetValue, utils::test_utils::*,
214 vm::vm_memory::memory::Memory,
215 };
216 use assert_matches::assert_matches;
217
218 #[test]
219 fn get_ptr_from_var_name_immediate_value() {
220 let mut vm = vm!();
221 vm.segments = segments![((1, 0), (0, 0))];
222 let mut hint_ref = HintReference::new(0, 0, true, false, true);
223 hint_ref.offset2 = OffsetValue::Value(2);
224 let ids_data = HashMap::from([("imm".to_string(), hint_ref)]);
225
226 assert_matches!(
227 get_ptr_from_var_name("imm", &vm, &ids_data, &ApTracking::new()),
228 Ok(x) if x == relocatable!(0, 2)
229 );
230 }
231
232 #[test]
233 fn get_maybe_relocatable_from_var_name_valid() {
234 let mut vm = vm!();
235 vm.segments = segments![((1, 0), (0, 0))];
236 let hint_ref = HintReference::new_simple(0);
237 let ids_data = HashMap::from([("value".to_string(), hint_ref)]);
238
239 assert_matches!(
240 get_maybe_relocatable_from_var_name("value", &vm, &ids_data, &ApTracking::new()),
241 Ok(x) if x == mayberelocatable!(0, 0)
242 );
243 }
244
245 #[test]
246 fn get_maybe_relocatable_from_var_name_invalid() {
247 let mut vm = vm!();
248 vm.segments.memory = Memory::new();
249 let hint_ref = HintReference::new_simple(0);
250 let ids_data = HashMap::from([("value".to_string(), hint_ref)]);
251
252 assert_matches!(
253 get_maybe_relocatable_from_var_name("value", &vm, &ids_data, &ApTracking::new()),
254 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "value"
255 );
256 }
257
258 #[test]
259 fn get_ptr_from_var_name_valid() {
260 let mut vm = vm!();
261 vm.segments = segments![((1, 0), (0, 0))];
262 let hint_ref = HintReference::new_simple(0);
263 let ids_data = HashMap::from([("value".to_string(), hint_ref)]);
264
265 assert_matches!(
266 get_ptr_from_var_name("value", &vm, &ids_data, &ApTracking::new()),
267 Ok(x) if x == relocatable!(0, 0)
268 );
269 }
270
271 #[test]
272 fn get_ptr_from_var_name_invalid() {
273 let mut vm = vm!();
274 vm.segments = segments![((1, 0), 0)];
275 let hint_ref = HintReference::new_simple(0);
276 let ids_data = HashMap::from([("value".to_string(), hint_ref)]);
277
278 assert_matches!(
279 get_ptr_from_var_name("value", &vm, &ids_data, &ApTracking::new()),
280 Err(HintError::IdentifierNotRelocatable(bx)) if bx.as_ref() == "value"
281 );
282 }
283
284 #[test]
285 fn get_relocatable_from_var_name_valid() {
286 let mut vm = vm!();
287 vm.segments = segments![((1, 0), (0, 0))];
288 let hint_ref = HintReference::new_simple(0);
289 let ids_data = HashMap::from([("value".to_string(), hint_ref)]);
290
291 assert_matches!(
292 get_relocatable_from_var_name("value", &vm, &ids_data, &ApTracking::new()),
293 Ok(x) if x == relocatable!(1, 0)
294 );
295 }
296
297 #[test]
298 fn get_relocatable_from_var_name_invalid() {
299 let mut vm = vm!();
300 vm.segments.memory = Memory::new();
301 let hint_ref = HintReference::new_simple(-8);
302 let ids_data = HashMap::from([("value".to_string(), hint_ref)]);
303
304 assert_matches!(
305 get_relocatable_from_var_name("value", &vm, &ids_data, &ApTracking::new()),
306 Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "value"
307 );
308 }
309
310 #[test]
311 fn get_integer_from_var_name_valid() {
312 let mut vm = vm!();
313 vm.segments = segments![((1, 0), 1)];
314 let hint_ref = HintReference::new_simple(0);
315 let ids_data = HashMap::from([("value".to_string(), hint_ref)]);
316
317 assert_matches!(
318 get_integer_from_var_name("value", &vm, &ids_data, &ApTracking::new()),
319 Ok(x) if x == Felt252::from(1)
320 );
321 }
322
323 #[test]
324 fn get_integer_from_var_name_invalid() {
325 let mut vm = vm!();
326 vm.segments = segments![((1, 0), (0, 0))];
327 let hint_ref = HintReference::new_simple(0);
328 let ids_data = HashMap::from([("value".to_string(), hint_ref)]);
329
330 assert_matches!(
331 get_integer_from_var_name("value", &vm, &ids_data, &ApTracking::new()),
332 Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "value"
333 );
334 }
335}