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