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: implement comptime support for as_slice builtin #5276

Merged
merged 8 commits into from
Jun 18, 2024
Merged
5 changes: 3 additions & 2 deletions compiler/noirc_frontend/src/hir/comptime/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@
arguments: Vec<(Value, Location)>,
location: Location,
) -> IResult<Value> {
let previous_state = self.enter_function();

let meta = self.interner.function_meta(&function);
if meta.parameters.len() != arguments.len() {
return Err(InterpreterError::ArgumentCountMismatch {
Expand All @@ -78,6 +76,8 @@
}

let parameters = meta.parameters.0.clone();
let previous_state = self.enter_function();

for ((parameter, typ, _), (argument, arg_location)) in parameters.iter().zip(arguments) {
self.define_pattern(parameter, typ, argument, arg_location)?;
}
Expand All @@ -102,6 +102,7 @@
if let Some(builtin) = func_attrs.builtin() {
match builtin.as_str() {
"array_len" => builtin::array_len(&arguments),
"as_slice" => builtin::as_slice(arguments),
_ => {
let item = format!("Evaluation for builtin function {builtin}");
Err(InterpreterError::Unimplemented { item, location })
Expand All @@ -119,7 +120,7 @@
}
} else {
let name = self.interner.function_name(&function);
unreachable!("Non-builtin, lowlevel or oracle builtin fn '{name}'")

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

View workflow job for this annotation

GitHub Actions / Code

Unknown word (lowlevel)
}
}

Expand Down
15 changes: 14 additions & 1 deletion compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use noirc_errors::Location;

use crate::hir::comptime::{errors::IResult, Value};
use crate::{
hir::comptime::{errors::IResult, Value},
Type,
};

pub(super) fn array_len(arguments: &[(Value, Location)]) -> IResult<Value> {
assert_eq!(arguments.len(), 1, "ICE: `array_len` should only receive a single argument");
Expand All @@ -10,3 +13,13 @@ pub(super) fn array_len(arguments: &[(Value, Location)]) -> IResult<Value> {
_ => unreachable!("ICE: Cannot query length of types other than arrays or slices"),
}
}

pub(super) fn as_slice(mut arguments: Vec<(Value, Location)>) -> IResult<Value> {
assert_eq!(arguments.len(), 1, "ICE: `as_slice` should only receive a single argument");
let (array, _) = arguments.pop().unwrap();
match array {
Value::Array(values, Type::Array(_, typ)) => Ok(Value::Slice(values, Type::Slice(typ))),
// Type checking should prevent this branch being taken.
_ => unreachable!("ICE: Cannot convert types other than arrays into slices"),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "array_to_slice"
type = "bin"
authors = [""]
compiler_version = ">=0.24.0"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fn main() {
comptime
{
let ws: [Field; 3] = [1; 3];
let ws_as_slice: [Field] = ws.as_slice();

assert_eq(ws[0], ws_as_slice[0]);
}
}
Loading