Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add FunctionDefinition::parameters, FunctionDefinition::return_type and impl Eq for Quoted #5681

Merged
merged 11 commits into from
Aug 5, 2024
213 changes: 66 additions & 147 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
};

use acvm::{AcirField, FieldElement};
use builtin_helpers::{
check_argument_count, check_one_argument, check_three_arguments, check_two_arguments,
get_function_def, get_quoted, get_slice, get_trait_constraint, get_trait_def, get_type,
get_u32, hir_pattern_to_tokens,
};
use chumsky::Parser;
use iter_extended::{try_vecmap, vecmap};
use noirc_errors::Location;
Expand All @@ -13,14 +18,15 @@
ast::IntegerBitSize,
hir::comptime::{errors::IResult, value::add_token_spans, InterpreterError, Value},
macros_api::{NodeInterner, Signedness},
node_interner::TraitId,
parser,
token::Token,
QuotedType, Shared, Type,
};

use super::Interpreter;

pub(crate) mod builtin_helpers;

impl<'local, 'context> Interpreter<'local, 'context> {
pub(super) fn call_builtin(
&mut self,
Expand All @@ -34,11 +40,16 @@
"array_len" => array_len(interner, arguments, location),
"as_slice" => as_slice(interner, arguments, location),
"is_unconstrained" => Ok(Value::Bool(true)),
"function_def_parameters" => function_def_parameters(interner, arguments, location),
"function_def_return_type" => function_def_return_type(interner, arguments, location),
"modulus_be_bits" => modulus_be_bits(interner, arguments, location),
"modulus_be_bytes" => modulus_be_bytes(interner, arguments, location),
"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_trait_constraint" => quoted_as_trait_constraint(self, arguments, location),
"quoted_as_type" => quoted_as_type(self, arguments, location),
"quoted_eq" => quoted_eq(arguments, location),
asterite marked this conversation as resolved.
Show resolved Hide resolved
"slice_insert" => slice_insert(interner, arguments, location),
"slice_pop_back" => slice_pop_back(interner, arguments, location),
"slice_pop_front" => slice_pop_front(interner, arguments, location),
Expand All @@ -55,8 +66,6 @@
}
"trait_def_eq" => trait_def_eq(interner, arguments, location),
"trait_def_hash" => trait_def_hash(interner, arguments, location),
"quoted_as_trait_constraint" => quoted_as_trait_constraint(self, arguments, location),
"quoted_as_type" => quoted_as_type(self, arguments, location),
"type_as_array" => type_as_array(arguments, return_type, location),
"type_as_constant" => type_as_constant(arguments, return_type, location),
"type_as_integer" => type_as_integer(arguments, return_type, location),
Expand All @@ -75,154 +84,10 @@
}
}

pub(super) fn check_argument_count(
expected: usize,
arguments: &[(Value, Location)],
location: Location,
) -> IResult<()> {
if arguments.len() == expected {
Ok(())
} else {
let actual = arguments.len();
Err(InterpreterError::ArgumentCountMismatch { expected, actual, location })
}
}

pub(super) fn check_one_argument(
mut arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
check_argument_count(1, &arguments, location)?;

Ok(arguments.pop().unwrap().0)
}

