Skip to content

Commit cbd764b

Browse files
Implement get_identifier_from_scoped_name
1 parent 7755d4b commit cbd764b

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

vm/src/hint_processor/builtin_hint_processor/hint_utils.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,36 @@ pub fn get_reference_from_var_name<'a>(
174174
.ok_or_else(|| HintError::UnknownIdentifier(Box::<str>::from(var_name)))
175175
}
176176

177+
pub fn get_identifier_from_scoped_name<'a>(
178+
scoped_name: &str,
179+
identifiers: &'a HashMap<String, Identifier>,
180+
accessible_scopes: &[String],
181+
) -> Result<&'a Identifier, HintError> {
182+
for scope in accessible_scopes.iter().rev() {
183+
let full_path = format!("{}.{}", scope, scoped_name);
184+
185+
if let Some(identifier) = identifiers.get(&full_path) {
186+
return Ok(identifier);
187+
}
188+
189+
// The scoped_name can itself contain multiple components (i.e. a.b.c).
190+
// If there is a match for at least the first component, we should
191+
// not continue with the next scope.
192+
if let Some(first_component) = scoped_name.split('.').next() {
193+
if identifiers
194+
.get(&format!("{}.{}", scope, first_component))
195+
.is_some()
196+
{
197+
break;
198+
}
199+
}
200+
}
201+
202+
Err(HintError::UnknownIdentifier(
203+
scoped_name.to_string().into_boxed_str(),
204+
))
205+
}
206+
177207
pub fn get_constant_from_var_name<'a>(
178208
var_name: &str,
179209
identifiers: &'a HashMap<String, Identifier>,
@@ -386,4 +416,62 @@ mod tests {
386416
Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "value"
387417
);
388418
}
419+
420+
#[test]
421+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
422+
fn get_identifier_from_scoped_name_valid() {
423+
let accessible_scopes = &["scope1".to_string(), "scope1.scope2".to_string()];
424+
425+
let identifier = const_identifier(5);
426+
427+
let identifiers = HashMap::from([(
428+
"scope1.scope2.constant1.constant2".to_string(),
429+
identifier.clone(),
430+
)]);
431+
432+
assert_matches!(
433+
get_identifier_from_scoped_name("constant1.constant2", &identifiers, accessible_scopes),
434+
Ok(id) if id == &identifier
435+
);
436+
}
437+
438+
#[test]
439+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
440+
fn get_identifier_from_scoped_name_invalid() {
441+
let accessible_scopes = &["scope1".to_string(), "scope1.scope2".to_string()];
442+
443+
let identifier = const_identifier(5);
444+
445+
let identifiers = HashMap::from([(
446+
"scope1.scope2.constant3.constant4".to_string(),
447+
identifier.clone(),
448+
)]);
449+
450+
assert_matches!(
451+
get_identifier_from_scoped_name("constant1.constant2", &identifiers, accessible_scopes),
452+
Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "constant1.constant2"
453+
);
454+
}
455+
456+
#[test]
457+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
458+
fn get_identifier_from_scoped_name_invalid_partial_match() {
459+
let accessible_scopes = &["scope1".to_string(), "scope1.scope2".to_string()];
460+
461+
let identifier = const_identifier(5);
462+
463+
let identifiers = HashMap::from([
464+
("scope1.scope2.constant1".to_string(), identifier.clone()),
465+
("scope1.constant1.constant2".to_string(), identifier.clone()),
466+
(
467+
"scope1.scope2.constant1.constant3".to_string(),
468+
identifier.clone(),
469+
),
470+
]);
471+
472+
assert_matches!(
473+
get_identifier_from_scoped_name("constant1.constant2", &identifiers, accessible_scopes),
474+
Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "constant1.constant2"
475+
);
476+
}
389477
}

0 commit comments

Comments
 (0)