neo_solidity/ir/context/
helpers.rs1fn load_expression(
2 expr: &Expression,
3 ctx: &mut LoweringContext,
4 instructions: &mut Vec<Instruction>,
5) {
6 let mut tmp = Vec::new();
7 if lower_expression(expr, ctx, &mut tmp) {
8 instructions.append(&mut tmp);
9 }
10}
11
12fn push_default_for_type(ty: &PtType, instructions: &mut Vec<Instruction>) {
13 match ty {
14 PtType::Address | PtType::AddressPayable => {
15 instructions.push(Instruction::PushLiteral(LiteralValue::Address(vec![
16 0u8;
17 20
18 ])));
19 }
20 PtType::Bool => instructions.push(Instruction::PushLiteral(LiteralValue::Boolean(false))),
21 PtType::String => {
22 instructions.push(Instruction::PushLiteral(LiteralValue::String(Vec::new())))
23 }
24 PtType::Uint(_) | PtType::Int(_) => {
25 instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
26 BigInt::zero(),
27 )));
28 }
29 PtType::Bytes(len) => instructions.push(Instruction::PushLiteral(LiteralValue::ByteArray(
30 vec![0u8; *len as usize],
31 ))),
32 PtType::DynamicBytes => instructions.push(Instruction::PushLiteral(
33 LiteralValue::ByteArray(Vec::new()),
34 )),
35 _ => instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
36 BigInt::zero(),
37 ))),
38 }
39}
40
41fn push_default_for_value_type(
42 value_type: &ValueType,
43 ctx: &mut LoweringContext,
44 instructions: &mut Vec<Instruction>,
45) -> bool {
46 match value_type {
47 ValueType::Integer { .. } => {
48 instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
49 BigInt::zero(),
50 )));
51 true
52 }
53 ValueType::Boolean => {
54 instructions.push(Instruction::PushLiteral(LiteralValue::Boolean(false)));
55 true
56 }
57 ValueType::String => {
58 instructions.push(Instruction::PushLiteral(LiteralValue::String(Vec::new())));
59 true
60 }
61 ValueType::Address => {
62 instructions.push(Instruction::PushLiteral(LiteralValue::Address(vec![
63 0u8;
64 20
65 ])));
66 true
67 }
68 ValueType::ByteArray { fixed_len } => {
69 let bytes = fixed_len
70 .map(|len| vec![0u8; len as usize])
71 .unwrap_or_else(Vec::new);
72 instructions.push(Instruction::PushLiteral(LiteralValue::ByteArray(bytes)));
73 true
74 }
75 ValueType::Array(element_type) => {
76 instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
77 BigInt::zero(),
78 )));
79 instructions.push(Instruction::NewArray {
80 element_type: (**element_type).clone(),
81 });
82 true
83 }
84 ValueType::Struct { fields, .. } => {
85 let tmp_id = ctx.next_label();
86 let struct_local = ctx.allocate_local(
87 format!("__default_struct_{tmp_id}"),
88 Some(ValueType::Array(Box::new(ValueType::Any))),
89 );
90
91 instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
92 BigInt::from(fields.len() as u64),
93 )));
94 instructions.push(Instruction::NewArray {
95 element_type: ValueType::Any,
96 });
97 instructions.push(Instruction::StoreLocal(struct_local));
98
99 for (index, field) in fields.iter().enumerate() {
100 instructions.push(Instruction::LoadLocal(struct_local));
101 instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
102 BigInt::from(index as u64),
103 )));
104 push_default_for_value_type(&field.ty, ctx, instructions);
105 instructions.push(Instruction::ArraySet);
106 }
107
108 instructions.push(Instruction::LoadLocal(struct_local));
109 true
110 }
111 ValueType::Mapping { .. } | ValueType::Any => {
112 instructions.push(Instruction::PushLiteral(LiteralValue::Null));
113 true
114 }
115 }
116}
117
118fn push_default_for_storage_value_type(
119 value_type: &ValueType,
120 ctx: &mut LoweringContext,
121 instructions: &mut Vec<Instruction>,
122) -> bool {
123 match value_type {
124 ValueType::Array(_) => {
126 instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
127 BigInt::zero(),
128 )));
129 true
130 }
131 ValueType::Struct { fields, .. } => {
134 let tmp_id = ctx.next_label();
135 let struct_local = ctx.allocate_local(
136 format!("__default_storage_struct_{tmp_id}"),
137 Some(ValueType::Array(Box::new(ValueType::Any))),
138 );
139
140 instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
141 BigInt::from(fields.len() as u64),
142 )));
143 instructions.push(Instruction::NewArray {
144 element_type: ValueType::Any,
145 });
146 instructions.push(Instruction::StoreLocal(struct_local));
147
148 for (index, field) in fields.iter().enumerate() {
149 instructions.push(Instruction::LoadLocal(struct_local));
150 instructions.push(Instruction::PushLiteral(LiteralValue::Integer(
151 BigInt::from(index as u64),
152 )));
153 push_default_for_storage_value_type(&field.ty, ctx, instructions);
154 instructions.push(Instruction::ArraySet);
155 }
156
157 instructions.push(Instruction::LoadLocal(struct_local));
158 true
159 }
160 _ => push_default_for_value_type(value_type, ctx, instructions),
161 }
162}