pub(super) fn check_two_arguments(
mut arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<(Value, Value)> {
check_argument_count(2, &arguments, location)?;

let argument2 = arguments.pop().unwrap().0;
let argument1 = arguments.pop().unwrap().0;

Ok((argument1, argument2))
}

pub(super) fn check_three_arguments(
mut arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<(Value, Value, Value)> {
check_argument_count(3, &arguments, location)?;

let argument3 = arguments.pop().unwrap().0;
let argument2 = arguments.pop().unwrap().0;
let argument1 = arguments.pop().unwrap().0;

Ok((argument1, argument2, argument3))
}

fn failing_constraint<T>(message: impl Into<String>, location: Location) -> IResult<T> {
Err(InterpreterError::FailingConstraint { message: Some(message.into()), location })
}

pub(super) fn get_array(
interner: &NodeInterner,
value: Value,
location: Location,
) -> IResult<(im::Vector<Value>, Type)> {
match value {
Value::Array(values, typ) => Ok((values, typ)),
value => {
let type_var = Box::new(interner.next_type_variable());
let expected = Type::Array(type_var.clone(), type_var);
let actual = value.get_type().into_owned();
Err(InterpreterError::TypeMismatch { expected, actual, location })
}
}
}

fn get_slice(
interner: &NodeInterner,
value: Value,
location: Location,
) -> IResult<(im::Vector<Value>, Type)> {
match value {
Value::Slice(values, typ) => Ok((values, typ)),
value => {
let type_var = Box::new(interner.next_type_variable());
let expected = Type::Slice(type_var);
let actual = value.get_type().into_owned();
Err(InterpreterError::TypeMismatch { expected, actual, location })
}
}
}

pub(super) fn get_field(value: Value, location: Location) -> IResult<FieldElement> {
match value {
Value::Field(value) => Ok(value),
value => {
let actual = value.get_type().into_owned();
Err(InterpreterError::TypeMismatch { expected: Type::FieldElement, actual, location })
}
}
}

pub(super) fn get_u32(value: Value, location: Location) -> IResult<u32> {
match value {
Value::U32(value) => Ok(value),
value => {
let expected = Type::Integer(Signedness::Unsigned, IntegerBitSize::ThirtyTwo);
let actual = value.get_type().into_owned();
Err(InterpreterError::TypeMismatch { expected, actual, location })
}
}
}

fn get_trait_constraint(value: Value, location: Location) -> IResult<(TraitId, Vec<Type>)> {
match value {
Value::TraitConstraint(trait_id, generics) => Ok((trait_id, generics)),
value => {
let expected = Type::Quoted(QuotedType::TraitConstraint);
let actual = value.get_type().into_owned();
Err(InterpreterError::TypeMismatch { expected, actual, location })
}
}
}

fn get_trait_def(value: Value, location: Location) -> IResult<TraitId> {
match value {
Value::TraitDefinition(id) => Ok(id),
value => {
let expected = Type::Quoted(QuotedType::TraitDefinition);
let actual = value.get_type().into_owned();
Err(InterpreterError::TypeMismatch { expected, actual, location })
}
}
}

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

fn get_quoted(value: Value, location: Location) -> IResult<Rc<Vec<Token>>> {
match value {
Value::Quoted(tokens) => Ok(tokens),
value => {
let expected = Type::Quoted(QuotedType::Quoted);
let actual = value.get_type().into_owned();
Err(InterpreterError::TypeMismatch { expected, actual, location })
}
}
}

fn array_len(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
Expand Down Expand Up @@ -486,7 +351,7 @@

let typ =
interpreter.elaborate_item(interpreter.current_function, |elab| elab.resolve_type(typ));

Check warning on line 354 in compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (elab)

Check warning on line 354 in compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (elab)
Ok(Value::Type(typ))
}

Expand Down Expand Up @@ -593,6 +458,9 @@
fn type_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult<Value> {
let (self_type, other_type) = check_two_arguments(arguments, location)?;

let self_type = get_type(self_type, location)?;
let other_type = get_type(other_type, location)?;

Ok(Value::Bool(self_type == other_type))
}

Expand Down Expand Up @@ -762,6 +630,47 @@
}
}

// fn parameters(self) -> [(Quoted, Type)]
fn function_def_parameters(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let self_argument = check_one_argument(arguments, location)?;
let func_id = get_function_def(self_argument, location)?;
let func_meta = interner.function_meta(&func_id);

let parameters = func_meta
.parameters
.iter()
.map(|(hir_pattern, typ, _visibility)| {
let name = Value::Quoted(Rc::new(hir_pattern_to_tokens(interner, hir_pattern)));
let typ = Value::Type(typ.clone());
Value::Tuple(vec![name, typ])
})
.collect();

let typ = Type::Slice(Box::new(Type::Tuple(vec![
Type::Quoted(QuotedType::Quoted),
Type::Quoted(QuotedType::Type),
])));

Ok(Value::Slice(parameters, typ))
}

// fn return_type(self) -> Type
fn function_def_return_type(
interner: &NodeInterner,
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let self_argument = check_one_argument(arguments, location)?;
let func_id = get_function_def(self_argument, location)?;
let func_meta = interner.function_meta(&func_id);

Ok(Value::Type(func_meta.return_type().follow_bindings()))
}

fn modulus_be_bits(
_interner: &mut NodeInterner,
arguments: Vec<(Value, Location)>,
Expand Down Expand Up @@ -826,6 +735,16 @@
Ok(Value::U64(bits))
}

// fn quoted_eq(_first: Quoted, _second: Quoted) -> bool
fn quoted_eq(arguments: Vec<(Value, Location)>, location: Location) -> IResult<Value> {
let (self_value, other_value) = check_two_arguments(arguments, location)?;

let self_quoted = get_quoted(self_value, location)?;
let other_quoted = get_quoted(other_value, location)?;

Ok(Value::Bool(self_quoted == other_quoted))
}

fn trait_def_as_trait_constraint(
interner: &mut NodeInterner,
arguments: Vec<(Value, Location)>,
Expand Down
Loading
Loading