neo_solidity/ir/statements/dispatch/
expressions.rs1fn lower_expression_statement(
2 expr: &Expression,
3 ctx: &mut LoweringContext,
4 instructions: &mut Vec<Instruction>,
5) -> bool {
6 if let Expression::Assign(_, lhs, rhs) = expr {
7 lower_assignment(lhs, rhs, ctx, instructions);
8 } else if let Expression::FunctionCall(_, func, args) = expr {
9 if let Expression::Variable(identifier) = func.as_ref() {
10 if identifier.name == "require" {
11 lower_require(args, ctx, instructions);
12 return false;
13 }
14 if identifier.name == "assert" {
15 lower_assert(args, ctx, instructions);
16 return false;
17 }
18 }
19 if lower_expression(expr, ctx, instructions) {
20 instructions.push(Instruction::Drop(ValueType::Any));
21 }
22 } else if lower_expression(expr, ctx, instructions) {
23 instructions.push(Instruction::Drop(ValueType::Any));
24 }
25 false
26}
27
28fn lower_variable_definition_statement(
29 decl: &solang_parser::pt::VariableDeclaration,
30 init: Option<&Expression>,
31 ctx: &mut LoweringContext,
32 instructions: &mut Vec<Instruction>,
33) -> bool {
34 if let Some(ident) = &decl.name {
35 if ctx.is_local_in_current_scope(&ident.name) {
36 ctx.record_error_with_suggestion(
37 format!("local variable '{}' redeclared", ident.name),
38 "use a different variable name or assign to the existing variable instead of redeclaring",
39 );
40 } else {
41 let is_storage_reference = matches!(decl.storage, Some(PtStorageLocation::Storage(_)));
42 let mut inferred_type = if is_storage_reference {
43 None
44 } else {
45 infer_type_from_expression(&decl.ty, ctx)
46 };
47
48 if !is_storage_reference && inferred_type.is_none() {
51 if let Expression::Variable(type_ident) = &decl.ty {
52 inferred_type = ctx
53 .defined_struct_types
54 .iter()
55 .chain(ctx.state_types.iter())
56 .chain(ctx.param_types.iter())
57 .chain(ctx.return_types.iter())
58 .chain(ctx.local_types.values())
59 .find_map(|ty| find_named_struct_type(ty, &type_ident.name));
60 }
61 }
62
63 let slot = ctx.allocate_local(ident.name.clone(), inferred_type.clone());
64 if let Some(initializer) = init {
65 if is_storage_reference {
66 if let Some(reference) = resolve_storage_reference(initializer, ctx) {
67 ctx.set_storage_alias(ident.name.clone(), reference);
68 } else if lower_expression(initializer, ctx, instructions) {
69 instructions.push(Instruction::Drop(ValueType::Any));
70 }
71 } else {
72 match parse_low_level_call_data(initializer, ctx) {
73 Ok(Some((method_name, encode_args))) => {
74 let mut lowered = true;
77 for arg in &encode_args {
78 if !lower_expression(arg, ctx, instructions) {
79 lowered = false;
80 }
81 }
82
83 if lowered {
84 instructions.push(Instruction::CallBuiltin {
85 builtin: BuiltinCall::AbiEncode,
86 arg_count: encode_args.len(),
87 });
88 instructions.push(Instruction::StoreLocal(slot));
89 ctx.set_call_data_local(slot, method_name);
90 }
91 }
92 Ok(None) => {
93 if lower_expression(initializer, ctx, instructions) {
94 instructions.push(Instruction::StoreLocal(slot));
95 ctx.clear_call_data_local(slot);
96 }
97 }
98 Err(message) => {
99 ctx.record_error(message);
100 ctx.clear_call_data_local(slot);
101 }
102 }
103 }
104 } else if !is_storage_reference {
105 if let Some(value_type) = inferred_type.as_ref() {
106 push_default_for_value_type(value_type, ctx, instructions);
107 } else {
108 instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
109 BigInt::from(0u8),
110 )));
111 }
112 instructions.push(Instruction::StoreLocal(slot));
113 ctx.clear_call_data_local(slot);
114 }
115 }
116 } else {
117 ctx.record_error_with_suggestion(
118 "variable declaration missing identifier",
119 "every variable declaration must have a name: e.g. uint256 myVar = 0",
120 );
121 }
122 false
123}
124
125fn lower_emit_statement(
126 call: &Expression,
127 ctx: &mut LoweringContext,
128 instructions: &mut Vec<Instruction>,
129) -> bool {
130 lower_emit(call, ctx, instructions);
131 false
132}
133
134fn lower_assembly_statement(ctx: &mut LoweringContext, instructions: &mut Vec<Instruction>) -> bool {
135 if !lower_special_assembly(ctx, instructions) {
136 ctx.record_error_with_suggestion(
137 "inline assembly is not supported",
138 "Neo N3 uses NeoVM opcodes; use NativeCalls.sol for low-level operations",
139 );
140 }
141 false
142}