diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index ac3b219282a..d52d4ca8c71 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -1559,81 +1559,6 @@ fn function_def_has_named_attribute( Ok(Value::Bool(false)) } -// fn resolve(self) -> TypedExpr -fn expr_resolve( - interpreter: &mut Interpreter, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { - let self_argument = check_one_argument(arguments, location)?; - let self_argument_location = self_argument.1; - let expr_value = get_expr(interpreter.elaborator.interner, self_argument)?; - let expr_value = unwrap_expr_value(interpreter.elaborator.interner, expr_value); - - let value = - interpreter.elaborate_item(interpreter.current_function, |elaborator| match expr_value { - ExprValue::Expression(expression_kind) => { - let expr = Expression { kind: expression_kind, span: self_argument_location.span }; - let (expr_id, _) = elaborator.elaborate_expression(expr); - Value::TypedExpr(TypedExpr::ExprId(expr_id)) - } - ExprValue::Statement(statement_kind) => { - let statement = - Statement { kind: statement_kind, span: self_argument_location.span }; - let (stmt_id, _) = elaborator.elaborate_statement(statement); - Value::TypedExpr(TypedExpr::StmtId(stmt_id)) - } - ExprValue::LValue(lvalue) => { - let expr = lvalue.as_expression(); - let (expr_id, _) = elaborator.elaborate_expression(expr); - Value::TypedExpr(TypedExpr::ExprId(expr_id)) - } - }); - - Ok(value) -} - -fn unwrap_expr_value(interner: &NodeInterner, mut expr_value: ExprValue) -> ExprValue { - loop { - match expr_value { - ExprValue::Expression(ExpressionKind::Parenthesized(expression)) => { - expr_value = ExprValue::Expression(expression.kind); - } - ExprValue::Statement(StatementKind::Expression(expression)) - | ExprValue::Statement(StatementKind::Semi(expression)) => { - expr_value = ExprValue::Expression(expression.kind); - } - ExprValue::Expression(ExpressionKind::Interned(id)) => { - expr_value = ExprValue::Expression(interner.get_expression_kind(id).clone()); - } - ExprValue::Statement(StatementKind::Interned(id)) => { - expr_value = ExprValue::Statement(interner.get_statement_kind(id).clone()); - } - ExprValue::LValue(LValue::Interned(id, span)) => { - expr_value = ExprValue::LValue(interner.get_lvalue(id, span).clone()); - } - _ => break, - } - } - expr_value -} - -// fn body(self) -> Expr -fn function_def_body( - interner: &NodeInterner, - arguments: Vec<(Value, Location)>, - location: Location, -) -> IResult { - let self_argument = check_one_argument(arguments, location)?; - let func_id = get_function_def(self_argument)?; - let func_meta = interner.function_meta(&func_id); - if let FunctionBody::Unresolved(_, block_expr, _) = &func_meta.function_body { - Ok(Value::expression(ExpressionKind::Block(block_expr.clone()))) - } else { - Err(InterpreterError::FunctionAlreadyResolved { location }) - } -} - // fn name(self) -> Quoted fn function_def_name( interner: &NodeInterner, diff --git a/noir/noir-repo/noir_stdlib/src/meta/expr.nr b/noir/noir-repo/noir_stdlib/src/meta/expr.nr index 45e432913c0..fe19f6870f9 100644 --- a/noir/noir-repo/noir_stdlib/src/meta/expr.nr +++ b/noir/noir-repo/noir_stdlib/src/meta/expr.nr @@ -458,6 +458,297 @@ fn modify_array(expr: Expr, f: fn[Env](Expr) -> Option) -> Option(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_assert().map( + |expr: (Expr, Option)| { + let (predicate, msg) = expr; + let predicate = predicate.modify(f); + let msg = msg.map(|msg: Expr| msg.modify(f)); + new_assert(predicate, msg) + } + ) +} + +fn modify_assign(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_assign().map( + |expr: (Expr, Expr)| { + let (lhs, rhs) = expr; + let lhs = lhs.modify(f); + let rhs = rhs.modify(f); + new_assign(lhs, rhs) + } + ) +} + +fn modify_binary_op(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_binary_op().map( + |expr: (Expr, BinaryOp, Expr)| { + let (lhs, op, rhs) = expr; + let lhs = lhs.modify(f); + let rhs = rhs.modify(f); + new_binary_op(lhs, op, rhs) + } + ) +} + +fn modify_block(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_block().map( + |exprs: [Expr]| { + let exprs = modify_expressions(exprs, f); + new_block(exprs) + } + ) +} + +fn modify_cast(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_cast().map( + |expr: (Expr, UnresolvedType)| { + let (expr, typ) = expr; + let expr = expr.modify(f); + new_cast(expr, typ) + } + ) +} + +fn modify_comptime(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_comptime().map( + |exprs: [Expr]| { + let exprs = exprs.map(|expr: Expr| expr.modify(f)); + new_comptime(exprs) + } + ) +} + +fn modify_function_call(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_function_call().map( + |expr: (Expr, [Expr])| { + let (function, arguments) = expr; + let function = function.modify(f); + let arguments = arguments.map(|arg: Expr| arg.modify(f)); + new_function_call(function, arguments) + } + ) +} + +fn modify_if(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_if().map( + |expr: (Expr, Expr, Option)| { + let (condition, consequence, alternative) = expr; + let condition = condition.modify(f); + let consequence = consequence.modify(f); + let alternative = alternative.map(|alternative: Expr| alternative.modify(f)); + new_if(condition, consequence, alternative) + } + ) +} + +fn modify_index(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_index().map( + |expr: (Expr, Expr)| { + let (object, index) = expr; + let object = object.modify(f); + let index = index.modify(f); + new_index(object, index) + } + ) +} + +fn modify_member_access(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_member_access().map( + |expr: (Expr, Quoted)| { + let (object, name) = expr; + let object = object.modify(f); + new_member_access(object, name) + } + ) +} + +fn modify_method_call(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_method_call().map( + |expr: (Expr, Quoted, [UnresolvedType], [Expr])| { + let (object, name, generics, arguments) = expr; + let object = object.modify(f); + let arguments = arguments.map(|arg: Expr| arg.modify(f)); + new_method_call(object, name, generics, arguments) + } + ) +} + +fn modify_repeated_element_array(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_repeated_element_array().map( + |expr: (Expr, Expr)| { + let (expr, length) = expr; + let expr = expr.modify(f); + let length = length.modify(f); + new_repeated_element_array(expr, length) + } + ) +} + +fn modify_repeated_element_slice(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_repeated_element_slice().map( + |expr: (Expr, Expr)| { + let (expr, length) = expr; + let expr = expr.modify(f); + let length = length.modify(f); + new_repeated_element_slice(expr, length) + } + ) +} + +fn modify_slice(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_slice().map( + |exprs: [Expr]| { + let exprs = modify_expressions(exprs, f); + new_slice(exprs) + } + ) +} + +fn modify_tuple(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_tuple().map( + |exprs: [Expr]| { + let exprs = modify_expressions(exprs, f); + new_tuple(exprs) + } + ) +} + +fn modify_unary_op(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_unary_op().map( + |expr: (UnaryOp, Expr)| { + let (op, rhs) = expr; + let rhs = rhs.modify(f); + new_unary_op(op, rhs) + } + ) +} + +fn modify_unsafe(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_unsafe().map( + |exprs: [Expr]| { + let exprs = exprs.map(|expr: Expr| expr.modify(f)); + new_unsafe(exprs) + } + ) +} + +fn modify_expressions(exprs: [Expr], f: fn[Env](Expr) -> Option) -> [Expr] { + exprs.map(|expr: Expr| expr.modify(f)) +} + +fn new_array(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { , }); + quote { [$exprs]}.as_expr().unwrap() +} + +fn new_assert(predicate: Expr, msg: Option) -> Expr { + if msg.is_some() { + let msg = msg.unwrap(); + quote { assert($predicate, $msg) }.as_expr().unwrap() + } else { + quote { assert($predicate) }.as_expr().unwrap() + } +} + +fn new_assign(lhs: Expr, rhs: Expr) -> Expr { + quote { $lhs = $rhs }.as_expr().unwrap() +} + +fn new_binary_op(lhs: Expr, op: BinaryOp, rhs: Expr) -> Expr { + let op = op.quoted(); + quote { ($lhs) $op ($rhs) }.as_expr().unwrap() +} + +fn new_block(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { ; }); + quote { { $exprs }}.as_expr().unwrap() +} + +fn new_cast(expr: Expr, typ: UnresolvedType) -> Expr { + quote { ($expr) as $typ }.as_expr().unwrap() +} + +fn new_comptime(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { ; }); + quote { comptime { $exprs }}.as_expr().unwrap() +} + +fn new_if(condition: Expr, consequence: Expr, alternative: Option) -> Expr { + if alternative.is_some() { + let alternative = alternative.unwrap(); + quote { if $condition { $consequence } else { $alternative }}.as_expr().unwrap() + } else { + quote { if $condition { $consequence } }.as_expr().unwrap() + } +} + +fn new_index(object: Expr, index: Expr) -> Expr { + quote { $object[$index] }.as_expr().unwrap() +} + +fn new_member_access(object: Expr, name: Quoted) -> Expr { + quote { $object.$name }.as_expr().unwrap() +} + +fn new_function_call(function: Expr, arguments: [Expr]) -> Expr { + let arguments = join_expressions(arguments, quote { , }); + + quote { $function($arguments) }.as_expr().unwrap() +} + +fn new_method_call(object: Expr, name: Quoted, generics: [UnresolvedType], arguments: [Expr]) -> Expr { + let arguments = join_expressions(arguments, quote { , }); + + if generics.len() == 0 { + quote { $object.$name($arguments) }.as_expr().unwrap() + } else { + let generics = generics.map(|generic| quote { $generic }).join(quote { , }); + quote { $object.$name::<$generics>($arguments) }.as_expr().unwrap() + } +} + +fn new_repeated_element_array(expr: Expr, length: Expr) -> Expr { + quote { [$expr; $length] }.as_expr().unwrap() +} + +fn new_repeated_element_slice(expr: Expr, length: Expr) -> Expr { + quote { &[$expr; $length] }.as_expr().unwrap() +} + +fn new_slice(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { , }); + quote { &[$exprs]}.as_expr().unwrap() +} + +fn new_tuple(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { , }); + quote { ($exprs) }.as_expr().unwrap() +} + +fn new_unary_op(op: UnaryOp, rhs: Expr) -> Expr { + let op = op.quoted(); + quote { $op($rhs) }.as_expr().unwrap() +} + +fn new_unsafe(exprs: [Expr]) -> Expr { + let exprs = join_expressions(exprs, quote { ; }); + quote { unsafe { $exprs }}.as_expr().unwrap() +} + +fn join_expressions(exprs: [Expr], separator: Quoted) -> Quoted { + exprs.map(|expr: Expr| expr.quoted()).join(separator) +} + +fn modify_array(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { + expr.as_array().map( + |exprs: [Expr]| { + let exprs = modify_expressions(exprs, f); + new_array(exprs) + } + ) +} + fn modify_assert(expr: Expr, f: fn[Env](Expr) -> Option) -> Option { expr.as_assert().map( |expr: (Expr, Option)| {