neo_solidity/ir/expressions/member_access/
selectors.rs1fn try_lower_selector_member_access(
2 inner: &Expression,
3 member: &Identifier,
4 ctx: &mut LoweringContext,
5 instructions: &mut Vec<Instruction>,
6) -> Option<bool> {
7 fn resolve_contract_type_name(expr: &Expression, ctx: &LoweringContext) -> Option<String> {
8 match expr {
9 Expression::Variable(type_name) if ctx.is_contract_type_name(&type_name.name) => {
10 Some(type_name.name.clone())
11 }
12 Expression::MemberAccess(_, namespace_expr, type_name)
13 if matches!(
14 namespace_expr.as_ref(),
15 Expression::Variable(namespace_id)
16 if !ctx.param_index_map.contains_key(&namespace_id.name)
17 && ctx.resolve_local(&namespace_id.name).is_none()
18 && !ctx.state_index_map.contains_key(&namespace_id.name)
19 && !ctx.is_contract_type_name(&namespace_id.name)
20 ) && ctx.is_contract_type_name(&type_name.name) =>
21 {
22 Some(type_name.name.clone())
23 }
24 _ => None,
25 }
26 }
27
28 if member.name != "selector" {
29 return None;
30 }
31
32 if let Expression::MemberAccess(_, target_inner, target_method) = inner {
37 if let Some(type_name) = resolve_contract_type_name(target_inner.as_ref(), ctx) {
38 if let Some(selectors) = ctx.type_method_selectors(&type_name, &target_method.name) {
39 if selectors.len() == 1 {
40 instructions.push(Instruction::PushLiteral(
41 LiteralValue::ByteArray(selectors[0].to_vec()),
42 ));
43 return Some(true);
44 }
45
46 ctx.record_error(format!(
47 "ambiguous selector '{}.{}': {} overload(s)",
48 type_name,
49 target_method.name,
50 selectors.len()
51 ));
52 return Some(false);
53 }
54
55 ctx.record_error(format!(
56 "unknown selector '{}.{}'",
57 type_name, target_method.name
58 ));
59 return Some(false);
60 }
61 }
62
63 ctx.record_error("unsupported selector expression");
64 Some(false)
65}