Skip to content

Commit b5bb1f9

Browse files
authored
feat(slang): add checked exponentiation (#344)
Add checked exponentiation support by routing `ExponentiationExpression` through `emit_binary_op` and the `Operator` enum. In checked mode, exponentiation now emits `sol.cexp`; in unchecked blocks it emits `sol.exp`.
1 parent d529afb commit b5bb1f9

3 files changed

Lines changed: 24 additions & 38 deletions

File tree

solx-slang/src/ast/contract/function/expression/mod.rs

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ pub mod storage;
1212
use std::collections::HashMap;
1313
use std::rc::Rc;
1414

15-
use melior::ir::BlockLike;
1615
use melior::ir::BlockRef;
1716
use melior::ir::Type;
1817
use melior::ir::Value;
@@ -26,7 +25,6 @@ use slang_solidity::cst::NodeId;
2625
use solx_mlir::CmpPredicate;
2726
use solx_mlir::Context;
2827
use solx_mlir::Environment;
29-
use solx_mlir::ods::sol::ExpOperation;
3028

3129
use self::call::type_conversion::TypeConversion;
3230

@@ -185,6 +183,13 @@ impl<'state, 'context, 'block> ExpressionEmitter<'state, 'context, 'block> {
185183
self.emit_binary_op(&left, &right, &operator.text, result_type, block)
186184
.map(|(value, block)| (Some(value), block))
187185
}
186+
Expression::ExponentiationExpression(expression) => {
187+
let target_type = self.resolve_expression_type(expression.node_id());
188+
let left = expression.left_operand();
189+
let right = expression.right_operand();
190+
self.emit_binary_op(&left, &right, "**", target_type, block)
191+
.map(|(value, block)| (Some(value), block))
192+
}
188193
Expression::EqualityExpression(expression) => {
189194
let left = expression.left_operand();
190195
let right = expression.right_operand();
@@ -272,40 +277,6 @@ impl<'state, 'context, 'block> ExpressionEmitter<'state, 'context, 'block> {
272277
.ok_or_else(|| anyhow::anyhow!("empty tuple element"))?;
273278
self.emit(&inner, block)
274279
}
275-
Expression::ExponentiationExpression(expression) => {
276-
// TODO: implement checked exponentiation (sol.cexp) for Solidity 0.8+.
277-
let target_type = self.resolve_expression_type(expression.node_id());
278-
let left = expression.left_operand();
279-
let right = expression.right_operand();
280-
let (lhs, block) = self.emit_value(&left, block)?;
281-
let (rhs, block) = self.emit_value(&right, block)?;
282-
let result_type = target_type.unwrap_or_else(|| self.state.builder.types.ui256);
283-
let lhs = TypeConversion::from_target_type(result_type, &self.state.builder).emit(
284-
lhs,
285-
&self.state.builder,
286-
&block,
287-
);
288-
let rhs = TypeConversion::from_target_type(result_type, &self.state.builder).emit(
289-
rhs,
290-
&self.state.builder,
291-
&block,
292-
);
293-
let result = block
294-
.append_operation(
295-
ExpOperation::builder(
296-
self.state.builder.context,
297-
self.state.builder.unknown_location,
298-
)
299-
.lhs(lhs)
300-
.rhs(rhs)
301-
.build()
302-
.into(),
303-
)
304-
.result(0)
305-
.expect("sol.exp always produces one result")
306-
.into();
307-
Ok((Some(result), block))
308-
}
309280
Expression::ConditionalExpression(conditional) => {
310281
let result_type = self
311282
.resolve_expression_type(conditional.node_id())

solx-slang/src/ast/contract/function/expression/operator.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ use solx_mlir::ods::sol::AddOperation;
1313
use solx_mlir::ods::sol::AndOperation;
1414
use solx_mlir::ods::sol::CAddOperation;
1515
use solx_mlir::ods::sol::CDivOperation;
16+
use solx_mlir::ods::sol::CExpOperation;
1617
use solx_mlir::ods::sol::CMulOperation;
1718
use solx_mlir::ods::sol::CSubOperation;
1819
use solx_mlir::ods::sol::DivOperation;
20+
use solx_mlir::ods::sol::ExpOperation;
1921
use solx_mlir::ods::sol::ModOperation;
2022
use solx_mlir::ods::sol::MulOperation;
2123
use solx_mlir::ods::sol::OrOperation;
@@ -38,6 +40,8 @@ pub enum Operator {
3840
Divide,
3941
/// `%`
4042
Remainder,
43+
/// `**`
44+
Exponentiation,
4145

4246
// ---- Arithmetic assignment ----
4347
/// `+=`
@@ -120,7 +124,7 @@ impl Operator {
120124
/// Builds a Sol dialect binary operation via ODS-generated builders.
121125
///
122126
/// When `checked` is true, uses checked variants (`sol.cadd`, `sol.csub`,
123-
/// `sol.cmul`, `sol.cdiv`) for arithmetic operators. Modulo, bitwise,
127+
/// `sol.cmul`, `sol.cdiv`, `sol.cexp`) for arithmetic operators. Modulo, bitwise,
124128
/// and shift operators are always unchecked. Result type is inferred
125129
/// from `lhs` (`SameOperandsAndResultType`).
126130
///
@@ -183,6 +187,16 @@ impl Operator {
183187
.rhs(rhs)
184188
.build()
185189
.into(),
190+
Self::Exponentiation if checked => CExpOperation::builder(context, location)
191+
.lhs(lhs)
192+
.rhs(rhs)
193+
.build()
194+
.into(),
195+
Self::Exponentiation => ExpOperation::builder(context, location)
196+
.lhs(lhs)
197+
.rhs(rhs)
198+
.build()
199+
.into(),
186200
Self::BitwiseAnd => AndOperation::builder(context, location)
187201
.lhs(lhs)
188202
.rhs(rhs)
@@ -242,6 +256,7 @@ impl FromStr for Operator {
242256
"*" => Ok(Self::Multiply),
243257
"/" => Ok(Self::Divide),
244258
"%" => Ok(Self::Remainder),
259+
"**" => Ok(Self::Exponentiation),
245260
"+=" => Ok(Self::AddAssign),
246261
"-=" => Ok(Self::SubtractAssign),
247262
"*=" => Ok(Self::MultiplyAssign),

0 commit comments

Comments
 (0)