diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 093dc370eb6..33f8c9d8332 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -897,6 +897,7 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::Bool(lhs == rhs)), (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs == rhs)), (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs == rhs)), + (Value::Bool(lhs), Value::Bool(rhs)) => Ok(Value::Bool(lhs == rhs)), (lhs, rhs) => make_error(self, lhs, rhs, "=="), }, BinaryOpKind::NotEqual => match (lhs, rhs) { @@ -909,6 +910,7 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { (Value::U16(lhs), Value::U16(rhs)) => Ok(Value::Bool(lhs != rhs)), (Value::U32(lhs), Value::U32(rhs)) => Ok(Value::Bool(lhs != rhs)), (Value::U64(lhs), Value::U64(rhs)) => Ok(Value::Bool(lhs != rhs)), + (Value::Bool(lhs), Value::Bool(rhs)) => Ok(Value::Bool(lhs != rhs)), (lhs, rhs) => make_error(self, lhs, rhs, "!="), }, BinaryOpKind::Less => match (lhs, rhs) { diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index c3528434a72..330a6efaac3 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -17,7 +17,7 @@ use rustc_hash::FxHashMap as HashMap; use crate::{ ast::{ - ExpressionKind, FunctionKind, FunctionReturnType, IntegerBitSize, UnresolvedType, + ExpressionKind, FunctionKind, FunctionReturnType, IntegerBitSize, Literal, UnresolvedType, UnresolvedTypeData, Visibility, }, hir::comptime::{errors::IResult, value::add_token_spans, InterpreterError, Value}, @@ -47,6 +47,7 @@ impl<'local, 'context> Interpreter<'local, 'context> { "array_as_str_unchecked" => array_as_str_unchecked(interner, arguments, location), "array_len" => array_len(interner, arguments, location), "as_slice" => as_slice(interner, arguments, location), + "expr_as_bool" => expr_as_bool(arguments, return_type, location), "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), @@ -753,6 +754,21 @@ fn zeroed(return_type: Type) -> IResult { } } +// fn as_bool(self) -> Option +fn expr_as_bool( + arguments: Vec<(Value, Location)>, + return_type: Type, + location: Location, +) -> IResult { + expr_as(arguments, return_type, location, |expr| { + if let ExpressionKind::Literal(Literal::Bool(bool)) = expr { + Some(Value::Bool(bool)) + } else { + None + } + }) +} + // fn as_function_call(self) -> Option<(Expr, [Expr])> fn expr_as_function_call( arguments: Vec<(Value, Location)>, diff --git a/noir_stdlib/src/meta/expr.nr b/noir_stdlib/src/meta/expr.nr index 2a463ef4d86..df375fa97d3 100644 --- a/noir_stdlib/src/meta/expr.nr +++ b/noir_stdlib/src/meta/expr.nr @@ -1,6 +1,9 @@ use crate::option::Option; impl Expr { + #[builtin(expr_as_bool)] + fn as_bool(self) -> Option {} + #[builtin(expr_as_function_call)] fn as_function_call(self) -> Option<(Expr, [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 81531310ff5..339b8ecdce6 100644 --- a/test_programs/compile_success_empty/comptime_exp/src/main.nr +++ b/test_programs/compile_success_empty/comptime_exp/src/main.nr @@ -27,5 +27,12 @@ fn main() { // Check parenthesized expression is automatically unwrapped let expr = quote { ((if 1 { 2 })) }.as_expr().unwrap(); assert(expr.as_if().is_some()); + + // Check Expr::as_bool + let expr = quote { false }.as_expr().unwrap(); + assert(expr.as_bool().unwrap() == false); + + let expr = quote { true }.as_expr().unwrap(); + assert_eq(expr.as_bool().unwrap(), true); } }