Skip to content

Commit

Permalink
feat: implement comptime support for array_len builtin (#5272)
Browse files Browse the repository at this point in the history
# Description

## Problem\*

Resolves <!-- Link to GitHub Issue -->

## Summary\*

This PR implements support for the `array_len` builtin so we can query
the length of arrays in `comptime` blocks. Ideally we'd tie this closer
to the `Intrinsics` struct in `noirc_evaluator` but we can handle this
morn cleanly later.

## 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 55d8e05 commit c91186a
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 2 deletions.
10 changes: 8 additions & 2 deletions compiler/noirc_frontend/src/hir/comptime/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use self::unquote::UnquoteArgs;
use super::errors::{IResult, InterpreterError};
use super::value::Value;

mod builtin;
mod unquote;

#[allow(unused)]
Expand Down Expand Up @@ -99,8 +100,13 @@ impl<'a> Interpreter<'a> {
.expect("all builtin functions must contain a function attribute which contains the opcode which it links to");

if let Some(builtin) = func_attrs.builtin() {
let item = format!("Evaluation for builtin functions like {builtin}");
Err(InterpreterError::Unimplemented { item, location })
match builtin.as_str() {
"array_len" => builtin::array_len(&arguments),
_ => {
let item = format!("Evaluation for builtin function {builtin}");
Err(InterpreterError::Unimplemented { item, location })
}
}
} else if let Some(foreign) = func_attrs.foreign() {
let item = format!("Evaluation for foreign functions like {foreign}");
Err(InterpreterError::Unimplemented { item, location })
Expand Down
12 changes: 12 additions & 0 deletions compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use noirc_errors::Location;

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

pub(super) fn array_len(arguments: &[(Value, Location)]) -> IResult<Value> {
assert_eq!(arguments.len(), 1, "ICE: `array_len` should only receive a single argument");
match &arguments[0].0 {
Value::Array(values, _) | Value::Slice(values, _) => Ok(Value::U32(values.len() as u32)),
// Type checking should prevent this branch being taken.
_ => unreachable!("ICE: Cannot query length of types other than arrays or slices"),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "comptime_array_len"
type = "bin"
authors = [""]

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fn main() {
comptime
{
assert_eq([1, 2, 3].len(), 3);
}
}

0 comments on commit c91186a

Please sign in to comment.