|
|
@@ -70,12 +70,6 @@ impl RetrieveType for Expression {
|
|
|
| Expression::Load(_, ty, _)
|
|
|
| Expression::GetRef(_, ty, _)
|
|
|
| Expression::StorageLoad(_, ty, _)
|
|
|
- | Expression::ZeroExt(_, ty, _)
|
|
|
- | Expression::SignExt(_, ty, _)
|
|
|
- | Expression::Trunc(_, ty, _)
|
|
|
- | Expression::CheckingTrunc(_, ty, _)
|
|
|
- | Expression::Cast(_, ty, _)
|
|
|
- | Expression::BytesCast(_, ty, ..)
|
|
|
| Expression::Complement(_, ty, _)
|
|
|
| Expression::UnaryMinus(_, ty, _)
|
|
|
| Expression::ConditionalOperator(_, ty, ..)
|
|
|
@@ -87,6 +81,12 @@ impl RetrieveType for Expression {
|
|
|
| Expression::PostDecrement(_, ty, ..)
|
|
|
| Expression::Assign(_, ty, ..) => ty.clone(),
|
|
|
Expression::Subscript(_, ty, ..) => ty.clone(),
|
|
|
+ Expression::ZeroExt { to, .. }
|
|
|
+ | Expression::SignExt { to, .. }
|
|
|
+ | Expression::Trunc { to, .. }
|
|
|
+ | Expression::CheckingTrunc { to, .. }
|
|
|
+ | Expression::Cast { to, .. }
|
|
|
+ | Expression::BytesCast { to, .. } => to.clone(),
|
|
|
Expression::StorageArrayLength { ty, .. } => ty.clone(),
|
|
|
Expression::ExternalFunctionCallRaw { .. } => {
|
|
|
panic!("two return values");
|
|
|
@@ -384,7 +384,11 @@ impl Expression {
|
|
|
&& from_dims.len() == 1
|
|
|
&& matches!(to_dims.last().unwrap(), ArrayLength::Dynamic)
|
|
|
{
|
|
|
- return Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())));
|
|
|
+ return Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -460,17 +464,21 @@ impl Expression {
|
|
|
|
|
|
// TODO needs runtime checks
|
|
|
match from_width.cmp(&to_width) {
|
|
|
- Ordering::Greater => {
|
|
|
- Ok(Expression::Trunc(*loc, to.clone(), Box::new(self.clone())))
|
|
|
- }
|
|
|
- Ordering::Less => Ok(Expression::ZeroExt(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- )),
|
|
|
- Ordering::Equal => {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
- }
|
|
|
+ Ordering::Greater => Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
+ Ordering::Less => Ok(Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
+ Ordering::Equal => Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
}
|
|
|
}
|
|
|
(Type::Enum(enum_no), Type::Uint(to_width))
|
|
|
@@ -490,17 +498,21 @@ impl Expression {
|
|
|
let from_width = enum_ty.ty.bits(ns);
|
|
|
|
|
|
match from_width.cmp(to_width) {
|
|
|
- Ordering::Greater => {
|
|
|
- Ok(Expression::Trunc(*loc, to.clone(), Box::new(self.clone())))
|
|
|
- }
|
|
|
- Ordering::Less => Ok(Expression::ZeroExt(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- )),
|
|
|
- Ordering::Equal => {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
- }
|
|
|
+ Ordering::Greater => Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
+ Ordering::Less => Ok(Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
+ Ordering::Equal => Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
}
|
|
|
}
|
|
|
(Type::Bytes(1), Type::Uint(8)) | (Type::Uint(8), Type::Bytes(1)) => Ok(self.clone()),
|
|
|
@@ -517,15 +529,23 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Trunc(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
- Ordering::Less => Ok(Expression::ZeroExt(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- )),
|
|
|
- Ordering::Equal => Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone()))),
|
|
|
+ Ordering::Less => Ok(Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
+ Ordering::Equal => Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
},
|
|
|
(Type::Int(from_len), Type::Int(to_len)) => match from_len.cmp(to_len) {
|
|
|
Ordering::Greater => {
|
|
|
@@ -540,19 +560,31 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Trunc(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
- Ordering::Less => Ok(Expression::SignExt(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- )),
|
|
|
- Ordering::Equal => Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone()))),
|
|
|
+ Ordering::Less => Ok(Expression::SignExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
+ Ordering::Equal => Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
},
|
|
|
- (Type::Uint(from_len), Type::Int(to_len)) if to_len > from_len => Ok(
|
|
|
- Expression::ZeroExt(*loc, to.clone(), Box::new(self.clone())),
|
|
|
- ),
|
|
|
+ (Type::Uint(from_len), Type::Int(to_len)) if to_len > from_len => {
|
|
|
+ Ok(Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
+ }
|
|
|
(Type::Int(from_len), Type::Uint(to_len)) => {
|
|
|
if implicit {
|
|
|
diagnostics.push(Diagnostic::cast_error(
|
|
|
@@ -565,15 +597,23 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else if from_len > to_len {
|
|
|
- Ok(Expression::Trunc(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
} else if from_len < to_len {
|
|
|
- Ok(Expression::SignExt(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- ))
|
|
|
+ Ok(Expression::SignExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
(Type::Uint(from_len), Type::Int(to_len)) => {
|
|
|
@@ -588,15 +628,23 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else if from_len > to_len {
|
|
|
- Ok(Expression::Trunc(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
} else if from_len < to_len {
|
|
|
- Ok(Expression::ZeroExt(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- ))
|
|
|
+ Ok(Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
// Casting value to uint
|
|
|
@@ -617,17 +665,23 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Trunc(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
- Ordering::Less => Ok(Expression::SignExt(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- )),
|
|
|
- Ordering::Equal => {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
- }
|
|
|
+ Ordering::Less => Ok(Expression::SignExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
+ Ordering::Equal => Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
}
|
|
|
}
|
|
|
(Type::Value, Type::Int(to_len)) => {
|
|
|
@@ -645,15 +699,23 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else if from_len > to_len {
|
|
|
- Ok(Expression::Trunc(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
} else if from_len < to_len {
|
|
|
- Ok(Expression::ZeroExt(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- ))
|
|
|
+ Ok(Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
// Casting value to uint
|
|
|
@@ -674,20 +736,22 @@ impl Expression {
|
|
|
),
|
|
|
));
|
|
|
|
|
|
- Ok(Expression::CheckingTrunc(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- ))
|
|
|
- }
|
|
|
- Ordering::Less => Ok(Expression::SignExt(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- )),
|
|
|
- Ordering::Equal => {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::CheckingTrunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
+ Ordering::Less => Ok(Expression::SignExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
+ Ordering::Equal => Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
}
|
|
|
}
|
|
|
// Casting int to address
|
|
|
@@ -711,19 +775,35 @@ impl Expression {
|
|
|
};
|
|
|
|
|
|
let expr = if *from_len > address_bits {
|
|
|
- Expression::Trunc(*loc, address_to_int, Box::new(self.clone()))
|
|
|
+ Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: address_to_int,
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }
|
|
|
} else if *from_len < address_bits {
|
|
|
if from.is_signed_int() {
|
|
|
- Expression::ZeroExt(*loc, address_to_int, Box::new(self.clone()))
|
|
|
+ Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: address_to_int,
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }
|
|
|
} else {
|
|
|
- Expression::SignExt(*loc, address_to_int, Box::new(self.clone()))
|
|
|
+ Expression::SignExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: address_to_int,
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }
|
|
|
}
|
|
|
} else {
|
|
|
self.clone()
|
|
|
};
|
|
|
|
|
|
// Now cast integer to address
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(expr)))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(expr),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
// Casting address to int
|
|
|
@@ -747,15 +827,31 @@ impl Expression {
|
|
|
Type::Uint(address_bits)
|
|
|
};
|
|
|
|
|
|
- let expr = Expression::Cast(*loc, address_to_int, Box::new(self.clone()));
|
|
|
+ let expr = Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: address_to_int,
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ };
|
|
|
// now resize int to request size with sign extension etc
|
|
|
if *to_len < address_bits {
|
|
|
- Ok(Expression::Trunc(*loc, to.clone(), Box::new(expr)))
|
|
|
+ Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(expr),
|
|
|
+ })
|
|
|
} else if *to_len > address_bits {
|
|
|
if to.is_signed_int() {
|
|
|
- Ok(Expression::ZeroExt(*loc, to.clone(), Box::new(expr)))
|
|
|
+ Ok(Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(expr),
|
|
|
+ })
|
|
|
} else {
|
|
|
- Ok(Expression::SignExt(*loc, to.clone(), Box::new(expr)))
|
|
|
+ Ok(Expression::SignExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(expr),
|
|
|
+ })
|
|
|
}
|
|
|
} else {
|
|
|
Ok(expr)
|
|
|
@@ -780,11 +876,11 @@ impl Expression {
|
|
|
Ok(Expression::ShiftLeft(
|
|
|
*loc,
|
|
|
to.clone(),
|
|
|
- Box::new(Expression::ZeroExt(
|
|
|
- self.loc(),
|
|
|
- to.clone(),
|
|
|
- Box::new(self.clone()),
|
|
|
- )),
|
|
|
+ Box::new(Expression::ZeroExt {
|
|
|
+ loc: self.loc(),
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
Box::new(Expression::NumberLiteral(
|
|
|
*loc,
|
|
|
Type::Uint(*to_len as u16 * 8),
|
|
|
@@ -794,10 +890,10 @@ impl Expression {
|
|
|
} else {
|
|
|
let shift = (from_len - to_len) * 8;
|
|
|
|
|
|
- Ok(Expression::Trunc(
|
|
|
- *loc,
|
|
|
- to.clone(),
|
|
|
- Box::new(Expression::ShiftRight(
|
|
|
+ Ok(Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(Expression::ShiftRight(
|
|
|
self.loc(),
|
|
|
from.clone(),
|
|
|
Box::new(self.clone()),
|
|
|
@@ -808,14 +904,18 @@ impl Expression {
|
|
|
)),
|
|
|
false,
|
|
|
)),
|
|
|
- ))
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
(Type::Rational, Type::Uint(_) | Type::Int(_) | Type::Value) => {
|
|
|
match eval_const_rational(self, ns) {
|
|
|
Ok((_, big_number)) => {
|
|
|
if big_number.is_integer() {
|
|
|
- return Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())));
|
|
|
+ return Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
diagnostics.push(Diagnostic::cast_error(
|
|
|
@@ -835,12 +935,19 @@ impl Expression {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- (Type::Uint(_) | Type::Int(_) | Type::Value, Type::Rational) => {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ (Type::Uint(_) | Type::Int(_) | Type::Value, Type::Rational) => Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
+ (Type::Bytes(_), Type::DynamicBytes) | (Type::DynamicBytes, Type::Bytes(_)) => {
|
|
|
+ Ok(Expression::BytesCast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ from: from.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
- (Type::Bytes(_), Type::DynamicBytes) | (Type::DynamicBytes, Type::Bytes(_)) => Ok(
|
|
|
- Expression::BytesCast(*loc, to.clone(), from.clone(), Box::new(self.clone())),
|
|
|
- ),
|
|
|
// Explicit conversion from bytesN to int/uint only allowed with expliciy
|
|
|
// cast and if it is the same size (i.e. no conversion required)
|
|
|
(Type::Bytes(from_len), Type::Uint(to_len))
|
|
|
@@ -866,7 +973,11 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
// Explicit conversion to bytesN from int/uint only allowed with expliciy
|
|
|
@@ -894,7 +1005,11 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
// Explicit conversion from bytesN to address only allowed with expliciy
|
|
|
@@ -921,7 +1036,11 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
// Explicit conversion between contract and address is allowed
|
|
|
@@ -939,7 +1058,11 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
// Conversion between contracts is allowed if it is a base
|
|
|
@@ -955,13 +1078,19 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
// conversion from address payable to address is implicitly allowed (not vice versa)
|
|
|
- (Type::Address(true), Type::Address(false)) => {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
- }
|
|
|
+ (Type::Address(true), Type::Address(false)) => Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ }),
|
|
|
// Explicit conversion to bytesN from int/uint only allowed with expliciy
|
|
|
// cast and if it is the same size (i.e. no conversion required)
|
|
|
(Type::Address(_), Type::Bytes(to_len)) => {
|
|
|
@@ -986,13 +1115,21 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
(Type::String, Type::DynamicBytes) | (Type::DynamicBytes, Type::String)
|
|
|
if !implicit =>
|
|
|
{
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
// string conversions
|
|
|
// (Type::Bytes(_), Type::String) => Ok(Expression::Cast(self.loc(), to.clone(), Box::new(self.clone()))),
|
|
|
@@ -1076,7 +1213,11 @@ impl Expression {
|
|
|
));
|
|
|
Err(())
|
|
|
} else {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
}
|
|
|
// Match any array with ArrayLength::AnyFixed if is it fixed for that dimension, and the
|
|
|
@@ -1091,7 +1232,11 @@ impl Expression {
|
|
|
Ok(self.clone())
|
|
|
}
|
|
|
(Type::DynamicBytes, Type::Slice(ty)) if ty.as_ref() == &Type::Bytes(1) => {
|
|
|
- Ok(Expression::Cast(*loc, to.clone(), Box::new(self.clone())))
|
|
|
+ Ok(Expression::Cast {
|
|
|
+ loc: *loc,
|
|
|
+ to: to.clone(),
|
|
|
+ expr: Box::new(self.clone()),
|
|
|
+ })
|
|
|
}
|
|
|
_ => {
|
|
|
diagnostics.push(Diagnostic::cast_error(
|
|
|
@@ -3656,11 +3801,11 @@ pub fn new(
|
|
|
),
|
|
|
));
|
|
|
|
|
|
- Expression::CheckingTrunc(
|
|
|
- size_loc,
|
|
|
- expected_ty.clone(),
|
|
|
- Box::new(size_expr.cast(&size_loc, &size_ty, true, ns, diagnostics)?),
|
|
|
- )
|
|
|
+ Expression::CheckingTrunc {
|
|
|
+ loc: size_loc,
|
|
|
+ to: expected_ty.clone(),
|
|
|
+ expr: Box::new(size_expr.cast(&size_loc, &size_ty, true, ns, diagnostics)?),
|
|
|
+ }
|
|
|
} else {
|
|
|
size_expr.cast(&size_loc, &expected_ty, true, ns, diagnostics)?
|
|
|
};
|
|
|
@@ -4069,11 +4214,23 @@ fn assign_expr(
|
|
|
if left_length == right_length {
|
|
|
set
|
|
|
} else if right_length < left_length && set_type.is_signed_int() {
|
|
|
- Expression::SignExt(*loc, ty.clone(), Box::new(set))
|
|
|
+ Expression::SignExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: ty.clone(),
|
|
|
+ expr: Box::new(set),
|
|
|
+ }
|
|
|
} else if right_length < left_length && !set_type.is_signed_int() {
|
|
|
- Expression::ZeroExt(*loc, ty.clone(), Box::new(set))
|
|
|
+ Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: ty.clone(),
|
|
|
+ expr: Box::new(set),
|
|
|
+ }
|
|
|
} else {
|
|
|
- Expression::Trunc(*loc, ty.clone(), Box::new(set))
|
|
|
+ Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: ty.clone(),
|
|
|
+ expr: Box::new(set),
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
_ => set.cast(&right.loc(), ty, true, ns, diagnostics)?,
|
|
|
@@ -4727,7 +4884,7 @@ fn member_access(
|
|
|
if ns.target.is_substrate() {
|
|
|
let mut is_this = false;
|
|
|
|
|
|
- if let Expression::Cast(_, _, this) = &expr {
|
|
|
+ if let Expression::Cast { expr: this, .. } = &expr {
|
|
|
if let Expression::Builtin(_, _, Builtin::GetAddress, _) = this.as_ref() {
|
|
|
is_this = true;
|
|
|
}
|
|
|
@@ -6901,11 +7058,23 @@ pub fn cast_shift_arg(
|
|
|
if from_width == to_width {
|
|
|
expr
|
|
|
} else if from_width < to_width && ty.is_signed_int() {
|
|
|
- Expression::SignExt(*loc, ty.clone(), Box::new(expr))
|
|
|
+ Expression::SignExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: ty.clone(),
|
|
|
+ expr: Box::new(expr),
|
|
|
+ }
|
|
|
} else if from_width < to_width && !ty.is_signed_int() {
|
|
|
- Expression::ZeroExt(*loc, ty.clone(), Box::new(expr))
|
|
|
+ Expression::ZeroExt {
|
|
|
+ loc: *loc,
|
|
|
+ to: ty.clone(),
|
|
|
+ expr: Box::new(expr),
|
|
|
+ }
|
|
|
} else {
|
|
|
- Expression::Trunc(*loc, ty.clone(), Box::new(expr))
|
|
|
+ Expression::Trunc {
|
|
|
+ loc: *loc,
|
|
|
+ to: ty.clone(),
|
|
|
+ expr: Box::new(expr),
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|