Skip to content

Commit

Permalink
feat: implement comptime support for as_slice builtin (#5276)
Browse files Browse the repository at this point in the history
# 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.
  • Loading branch information
TomAFrench authored Jun 18, 2024
1 parent 963b9a3 commit 9db65d8
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 3 deletions.
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 @@ impl<'a> Interpreter<'a> {
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 @@ impl<'a> Interpreter<'a> {
}

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 @@ impl<'a> Interpreter<'a> {
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 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]);
}
}

0 comments on commit 9db65d8

Please sign in to comment.