Skip to content

Commit

Permalink
feat: add Quoted::as_expr and Expr::as_function_call (#5708)
Browse files Browse the repository at this point in the history
# Description

## Problem

Part of #5668

## Summary

What the title says.

## Additional Context

I didn't know how to test the exprs. I tried implementing `impl Eq for
Expr` but even though two exprs looked the same (same tokens) they
weren't equal... but I didn't dig deeper into why that is (I didn't know
if `Eq` was desired in this case)

## Documentation\*

Check one:
- [x] No documentation needed.
- [ ] Documentation included in this PR.
- [ ] **[For Experimental Features]** Documentation to be submitted in a
separate PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.
  • Loading branch information
asterite authored Aug 12, 2024
1 parent 226aeb1 commit 3f79607
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 5 deletions.
58 changes: 55 additions & 3 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
use acvm::{AcirField, FieldElement};
use builtin_helpers::{
check_argument_count, check_function_not_yet_resolved, check_one_argument,
check_three_arguments, check_two_arguments, get_function_def, get_module, get_quoted,
check_three_arguments, check_two_arguments, get_expr, get_function_def, get_module, get_quoted,
get_slice, get_struct, get_trait_constraint, get_trait_def, get_tuple, get_type, get_u32,
hir_pattern_to_tokens, mutate_func_meta_type, parse, parse_tokens,
replace_func_meta_parameters, replace_func_meta_return_type,
Expand All @@ -17,8 +17,8 @@ use rustc_hash::FxHashMap as HashMap;

use crate::{
ast::{
FunctionKind, FunctionReturnType, IntegerBitSize, UnresolvedType, UnresolvedTypeData,
Visibility,
ExpressionKind, FunctionKind, FunctionReturnType, IntegerBitSize, UnresolvedType,
UnresolvedTypeData, Visibility,
},
hir::comptime::{errors::IResult, value::add_token_spans, InterpreterError, Value},
hir_def::function::FunctionBody,
Expand Down Expand Up @@ -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_function_call" => expr_as_function_call(arguments, return_type, location),
"is_unconstrained" => Ok(Value::Bool(true)),
"function_def_name" => function_def_name(interner, arguments, location),
"function_def_parameters" => function_def_parameters(interner, arguments, location),
Expand All @@ -64,6 +65,7 @@ impl<'local, 'context> Interpreter<'local, 'context> {
"modulus_le_bits" => modulus_le_bits(interner, arguments, location),
"modulus_le_bytes" => modulus_le_bytes(interner, arguments, location),
"modulus_num_bits" => modulus_num_bits(interner, arguments, location),
"quoted_as_expr" => quoted_as_expr(arguments, return_type, location),
"quoted_as_module" => quoted_as_module(self, arguments, return_type, location),
"quoted_as_trait_constraint" => quoted_as_trait_constraint(self, arguments, location),
"quoted_as_type" => quoted_as_type(self, arguments, location),
Expand Down Expand Up @@ -312,6 +314,20 @@ fn slice_insert(
Ok(Value::Slice(values, typ))
}

// fn as_expr(quoted: Quoted) -> Option<Expr>
fn quoted_as_expr(
arguments: Vec<(Value, Location)>,
return_type: Type,
location: Location,
) -> IResult<Value> {
let argument = check_one_argument(arguments, location)?;

let expr = parse(argument, parser::expression(), "an expression").ok();
let value = expr.map(|expr| Value::Expr(expr.kind));

option(return_type, value)
}

// fn as_module(quoted: Quoted) -> Option<Module>
fn quoted_as_module(
interpreter: &mut Interpreter,
Expand Down Expand Up @@ -672,6 +688,42 @@ fn zeroed(return_type: Type) -> IResult<Value> {
}
}

// fn as_function_call(self) -> Option<(Expr, [Expr])>
fn expr_as_function_call(
arguments: Vec<(Value, Location)>,
return_type: Type,
location: Location,
) -> IResult<Value> {
expr_as(arguments, return_type, location, |expr| {
if let ExpressionKind::Call(call_expression) = expr {
let function = Value::Expr(call_expression.func.kind);
let arguments = call_expression.arguments.into_iter();
let arguments = arguments.map(|argument| Value::Expr(argument.kind)).collect();
let arguments =
Value::Slice(arguments, Type::Slice(Box::new(Type::Quoted(QuotedType::Expr))));
Some(Value::Tuple(vec![function, arguments]))
} else {
None
}
})
}

// Helper function for implementing the `expr_as_...` functions.
fn expr_as<F>(
arguments: Vec<(Value, Location)>,
return_type: Type,
location: Location,
f: F,
) -> IResult<Value>
where
F: FnOnce(ExpressionKind) -> Option<Value>,
{
let self_argument = check_one_argument(arguments, location)?;
let expr = get_expr(self_argument)?;
let option_value = f(expr);
option(return_type, option_value)
}

// fn name(self) -> Quoted
fn function_def_name(
interner: &NodeInterner,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use acvm::FieldElement;
use noirc_errors::Location;

use crate::{
ast::{IntegerBitSize, Signedness},
ast::{ExpressionKind, IntegerBitSize, Signedness},
hir::{
comptime::{errors::IResult, value::add_token_spans, Interpreter, InterpreterError, Value},
def_map::ModuleId,
Expand Down Expand Up @@ -145,6 +145,17 @@ pub(crate) fn get_u32((value, location): (Value, Location)) -> IResult<u32> {
}
}

pub(crate) fn get_expr((value, location): (Value, Location)) -> IResult<ExpressionKind> {
match value {
Value::Expr(expr) => Ok(expr),
value => {
let expected = Type::Quoted(QuotedType::Expr);
let actual = value.get_type().into_owned();
Err(InterpreterError::TypeMismatch { expected, actual, location })
}
}
}

pub(crate) fn get_function_def((value, location): (Value, Location)) -> IResult<FuncId> {
match value {
Value::FunctionDefinition(id) => Ok(id),
Expand Down
7 changes: 6 additions & 1 deletion compiler/noirc_frontend/src/hir/comptime/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub enum Value {
ModuleDefinition(ModuleId),
Type(Type),
Zeroed(Type),
Expr(ExpressionKind),
}

impl Value {
Expand Down Expand Up @@ -103,6 +104,7 @@ impl Value {
Value::ModuleDefinition(_) => Type::Quoted(QuotedType::Module),
Value::Type(_) => Type::Quoted(QuotedType::Type),
Value::Zeroed(typ) => return Cow::Borrowed(typ),
Value::Expr(_) => Type::Quoted(QuotedType::Expr),
})
}

Expand Down Expand Up @@ -223,6 +225,7 @@ impl Value {
}
};
}
Value::Expr(expr) => expr,
Value::Pointer(..)
| Value::StructDefinition(_)
| Value::TraitConstraint(..)
Expand Down Expand Up @@ -345,7 +348,8 @@ impl Value {
HirExpression::Literal(HirLiteral::Slice(HirArrayLiteral::Standard(elements)))
}
Value::Quoted(tokens) => HirExpression::Unquote(add_token_spans(tokens, location.span)),
Value::Pointer(..)
Value::Expr(..)
| Value::Pointer(..)
| Value::StructDefinition(_)
| Value::TraitConstraint(..)
| Value::TraitDefinition(_)
Expand Down Expand Up @@ -530,6 +534,7 @@ impl<'value, 'interner> Display for ValuePrinter<'value, 'interner> {
Value::ModuleDefinition(_) => write!(f, "(module)"),
Value::Zeroed(typ) => write!(f, "(zeroed {typ})"),
Value::Type(typ) => write!(f, "{}", typ),
Value::Expr(expr) => write!(f, "{}", expr),
}
}
}
6 changes: 6 additions & 0 deletions noir_stdlib/src/meta/expr.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use crate::option::Option;

impl Expr {
#[builtin(expr_as_function_call)]
fn as_function_call(self) -> Option<(Expr, [Expr])> {}
}
1 change: 1 addition & 0 deletions noir_stdlib/src/meta/mod.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::collections::umap::UHashMap;
use crate::hash::BuildHasherDefault;
use crate::hash::poseidon2::Poseidon2Hasher;

mod expr;
mod function_def;
mod module;
mod struct_def;
Expand Down
3 changes: 3 additions & 0 deletions noir_stdlib/src/meta/quoted.nr
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use crate::cmp::Eq;
use crate::option::Option;

impl Quoted {
#[builtin(quoted_as_expr)]
fn as_expr(self) -> Option<Expr> {}

#[builtin(quoted_as_module)]
fn as_module(self) -> Option<Module> {}

Expand Down
7 changes: 7 additions & 0 deletions test_programs/compile_success_empty/comptime_exp/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "comptime_exp"
type = "bin"
authors = [""]
compiler_version = ">=0.31.0"

[dependencies]
8 changes: 8 additions & 0 deletions test_programs/compile_success_empty/comptime_exp/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
comptime
{
let expr = quote { foo(bar) }.as_expr().unwrap();
let (_function, args) = expr.as_function_call().unwrap();
assert_eq(args.len(), 1);
}
}

0 comments on commit 3f79607

Please sign in to comment.