diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index 3449d402fbc..cec4b1fd434 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -52,6 +52,8 @@ impl<'local, 'context> Interpreter<'local, 'context> { "expr_as_function_call" => expr_as_function_call(arguments, return_type, location), "expr_as_if" => expr_as_if(arguments, return_type, location), "expr_as_index" => expr_as_index(arguments, return_type, location), + "expr_as_integer" => expr_as_integer(arguments, return_type, location), + "expr_as_member_access" => expr_as_member_access(arguments, return_type, location), "expr_as_unary_op" => expr_as_unary_op(arguments, return_type, location), "expr_as_tuple" => expr_as_tuple(arguments, return_type, location), "is_unconstrained" => Ok(Value::Bool(true)), @@ -839,6 +841,37 @@ fn expr_as_index( }) } +// fn as_integer(self) -> Option<(Field, bool)> +fn expr_as_integer( + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, +) -> IResult { + expr_as(arguments, return_type.clone(), location, |expr| { + if let ExpressionKind::Literal(Literal::Integer(field, sign)) = expr { + Some(Value::Tuple(vec![Value::Field(field), Value::Bool(sign)])) + } else { + None + } + }) +} + +// fn as_member_access(self) -> Option<(Expr, Quoted)> +fn expr_as_member_access( + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, +) -> IResult { + expr_as(arguments, return_type, location, |expr| { + if let ExpressionKind::MemberAccess(member_access) = expr { + let tokens = Rc::new(vec![Token::Ident(member_access.rhs.0.contents.clone())]); + Some(Value::Tuple(vec![Value::Expr(member_access.lhs.kind), Value::Quoted(tokens)])) + } else { + None + } + }) +} + // fn as_unary_op(self) -> Option<(UnaryOp, Expr)> fn expr_as_unary_op( arguments: Vec<(Value, Location)>, diff --git a/noir_stdlib/src/meta/expr.nr b/noir_stdlib/src/meta/expr.nr index 2c25e20fe70..55c49531017 100644 --- a/noir_stdlib/src/meta/expr.nr +++ b/noir_stdlib/src/meta/expr.nr @@ -3,6 +3,9 @@ use crate::meta::op::UnaryOp; use crate::meta::op::BinaryOp; impl Expr { + #[builtin(expr_as_integer)] + fn as_integer(self) -> Option<(Field, bool)> {} + #[builtin(expr_as_binary_op)] fn as_binary_op(self) -> Option<(Expr, BinaryOp, Expr)> {} @@ -18,6 +21,9 @@ impl Expr { #[builtin(expr_as_index)] fn as_index(self) -> Option<(Expr, Expr)> {} + #[builtin(expr_as_member_access)] + fn as_member_access(self) -> Option<(Expr, Quoted)> {} + #[builtin(expr_as_tuple)] fn as_tuple(self) -> Option<[Expr]> {} diff --git a/test_programs/compile_success_empty/comptime_exp/src/main.nr b/test_programs/compile_success_empty/comptime_exp/src/main.nr index 4149beacece..7b25dcb5097 100644 --- a/test_programs/compile_success_empty/comptime_exp/src/main.nr +++ b/test_programs/compile_success_empty/comptime_exp/src/main.nr @@ -59,6 +59,18 @@ fn main() { assert(get_binary_op(quote { x >> y }).is_shift_right()); assert(get_binary_op(quote { x << y }).is_shift_left()); assert(get_binary_op(quote { x % y }).is_modulo()); + + // Check Expr::as_integer + let expr = quote { 1 }.as_expr().unwrap(); + assert_eq((1, false), expr.as_integer().unwrap()); + + let expr = quote { -2 }.as_expr().unwrap(); + assert_eq((2, true), expr.as_integer().unwrap()); + + // Check Expr::as_member_access + let expr = quote { foo.bar }.as_expr().unwrap(); + let (_, name) = expr.as_member_access().unwrap(); + assert_eq(name, quote { bar }); } }