From b461dc938a47422d2b353e465f96eb7a71011c38 Mon Sep 17 00:00:00 2001 From: Tom French Date: Tue, 18 Jun 2024 13:34:12 +0100 Subject: [PATCH 1/3] feat: implement comptime support for `array_len` builtin --- .../noirc_frontend/src/hir/comptime/interpreter.rs | 10 ++++++++-- .../src/hir/comptime/interpreter/builtin.rs | 12 ++++++++++++ .../execution_success/array_len/src/main.nr | 3 +++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 3648881e501..c473ac7f8a6 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -31,6 +31,7 @@ use self::unquote::UnquoteArgs; use super::errors::{IResult, InterpreterError}; use super::value::Value; +mod builtin; mod unquote; #[allow(unused)] @@ -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 }) diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs new file mode 100644 index 00000000000..3e5ad207719 --- /dev/null +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -0,0 +1,12 @@ +use noirc_errors::Location; + +use crate::hir::comptime::{errors::IResult, Value}; + +pub(super) fn array_len(arguments: &[(Value, Location)]) -> IResult { + 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"), + } +} diff --git a/test_programs/execution_success/array_len/src/main.nr b/test_programs/execution_success/array_len/src/main.nr index 45c09b8a282..7ff741f4c0c 100644 --- a/test_programs/execution_success/array_len/src/main.nr +++ b/test_programs/execution_success/array_len/src/main.nr @@ -11,6 +11,9 @@ fn nested_call(b: [Field; N]) -> u32 { } fn main(x: Field, len3: [u8; 3], len4: [Field; 4]) { + comptime { + assert_eq([1,2,3].len(), 3); + } assert(len_plus_1(len3) == 4); assert(len_plus_1(len4) == 5); assert(add_lens(len3, len4) == 7); From 75bfd13d0a6b0b45632b2340366dc9beeb6d55cc Mon Sep 17 00:00:00 2001 From: Tom French Date: Tue, 18 Jun 2024 14:09:04 +0100 Subject: [PATCH 2/3] chore: fmt --- test_programs/execution_success/array_len/src/main.nr | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test_programs/execution_success/array_len/src/main.nr b/test_programs/execution_success/array_len/src/main.nr index 7ff741f4c0c..fc5853f6625 100644 --- a/test_programs/execution_success/array_len/src/main.nr +++ b/test_programs/execution_success/array_len/src/main.nr @@ -11,8 +11,9 @@ fn nested_call(b: [Field; N]) -> u32 { } fn main(x: Field, len3: [u8; 3], len4: [Field; 4]) { - comptime { - assert_eq([1,2,3].len(), 3); + comptime + { + assert_eq([1, 2, 3].len(), 3); } assert(len_plus_1(len3) == 4); assert(len_plus_1(len4) == 5); From c4b300917ab15f4ac83e99dd3b0ec234b1fbb839 Mon Sep 17 00:00:00 2001 From: Tom French Date: Tue, 18 Jun 2024 14:10:55 +0100 Subject: [PATCH 3/3] chore: move test to `compile_success_empty` --- .../compile_success_empty/comptime_array_len/Nargo.toml | 6 ++++++ .../compile_success_empty/comptime_array_len/src/main.nr | 6 ++++++ test_programs/execution_success/array_len/src/main.nr | 4 ---- 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 test_programs/compile_success_empty/comptime_array_len/Nargo.toml create mode 100644 test_programs/compile_success_empty/comptime_array_len/src/main.nr diff --git a/test_programs/compile_success_empty/comptime_array_len/Nargo.toml b/test_programs/compile_success_empty/comptime_array_len/Nargo.toml new file mode 100644 index 00000000000..c07deddc6c5 --- /dev/null +++ b/test_programs/compile_success_empty/comptime_array_len/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "comptime_array_len" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/comptime_array_len/src/main.nr b/test_programs/compile_success_empty/comptime_array_len/src/main.nr new file mode 100644 index 00000000000..c98a3de01dd --- /dev/null +++ b/test_programs/compile_success_empty/comptime_array_len/src/main.nr @@ -0,0 +1,6 @@ +fn main() { + comptime + { + assert_eq([1, 2, 3].len(), 3); + } +} diff --git a/test_programs/execution_success/array_len/src/main.nr b/test_programs/execution_success/array_len/src/main.nr index fc5853f6625..45c09b8a282 100644 --- a/test_programs/execution_success/array_len/src/main.nr +++ b/test_programs/execution_success/array_len/src/main.nr @@ -11,10 +11,6 @@ fn nested_call(b: [Field; N]) -> u32 { } fn main(x: Field, len3: [u8; 3], len4: [Field; 4]) { - comptime - { - assert_eq([1, 2, 3].len(), 3); - } assert(len_plus_1(len3) == 4); assert(len_plus_1(len4) == 5); assert(add_lens(len3, len4) == 7);