Skip to content

Commit 9db65d8

Browse files
authored
feat: implement comptime support for as_slice builtin (#5276)
# Description ## Problem\* Resolves #5274 ## Summary\* This PR implements the `as_slice` builtin function for the comptime interpreter. I've also fixed an issue where due to builtin/foreign/oracle functions having an early return, we don't call `exit_function` which results in the scopes being left in an inconsistent state. ## Additional Context ## 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.
1 parent 963b9a3 commit 9db65d8

4 files changed

Lines changed: 33 additions & 3 deletions

File tree

compiler/noirc_frontend/src/hir/comptime/interpreter.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ impl<'a> Interpreter<'a> {
6262
arguments: Vec<(Value, Location)>,
6363
location: Location,
6464
) -> IResult<Value> {
65-
let previous_state = self.enter_function();
66-
6765
let meta = self.interner.function_meta(&function);
6866
if meta.parameters.len() != arguments.len() {
6967
return Err(InterpreterError::ArgumentCountMismatch {
@@ -78,6 +76,8 @@ impl<'a> Interpreter<'a> {
7876
}
7977

8078
let parameters = meta.parameters.0.clone();
79+
let previous_state = self.enter_function();
80+
8181
for ((parameter, typ, _), (argument, arg_location)) in parameters.iter().zip(arguments) {
8282
self.define_pattern(parameter, typ, argument, arg_location)?;
8383
}
@@ -102,6 +102,7 @@ impl<'a> Interpreter<'a> {
102102
if let Some(builtin) = func_attrs.builtin() {
103103
match builtin.as_str() {
104104
"array_len" => builtin::array_len(&arguments),
105+
"as_slice" => builtin::as_slice(arguments),
105106
_ => {
106107
let item = format!("Evaluation for builtin function {builtin}");
107108
Err(InterpreterError::Unimplemented { item, location })

compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use noirc_errors::Location;
22

3-
use crate::hir::comptime::{errors::IResult, Value};
3+
use crate::{
4+
hir::comptime::{errors::IResult, Value},
5+
Type,
6+
};
47

58
pub(super) fn array_len(arguments: &[(Value, Location)]) -> IResult<Value> {
69
assert_eq!(arguments.len(), 1, "ICE: `array_len` should only receive a single argument");
@@ -10,3 +13,13 @@ pub(super) fn array_len(arguments: &[(Value, Location)]) -> IResult<Value> {
1013
_ => unreachable!("ICE: Cannot query length of types other than arrays or slices"),
1114
}
1215
}
16+
17+
pub(super) fn as_slice(mut arguments: Vec<(Value, Location)>) -> IResult<Value> {
18+
assert_eq!(arguments.len(), 1, "ICE: `as_slice` should only receive a single argument");
19+
let (array, _) = arguments.pop().unwrap();
20+
match array {
21+
Value::Array(values, Type::Array(_, typ)) => Ok(Value::Slice(values, Type::Slice(typ))),
22+
// Type checking should prevent this branch being taken.
23+
_ => unreachable!("ICE: Cannot convert types other than arrays into slices"),
24+
}
25+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "array_to_slice"
3+
type = "bin"
4+
authors = [""]
5+
compiler_version = ">=0.24.0"
6+
7+
[dependencies]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn main() {
2+
comptime
3+
{
4+
let ws: [Field; 3] = [1; 3];
5+
let ws_as_slice: [Field] = ws.as_slice();
6+
7+
assert_eq(ws[0], ws_as_slice[0]);
8+
}
9+
}

0 commit comments

Comments
 (0)